From 5076ba57b4c08b3c9d724e8d99cd95f24ed512f5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Mar 2022 09:44:07 +0300 Subject: [PATCH] Squashed 'bridges/' changes from 1602249f0a..f220d2fcca f220d2fcca Polkadot staging update (#1356) 02fd3d497c fix parse_transaction on Rialto+Millau (#1360) bc191fd9a2 update parity-scale-codec to 3.1.2 (#1359) a37226e79c update chain versions (#1358) ff5d539fcb Update Substrate/Polkadot/Cumulus references (#1353) 1581f60cd5 Support dedicated lanes for pallets (#962) 0a7ccf5c57 ignore more "increase" alerts that are sometimes signalling NoData at startup (#1351) 31165127cc added no_stack_overflow_when_decoding_nested_call_during_dispatch test (#1349) 7000619eb8 replace From<>InboundLaneApi with direct storage reads (#1348) 515df10ccc added alerts for relay balances (#1347) b56f6a87de Mortal conversion rate updater transactions (#1257) 20f2f331ec edition = "2021" (#1346) 99147d4f75 update regex to 1.5.5 (#1345) 686191f379 use DecodeLimit when decoding incoming calls (#1344) a70c276006 get rid of '[No Data] Messages from Millau to Rialto are not being delivered' warnings (#1342) 01f29b8ac1 fix conversion rate metric in dashboards (#1341) 51c3bf351f Increase rate from metric when estimating fee (#1340) 3bb9c4f68f fix generator scripts to be consistent with updatedrelay output (#1339) 0475a1667b fixed mess with conversion rates (#1338) d8fdd7d716 synchronize relay cli changes and token swap generator script (#1337) 6e928137a5 fix conversion rate override in token swap (#1336) 62d4a4811d override conversion rate in tokens swap generator (#1335) ed9e1c839c fi typo in generator script (#1334) 3254b5af7a Override conversion rate when computing message fee (#1261) 66df68b5b8 Revert "Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275)" (#1333) 0ca6fc6ef8 fix clippy issues (#1332) 5414b2fffb Reinitialize bridge relay subcommand (#1331) a63d95ba7d removed extra *_RUNTIME_VERSION consts from relay code (#1330) 59fb18a310 fix typo in alert expression (#1329) a6267a47ee Using-same-fork metric for finality and complex relay (#1327) 88d684d37e use mortal transactions in transaction resubmitter (#1326) 8ff88b6844 impl Decode for SignedExtensions (otherwise transaction resubmitter panicks) (#1325) 1ed09854f0 Encode and estimate Rococo/Wococo/Kusama/Polkadot messages (#1322) ddb4517e13 Add some tests to check integrity of chain constants + bridge configuration (#1316) bdeedb7ab9 Fix issues from cargo deny (#1311) d3d79d01e0 expose fee multiplier metrics in messages relay (#1312) c8b3f0ea16 Endow relayer account at target chain in message benchmarks (#1310) f51ecd92b6 fix benchmarks before using it in Polkadot/Kusama/Rococo runtimes (#1309) 6935c619ad increase relay balance guard limits for Polkadot<>Kusama bridge (#1308) 7e31834c66 Fix mandatory headers scanning in on-demand relay (#1306) 92ddc3ea7a Polkadot-staging update (#1305) 3787193a31 fix session length of Rococo and Wococo (#1304) eb468d29c0 Revert nightly docker pin (#1301) e2d4c073e1 Use raw balance value if tokenDecimals property is missing (#1299) 108f4b29d1 Fix ss58 prefixes of Polkadot, Kusama and Westend used by relay (#1298) 64fbd2705e bump chain spec versions (#1297) 5707777b86 Bump Substrate/Polkadot/Cumulus refs (#1295) 29eecdf1fa Merge pull request #1294 from paritytech/polkadot-staging-update 1f0c05368e Relay balance metrics (#1291) 6356bb90b3 when messages pallet is halted, relay shall not submit messages delivery/confirmation transactions (#1289) 800dc2df8d when GRANDPA pallet is halted, relay shall not submit finality transactions (#1288) 3dd8e4f936 disable BEEFY allerts for Rialto (#1285) f58fed7380 support version mode cli options in send-message subcommand (#1284) 3aac448da3 reuse polkadot-service code (#1273) 2bdbb651e1 replace latest_confirmed_nonce runtime APIs with direct storage reads (#1282) 5f9c6d241f move "common" code of messages pallet benchmarks helpers to the common library (#1281) 173d2d8229 Merge pull request #1280 from paritytech/polkadot-staging-update 8b9c4ec16d do not start spec_version guard when version mode is set to auto (#1278) e98d682de2 removed extra messages benchmarks (#1279) c730e25b61 Move benchmarks from Rialto to Millau (#1277) 54146416e7 Merge pull request #1276 from paritytech/polkadot-staging-update df70118174 Merge branch 'master' into polkadot-staging-update ed7def64c4 Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275) 38c6c3a49f Use "production" floating tag when uilding docker image from version git tags (#1272) ded9ff6dbb Replace InboundLaneApi::latest_received_nonce with direct storage read (#1269) f704a741ee Polkadot staging update (#1270) 8c65f0d7ab verify that GRANDPA pallet is not initialized before submitting initialization transaction (#1267) e7e83d8944 remove OutboundLaneApi::latest_received_nonce (#1262) 9f4b34acf1 bump rococo version (#1263) 82c08c5a87 read latest_generated_nonce directly from storage (#1260) 50ffb5dd08 override conversion rate in estimate-message-fee RPC (#1189) 467ca5ef59 move storage keys computation to primitivs (#1254) 4f9884066b remporary use pinned bridges-ci image in Dockerfile (#1258) edfcb74e00 Change submit transaction spec_version and transaction_version query from chain (#1248) 4009d970d0 pin bridges-ci image (#1256) 65e51b5e1c decrease startup sleep to 5s for relays and to 120s for generators + remove curl (#1251) 3bc74355d9 Add missing RPC APIs to rialto parachain node (#1250) 80c9429284 Bump relay version to 1.0.0 (#1249) 9ead06af2a runtimes: fix call_size() test (#1245) 4fc8a29357 Use same endowed accounts set on dev/local chains (#1244) fed54371c2 Refactor message relay helpers (#1234) a15b4faae7 post-merge build fix (#1243) 52232d8d54 Fix transactions mortality (#1196) c07bba931f Expose prometheus BEEFY metrics and add them to grafana dashboard (#1242) f927775bd5 Refactor finality relay helpers (#1220) 7bf76f14a8 Update Rococo/Wococo version + prepare relay for Rococo<>Wococo bridge (#1241) e860fecd04 Enable offchain indexing for Rialto/Millau nodes (#1239) 04d4d1c6b4 Enable Beefy debug logs in test deployment (#1237) cd771f1089 Fix storage parameter name computation (#1238) 816ddd2dd2 Integrate BEEFY with Rialto & Millau runtimes (#1227) d94b62b1ac update dependencies (#1229) 98eb9ee13d Add mut support (#1232) ffef6f89f9 fixed set_operational in GRANDPA pallet (#1226) bd2f8bfbd7 Add CODEOWNERS file (#1219) 6b5cf2b591 Unify metric names (#1209) d1541e797e remove abandoned exchange relay (#1217) 39140d0b34 Remove unused `relays/headers` (#1216) 9bc071d42b Remove unused PoA<>Substrate bridge (#1210) 877e8d01e3 Fix UI deployment. (#1211) 6cd5775ebe Add `AtLeast32BitUnsigned` for MessageLance::SourceChainBalance (#1207) git-subtree-dir: bridges git-subtree-split: f220d2fccabbf141101d19456ecb4e3576a1d797 --- .gitlab-ci.yml | 15 +- .maintain/rialto-weight-template.hbs | 103 - Cargo.lock | 3269 ++++++++++------- Dockerfile | 4 +- bin/millau/node/Cargo.toml | 4 +- bin/millau/node/src/chain_spec.rs | 106 +- bin/millau/node/src/cli.rs | 7 +- bin/millau/node/src/service.rs | 62 +- bin/millau/runtime/Cargo.toml | 19 +- bin/millau/runtime/src/lib.rs | 215 +- bin/millau/runtime/src/rialto_messages.rs | 169 +- bin/rialto-parachain/node/Cargo.toml | 8 +- bin/rialto-parachain/node/src/chain_spec.rs | 4 +- bin/rialto-parachain/node/src/cli.rs | 50 +- bin/rialto-parachain/node/src/command.rs | 36 +- bin/rialto-parachain/node/src/service.rs | 178 +- bin/rialto-parachain/runtime/Cargo.toml | 6 +- bin/rialto-parachain/runtime/src/lib.rs | 26 +- bin/rialto/node/Cargo.toml | 38 +- bin/rialto/node/src/chain_spec.rs | 135 +- bin/rialto/node/src/cli.rs | 13 +- bin/rialto/node/src/command.rs | 77 +- bin/rialto/node/src/main.rs | 4 - bin/rialto/node/src/overseer.rs | 316 -- bin/rialto/node/src/parachains_db.rs | 104 - bin/rialto/node/src/service.rs | 756 ---- bin/rialto/runtime/Cargo.toml | 10 +- bin/rialto/runtime/src/lib.rs | 450 +-- bin/rialto/runtime/src/millau_messages.rs | 212 +- bin/rialto/runtime/src/parachains.rs | 26 +- bin/runtime-common/Cargo.toml | 18 +- bin/runtime-common/README.md | 7 +- bin/runtime-common/src/integrity.rs | 331 ++ bin/runtime-common/src/lib.rs | 3 + bin/runtime-common/src/messages.rs | 161 +- .../src/messages_benchmarking.rs | 375 +- ci.Dockerfile | 2 +- deny.toml | 8 +- deployments/BridgeDeps.Dockerfile | 2 +- ...y-millau-to-rialto-messages-dashboard.json | 31 +- ...y-rialto-to-millau-messages-dashboard.json | 27 +- .../rialto-millau-maintenance-dashboard.json | 633 +++- .../bridges/rialto-millau/docker-compose.yml | 1 + ...ay-messages-millau-to-rialto-entrypoint.sh | 4 +- ...ay-messages-rialto-to-millau-entrypoint.sh | 4 +- ...messages-to-millau-generator-entrypoint.sh | 23 +- ...messages-to-rialto-generator-entrypoint.sh | 25 +- ...ssages-to-rialto-resubmitter-entrypoint.sh | 3 +- .../relay-millau-rialto-entrypoint.sh | 6 +- .../relay-token-swap-generator-entrypoint.sh | 6 +- ...y-westend-to-millau-headers-dashboard.json | 161 +- ...ay-headers-westend-to-millau-entrypoint.sh | 4 +- .../relay-messages-millau-to-rialto.sh | 1 + .../relay-messages-rialto-to-millau.sh | 1 + .../local-scripts/relay-millau-to-rialto.sh | 2 + .../monitoring/GrafanaMatrix.Dockerfile | 2 +- .../dashboard/grafana/beefy-dashboard.json | 539 +++ .../dashboard/prometheus/millau-targets.yml | 2 + .../dashboard/prometheus/rialto-targets.yml | 2 + .../rialto-parachain-registrar-entrypoint.sh | 4 +- deployments/networks/millau.yml | 14 + deployments/networks/rialto.yml | 14 + fuzz/storage-proof/Cargo.toml | 3 +- fuzz/storage-proof/src/main.rs | 8 +- modules/dispatch/Cargo.toml | 6 +- modules/dispatch/src/lib.rs | 8 +- modules/grandpa/Cargo.toml | 10 +- modules/grandpa/src/lib.rs | 21 +- modules/grandpa/src/mock.rs | 8 + modules/grandpa/src/weights.rs | 26 +- modules/messages/Cargo.toml | 12 +- modules/messages/README.md | 5 +- modules/messages/src/benchmarking.rs | 361 +- modules/messages/src/instant_payments.rs | 94 +- modules/messages/src/lib.rs | 184 +- modules/messages/src/mock.rs | 32 +- modules/messages/src/outbound_lane.rs | 2 +- modules/messages/src/weights.rs | 203 +- modules/messages/src/weights_ext.rs | 2 +- modules/shift-session-manager/Cargo.toml | 6 +- modules/shift-session-manager/src/lib.rs | 2 + modules/token-swap/Cargo.toml | 8 +- modules/token-swap/src/benchmarking.rs | 29 +- modules/token-swap/src/lib.rs | 112 +- modules/token-swap/src/mock.rs | 21 +- modules/token-swap/src/weights.rs | 14 +- primitives/chain-kusama/Cargo.toml | 4 +- primitives/chain-kusama/src/lib.rs | 59 +- primitives/chain-millau/Cargo.toml | 8 +- primitives/chain-millau/src/lib.rs | 104 +- primitives/chain-polkadot/Cargo.toml | 4 +- primitives/chain-polkadot/src/lib.rs | 61 +- primitives/chain-rialto-parachain/Cargo.toml | 2 +- primitives/chain-rialto-parachain/src/lib.rs | 26 +- primitives/chain-rialto/Cargo.toml | 2 +- primitives/chain-rialto/src/lib.rs | 87 +- primitives/chain-rococo/Cargo.toml | 4 +- primitives/chain-rococo/src/lib.rs | 61 +- primitives/chain-westend/Cargo.toml | 8 +- primitives/chain-westend/src/lib.rs | 85 +- primitives/chain-wococo/Cargo.toml | 4 +- primitives/chain-wococo/src/lib.rs | 58 +- primitives/header-chain/Cargo.toml | 15 +- primitives/header-chain/src/lib.rs | 1 + primitives/header-chain/src/storage_keys.rs | 78 + .../header-chain/tests/justification.rs | 3 +- primitives/message-dispatch/Cargo.toml | 6 +- primitives/messages/Cargo.toml | 15 +- primitives/messages/src/lib.rs | 15 +- primitives/messages/src/source_chain.rs | 46 +- primitives/messages/src/storage_keys.rs | 128 + primitives/polkadot-core/Cargo.toml | 6 +- primitives/polkadot-core/src/lib.rs | 98 +- primitives/runtime/Cargo.toml | 6 +- primitives/runtime/src/chain.rs | 83 +- primitives/runtime/src/lib.rs | 70 +- primitives/runtime/src/storage_proof.rs | 29 +- primitives/test-utils/Cargo.toml | 6 +- primitives/test-utils/src/keyring.rs | 3 +- primitives/token-swap/Cargo.toml | 17 +- primitives/token-swap/src/lib.rs | 17 +- primitives/token-swap/src/storage_keys.rs | 51 + relays/bin-substrate/Cargo.toml | 15 +- relays/bin-substrate/src/chains/kusama.rs | 93 +- .../src/chains/kusama_headers_to_polkadot.rs | 117 +- .../src/chains/kusama_messages_to_polkadot.rs | 346 +- relays/bin-substrate/src/chains/millau.rs | 51 +- .../src/chains/millau_headers_to_rialto.rs | 67 +- .../src/chains/millau_messages_to_rialto.rs | 333 +- relays/bin-substrate/src/chains/mod.rs | 57 +- relays/bin-substrate/src/chains/polkadot.rs | 93 +- .../src/chains/polkadot_headers_to_kusama.rs | 115 +- .../src/chains/polkadot_messages_to_kusama.rs | 346 +- relays/bin-substrate/src/chains/rialto.rs | 51 +- .../src/chains/rialto_headers_to_millau.rs | 75 +- .../src/chains/rialto_messages_to_millau.rs | 332 +- .../src/chains/rialto_parachain.rs | 30 +- relays/bin-substrate/src/chains/rococo.rs | 75 +- .../src/chains/rococo_headers_to_wococo.rs | 104 +- .../src/chains/rococo_messages_to_wococo.rs | 298 +- relays/bin-substrate/src/chains/westend.rs | 10 +- .../src/chains/westend_headers_to_millau.rs | 80 +- relays/bin-substrate/src/chains/wococo.rs | 79 +- .../src/chains/wococo_headers_to_rococo.rs | 104 +- .../src/chains/wococo_messages_to_rococo.rs | 296 +- relays/bin-substrate/src/cli/bridge.rs | 12 +- relays/bin-substrate/src/cli/encode_call.rs | 20 +- .../bin-substrate/src/cli/encode_message.rs | 11 +- relays/bin-substrate/src/cli/estimate_fee.rs | 166 +- relays/bin-substrate/src/cli/init_bridge.rs | 24 +- relays/bin-substrate/src/cli/mod.rs | 115 +- .../src/cli/register_parachain.rs | 84 +- relays/bin-substrate/src/cli/reinit_bridge.rs | 553 +++ relays/bin-substrate/src/cli/relay_headers.rs | 20 +- .../src/cli/relay_headers_and_messages.rs | 355 +- .../bin-substrate/src/cli/relay_messages.rs | 16 +- .../src/cli/resubmit_transactions.rs | 79 +- relays/bin-substrate/src/cli/send_message.rs | 119 +- relays/bin-substrate/src/cli/swap_tokens.rs | 156 +- relays/client-kusama/Cargo.toml | 6 +- relays/client-kusama/src/lib.rs | 63 +- relays/client-kusama/src/runtime.rs | 12 + relays/client-millau/Cargo.toml | 5 +- relays/client-millau/src/lib.rs | 108 +- relays/client-polkadot/Cargo.toml | 6 +- relays/client-polkadot/src/lib.rs | 64 +- relays/client-polkadot/src/runtime.rs | 12 + relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rialto-parachain/src/lib.rs | 12 + relays/client-rialto/Cargo.toml | 5 +- relays/client-rialto/src/lib.rs | 108 +- relays/client-rococo/Cargo.toml | 6 +- relays/client-rococo/src/lib.rs | 63 +- relays/client-rococo/src/runtime.rs | 18 +- relays/client-substrate/Cargo.toml | 15 +- relays/client-substrate/src/chain.rs | 99 +- relays/client-substrate/src/client.rs | 310 +- relays/client-substrate/src/error.rs | 5 +- relays/client-substrate/src/guard.rs | 26 +- relays/client-substrate/src/lib.rs | 17 +- .../src/metrics/float_storage_value.rs | 80 +- relays/client-substrate/src/metrics/mod.rs | 2 +- relays/client-substrate/src/rpc.rs | 79 +- relays/client-substrate/src/sync_header.rs | 6 +- relays/client-westend/Cargo.toml | 5 +- relays/client-westend/src/lib.rs | 19 +- relays/client-wococo/Cargo.toml | 6 +- relays/client-wococo/src/lib.rs | 63 +- relays/client-wococo/src/runtime.rs | 18 +- relays/finality/Cargo.toml | 2 +- relays/finality/src/finality_loop.rs | 69 +- relays/finality/src/finality_loop_tests.rs | 198 +- relays/finality/src/lib.rs | 11 +- relays/finality/src/sync_loop_metrics.rs | 60 +- relays/lib-substrate-relay/Cargo.toml | 12 +- .../src/conversion_rate_update.rs | 249 +- relays/lib-substrate-relay/src/error.rs | 3 + .../src/finality_guards.rs | 48 + .../src/finality_pipeline.rs | 220 +- .../src/finality_source.rs | 90 +- .../src/finality_target.rs | 126 +- .../src/headers_initialize.rs | 55 +- relays/lib-substrate-relay/src/helpers.rs | 81 +- relays/lib-substrate-relay/src/lib.rs | 12 + .../lib-substrate-relay/src/messages_lane.rs | 715 ++-- .../src/messages_metrics.rs | 389 ++ .../src/messages_source.rs | 318 +- .../src/messages_target.rs | 399 +- .../src/on_demand_headers.rs | 292 +- relays/messages/Cargo.toml | 3 +- relays/messages/src/message_lane_loop.rs | 7 + relays/messages/src/metrics.rs | 53 +- relays/utils/Cargo.toml | 5 +- relays/utils/src/initialize.rs | 12 +- relays/utils/src/metrics.rs | 4 +- relays/utils/src/relay_loop.rs | 32 +- scripts/dump-logs.sh | 2 +- scripts/update-weights.sh | 8 +- 218 files changed, 11645 insertions(+), 9252 deletions(-) delete mode 100644 .maintain/rialto-weight-template.hbs delete mode 100644 bin/rialto/node/src/overseer.rs delete mode 100644 bin/rialto/node/src/parachains_db.rs delete mode 100644 bin/rialto/node/src/service.rs create mode 100644 bin/runtime-common/src/integrity.rs create mode 100644 deployments/networks/dashboard/grafana/beefy-dashboard.json create mode 100644 deployments/networks/dashboard/prometheus/millau-targets.yml create mode 100644 deployments/networks/dashboard/prometheus/rialto-targets.yml create mode 100644 primitives/header-chain/src/storage_keys.rs create mode 100644 primitives/messages/src/storage_keys.rs create mode 100644 primitives/token-swap/src/storage_keys.rs create mode 100644 relays/bin-substrate/src/cli/reinit_bridge.rs create mode 100644 relays/lib-substrate-relay/src/finality_guards.rs rename relays/{client-substrate => lib-substrate-relay}/src/finality_source.rs (66%) create mode 100644 relays/lib-substrate-relay/src/messages_metrics.rs mode change 100644 => 100755 scripts/dump-logs.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0e69a91af165..7d3bf6fd8ac2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -47,7 +47,7 @@ default: when: - runner_system_failure - unknown_failure - - api_failure + - api_failure interruptible: true tags: - linux-docker @@ -240,7 +240,14 @@ build-nightly: elif [[ "${CI_COMMIT_REF_NAME}" ]]; then VERSION=$(echo ${CI_COMMIT_REF_NAME} | sed -r 's#/+#-#g'); fi - - echo "Effective tags = ${VERSION} sha-${CI_COMMIT_SHORT_SHA} latest" + # When building from version tags (v1.0, v2.1rc1, ...) we'll use "production" to tag + # docker image. In all other cases, it'll be "latest". + - if [[ $CI_COMMIT_REF_NAME =~ ^v[0-9]+\.[0-9]+.*$ ]]; then + FLOATING_TAG="production"; + else + FLOATING_TAG="latest"; + fi + - echo "Effective tags = ${VERSION} sha-${CI_COMMIT_SHORT_SHA} ${FLOATING_TAG}" secrets: DOCKER_HUB_USER: vault: cicd/gitlab/parity/DOCKER_HUB_USER@kv @@ -260,7 +267,7 @@ build-nightly: --build-arg VERSION="${VERSION}" --tag "${IMAGE_NAME}:${VERSION}" --tag "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}" - --tag "${IMAGE_NAME}:latest" + --tag "${IMAGE_NAME}:${FLOATING_TAG}" --file "${DOCKERFILE}" . # The job will success only on the protected branch - echo "${DOCKER_HUB_PASS}" | @@ -268,7 +275,7 @@ build-nightly: - buildah info - buildah push --format=v2s2 "${IMAGE_NAME}:${VERSION}" - buildah push --format=v2s2 "${IMAGE_NAME}:sha-${CI_COMMIT_SHORT_SHA}" - - buildah push --format=v2s2 "${IMAGE_NAME}:latest" + - buildah push --format=v2s2 "${IMAGE_NAME}:${FLOATING_TAG}" after_script: - env REGISTRY_AUTH_FILE= buildah logout --all diff --git a/.maintain/rialto-weight-template.hbs b/.maintain/rialto-weight-template.hbs deleted file mode 100644 index 297b58e0d3bf..000000000000 --- a/.maintain/rialto-weight-template.hbs +++ /dev/null @@ -1,103 +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 . - -//! Autogenerated weights for `{{pallet}}` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} -//! DATE: {{date}}, STEPS: {{cmd.steps}}, REPEAT: {{cmd.repeat}} -//! LOW RANGE: {{cmd.lowest_range_values}}, HIGH RANGE: {{cmd.highest_range_values}} -//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}} -//! CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} - -// Executed Command: -{{#each args as |arg|~}} -// {{arg}} -{{/each}} - -#![allow(clippy::all)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for `{{pallet}}`. -pub trait WeightInfo { - {{~#each benchmarks as |benchmark|}} - fn {{benchmark.name~}} - ( - {{~#each benchmark.components as |c| ~}} - {{c.name}}: u32, {{/each~}} - ) -> Weight; - {{~/each}} -} - -/// Weights for `{{pallet}}` using the Rialto node and recommended hardware. -pub struct RialtoWeight(PhantomData); -impl WeightInfo for RialtoWeight { - {{~#each benchmarks as |benchmark|}} - fn {{benchmark.name~}} - ( - {{~#each benchmark.components as |c| ~}} - {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} - ) -> Weight { - ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} - .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} - .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} - .saturating_add(T::DbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} - .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} - .saturating_add(T::DbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} - } - {{~/each}} -} - -// For backwards compatibility and tests -impl WeightInfo for () { - {{~#each benchmarks as |benchmark|}} - fn {{benchmark.name~}} - ( - {{~#each benchmark.components as |c| ~}} - {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} - ) -> Weight { - ({{underscore benchmark.base_weight}} as Weight) - {{~#each benchmark.component_weight as |cw|}} - .saturating_add(({{underscore cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight)) - {{~/each}} - {{~#if (ne benchmark.base_reads "0")}} - .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as Weight)) - {{~/if}} - {{~#each benchmark.component_reads as |cr|}} - .saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as Weight).saturating_mul({{cr.name}} as Weight))) - {{~/each}} - {{~#if (ne benchmark.base_writes "0")}} - .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as Weight)) - {{~/if}} - {{~#each benchmark.component_writes as |cw|}} - .saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as Weight).saturating_mul({{cw.name}} as Weight))) - {{~/each}} - } - {{~/each}} -} diff --git a/Cargo.lock b/Cargo.lock index 115fe33dee38..54e6f03c9d51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,22 +12,13 @@ dependencies = [ "regex", ] -[[package]] -name = "addr2line" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" -dependencies = [ - "gimli 0.25.0", -] - [[package]] name = "addr2line" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ - "gimli 0.26.1", + "gimli", ] [[package]] @@ -246,7 +237,7 @@ dependencies = [ "parking", "polling", "slab", - "socket2 0.4.2", + "socket2 0.4.4", "waker-fn", "winapi 0.3.9", ] @@ -297,7 +288,6 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "async-process", "crossbeam-utils", "futures-channel", "futures-core", @@ -337,9 +327,9 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2", "quote", @@ -420,7 +410,7 @@ version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ - "addr2line 0.17.0", + "addr2line", "cc", "cfg-if 1.0.0", "libc", @@ -429,25 +419,18 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bae" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107f431ee3d8a8e45e6dd117adab769556ef463959e77bf6a4888d5fd500cf" -dependencies = [ - "heck", - "proc-macro-error 0.4.12", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "base-x" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base58" version = "0.2.0" @@ -460,6 +443,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71acf5509fc522cce1b100ac0121c635129bfd4d91cdf036bcc9b9935f97ccf5" + [[package]] name = "beef" version = "0.5.1" @@ -472,14 +461,16 @@ dependencies = [ [[package]] name = "beefy-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "beefy-primitives", "fnv", - "futures 0.3.18", + "futures 0.3.21", + "hex", "log", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", + "sc-chain-spec", "sc-client-api", "sc-keystore", "sc-network", @@ -500,32 +491,35 @@ dependencies = [ [[package]] name = "beefy-gadget-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "beefy-gadget", "beefy-primitives", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", "log", "parity-scale-codec", + "parking_lot 0.12.0", "sc-rpc", + "sc-utils", "serde", "sp-core", "sp-runtime", + "thiserror", ] [[package]] name = "beefy-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" [[package]] name = "beefy-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -578,9 +572,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.20.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" dependencies = [ "funty", "radium", @@ -599,6 +593,15 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "blake2" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" +dependencies = [ + "digest 0.10.3", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -646,6 +649,20 @@ dependencies = [ "digest 0.9.0", ] +[[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 1.0.0", + "constant_time_eq", + "digest 0.10.3", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -668,6 +685,15 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "block-buffer" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +dependencies = [ + "generic-array 0.14.4", +] + [[package]] name = "block-padding" version = "0.1.5" @@ -699,9 +725,9 @@ dependencies = [ [[package]] name = "bounded-vec" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afdd1dffefe5fc66262a524b91087c43b16e478b2e3dc49eb11b0e2fd6b6ec90" +checksum = "b47cca82fca99417fe405f09d93bb8fff90bdd03d13c631f18096ee123b4281c" dependencies = [ "thiserror", ] @@ -711,9 +737,12 @@ name = "bp-header-chain" version = "0.1.0" dependencies = [ "assert_matches", + "bp-runtime", "bp-test-utils", "finality-grandpa", "frame-support", + "hex", + "hex-literal", "parity-scale-codec", "scale-info", "serde", @@ -733,6 +762,7 @@ dependencies = [ "frame-support", "smallvec", "sp-api", + "sp-runtime", "sp-std", "sp-version", ] @@ -756,10 +786,13 @@ dependencies = [ "bp-runtime", "frame-support", "frame-system", + "hex", + "hex-literal", "impl-trait-for-tuples", "parity-scale-codec", "scale-info", "serde", + "sp-core", "sp-std", ] @@ -796,6 +829,7 @@ dependencies = [ "frame-support", "smallvec", "sp-api", + "sp-runtime", "sp-std", "sp-version", ] @@ -898,10 +932,14 @@ dependencies = [ name = "bp-token-swap" version = "0.1.0" dependencies = [ + "bp-runtime", "frame-support", + "hex", + "hex-literal", "parity-scale-codec", "scale-info", "sp-core", + "sp-io", "sp-std", ] @@ -910,7 +948,6 @@ name = "bp-westend" version = "0.1.0" dependencies = [ "bp-header-chain", - "bp-messages", "bp-polkadot-core", "bp-runtime", "frame-support", @@ -946,18 +983,23 @@ dependencies = [ "bp-runtime", "ed25519-dalek", "frame-support", + "frame-system", "hash-db", + "pallet-balances", "pallet-bridge-dispatch", "pallet-bridge-grandpa", "pallet-bridge-messages", "pallet-transaction-payment", "parity-scale-codec", "scale-info", + "sp-api", "sp-core", "sp-runtime", "sp-state-machine", "sp-std", "sp-trie", + "sp-version", + "static_assertions", ] [[package]] @@ -1024,6 +1066,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cache-padded" version = "1.1.1" @@ -1190,19 +1243,40 @@ dependencies = [ "ansi_term 0.11.0", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "clap" +version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ + "atty", "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap 0.15.0", +] + +[[package]] +name = "clap_derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1215,10 +1289,10 @@ dependencies = [ ] [[package]] -name = "const_fn" -version = "0.4.8" +name = "const-oid" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "constant_time_eq" @@ -1277,24 +1351,24 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513" +checksum = "9516ba6b2ba47b4cbf63b713f75b432fafa0a0e0464ec8381ec76e6efe931ab3" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c" +checksum = "489e5d0081f7edff6be12d71282a8bf387b5df64d5592454b75d662397f2d642" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", - "gimli 0.25.0", + "gimli", "log", "regalloc", "smallvec", @@ -1303,34 +1377,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf" +checksum = "d36ee1140371bb0f69100e734b30400157a4adf7b86148dee8b0a438763ead48" dependencies = [ "cranelift-codegen-shared", - "cranelift-entity", ] [[package]] name = "cranelift-codegen-shared" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be" +checksum = "981da52d8f746af1feb96290c83977ff8d41071a7499e991d8abae0d4869f564" [[package]] name = "cranelift-entity" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a" +checksum = "a2906740053dd3bcf95ce53df0fd9b5649c68ae4bd9adada92b406f059eae461" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525" +checksum = "b7cb156de1097f567d46bf57a0cd720a72c3e15e1a2bd8b1041ba2fc894471b7" dependencies = [ "cranelift-codegen", "log", @@ -1340,9 +1413,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b" +checksum = "166028ca0343a6ee7bddac0e70084e142b23f99c701bd6f6ea9123afac1a7a46" dependencies = [ "cranelift-codegen", "libc", @@ -1351,9 +1424,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.78.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f46fec547a1f8a32c54ea61c28be4f4ad234ad95342b718a9a9adcaadb0c778" +checksum = "5012a1cde0c8b3898770b711490d803018ae9bec2d60674ba0e5b2058a874f80" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1424,6 +1497,28 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array 0.14.4", + "rand_core 0.6.3", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array 0.14.4", + "typenum", +] + [[package]] name = "crypto-mac" version = "0.8.0" @@ -1450,7 +1545,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" dependencies = [ - "sct", + "sct 0.6.1", ] [[package]] @@ -1486,24 +1581,26 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ + "clap 3.1.6", "sc-cli", "sc-service", - "structopt", + "url 2.2.2", ] [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", "cumulus-primitives-core", - "futures 0.3.18", + "cumulus-relay-chain-interface", + "futures 0.3.21", "parity-scale-codec", - "parking_lot 0.10.2", + "parking_lot 0.12.0", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", @@ -1519,14 +1616,13 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "async-trait", "cumulus-client-consensus-common", "cumulus-primitives-core", - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", - "polkadot-client", "sc-client-api", "sc-consensus", "sc-consensus-aura", @@ -1549,11 +1645,12 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "async-trait", + "cumulus-relay-chain-interface", "dyn-clone", - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", "polkadot-primitives", "sc-client-api", @@ -1569,14 +1666,15 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ + "async-trait", + "cumulus-relay-chain-interface", "derive_more", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "parity-scale-codec", - "parking_lot 0.10.2", - "polkadot-client", + "parking_lot 0.12.0", "polkadot-node-primitives", "polkadot-parachain", "polkadot-primitives", @@ -1586,23 +1684,25 @@ dependencies = [ "sp-consensus", "sp-core", "sp-runtime", + "sp-state-machine", "tracing", ] [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", - "futures 0.3.18", - "futures-timer 3.0.2", + "cumulus-relay-chain-interface", + "futures 0.3.21", + "futures-timer", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sc-client-api", "sc-consensus", "sp-api", @@ -1615,17 +1715,18 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ + "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-common", "cumulus-client-pov-recovery", "cumulus-primitives-core", + "cumulus-relay-chain-interface", "parity-scale-codec", - "parking_lot 0.10.2", + "parking_lot 0.12.0", "polkadot-overseer", "polkadot-primitives", - "polkadot-service", "sc-chain-spec", "sc-client-api", "sc-consensus", @@ -1644,7 +1745,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "frame-executive", "frame-support", @@ -1662,7 +1763,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1680,7 +1781,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-pallet-parachain-system-proc-macro", "cumulus-primitives-core", @@ -1688,6 +1789,7 @@ dependencies = [ "environmental", "frame-support", "frame-system", + "impl-trait-for-tuples", "log", "pallet-balances", "parity-scale-codec", @@ -1709,9 +1811,9 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -1720,7 +1822,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1737,7 +1839,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1755,10 +1857,9 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "frame-support", - "impl-trait-for-tuples", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", @@ -1772,13 +1873,13 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "async-trait", "cumulus-primitives-core", + "cumulus-relay-chain-interface", "cumulus-test-relay-sproof-builder", "parity-scale-codec", - "polkadot-client", "sc-client-api", "scale-info", "sp-api", @@ -1787,6 +1888,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-std", + "sp-storage", "sp-trie", "tracing", ] @@ -1794,9 +1896,11 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", + "futures 0.3.21", + "parity-scale-codec", "sp-inherents", "sp-std", "sp-timestamp", @@ -1805,7 +1909,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1819,10 +1923,62 @@ dependencies = [ "xcm", ] +[[package]] +name = "cumulus-relay-chain-inprocess-interface" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "cumulus-relay-chain-interface", + "futures 0.3.21", + "futures-timer", + "parking_lot 0.12.0", + "polkadot-client", + "polkadot-service", + "sc-client-api", + "sc-consensus-babe", + "sc-network", + "sc-service", + "sc-telemetry", + "sc-tracing", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "sp-state-machine", + "tracing", +] + +[[package]] +name = "cumulus-relay-chain-interface" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "derive_more", + "futures 0.3.21", + "jsonrpsee-core 0.9.0", + "parity-scale-codec", + "parking_lot 0.12.0", + "polkadot-overseer", + "polkadot-service", + "sc-client-api", + "sc-service", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-state-machine", + "thiserror", +] + [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -1843,7 +1999,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "socket2 0.4.2", + "socket2 0.4.4", "winapi 0.3.9", ] @@ -1915,6 +2071,15 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1957,6 +2122,17 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.0", + "crypto-common", + "subtle", +] + [[package]] name = "directories" version = "4.0.1" @@ -1998,12 +2174,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "dns-parser" version = "0.8.0" @@ -2059,6 +2229,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" +[[package]] +name = "ecdsa" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +dependencies = [ + "der", + "elliptic-curve", + "signature", +] + [[package]] name = "ed25519" version = "1.3.0" @@ -2088,6 +2269,24 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "elliptic-curve" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "ff", + "generic-array 0.14.4", + "group", + "rand_core 0.6.3", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.29" @@ -2103,7 +2302,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -2207,45 +2406,42 @@ dependencies = [ ] [[package]] -name = "ethbloom" -version = "0.11.1" +name = "event-listener" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-rlp", - "impl-serde", - "tiny-keccak", -] +checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] -name = "ethereum-types" -version = "0.12.1" +name = "exit-future" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" +checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" dependencies = [ - "ethbloom", - "fixed-hash", - "impl-rlp", - "impl-serde", - "primitive-types", - "uint", + "futures 0.3.21", ] [[package]] -name = "event-listener" -version = "2.5.1" +name = "expander" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "a718c0675c555c5f976fff4ea9e2c150fa06cefa201cadef87cfbf9324075881" +dependencies = [ + "blake3 1.3.1", + "fs-err", + "proc-macro2", + "quote", +] [[package]] -name = "exit-future" -version = "0.2.0" +name = "expander" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" +checksum = "3774182a5df13c3d1690311ad32fbe913feef26baba609fa2dd5f72042bd2ab6" dependencies = [ - "futures 0.3.18", + "blake2 0.10.4", + "fs-err", + "proc-macro2", + "quote", ] [[package]] @@ -2270,33 +2466,68 @@ dependencies = [ ] [[package]] -name = "fdlimit" -version = "0.2.1" +name = "fatality" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4c9e43643f5a3be4ca5b67d26b98031ff9db6806c3440ae32e02e3ceac3f1b" +checksum = "2ad875162843b0d046276327afe0136e9ed3a23d5a754210fb6f1f33610d39ab" dependencies = [ - "libc", + "fatality-proc-macro", + "thiserror", ] [[package]] -name = "file-per-thread-logger" -version = "0.1.4" +name = "fatality-proc-macro" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fdbe0d94371f9ce939b555dd342d0686cc4c0cadbcd4b61d70af5ff97eb4126" +checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ - "env_logger 0.7.1", - "log", + "expander 0.0.4", + "indexmap", + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn", + "thiserror", ] [[package]] -name = "finality-grandpa" -version = "0.14.4" +name = "fdlimit" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ac3ff5224ef91f3c97e03eb1de2db82743427e91aaa5ac635f454f0b164f5a" +checksum = "2c4c9e43643f5a3be4ca5b67d26b98031ff9db6806c3440ae32e02e3ceac3f1b" dependencies = [ - "either", - "futures 0.3.18", - "futures-timer 3.0.2", + "libc", +] + +[[package]] +name = "ff" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" +dependencies = [ + "rand_core 0.6.3", + "subtle", +] + +[[package]] +name = "file-per-thread-logger" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdbe0d94371f9ce939b555dd342d0686cc4c0cadbcd4b61d70af5ff97eb4126" +dependencies = [ + "env_logger 0.7.1", + "log", +] + +[[package]] +name = "finality-grandpa" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9def033d8505edf199f6a5d07aa7e6d2d6185b164293b77f0efd108f4f3e11d" +dependencies = [ + "either", + "futures 0.3.21", + "futures-timer", "log", "num-traits", "parity-scale-codec", @@ -2312,7 +2543,7 @@ dependencies = [ "async-trait", "backoff", "bp-header-chain", - "futures 0.3.18", + "futures 0.3.21", "log", "num-traits", "parking_lot 0.11.2", @@ -2326,7 +2557,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.4", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -2359,7 +2590,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", ] @@ -2377,7 +2608,7 @@ dependencies = [ [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -2386,7 +2617,9 @@ dependencies = [ "parity-scale-codec", "paste", "scale-info", + "serde", "sp-api", + "sp-application-crypto", "sp-io", "sp-runtime", "sp-runtime-interface", @@ -2397,33 +2630,48 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "Inflector", "chrono", + "clap 3.1.6", "frame-benchmarking", "frame-support", "handlebars", + "hash-db", + "hex", + "itertools", + "kvdb", "linked-hash-map", "log", + "memory-db", "parity-scale-codec", + "rand 0.8.5", "sc-cli", + "sc-client-api", "sc-client-db", "sc-executor", "sc-service", "serde", + "serde_json", + "serde_nanos", + "sp-api", + "sp-blockchain", "sp-core", + "sp-database", "sp-externalities", "sp-keystore", "sp-runtime", "sp-state-machine", - "structopt", + "sp-std", + "sp-storage", + "sp-trie", ] [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -2431,13 +2679,14 @@ dependencies = [ "scale-info", "sp-arithmetic", "sp-npos-elections", + "sp-runtime", "sp-std", ] [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -2452,9 +2701,9 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "14.2.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" +checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" dependencies = [ "cfg-if 1.0.0", "parity-scale-codec", @@ -2465,7 +2714,7 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "bitflags", "frame-metadata", @@ -2494,7 +2743,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "Inflector", "frame-support-procedural-tools", @@ -2506,10 +2755,10 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -2518,7 +2767,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "proc-macro2", "quote", @@ -2528,7 +2777,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "log", @@ -2545,7 +2794,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -2560,7 +2809,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "sp-api", @@ -2569,7 +2818,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "sp-api", @@ -2605,6 +2854,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -2623,9 +2878,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "funty" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" @@ -2635,9 +2890,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -2650,9 +2905,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -2660,15 +2915,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -2678,9 +2933,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -2699,9 +2954,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", @@ -2715,27 +2970,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a1387e07917c711fb4ee4f48ea0adb04a3c9739e53ef85bf43ae1edc2937a8b" dependencies = [ "futures-io", - "rustls", - "webpki", + "rustls 0.19.1", + "webpki 0.21.4", ] [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" - -[[package]] -name = "futures-timer" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -2745,9 +2994,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures 0.1.31", "futures-channel", @@ -2817,21 +3066,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" dependencies = [ "fallible-iterator", "indexmap", "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - [[package]] name = "glob" version = "0.3.0" @@ -2864,11 +3107,22 @@ dependencies = [ "web-sys", ] +[[package]] +name = "group" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +dependencies = [ + "ff", + "rand_core 0.6.3", + "subtle", +] + [[package]] name = "h2" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" dependencies = [ "bytes 1.1.0", "fnv", @@ -2885,9 +3139,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.1.5" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad84da8f63da982543fc85fcabaee2ad1fdd809d99d64a48887e2e942ddfe46" +checksum = "25546a65e5cf1f471f3438796fc634650b31d7fcde01d444c309aeb28b92e3a8" dependencies = [ "log", "pest", @@ -2921,6 +3175,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +dependencies = [ + "ahash", +] + [[package]] name = "heck" version = "0.3.3" @@ -2930,6 +3193,12 @@ dependencies = [ "unicode-segmentation", ] +[[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" @@ -3018,7 +3287,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes 1.1.0", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -3061,9 +3330,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.15" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -3074,9 +3343,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite 0.2.7", - "socket2 0.4.2", + "socket2 0.4.4", "tokio", "tower-service", "tracing", @@ -3093,11 +3362,11 @@ dependencies = [ "futures-util", "hyper", "log", - "rustls", - "rustls-native-certs", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", "tokio", - "tokio-rustls", - "webpki", + "tokio-rustls 0.22.0", + "webpki 0.21.4", ] [[package]] @@ -3150,7 +3419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae8ab7f67bad3240049cb24fb9cb0b4c2c6af4c245840917fbbdededeee91179" dependencies = [ "async-io", - "futures 0.3.18", + "futures 0.3.21", "futures-lite", "if-addrs", "ipnet", @@ -3161,22 +3430,13 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" dependencies = [ "parity-scale-codec", ] -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - [[package]] name = "impl-serde" version = "0.3.2" @@ -3188,9 +3448,9 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", @@ -3199,12 +3459,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", "serde", ] @@ -3219,9 +3479,9 @@ dependencies = [ [[package]] name = "integer-encoding" -version = "1.1.7" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dc51180a9b377fd75814d0cc02199c20f8e99433d6762f650d39cdbbd3b56f" +checksum = "90c11140ffea82edce8dcd74137ce9324ec24b3cf0175fc9d7e29164da9915b8" [[package]] name = "integer-sqrt" @@ -3232,23 +3492,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "intervalier" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa110ec7b8f493f416eed552740d10e7030ad5f63b2308f82c9608ec2df275" -dependencies = [ - "futures 0.3.18", - "futures-timer 2.0.2", -] - [[package]] name = "io-lifetimes" -version = "0.3.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278e90d6f8a6c76a8334b336e306efa3c5f2b604048cbfd486d6f49878e3af14" +checksum = "f6ef6787e7f0faedc040f95716bdd0e62bcfcf4ba93da053b62dea2691c13864" dependencies = [ - "rustc_version 0.4.0", "winapi 0.3.9", ] @@ -3314,9 +3563,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -3327,6 +3576,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jobserver" version = "0.1.24" @@ -3365,7 +3620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -3380,7 +3635,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "futures-executor", "futures-util", "log", @@ -3395,7 +3650,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-client-transports", ] @@ -3417,7 +3672,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -3433,7 +3688,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "382bb0206323ca7cda3dcd7e245cea86d37d02457a02a975e3378fb149a48845" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -3448,7 +3703,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "lazy_static", "log", @@ -3464,7 +3719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "globset", "jsonrpc-core", "lazy_static", @@ -3481,7 +3736,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f892c7d766369475ab7b0669f417906302d7c0fb521285c0a0c92e52e7c8e946" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -3496,55 +3751,96 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373a33d987866ccfe1af4bc11b089dce941764313f9fd8b7cf13fcb51b72dc5" dependencies = [ - "jsonrpsee-proc-macros 0.4.1", "jsonrpsee-types 0.4.1", "jsonrpsee-utils", "jsonrpsee-ws-client 0.4.1", ] [[package]] -name = "jsonrpsee-proc-macros" -version = "0.3.1" +name = "jsonrpsee" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8edb341d35279b59c79d7fe9e060a51aec29d45af99cc7c72ea7caa350fa71a4" +checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" dependencies = [ - "Inflector", - "bae", - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", + "jsonrpsee-core 0.8.0", + "jsonrpsee-proc-macros", + "jsonrpsee-types 0.8.0", + "jsonrpsee-ws-client 0.8.0", ] [[package]] -name = "jsonrpsee-proc-macros" -version = "0.4.1" +name = "jsonrpsee-client-transport" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d802063f7a3c867456955f9d2f15eb3ee0edb5ec9ec2b5526324756759221c0f" +checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" dependencies = [ - "log", - "proc-macro-crate 1.1.0", - "proc-macro2", - "quote", - "syn", + "futures 0.3.21", + "http", + "jsonrpsee-core 0.8.0", + "jsonrpsee-types 0.8.0", + "pin-project 1.0.10", + "rustls-native-certs 0.6.1", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.23.2", + "tokio-util", + "tracing", + "webpki-roots 0.22.2", ] [[package]] -name = "jsonrpsee-types" -version = "0.3.1" +name = "jsonrpsee-core" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc738fd55b676ada3271ef7c383a14a0867a2a88b0fa941311bf5fc0a29d498" +checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" dependencies = [ + "anyhow", + "arrayvec 0.7.2", "async-trait", "beef", "futures-channel", "futures-util", "hyper", - "log", + "jsonrpsee-types 0.8.0", + "rustc-hash", "serde", "serde_json", - "soketto 0.6.0", + "soketto", "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22abc3274b265dcefe2e26c4beecf9fda4fffa48cf94930443a6c73678f020d5" +dependencies = [ + "anyhow", + "arrayvec 0.7.2", + "async-trait", + "beef", + "futures-channel", + "hyper", + "jsonrpsee-types 0.9.0", + "serde", + "serde_json", + "soketto", + "thiserror", +] + +[[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 1.1.3", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3562,43 +3858,47 @@ dependencies = [ "log", "serde", "serde_json", - "soketto 0.7.1", + "soketto", "thiserror", ] [[package]] -name = "jsonrpsee-utils" -version = "0.4.1" +name = "jsonrpsee-types" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c" +checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" dependencies = [ - "arrayvec 0.7.2", + "anyhow", "beef", - "jsonrpsee-types 0.4.1", + "serde", + "serde_json", + "thiserror", + "tracing", ] [[package]] -name = "jsonrpsee-ws-client" -version = "0.3.1" +name = "jsonrpsee-types" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9841352dbecf4c2ed5dc71698df9f1660262ae4e0b610e968602529bdbcf7b30" +checksum = "9f4c45d2e2aa1db4c7d7d7dbaabc10a5b5258d99cd9d42fbfd5260b76f80c324" dependencies = [ - "async-trait", - "fnv", - "futures 0.3.18", - "jsonrpsee-types 0.3.1", - "log", - "pin-project 1.0.8", - "rustls", - "rustls-native-certs", + "anyhow", + "beef", "serde", "serde_json", - "soketto 0.6.0", "thiserror", - "tokio", - "tokio-rustls", - "tokio-util", - "url 2.2.2", + "tracing", +] + +[[package]] +name = "jsonrpsee-utils" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0109c4f972058f3b1925b73a17210aff7b63b65967264d0045d15ee88fe84f0c" +dependencies = [ + "arrayvec 0.7.2", + "beef", + "jsonrpsee-types 0.4.1", ] [[package]] @@ -3610,21 +3910,44 @@ dependencies = [ "arrayvec 0.7.2", "async-trait", "fnv", - "futures 0.3.18", + "futures 0.3.21", "http", "jsonrpsee-types 0.4.1", "log", - "pin-project 1.0.8", - "rustls-native-certs", + "pin-project 1.0.10", + "rustls-native-certs 0.5.0", "serde", "serde_json", - "soketto 0.7.1", + "soketto", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", "tokio-util", ] +[[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 = "k256" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "587f53e46eb6dc82b53cda7ebf3ae3ad568ed987ced60962fc845f7fe22904e3" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sec1", +] + [[package]] name = "keccak" version = "0.1.0" @@ -3641,6 +3964,101 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "kusama-runtime" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "beefy-primitives", + "bitvec", + "frame-election-provider-support", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "kusama-runtime-constants", + "log", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-bags-list", + "pallet-balances", + "pallet-bounties", + "pallet-collective", + "pallet-democracy", + "pallet-election-provider-multi-phase", + "pallet-elections-phragmen", + "pallet-gilt", + "pallet-grandpa", + "pallet-identity", + "pallet-im-online", + "pallet-indices", + "pallet-membership", + "pallet-mmr-primitives", + "pallet-multisig", + "pallet-nicks", + "pallet-offences", + "pallet-preimage", + "pallet-proxy", + "pallet-recovery", + "pallet-scheduler", + "pallet-session", + "pallet-society", + "pallet-staking", + "pallet-staking-reward-fn", + "pallet-timestamp", + "pallet-tips", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-vesting", + "pallet-xcm", + "parity-scale-codec", + "polkadot-primitives", + "polkadot-runtime-common", + "polkadot-runtime-parachains", + "rustc-hex", + "scale-info", + "serde", + "serde_derive", + "smallvec", + "sp-api", + "sp-arithmetic", + "sp-authority-discovery", + "sp-block-builder", + "sp-consensus-babe", + "sp-core", + "sp-inherents", + "sp-io", + "sp-npos-elections", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std", + "sp-transaction-pool", + "sp-version", + "static_assertions", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "kusama-runtime-constants" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-runtime", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -3652,9 +4070,9 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a3f58dc069ec0e205a27f5b45920722a46faed802a0541538241af6228f512" +checksum = "a301d8ecb7989d4a6e2c57a49baca77d353bdbf879909debe3f375fe25d61f86" dependencies = [ "parity-util-mem", "smallvec", @@ -3662,38 +4080,20 @@ dependencies = [ [[package]] name = "kvdb-memorydb" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b6b85fc643f5acd0bffb2cc8a6d150209379267af0d41db72170021841f9f5" -dependencies = [ - "kvdb", - "parity-util-mem", - "parking_lot 0.11.2", -] - -[[package]] -name = "kvdb-rocksdb" -version = "0.12.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d169dbb316aa0fa185d02d847c047f1aa20e292cf1563d790c13536a2a732c8" +checksum = "ece7e668abd21387aeb6628130a6f4c802787f014fa46bc83221448322250357" dependencies = [ - "fs-swap", "kvdb", - "log", - "num_cpus", - "owning_ref", "parity-util-mem", - "parking_lot 0.11.2", - "regex", - "rocksdb", - "smallvec", + "parking_lot 0.12.0", ] [[package]] name = "kvdb-rocksdb" -version = "0.14.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1b6ea8f2536f504b645ad78419c8246550e19d2c3419a167080ce08edee35a" +checksum = "a1e72a631a32527fafe22d0751c002e67d28173c49dcaecf79d1aaa323c520e9" dependencies = [ "fs-swap", "kvdb", @@ -3701,7 +4101,7 @@ dependencies = [ "num_cpus", "owning_ref", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "regex", "rocksdb", "smallvec", @@ -3721,9 +4121,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "ad5c14e80759d0939d013e6ca49930e59fc53dd8e5009132f76240c179380c09" [[package]] name = "libloading" @@ -3769,7 +4169,7 @@ checksum = "3bec54343492ba5940a6c555e512c6721139835d28c59bc22febece72dfd0d9d" dependencies = [ "atomic", "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "lazy_static", "libp2p-core", "libp2p-deflate", @@ -3797,24 +4197,25 @@ dependencies = [ "libp2p-yamux", "multiaddr", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "smallvec", "wasm-timer", ] [[package]] name = "libp2p-core" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef22d9bba1e8bcb7ec300073e6802943fe8abb8190431842262b5f1c30abba1" +checksum = "86aad7d54df283db817becded03e611137698a6509d4237a96881976a162340c" dependencies = [ "asn1_der", "bs58", "ed25519-dalek", "either", "fnv", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", + "instant", "lazy_static", "libsecp256k1", "log", @@ -3822,10 +4223,10 @@ dependencies = [ "multihash 0.14.0", "multistream-select", "parking_lot 0.11.2", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "ring", "rw-stream-sink", "sha2 0.9.8", @@ -3843,7 +4244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51a800adb195f33de63f4b17b63fe64cfc23bf2c6a0d3d0d5321328664e65197" dependencies = [ "flate2", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", ] @@ -3854,7 +4255,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb8f89d15cb6e3c5bc22afff7513b11bab7856f2872d3cfba86f7f63a06bc498" dependencies = [ "async-std-resolver", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "log", "smallvec", @@ -3869,7 +4270,7 @@ checksum = "aab3d7210901ea51b7bae2b581aa34521797af8c4ec738c980bda4a06434067f" dependencies = [ "cuckoofilter", "fnv", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", @@ -3890,7 +4291,7 @@ dependencies = [ "byteorder", "bytes 1.1.0", "fnv", - "futures 0.3.18", + "futures 0.3.21", "hex_fmt", "libp2p-core", "libp2p-swarm", @@ -3911,7 +4312,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca1275574183f288ff8b72d535d5ffa5ea9292ef7829af8b47dcb197c7b0dcd" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", @@ -3933,7 +4334,7 @@ dependencies = [ "bytes 1.1.0", "either", "fnv", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", @@ -3957,15 +4358,15 @@ dependencies = [ "async-io", "data-encoding", "dns-parser", - "futures 0.3.18", + "futures 0.3.21", "if-watch", "lazy_static", "libp2p-core", "libp2p-swarm", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", - "socket2 0.4.2", + "socket2 0.4.4", "void", ] @@ -3991,7 +4392,7 @@ checksum = "7f2cd64ef597f40e14bfce0497f50ecb63dd6d201c61796daeb4227078834fbf" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "log", "nohash-hasher", @@ -4009,13 +4410,13 @@ checksum = "a8772c7a99088221bb7ca9c5c0574bf55046a7ab4c319f3619b275f28c8fb87a" dependencies = [ "bytes 1.1.0", "curve25519-dalek 3.2.0", - "futures 0.3.18", + "futures 0.3.21", "lazy_static", "libp2p-core", "log", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.9.8", "snow", "static_assertions", @@ -4029,7 +4430,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80ef7b0ec5cf06530d9eb6cf59ae49d46a2c45663bde31c25a12f682664adbcf" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", @@ -4046,7 +4447,7 @@ checksum = "5fba1a6ff33e4a274c89a3b1d78b9f34f32af13265cc5c46c16938262d4e945a" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "log", "prost", @@ -4061,12 +4462,12 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f1a458bbda880107b5b36fcb9b5a1ef0c329685da0e203ed692a8ebe64cc92c" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "log", - "pin-project 1.0.8", + "pin-project 1.0.10", "rand 0.7.3", "salsa20", - "sha3", + "sha3 0.9.1", ] [[package]] @@ -4077,12 +4478,12 @@ checksum = "2852b61c90fa8ce3c8fcc2aba76e6cefc20d648f9df29157d6b3a916278ef3e3" dependencies = [ "asynchronous-codec 0.6.0", "bytes 1.1.0", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "libp2p-core", "libp2p-swarm", "log", - "pin-project 1.0.8", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.7.3", @@ -4100,13 +4501,13 @@ checksum = "14a6d2b9e7677eff61dc3d2854876aaf3976d84a01ef6664b610c77a0c9407c5" dependencies = [ "asynchronous-codec 0.6.0", "bimap", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", "prost", "prost-build", - "rand 0.8.4", + "rand 0.8.5", "sha2 0.9.8", "thiserror", "unsigned-varint 0.7.1", @@ -4122,11 +4523,11 @@ checksum = "a877a4ced6d46bf84677e1974e8cf61fb434af73b2e96fb48d6cb6223a4634d8" dependencies = [ "async-trait", "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "libp2p-swarm", "log", - "lru 0.7.0", + "lru 0.7.3", "rand 0.7.3", "smallvec", "unsigned-varint 0.7.1", @@ -4140,7 +4541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f5184a508f223bc100a12665517773fb8730e9f36fc09eefb670bf01b107ae9" dependencies = [ "either", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "log", "rand 0.7.3", @@ -4166,14 +4567,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7399c5b6361ef525d41c11fcf51635724f832baf5819b30d3d873eabb4fbae4b" dependencies = [ "async-io", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "if-watch", "ipnet", "libc", "libp2p-core", "log", - "socket2 0.4.2", + "socket2 0.4.4", ] [[package]] @@ -4183,7 +4584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8b7563e46218165dfd60f64b96f7ce84590d75f53ecbdc74a7dd01450dc5973" dependencies = [ "async-std", - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "log", ] @@ -4194,7 +4595,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1008a302b73c5020251f9708c653f5ed08368e530e247cc9cd2f109ff30042cf" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "js-sys", "libp2p-core", "parity-send-wrapper", @@ -4209,15 +4610,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e12df82d1ed64969371a9e65ea92b91064658604cc2576c2757f18ead9a1cf" dependencies = [ "either", - "futures 0.3.18", + "futures 0.3.21", "futures-rustls", "libp2p-core", "log", "quicksink", "rw-stream-sink", - "soketto 0.7.1", + "soketto", "url 2.2.2", - "webpki-roots", + "webpki-roots 0.21.1", ] [[package]] @@ -4226,7 +4627,7 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7362abb8867d7187e7e93df17f460d554c997fc5c8ac57dc1259057f6889af" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "libp2p-core", "parking_lot 0.11.2", "thiserror", @@ -4235,14 +4636,17 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "6.20.3" +version = "0.6.1+6.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c309a9d2470844aceb9a4a098cf5286154d20596868b75a6b36357d2bb9ca25d" +checksum = "81bc587013734dadb7cf23468e531aa120788b87243648be42e2d3a072186291" dependencies = [ "bindgen", + "bzip2-sys", "cc", "glob", "libc", + "libz-sys", + "tikv-jemalloc-sys", ] [[package]] @@ -4258,7 +4662,7 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.4", + "rand 0.8.5", "serde", "sha2 0.9.8", "typenum", @@ -4332,24 +4736,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "687387ff42ec7ea4f2149035a5675fedb675d26f98db90a1846ac63d3addb5f5" - -[[package]] -name = "lock_api" -version = "0.3.4" +version = "0.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] +checksum = "a261afc61b7a5e323933b402ca6a1765183687c614789b1e4db7762ed4230bca" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -4370,16 +4765,16 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ea2d928b485416e8908cff2d97d621db22b27f7b3b6729e438bcf42c671ba91" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", ] [[package]] name = "lru" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c748cfe47cb8da225c37595b3108bea1c198c84aaae8ea0ba76d01dda9fc803" +checksum = "fcb87f3080f6d1d69e8c564c0fcfde1d7aa8cc451ce40cae89479111f03bc0eb" dependencies = [ - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -4501,12 +4896,12 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.27.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de006e09d04fc301a5f7e817b75aa49801c4479a8af753764416b085337ddcc5" +checksum = "6566c70c1016f525ced45d7b7f97730a2bafb037c788211d0c186ef5b2189f0a" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.12.0", "parity-util-mem", ] @@ -4545,7 +4940,8 @@ dependencies = [ "async-trait", "bp-messages", "bp-runtime", - "futures 0.3.18", + "finality-relay", + "futures 0.3.21", "hex", "log", "num-traits", @@ -4556,24 +4952,24 @@ dependencies = [ [[package]] name = "metered-channel" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derive_more", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "thiserror", "tracing", ] [[package]] name = "mick-jaeger" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa77fad8461bb1e0d01be11299e24c6e544007715ed442bfec29f165dc487ae" +checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" dependencies = [ - "futures 0.3.18", - "rand 0.7.3", + "futures 0.3.21", + "rand 0.8.5", "thrift", ] @@ -4586,6 +4982,7 @@ dependencies = [ "beefy-primitives", "bp-millau", "bp-runtime", + "clap 3.1.6", "frame-benchmarking", "frame-benchmarking-cli", "jsonrpc-core", @@ -4614,7 +5011,6 @@ dependencies = [ "sp-finality-grandpa", "sp-runtime", "sp-timestamp", - "structopt", "substrate-build-script-utils", "substrate-frame-rpc-system", ] @@ -4625,6 +5021,7 @@ version = "0.1.0" dependencies = [ "beefy-primitives", "bp-header-chain", + "bp-message-dispatch", "bp-messages", "bp-millau", "bp-rialto", @@ -4637,6 +5034,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "hex-literal", + "libsecp256k1", "pallet-aura", "pallet-balances", "pallet-beefy", @@ -4671,6 +5069,7 @@ dependencies = [ "sp-transaction-pool", "sp-trie", "sp-version", + "static_assertions", "substrate-wasm-builder", ] @@ -4717,14 +5116,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "7ba42135c6a5917b9db9cd7b293e5409e1c6b041e6f9825e92e55a894c63b6f8" dependencies = [ "libc", "log", "miow 0.3.7", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -4804,12 +5204,12 @@ checksum = "4dac63698b887d2d929306ea48b63760431ff8a24fac40ddb22f9c7f49fb7cab" dependencies = [ "blake2b_simd", "blake2s_simd", - "blake3", + "blake3 0.3.8", "digest 0.9.0", "generic-array 0.14.4", "multihash-derive", "sha2 0.9.8", - "sha3", + "sha3 0.9.1", "unsigned-varint 0.5.1", ] @@ -4832,8 +5232,8 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" dependencies = [ - "proc-macro-crate 1.1.0", - "proc-macro-error 1.0.4", + "proc-macro-crate 1.1.3", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -4853,9 +5253,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56a336acba8bc87c8876f6425407dbbe6c417bf478b22015f8fb0994ef3bc0ab" dependencies = [ "bytes 1.1.0", - "futures 0.3.18", + "futures 0.3.21", "log", - "pin-project 1.0.8", + "pin-project 1.0.10", "smallvec", "unsigned-varint 0.7.1", ] @@ -4872,7 +5272,7 @@ dependencies = [ "num-complex", "num-rational 0.4.0", "num-traits", - "rand 0.8.4", + "rand 0.8.5", "rand_distr", "simba", "typenum", @@ -4895,7 +5295,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a8690bf09abf659851e58cd666c3d37ac6af07c2bd7a9e332cfba471715775" dependencies = [ - "rand 0.8.4", + "rand 0.8.5", ] [[package]] @@ -4912,9 +5312,9 @@ dependencies = [ [[package]] name = "node-inspect" version = "0.9.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "derive_more", + "clap 3.1.6", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -4923,7 +5323,7 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", - "structopt", + "thiserror", ] [[package]] @@ -4985,7 +5385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ "arrayvec 0.4.12", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -5041,6 +5441,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.27.1" @@ -5077,7 +5486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -5121,6 +5530,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "owning_ref" version = "0.4.1" @@ -5133,7 +5551,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5149,7 +5567,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5165,7 +5583,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5180,7 +5598,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5204,7 +5622,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-election-provider-support", "frame-support", @@ -5219,7 +5637,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5234,7 +5652,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "beefy-primitives", "frame-support", @@ -5250,14 +5668,14 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "beefy-merkle-tree", "beefy-primitives", "frame-support", "frame-system", "hex", - "libsecp256k1", + "k256", "log", "pallet-beefy", "pallet-mmr", @@ -5275,7 +5693,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5341,8 +5759,6 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "hex", - "hex-literal", "log", "num-traits", "pallet-balances", @@ -5382,7 +5798,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5399,7 +5815,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5415,13 +5831,15 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ + "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "log", "parity-scale-codec", + "rand 0.7.3", "scale-info", "sp-arithmetic", "sp-core", @@ -5430,12 +5848,13 @@ dependencies = [ "sp-runtime", "sp-std", "static_assertions", + "strum 0.23.0", ] [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5449,10 +5868,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-gilt" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5475,7 +5909,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "enumflags2", "frame-benchmarking", @@ -5491,7 +5925,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5510,7 +5944,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5526,7 +5960,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5543,7 +5977,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "ckb-merkle-mountain-range", "frame-benchmarking", @@ -5561,7 +5995,7 @@ dependencies = [ [[package]] name = "pallet-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5577,7 +6011,7 @@ dependencies = [ [[package]] name = "pallet-mmr-rpc" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -5594,7 +6028,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5608,7 +6042,7 @@ dependencies = [ [[package]] name = "pallet-nicks" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5622,7 +6056,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5636,10 +6070,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-preimage" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5653,7 +6103,7 @@ dependencies = [ [[package]] name = "pallet-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5664,10 +6114,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-recovery" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5683,7 +6147,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5716,10 +6180,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-society" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "rand_chacha 0.2.2", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-election-provider-support", "frame-support", @@ -5740,18 +6218,27 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", ] +[[package]] +name = "pallet-staking-reward-fn" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" +dependencies = [ + "log", + "sp-arithmetic", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5765,7 +6252,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-benchmarking", "frame-support", @@ -5783,7 +6270,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5801,7 +6288,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5818,7 +6305,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -5835,7 +6322,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -5846,7 +6333,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5862,7 +6349,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5877,7 +6364,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-support", "frame-system", @@ -5890,8 +6377,8 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "frame-support", "frame-system", @@ -5909,7 +6396,7 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=master#5b245a21eb84ff7b1da6b47ad4386bda3dfb5880" +source = "git+https://github.com/paritytech/cumulus?branch=master#4e952282914719fafd2df450993ccc2ce9395415" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -5921,9 +6408,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a95abf24f1097c6e3181abbbbfc3630b3b5e681470940f719b69acb4911c7f" +checksum = "865edee5b792f537356d9e55cbc138e7f4718dc881a7ea45a18b37bf61c21e3d" dependencies = [ "blake2-rfc", "crc32fast", @@ -5934,15 +6421,15 @@ dependencies = [ "lz4", "memmap2 0.2.3", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "snap", ] [[package]] name = "parity-scale-codec" -version = "2.3.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" +checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" dependencies = [ "arrayvec 0.7.2", "bitvec", @@ -5954,11 +6441,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "2.3.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" +checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -5976,7 +6463,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9981e32fb75e004cc148f5fb70342f393830e0a4aa62e3cc93b50976218d42b6" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "libc", "log", "rand 0.7.3", @@ -5986,17 +6473,15 @@ dependencies = [ [[package]] name = "parity-util-mem" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" +checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ "cfg-if 1.0.0", - "ethereum-types", - "hashbrown", + "hashbrown 0.12.0", "impl-trait-for-tuples", - "lru 0.6.6", "parity-util-mem-derive", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "primitive-types", "smallvec", "winapi 0.3.9", @@ -6054,51 +6539,50 @@ checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" -version = "0.10.2" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.2", + "instant", + "lock_api", + "parking_lot_core 0.8.5", ] [[package]] name = "parking_lot" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ - "instant", - "lock_api 0.4.5", - "parking_lot_core 0.8.5", + "lock_api", + "parking_lot_core 0.9.1", ] [[package]] name = "parking_lot_core" -version = "0.7.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", + "cfg-if 1.0.0", + "instant", "libc", - "redox_syscall 0.1.57", + "redox_syscall", "smallvec", "winapi 0.3.9", ] [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" dependencies = [ "cfg-if 1.0.0", - "instant", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "smallvec", - "winapi 0.3.9", + "windows-sys", ] [[package]] @@ -6198,27 +6682,27 @@ dependencies = [ [[package]] name = "pin-project" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" +checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" dependencies = [ - "pin-project-internal 0.4.28", + "pin-project-internal 0.4.29", ] [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ - "pin-project-internal 1.0.8", + "pin-project-internal 1.0.10", ] [[package]] name = "pin-project-internal" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" +checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" dependencies = [ "proc-macro2", "quote", @@ -6227,9 +6711,9 @@ dependencies = [ [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -6254,6 +6738,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.22" @@ -6268,10 +6763,10 @@ checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" [[package]] name = "polkadot-approval-distribution" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -6282,10 +6777,10 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -6295,12 +6790,13 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derive_more", - "futures 0.3.18", - "lru 0.7.0", + "fatality", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6308,7 +6804,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sp-core", "sp-keystore", "thiserror", @@ -6317,11 +6813,12 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "lru 0.7.0", + "fatality", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6329,7 +6826,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sc-network", "thiserror", "tracing", @@ -6337,19 +6834,22 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ + "clap 3.1.6", "frame-benchmarking-cli", - "futures 0.3.18", + "futures 0.3.21", "log", "polkadot-node-core-pvf", + "polkadot-node-metrics", + "polkadot-performance-test", "polkadot-service", "sc-cli", "sc-service", + "sc-tracing", "sp-core", "sp-trie", - "structopt", "substrate-build-script-utils", "thiserror", "try-runtime-cli", @@ -6357,8 +6857,8 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "beefy-primitives", "frame-benchmarking", @@ -6387,13 +6887,13 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "always-assert", - "derive_more", - "futures 0.3.18", - "futures-timer 3.0.2", + "fatality", + "futures 0.3.21", + "futures-timer", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -6408,8 +6908,8 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "parity-scale-codec", "parity-util-mem", @@ -6421,12 +6921,13 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derive_more", - "futures 0.3.18", - "lru 0.7.0", + "fatality", + "futures 0.3.21", + "lru 0.7.3", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6443,8 +6944,8 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -6457,16 +6958,16 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "rand_chacha 0.3.1", "sc-network", "sp-application-crypto", @@ -6477,13 +6978,13 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "polkadot-node-network-protocol", "polkadot-node-subsystem", "polkadot-node-subsystem-util", @@ -6496,10 +6997,10 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-primitives", @@ -6514,15 +7015,15 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bitvec", "derive_more", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "kvdb", - "lru 0.7.0", + "lru 0.7.3", "merlin", "parity-scale-codec", "polkadot-node-jaeger", @@ -6542,12 +7043,12 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bitvec", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "kvdb", "parity-scale-codec", "polkadot-erasure-coding", @@ -6562,11 +7063,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bitvec", - "futures 0.3.18", + "futures 0.3.21", "polkadot-erasure-coding", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -6580,10 +7081,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", @@ -6595,11 +7096,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", "polkadot-node-core-pvf", "polkadot-node-primitives", @@ -6613,10 +7114,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", @@ -6628,11 +7129,11 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "kvdb", "parity-scale-codec", "polkadot-node-primitives", @@ -6645,13 +7146,13 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "bitvec", - "derive_more", - "futures 0.3.18", + "fatality", + "futures 0.3.21", "kvdb", + "lru 0.7.3", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -6664,12 +7165,12 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "polkadot-node-subsystem", "polkadot-primitives", "sp-blockchain", @@ -6681,36 +7182,38 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "bitvec", + "futures 0.3.21", + "futures-timer", + "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", + "rand 0.8.5", "thiserror", "tracing", ] [[package]] name = "polkadot-node-core-pvf" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "always-assert", "assert_matches", "async-process", "async-std", - "futures 0.3.18", - "futures-timer 3.0.2", - "libc", + "futures 0.3.21", + "futures-timer", "parity-scale-codec", - "pin-project 1.0.8", + "pin-project 1.0.10", "polkadot-core-primitives", "polkadot-node-subsystem-util", "polkadot-parachain", - "rand 0.8.4", + "rand 0.8.5", "sc-executor", "sc-executor-common", "sc-executor-wasmtime", @@ -6724,12 +7227,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "polkadot-node-core-pvf-checker" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "futures 0.3.21", + "polkadot-node-primitives", + "polkadot-node-subsystem", + "polkadot-node-subsystem-util", + "polkadot-overseer", + "polkadot-primitives", + "sp-keystore", + "thiserror", + "tracing", +] + [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "memory-lru", "parity-util-mem", "polkadot-node-subsystem", @@ -6744,15 +7263,15 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-std", "lazy_static", "log", "mick-jaeger", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "polkadot-node-primitives", "polkadot-primitives", "sc-network", @@ -6762,40 +7281,48 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "bs58", + "futures 0.3.21", + "futures-timer", + "log", "metered-channel", + "parity-scale-codec", + "polkadot-primitives", + "sc-cli", + "sc-service", + "sc-tracing", "substrate-prometheus-endpoint", + "tracing", ] [[package]] name = "polkadot-node-network-protocol" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.18", + "fatality", + "futures 0.3.21", "parity-scale-codec", "polkadot-node-jaeger", "polkadot-node-primitives", "polkadot-primitives", "sc-authority-discovery", "sc-network", - "strum 0.23.0", + "strum 0.24.0", "thiserror", ] [[package]] name = "polkadot-node-primitives" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bounded-vec", - "futures 0.3.18", + "futures 0.3.21", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", @@ -6813,8 +7340,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -6823,11 +7350,11 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derive_more", - "futures 0.3.18", + "futures 0.3.21", "polkadot-node-jaeger", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -6842,17 +7369,22 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", "derive_more", - "futures 0.3.18", + "fatality", + "futures 0.3.21", "itertools", - "lru 0.7.0", + "kvdb", + "lru 0.7.3", "metered-channel", + "parity-db", "parity-scale-codec", - "pin-project 1.0.8", + "parity-util-mem", + "parking_lot 0.11.2", + "pin-project 1.0.10", "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -6860,7 +7392,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives", - "rand 0.8.4", + "rand 0.8.5", "sp-application-crypto", "sp-core", "sp-keystore", @@ -6870,14 +7402,14 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", - "lru 0.7.0", + "futures 0.3.21", + "futures-timer", + "lru 0.7.3", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -6891,14 +7423,14 @@ dependencies = [ [[package]] name = "polkadot-overseer-gen" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "metered-channel", - "pin-project 1.0.8", + "pin-project 1.0.10", "polkadot-node-network-protocol", "polkadot-node-primitives", "polkadot-overseer-gen-proc-macro", @@ -6908,10 +7440,11 @@ dependencies = [ [[package]] name = "polkadot-overseer-gen-proc-macro" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ - "proc-macro-crate 1.1.0", + "expander 0.0.6", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -6919,8 +7452,8 @@ dependencies = [ [[package]] name = "polkadot-parachain" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derive_more", "frame-support", @@ -6934,10 +7467,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "polkadot-performance-test" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "env_logger 0.9.0", + "kusama-runtime", + "log", + "polkadot-erasure-coding", + "polkadot-node-core-pvf", + "polkadot-node-primitives", + "quote", + "thiserror", +] + [[package]] name = "polkadot-primitives" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bitvec", "frame-system", @@ -6966,8 +7514,8 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "beefy-gadget", "beefy-gadget-rpc", @@ -6997,8 +7545,8 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "beefy-primitives", "bitvec", @@ -7028,6 +7576,7 @@ dependencies = [ "pallet-multisig", "pallet-nicks", "pallet-offences", + "pallet-preimage", "pallet-proxy", "pallet-scheduler", "pallet-session", @@ -7044,6 +7593,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "polkadot-runtime-common", + "polkadot-runtime-constants", "polkadot-runtime-parachains", "rustc-hex", "scale-info", @@ -7074,8 +7624,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "beefy-primitives", "bitvec", @@ -7117,10 +7667,34 @@ dependencies = [ "xcm", ] +[[package]] +name = "polkadot-runtime-constants" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-runtime", +] + +[[package]] +name = "polkadot-runtime-metrics" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "bs58", + "parity-scale-codec", + "polkadot-primitives", + "sp-std", + "sp-tracing", +] + [[package]] name = "polkadot-runtime-parachains" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "bitflags", "bitvec", @@ -7138,7 +7712,8 @@ dependencies = [ "pallet-vesting", "parity-scale-codec", "polkadot-primitives", - "rand 0.8.4", + "polkadot-runtime-metrics", + "rand 0.8.5", "rand_chacha 0.3.1", "rustc-hex", "scale-info", @@ -7158,23 +7733,24 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "async-trait", "beefy-gadget", "beefy-primitives", "frame-system-rpc-runtime-api", - "futures 0.3.18", + "futures 0.3.21", "hex-literal", "kvdb", - "kvdb-rocksdb 0.14.0", - "lru 0.7.0", + "kvdb-rocksdb", + "lru 0.7.3", "pallet-babe", "pallet-im-online", "pallet-mmr-primitives", "pallet-staking", "pallet-transaction-payment-rpc-runtime-api", + "parity-db", "polkadot-approval-distribution", "polkadot-availability-bitfield-distribution", "polkadot-availability-distribution", @@ -7195,6 +7771,7 @@ dependencies = [ "polkadot-node-core-dispute-coordinator", "polkadot-node-core-parachains-inherent", "polkadot-node-core-provisioner", + "polkadot-node-core-pvf-checker", "polkadot-node-core-runtime-api", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -7205,6 +7782,7 @@ dependencies = [ "polkadot-primitives", "polkadot-rpc", "polkadot-runtime", + "polkadot-runtime-constants", "polkadot-runtime-parachains", "polkadot-statement-distribution", "sc-authority-discovery", @@ -7253,12 +7831,12 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "arrayvec 0.5.2", - "derive_more", - "futures 0.3.18", + "fatality", + "futures 0.3.21", "indexmap", "parity-scale-codec", "polkadot-node-network-protocol", @@ -7274,8 +7852,8 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -7284,8 +7862,8 @@ dependencies = [ [[package]] name = "polkadot-test-runtime" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "beefy-primitives", "bitvec", @@ -7338,6 +7916,7 @@ dependencies = [ "sp-transaction-pool", "sp-version", "substrate-wasm-builder", + "test-runtime-constants", "xcm", "xcm-builder", "xcm-executor", @@ -7345,13 +7924,13 @@ dependencies = [ [[package]] name = "polkadot-test-service" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "frame-benchmarking", "frame-system", "futures 0.1.31", - "futures 0.3.18", + "futures 0.3.21", "hex", "pallet-balances", "pallet-staking", @@ -7366,7 +7945,7 @@ dependencies = [ "polkadot-runtime-parachains", "polkadot-service", "polkadot-test-runtime", - "rand 0.8.4", + "rand 0.8.5", "sc-authority-discovery", "sc-chain-spec", "sc-cli", @@ -7392,6 +7971,7 @@ dependencies = [ "sp-state-machine", "substrate-test-client", "tempfile", + "test-runtime-constants", "tokio", "tracing", ] @@ -7440,13 +8020,12 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "primitive-types" -version = "0.10.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ "fixed-hash", "impl-codec", - "impl-rlp", "impl-serde", "scale-info", "uint", @@ -7463,50 +8042,24 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", "toml", ] -[[package]] -name = "proc-macro-error" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" -dependencies = [ - "proc-macro-error-attr 0.4.12", - "proc-macro2", - "quote", - "syn", - "version_check", -] - [[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 1.0.4", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" -dependencies = [ + "proc-macro-error-attr", "proc-macro2", "quote", "syn", - "syn-mid", "version_check", ] @@ -7521,17 +8074,11 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] @@ -7567,7 +8114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ "bytes 1.1.0", - "heck", + "heck 0.3.3", "itertools", "lazy_static", "log", @@ -7612,17 +8159,6 @@ dependencies = [ "cc", ] -[[package]] -name = "pwasm-utils" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "880b3384fb00b8f6ecccd5d358b93bd2201900ae3daad213791d1864f6441f5c" -dependencies = [ - "byteorder", - "log", - "parity-wasm 0.42.2", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -7648,18 +8184,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] [[package]] name = "radium" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -7671,20 +8207,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -7732,25 +8267,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f" dependencies = [ "num-traits", - "rand 0.8.4", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "rand 0.8.5", ] [[package]] name = "rand_hc" -version = "0.3.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.5.1", ] [[package]] @@ -7793,12 +8319,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.10" @@ -7815,7 +8335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.3", - "redox_syscall 0.2.10", + "redox_syscall", ] [[package]] @@ -7853,9 +8373,9 @@ dependencies = [ [[package]] name = "regalloc" -version = "0.0.32" +version = "0.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4" +checksum = "7d808cff91dfca7b239d40b972ba628add94892b1d9e19a842aedc5cfae8ab1a" dependencies = [ "log", "rustc-hash", @@ -7864,9 +8384,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -7926,6 +8446,7 @@ dependencies = [ name = "relay-millau-client" version = "0.1.0" dependencies = [ + "bp-messages", "bp-millau", "frame-support", "frame-system", @@ -7964,6 +8485,7 @@ dependencies = [ name = "relay-rialto-client" version = "0.1.0" dependencies = [ + "bp-messages", "bp-rialto", "frame-support", "frame-system", @@ -8019,23 +8541,26 @@ dependencies = [ "async-std", "async-trait", "bp-header-chain", + "bp-messages", "bp-runtime", "finality-relay", "frame-support", "frame-system", - "futures 0.3.18", - "jsonrpsee-proc-macros 0.3.1", - "jsonrpsee-ws-client 0.3.1", + "futures 0.3.21", + "jsonrpsee 0.8.0", "log", "num-traits", "pallet-balances", + "pallet-bridge-messages", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "rand 0.7.3", "relay-utils", + "sc-chain-spec", "sc-rpc-api", "sc-transaction-pool-api", + "serde", "sp-core", "sp-finality-grandpa", "sp-rpc", @@ -8058,7 +8583,7 @@ dependencies = [ "backoff", "bp-runtime", "env_logger 0.8.4", - "futures 0.3.18", + "futures 0.3.21", "isahc", "jsonpath_lib", "log", @@ -8067,7 +8592,8 @@ dependencies = [ "substrate-prometheus-endpoint", "sysinfo", "thiserror", - "time 0.2.27", + "time 0.3.7", + "tokio", ] [[package]] @@ -8075,6 +8601,7 @@ name = "relay-westend-client" version = "0.1.0" dependencies = [ "bp-westend", + "frame-support", "parity-scale-codec", "relay-substrate-client", "relay-utils", @@ -8108,10 +8635,10 @@ dependencies = [ [[package]] name = "remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "env_logger 0.9.0", - "jsonrpsee", + "jsonrpsee 0.8.0", "log", "parity-scale-codec", "serde", @@ -8156,48 +8683,25 @@ dependencies = [ "beefy-primitives", "bp-rialto", "bp-runtime", + "clap 3.1.6", "frame-benchmarking", "frame-benchmarking-cli", "frame-system-rpc-runtime-api", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "kvdb", - "kvdb-rocksdb 0.12.1", - "lru 0.7.0", + "kvdb-rocksdb", + "lru 0.7.3", "node-inspect", "pallet-bridge-messages", "pallet-mmr-primitives", "pallet-mmr-rpc", "pallet-transaction-payment-rpc", "pallet-transaction-payment-rpc-runtime-api", - "polkadot-approval-distribution", - "polkadot-availability-bitfield-distribution", - "polkadot-availability-distribution", - "polkadot-availability-recovery", - "polkadot-client", - "polkadot-collator-protocol", - "polkadot-dispute-distribution", - "polkadot-gossip-support", - "polkadot-network-bridge", - "polkadot-node-collation-generation", - "polkadot-node-core-approval-voting", - "polkadot-node-core-av-store", - "polkadot-node-core-backing", - "polkadot-node-core-bitfield-signing", - "polkadot-node-core-candidate-validation", - "polkadot-node-core-chain-api", - "polkadot-node-core-chain-selection", - "polkadot-node-core-dispute-coordinator", - "polkadot-node-core-parachains-inherent", - "polkadot-node-core-provisioner", "polkadot-node-core-pvf", - "polkadot-node-core-runtime-api", - "polkadot-node-network-protocol", - "polkadot-node-subsystem-util", - "polkadot-overseer", "polkadot-primitives", "polkadot-runtime-parachains", - "polkadot-statement-distribution", + "polkadot-service", "rialto-runtime", "sc-authority-discovery", "sc-basic-authorship", @@ -8232,7 +8736,6 @@ dependencies = [ "sp-session", "sp-timestamp", "sp-transaction-pool", - "structopt", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -8243,6 +8746,7 @@ dependencies = [ name = "rialto-parachain-collator" version = "0.1.0" dependencies = [ + "clap 3.1.6", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", @@ -8251,6 +8755,8 @@ dependencies = [ "cumulus-client-service", "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", + "cumulus-relay-chain-inprocess-interface", + "cumulus-relay-chain-interface", "derive_more", "frame-benchmarking", "frame-benchmarking-cli", @@ -8293,7 +8799,6 @@ dependencies = [ "sp-session", "sp-timestamp", "sp-transaction-pool", - "structopt", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -8408,6 +8913,7 @@ dependencies = [ "sp-transaction-pool", "sp-trie", "sp-version", + "static_assertions", "substrate-wasm-builder", ] @@ -8426,21 +8932,11 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rlp" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" -dependencies = [ - "bytes 1.1.0", - "rustc-hex", -] - [[package]] name = "rocksdb" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a62eca5cacf2c8261128631bed9f045598d40bfbe4b29f5163f0f802f8f44a7" +checksum = "620f4129485ff1a7128d184bc687470c21c7951b64779ebc9cfdad3dcd920290" dependencies = [ "libc", "librocksdb-sys", @@ -8456,23 +8952,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "rsix" -version = "0.23.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f64c5788d5aab8b75441499d99576a24eb09f76fb267b36fec7e3d970c66431" -dependencies = [ - "bitflags", - "cc", - "errno", - "io-lifetimes", - "itoa", - "libc", - "linux-raw-sys", - "once_cell", - "rustc_version 0.4.0", -] - [[package]] name = "rustc-demangle" version = "0.1.21" @@ -8518,6 +8997,20 @@ dependencies = [ "semver 1.0.4", ] +[[package]] +name = "rustix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2dcfc2778a90e38f56a708bfc90572422e11d6c7ee233d053d1f782cf9df6d2" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "winapi 0.3.9", +] + [[package]] name = "rustls" version = "0.19.1" @@ -8527,8 +9020,20 @@ dependencies = [ "base64", "log", "ring", - "sct", - "webpki", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", ] [[package]] @@ -8538,11 +9043,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" dependencies = [ "openssl-probe", - "rustls", + "rustls 0.19.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +dependencies = [ + "openssl-probe", + "rustls-pemfile", "schannel", "security-framework", ] +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + [[package]] name = "rustversion" version = "1.0.5" @@ -8555,8 +9081,8 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ - "futures 0.3.18", - "pin-project 0.4.28", + "futures 0.3.21", + "pin-project 0.4.29", "static_assertions", ] @@ -8596,7 +9122,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "log", "sp-core", @@ -8607,12 +9133,11 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "ip_network", "libp2p", "log", @@ -8629,15 +9154,16 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "log", "parity-scale-codec", "sc-block-builder", @@ -8657,7 +9183,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -8673,7 +9199,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "impl-trait-for-tuples", "memmap2 0.5.0", @@ -8690,9 +9216,9 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -8701,11 +9227,12 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "chrono", + "clap 3.1.6", "fdlimit", - "futures 0.3.18", + "futures 0.3.21", "hex", "libp2p", "log", @@ -8730,7 +9257,6 @@ dependencies = [ "sp-panic-handler", "sp-runtime", "sp-version", - "structopt", "thiserror", "tiny-bip39", "tokio", @@ -8739,14 +9265,14 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "fnv", - "futures 0.3.18", + "futures 0.3.21", "hash-db", "log", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -8767,17 +9293,17 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "hash-db", "kvdb", "kvdb-memorydb", - "kvdb-rocksdb 0.14.0", + "kvdb-rocksdb", "linked-hash-map", "log", "parity-db", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sc-state-db", "sp-arithmetic", @@ -8792,14 +9318,14 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "libp2p", "log", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sc-utils", "serde", @@ -8816,11 +9342,10 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.18", + "futures 0.3.21", "log", "parity-scale-codec", "sc-block-builder", @@ -8840,24 +9365,24 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "derive_more", "fork-tree", - "futures 0.3.18", + "futures 0.3.21", "log", "merlin", "num-bigint", "num-rational 0.2.4", "num-traits", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "retain_mut", "sc-client-api", @@ -8883,15 +9408,15 @@ dependencies = [ "sp-runtime", "sp-version", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "derive_more", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -8907,12 +9432,13 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", + "thiserror", ] [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "fork-tree", "parity-scale-codec", @@ -8925,17 +9451,16 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "log", "parity-scale-codec", "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-api", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -8951,7 +9476,7 @@ dependencies = [ [[package]] name = "sc-consensus-uncles" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "sc-client-api", "sp-authorship", @@ -8962,13 +9487,12 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "lazy_static", - "libsecp256k1", - "log", + "lru 0.6.6", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-executor-common", "sc-executor-wasmi", "sc-executor-wasmtime", @@ -8983,31 +9507,31 @@ dependencies = [ "sp-trie", "sp-version", "sp-wasm-interface", + "tracing", "wasmi", ] [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "derive_more", "environmental", "parity-scale-codec", - "pwasm-utils", "sc-allocator", "sp-core", "sp-maybe-compressed-blob", "sp-serializer", "sp-wasm-interface", "thiserror", + "wasm-instrument", "wasmi", ] [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "log", "parity-scale-codec", @@ -9023,7 +9547,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "cfg-if 1.0.0", "libc", @@ -9041,20 +9565,22 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ + "ahash", "async-trait", - "derive_more", "dyn-clone", "finality-grandpa", "fork-tree", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", + "hex", "log", "parity-scale-codec", - "parking_lot 0.11.2", - "rand 0.8.4", + "parking_lot 0.12.0", + "rand 0.8.5", "sc-block-builder", + "sc-chain-spec", "sc-client-api", "sc-consensus", "sc-keystore", @@ -9073,16 +9599,16 @@ dependencies = [ "sp-keystore", "sp-runtime", "substrate-prometheus-endpoint", + "thiserror", ] [[package]] name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "derive_more", "finality-grandpa", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -9097,16 +9623,17 @@ dependencies = [ "sp-blockchain", "sp-core", "sp-runtime", + "thiserror", ] [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "ansi_term 0.12.1", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "log", "parity-util-mem", "sc-client-api", @@ -9119,45 +9646,43 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "derive_more", "hex", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "serde_json", "sp-application-crypto", "sp-core", "sp-keystore", + "thiserror", ] [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "async-std", "async-trait", "asynchronous-codec 0.5.0", "bitflags", "bytes 1.1.0", "cid", - "derive_more", "either", "fnv", "fork-tree", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "hex", "ip_network", "libp2p", "linked-hash-map", "linked_hash_set", "log", - "lru 0.7.0", + "lru 0.7.3", "parity-scale-codec", - "parking_lot 0.11.2", - "pin-project 1.0.8", + "parking_lot 0.12.0", + "pin-project 1.0.10", "prost", "prost-build", "rand 0.7.3", @@ -9185,13 +9710,14 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "ahash", + "futures 0.3.21", + "futures-timer", "libp2p", "log", - "lru 0.7.0", + "lru 0.7.3", "sc-network", "sp-runtime", "substrate-prometheus-endpoint", @@ -9201,19 +9727,19 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "bytes 1.1.0", "fnv", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "hex", "hyper", "hyper-rustls", "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "sc-client-api", "sc-network", @@ -9229,9 +9755,9 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "libp2p", "log", "sc-utils", @@ -9242,7 +9768,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -9251,15 +9777,15 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", "log", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -9282,16 +9808,16 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", "jsonrpc-pubsub", "log", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-chain-spec", "sc-transaction-pool-api", "serde", @@ -9307,9 +9833,9 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-http-server", "jsonrpc-ipc-server", @@ -9324,21 +9850,21 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "directories", "exit-future", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "hash-db", "jsonrpc-core", "jsonrpc-pubsub", "log", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", - "pin-project 1.0.8", + "parking_lot 0.12.0", + "pin-project 1.0.10", "rand 0.7.3", "sc-block-builder", "sc-chain-spec", @@ -9388,13 +9914,13 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "log", "parity-scale-codec", "parity-util-mem", "parity-util-mem-derive", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sc-client-api", "sp-core", ] @@ -9402,7 +9928,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "jsonrpc-core", "jsonrpc-core-client", @@ -9413,7 +9939,6 @@ dependencies = [ "sc-consensus-babe", "sc-consensus-epochs", "sc-finality-grandpa", - "sc-rpc-api", "serde", "serde_json", "sp-blockchain", @@ -9424,14 +9949,14 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "chrono", - "futures 0.3.18", + "futures 0.3.21", "libp2p", "log", - "parking_lot 0.11.2", - "pin-project 1.0.8", + "parking_lot 0.12.0", + "pin-project 1.0.10", "rand 0.7.3", "serde", "serde_json", @@ -9442,7 +9967,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "ansi_term 0.12.1", "atty", @@ -9451,7 +9976,7 @@ dependencies = [ "libc", "log", "once_cell", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "regex", "rustc-hash", "sc-client-api", @@ -9473,9 +9998,9 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9484,15 +10009,15 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", - "intervalier", + "futures 0.3.21", + "futures-timer", "linked-hash-map", "log", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "retain_mut", "sc-client-api", "sc-transaction-pool-api", @@ -9511,10 +10036,9 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "derive_more", - "futures 0.3.18", + "futures 0.3.21", "log", "serde", "sp-blockchain", @@ -9525,19 +10049,21 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "lazy_static", + "log", + "parking_lot 0.12.0", "prometheus", ] [[package]] name = "scale-info" -version = "1.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +checksum = "0563970d79bcbf3c537ce3ad36d859b30d36fc5b190efd227f1f7a84d7cf0d42" dependencies = [ "bitvec", "cfg-if 1.0.0", @@ -9549,11 +10075,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +checksum = "b7805950c36512db9e3251c970bb7ac425f326716941862205d612ab3b5e46e2" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9609,6 +10135,47 @@ dependencies = [ "untrusted", ] +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +dependencies = [ + "der", + "generic-array 0.14.4", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c42e6f1735c5f00f51e43e28d6634141f2bcad10931b2609ddd74a86d751260" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -9694,18 +10261,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -9714,16 +10281,25 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085" dependencies = [ "indexmap", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] +[[package]] +name = "serde_nanos" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44969a61f5d316be20a42ff97816efb3b407a924d06824c3d8a49fa8450de0e" +dependencies = [ + "serde", +] + [[package]] name = "sha-1" version = "0.8.2" @@ -9749,12 +10325,6 @@ dependencies = [ "opaque-debug 0.3.0", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - [[package]] name = "sha2" version = "0.8.2" @@ -9780,6 +10350,17 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures 0.2.1", + "digest 0.10.3", +] + [[package]] name = "sha3" version = "0.9.1" @@ -9792,6 +10373,16 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "sha3" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" +dependencies = [ + "digest 0.10.3", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -9831,6 +10422,9 @@ name = "signature" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +dependencies = [ + "rand_core 0.6.3", +] [[package]] name = "simba" @@ -9852,8 +10446,8 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "slot-range-helper" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "enumn", "parity-scale-codec", @@ -9884,9 +10478,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "snap" @@ -9901,9 +10495,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6142f7c25e94f6fd25a32c3348ec230df9109b463f59c8c7acc4bd34936babb7" dependencies = [ "aes-gcm", - "blake2", + "blake2 0.9.2", "chacha20poly1305", - "rand 0.8.4", + "rand 0.8.5", "rand_core 0.6.3", "ring", "rustc_version 0.3.3", @@ -9925,29 +10519,14 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", ] -[[package]] -name = "soketto" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74e48087dbeed4833785c2f3352b59140095dc192dce966a3bfc155020a439f" -dependencies = [ - "base64", - "bytes 1.1.0", - "futures 0.3.18", - "httparse", - "log", - "rand 0.8.4", - "sha-1 0.9.8", -] - [[package]] name = "soketto" version = "0.7.1" @@ -9957,17 +10536,17 @@ dependencies = [ "base64", "bytes 1.1.0", "flate2", - "futures 0.3.18", + "futures 0.3.21", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1 0.9.8", ] [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "hash-db", "log", @@ -9984,10 +10563,10 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "blake2-rfc", - "proc-macro-crate 1.1.0", + "blake2 0.10.4", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -9995,8 +10574,8 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -10008,8 +10587,8 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "integer-sqrt", "num-traits", @@ -10024,7 +10603,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -10037,7 +10616,7 @@ dependencies = [ [[package]] name = "sp-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "parity-scale-codec", @@ -10049,7 +10628,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "sp-api", @@ -10061,13 +10640,13 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "log", - "lru 0.7.0", + "lru 0.7.3", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "sp-api", "sp-consensus", "sp-database", @@ -10079,11 +10658,11 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "futures 0.3.18", - "futures-timer 3.0.2", + "futures 0.3.21", + "futures-timer", "log", "parity-scale-codec", "sp-core", @@ -10098,7 +10677,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "parity-scale-codec", @@ -10116,7 +10695,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "merlin", @@ -10139,19 +10718,21 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", "serde", "sp-arithmetic", "sp-runtime", + "sp-std", + "sp-timestamp", ] [[package]] name = "sp-consensus-vrf" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "schnorrkel", @@ -10162,8 +10743,8 @@ dependencies = [ [[package]] name = "sp-core" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "base58", "bitflags", @@ -10171,7 +10752,7 @@ dependencies = [ "byteorder", "dyn-clonable", "ed25519-dalek", - "futures 0.3.18", + "futures 0.3.21", "hash-db", "hash256-std-hasher", "hex", @@ -10183,15 +10764,15 @@ dependencies = [ "num-traits", "parity-scale-codec", "parity-util-mem", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "primitive-types", "rand 0.7.3", "regex", "scale-info", "schnorrkel", + "secp256k1", "secrecy", "serde", - "sha2 0.9.8", "sp-core-hashing", "sp-debug-derive", "sp-externalities", @@ -10202,29 +10783,28 @@ dependencies = [ "substrate-bip39", "thiserror", "tiny-bip39", - "tiny-keccak", - "twox-hash", "wasmi", "zeroize", ] [[package]] name = "sp-core-hashing" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "blake2-rfc", + "blake2 0.10.4", "byteorder", - "sha2 0.9.8", + "digest 0.10.3", + "sha2 0.10.1", + "sha3 0.10.1", "sp-std", - "tiny-keccak", "twox-hash", ] [[package]] name = "sp-core-hashing-proc-macro" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "proc-macro2", "quote", @@ -10235,16 +10815,16 @@ dependencies = [ [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "kvdb", - "parking_lot 0.11.2", + "parking_lot 0.12.0", ] [[package]] name = "sp-debug-derive" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "proc-macro2", "quote", @@ -10253,8 +10833,8 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "0.12.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "environmental", "parity-scale-codec", @@ -10265,7 +10845,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "finality-grandpa", "log", @@ -10283,7 +10863,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -10296,15 +10876,16 @@ dependencies = [ [[package]] name = "sp-io" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "hash-db", "libsecp256k1", "log", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", + "secp256k1", "sp-core", "sp-externalities", "sp-keystore", @@ -10320,44 +10901,45 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "lazy_static", "sp-core", "sp-runtime", - "strum 0.22.0", + "strum 0.23.0", ] [[package]] name = "sp-keystore" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "0.12.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "derive_more", - "futures 0.3.18", + "futures 0.3.21", "merlin", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "schnorrkel", "serde", "sp-core", "sp-externalities", + "thiserror", ] [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ + "thiserror", "zstd", ] [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -10372,9 +10954,9 @@ dependencies = [ [[package]] name = "sp-npos-elections-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -10383,7 +10965,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "sp-api", "sp-core", @@ -10392,8 +10974,8 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "backtrace", "lazy_static", @@ -10402,8 +10984,8 @@ dependencies = [ [[package]] name = "sp-rpc" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "rustc-hash", "serde", @@ -10412,8 +10994,8 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "either", "hash256-std-hasher", @@ -10434,8 +11016,8 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -10451,11 +11033,11 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "Inflector", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", "syn", @@ -10464,7 +11046,7 @@ dependencies = [ [[package]] name = "sp-serializer" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "serde", "serde_json", @@ -10473,7 +11055,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -10487,7 +11069,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "scale-info", @@ -10497,14 +11079,14 @@ dependencies = [ [[package]] name = "sp-state-machine" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "0.12.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "hash-db", "log", "num-traits", "parity-scale-codec", - "parking_lot 0.11.2", + "parking_lot 0.12.0", "rand 0.7.3", "smallvec", "sp-core", @@ -10520,13 +11102,13 @@ dependencies = [ [[package]] name = "sp-std" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" [[package]] name = "sp-storage" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10539,7 +11121,7 @@ dependencies = [ [[package]] name = "sp-tasks" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "log", "sp-core", @@ -10552,10 +11134,10 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "futures-timer 3.0.2", + "futures-timer", "log", "parity-scale-codec", "sp-api", @@ -10567,8 +11149,8 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "sp-std", @@ -10580,7 +11162,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "sp-api", "sp-runtime", @@ -10589,7 +11171,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", "log", @@ -10604,8 +11186,8 @@ dependencies = [ [[package]] name = "sp-trie" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "hash-db", "memory-db", @@ -10613,20 +11195,22 @@ dependencies = [ "scale-info", "sp-core", "sp-std", + "thiserror", "trie-db", "trie-root", ] [[package]] name = "sp-version" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "impl-serde", "parity-scale-codec", "parity-wasm 0.42.2", "scale-info", "serde", + "sp-core-hashing-proc-macro", "sp-runtime", "sp-std", "sp-version-proc-macro", @@ -10636,7 +11220,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -10646,13 +11230,15 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "impl-trait-for-tuples", + "log", "parity-scale-codec", "sp-std", "wasmi", + "wasmtime", ] [[package]] @@ -10661,11 +11247,21 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "ss58-registry" -version = "1.8.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78abb01d308934b82e34e9cf1f45846d31539246501745b129539176f4f3368d" +checksum = "8319f44e20b42e5c11b88b1ad4130c35fe2974665a007b08b02322070177136a" dependencies = [ "Inflector", "proc-macro2", @@ -10681,15 +11277,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -10731,58 +11318,9 @@ dependencies = [ "lazy_static", "nalgebra", "num-traits", - "rand 0.8.4", -] - -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", + "rand 0.8.5", ] -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "storage-proof-fuzzer" version = "0.1.0" @@ -10792,6 +11330,7 @@ dependencies = [ "honggfuzz", "log", "sp-core", + "sp-runtime", "sp-state-machine", "sp-std", "sp-trie", @@ -10803,13 +11342,19 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ - "clap", + "clap 2.33.3", "lazy_static", "structopt-derive", ] @@ -10820,8 +11365,8 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", - "proc-macro-error 1.0.4", + "heck 0.3.3", + "proc-macro-error", "proc-macro2", "quote", "syn", @@ -10838,20 +11383,20 @@ dependencies = [ [[package]] name = "strum" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros 0.22.0", + "strum_macros 0.23.1", ] [[package]] name = "strum" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" +checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8" dependencies = [ - "strum_macros 0.23.1", + "strum_macros 0.24.0", ] [[package]] @@ -10860,7 +11405,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -10868,23 +11413,24 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" +checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", + "rustversion", "syn", ] [[package]] name = "strum_macros" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" +checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro2", "quote", "rustversion", @@ -10907,7 +11453,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "platforms", ] @@ -10915,10 +11461,10 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "frame-system-rpc-runtime-api", - "futures 0.3.18", + "futures 0.3.21", "jsonrpc-core", "jsonrpc-core-client", "jsonrpc-derive", @@ -10937,23 +11483,23 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "async-std", - "derive_more", "futures-util", "hyper", "log", "prometheus", + "thiserror", "tokio", ] [[package]] name = "substrate-relay" -version = "0.1.0" +version = "1.0.1" dependencies = [ "anyhow", "async-std", + "async-trait", "bp-header-chain", "bp-kusama", "bp-message-dispatch", @@ -10964,6 +11510,7 @@ dependencies = [ "bp-rialto-parachain", "bp-rococo", "bp-runtime", + "bp-test-utils", "bp-token-swap", "bp-westend", "bp-wococo", @@ -10971,7 +11518,7 @@ dependencies = [ "finality-grandpa", "finality-relay", "frame-support", - "futures 0.3.18", + "futures 0.3.21", "hex", "hex-literal", "log", @@ -10990,7 +11537,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", - "rand 0.8.4", + "rand 0.8.5", "relay-kusama-client", "relay-millau-client", "relay-polkadot-client", @@ -11024,6 +11571,7 @@ dependencies = [ "bp-header-chain", "bp-messages", "bp-millau", + "bp-rialto", "bp-rococo", "bp-runtime", "bp-wococo", @@ -11031,11 +11579,15 @@ dependencies = [ "finality-grandpa", "finality-relay", "frame-support", - "futures 0.3.18", + "frame-system", + "futures 0.3.21", "log", "messages-relay", "num-traits", + "pallet-balances", + "pallet-bridge-grandpa", "pallet-bridge-messages", + "pallet-transaction-payment", "parity-scale-codec", "relay-rococo-client", "relay-substrate-client", @@ -11051,10 +11603,10 @@ dependencies = [ [[package]] name = "substrate-test-client" version = "2.0.1" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "async-trait", - "futures 0.3.18", + "futures 0.3.21", "hex", "parity-scale-codec", "sc-client-api", @@ -11077,12 +11629,13 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ "ansi_term 0.12.1", "build-helper", "cargo_metadata", "sp-maybe-compressed-blob", + "strum 0.23.0", "tempfile", "toml", "walkdir", @@ -11097,26 +11650,15 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "ebd69e719f31e88618baa1eaa6ee2de5c9a1c004f1e9ecdb58e8352a13f20a01" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] -[[package]] -name = "syn-mid" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "synstructure" version = "0.12.6" @@ -11166,8 +11708,8 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if 1.0.0", "libc", - "rand 0.8.4", - "redox_syscall 0.2.10", + "rand 0.8.5", + "redox_syscall", "remove_dir_all", "winapi 0.3.9", ] @@ -11181,6 +11723,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-runtime-constants" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" +dependencies = [ + "frame-support", + "polkadot-primitives", + "polkadot-runtime-common", + "smallvec", + "sp-runtime", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -11190,6 +11744,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.30" @@ -11212,9 +11772,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -11230,9 +11790,9 @@ dependencies = [ [[package]] name = "thrift" -version = "0.13.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6d965454947cc7266d22716ebfd07b18d84ebaf35eec558586bbb2a8cb6b5b" +checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" dependencies = [ "byteorder", "integer-encoding", @@ -11242,52 +11802,36 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.1.44" +name = "tikv-jemalloc-sys" +version = "0.4.3+5.2.1-patched.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "a1792ccb507d955b46af42c123ea8863668fae24d03721e40cad6a41773dbb49" dependencies = [ + "cc", + "fs_extra", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", ] [[package]] name = "time" -version = "0.2.27" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ - "const_fn", "libc", - "standback", - "stdweb", - "time-macros", - "version_check", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] [[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.2" +name = "time" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", + "itoa 1.0.1", + "libc", + "num_threads", ] [[package]] @@ -11309,15 +11853,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinyvec" version = "1.5.1" @@ -11335,28 +11870,29 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ - "autocfg", "bytes 1.1.0", "libc", "memchr", - "mio 0.7.14", + "mio 0.8.1", "num_cpus", "once_cell", + "parking_lot 0.12.0", "pin-project-lite 0.2.7", "signal-hook-registry", + "socket2 0.4.4", "tokio-macros", "winapi 0.3.9", ] [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -11369,9 +11905,20 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "rustls", + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls 0.20.4", "tokio", - "webpki", + "webpki 0.22.0", ] [[package]] @@ -11417,9 +11964,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if 1.0.0", "log", @@ -11430,9 +11977,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" dependencies = [ "proc-macro2", "quote", @@ -11441,11 +11988,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" dependencies = [ "lazy_static", + "valuable", ] [[package]] @@ -11454,7 +12002,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ - "pin-project 1.0.8", + "pin-project 1.0.10", "tracing", ] @@ -11504,12 +12052,12 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.22.6" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eac131e334e81b6b3be07399482042838adcd7957aa0010231d0813e39e02fa" +checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.12.0", "log", "rustc-hex", "smallvec", @@ -11517,9 +12065,9 @@ dependencies = [ [[package]] name = "trie-root" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652931506d2c1244d7217a70b99f56718a7b4161b37f04e7cd868072a99f68cd" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" dependencies = [ "hash-db", ] @@ -11541,7 +12089,7 @@ dependencies = [ "ipnet", "lazy_static", "log", - "rand 0.8.4", + "rand 0.8.5", "smallvec", "thiserror", "tinyvec", @@ -11576,9 +12124,10 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=master#3fdb445b3b14880017680a3af85e89fb591666a0" +source = "git+https://github.com/paritytech/substrate?branch=master#89fcb3e4f62d221d4e161a437768e77d6265889e" dependencies = [ - "jsonrpsee", + "clap 3.1.6", + "jsonrpsee 0.4.1", "log", "parity-scale-codec", "remote-externalities", @@ -11594,7 +12143,7 @@ dependencies = [ "sp-runtime", "sp-state-machine", "sp-version", - "structopt", + "zstd", ] [[package]] @@ -11605,12 +12154,13 @@ checksum = "5e66dcbec4290c69dd03c57e76c2469ea5c7ce109c6dd4351c13055cf71ea055" [[package]] name = "twox-hash" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" +checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if 1.0.0", - "rand 0.8.4", + "digest 0.10.3", + "rand 0.8.5", "static_assertions", ] @@ -11749,6 +12299,12 @@ dependencies = [ "percent-encoding 2.1.0", ] +[[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.8" @@ -11822,6 +12378,12 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.78" @@ -11899,13 +12461,22 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "wasm-instrument" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "962e5b0401bbb6c887f54e69b8c496ea36f704df65db73e81fd5ff8dc3e63a9f" +dependencies = [ + "parity-wasm 0.42.2", +] + [[package]] name = "wasm-timer" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "js-sys", "parking_lot 0.11.2", "pin-utils", @@ -11946,9 +12517,9 @@ checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" [[package]] name = "wasmtime" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311d06b0c49346d1fbf48a17052e844036b95a7753c1afb34e8c0af3f6b5bb13" +checksum = "414be1bc5ca12e755ffd3ff7acc3a6d1979922f8237fc34068b2156cebcc3270" dependencies = [ "anyhow", "backtrace", @@ -11978,9 +12549,9 @@ dependencies = [ [[package]] name = "wasmtime-cache" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147930a4995137dc096e5b17a573b446799be2bbaea433e821ce6a80abe2c5" +checksum = "8b9b4cd1949206fda9241faf8c460a7d797aa1692594d3dd6bc1cbfa57ee20d0" dependencies = [ "anyhow", "base64", @@ -11988,7 +12559,7 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rsix", + "rustix", "serde", "sha2 0.9.8", "toml", @@ -11998,9 +12569,9 @@ dependencies = [ [[package]] name = "wasmtime-cranelift" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3083a47e1ede38aac06a1d9831640d673f9aeda0b82a64e4ce002f3432e2e7" +checksum = "a4693d33725773615a4c9957e4aa731af57b27dca579702d1d8ed5750760f1a9" dependencies = [ "anyhow", "cranelift-codegen", @@ -12008,7 +12579,7 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "cranelift-wasm", - "gimli 0.25.0", + "gimli", "log", "more-asserts", "object", @@ -12020,14 +12591,13 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c2d194b655321053bc4111a1aa4ead552655c8a17d17264bc97766e70073510" +checksum = "5b17e47116a078b9770e6fb86cff8b9a660826623cebcfff251b047c8d8993ef" dependencies = [ "anyhow", - "cfg-if 1.0.0", "cranelift-entity", - "gimli 0.25.0", + "gimli", "indexmap", "log", "more-asserts", @@ -12041,24 +12611,21 @@ dependencies = [ [[package]] name = "wasmtime-jit" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864ac8dfe4ce310ac59f16fdbd560c257389cb009ee5d030ac6e30523b023d11" +checksum = "60ea5b380bdf92e32911400375aeefb900ac9d3f8e350bb6ba555a39315f2ee7" dependencies = [ - "addr2line 0.16.0", + "addr2line", "anyhow", "bincode", "cfg-if 1.0.0", - "gimli 0.25.0", - "log", - "more-asserts", + "gimli", "object", "region", - "rsix", + "rustix", "serde", "target-lexicon", "thiserror", - "wasmparser", "wasmtime-environ", "wasmtime-runtime", "winapi 0.3.9", @@ -12066,9 +12633,9 @@ dependencies = [ [[package]] name = "wasmtime-runtime" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab97da813a26b98c9abfd3b0c2d99e42f6b78b749c0646344e2e262d212d8c8b" +checksum = "abc7cd79937edd6e238b337608ebbcaf9c086a8457f01dfd598324f7fa56d81a" dependencies = [ "anyhow", "backtrace", @@ -12081,9 +12648,9 @@ dependencies = [ "mach", "memoffset", "more-asserts", - "rand 0.8.4", + "rand 0.8.5", "region", - "rsix", + "rustix", "thiserror", "wasmtime-environ", "winapi 0.3.9", @@ -12091,9 +12658,9 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff94409cc3557bfbbcce6b14520ccd6bd3727e965c0fe68d63ef2c185bf379c6" +checksum = "d9e5e51a461a2cf2b69e1fc48f325b17d78a8582816e18479e8ead58844b23f8" dependencies = [ "cranelift-entity", "serde", @@ -12121,13 +12688,32 @@ dependencies = [ "untrusted", ] +[[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.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "webpki", + "webpki 0.21.4", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", ] [[package]] @@ -12199,6 +12785,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -12220,9 +12849,12 @@ dependencies = [ [[package]] name = "wyz" -version = "0.2.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +dependencies = [ + "tap", +] [[package]] name = "x25519-dalek" @@ -12237,8 +12869,8 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "derivative", "impl-trait-for-tuples", @@ -12250,8 +12882,8 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "frame-support", "frame-system", @@ -12270,8 +12902,8 @@ dependencies = [ [[package]] name = "xcm-executor" -version = "0.9.13" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +version = "0.9.18" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -12288,8 +12920,9 @@ dependencies = [ [[package]] name = "xcm-procedural" version = "0.1.0" -source = "git+https://github.com/paritytech/polkadot?branch=master#bd69f54b6853e9a2f5e0869e5e76213259d4573d" +source = "git+https://github.com/paritytech/polkadot?branch=master#975e780ae0d988dc033f400ba822d14b326ee5b9" dependencies = [ + "Inflector", "proc-macro2", "quote", "syn", @@ -12301,11 +12934,11 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7d9028f208dd5e63c614be69f115c1b53cacc1111437d4c765185856666c107" dependencies = [ - "futures 0.3.18", + "futures 0.3.21", "log", "nohash-hasher", "parking_lot 0.11.2", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] @@ -12332,18 +12965,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.9.0+zstd.1.5.0" +version = "0.9.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07749a5dc2cb6b36661290245e350f15ec3bbb304e493db54a1d354480522ccd" +checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "4.1.1+zstd.1.5.0" +version = "4.1.3+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91c90f2c593b003603e5e0493c837088df4469da25aafff8bce42ba48caf079" +checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79" dependencies = [ "libc", "zstd-sys", @@ -12351,9 +12984,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.6.1+zstd.1.5.0" +version = "1.6.2+zstd.1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "615120c7a2431d16cf1cf979e7fc31ba7a5b5e5707b29c8a99e5dbf8a8392a33" +checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f" dependencies = [ "cc", "libc", diff --git a/Dockerfile b/Dockerfile index ff88c6a5a0a5..bc51f76ba99b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ # # See the `deployments/README.md` for all the available `PROJECT` values. -FROM paritytech/bridges-ci:latest as builder +FROM docker.io/paritytech/bridges-ci:latest as builder WORKDIR /parity-bridges-common COPY . . @@ -19,7 +19,7 @@ RUN cargo build --release --verbose -p ${PROJECT} && \ # In this final stage we copy over the final binary and do some checks # to make sure that everything looks good. -FROM ubuntu:20.04 as runtime +FROM docker.io/library/ubuntu:20.04 as runtime # show backtraces ENV RUST_BACKTRACE 1 diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index c4438d0cef3e..3825b92b703c 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -3,15 +3,15 @@ name = "millau-bridge-node" description = "Substrate node compatible with Millau runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +clap = { version = "3.1", features = ["derive"] } jsonrpc-core = "18.0" -structopt = "0.3.21" serde_json = "1.0.59" # Bridge dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index fbfca8692fcb..a7e3c7c87718 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -88,21 +88,14 @@ impl Alternative { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - ], + endowed_accounts(), true, ) }, vec![], None, None, + None, properties, None, ), @@ -120,54 +113,14 @@ impl Alternative { get_authority_keys_from_seed("Eve"), ], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("RialtoMessagesOwner"), - get_account_id_from_seed::("WithRialtoTokenSwap"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_millau::AccountId, - bp_millau::AccountIdConverter, - >(), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), - ], + endowed_accounts(), true, ) }, vec![], None, None, + None, properties, None, ), @@ -175,6 +128,55 @@ impl Alternative { } } +/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make +/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, +/// accounts used by relayers in our test deployments, accounts used for demonstration +/// purposes), are all available on these chains. +fn endowed_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("RialtoMessagesOwner"), + get_account_id_from_seed::("WithRialtoTokenSwap"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_millau::AccountId, + bp_millau::AccountIdConverter, + >(), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), + ] +} + fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys { SessionKeys { aura, beefy, grandpa } } @@ -195,7 +197,7 @@ fn testnet_genesis( aura: AuraConfig { authorities: Vec::new() }, beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, - sudo: SudoConfig { key: root_key }, + sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities .iter() diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 086def633c59..c3c3d134e341 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use clap::Parser; use sc_cli::RunCmd; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, @@ -27,9 +27,10 @@ pub struct Cli { } /// Possible subcommands of the main binary. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Key management CLI utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index b01c0bfca906..15f88269aa9c 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -30,14 +30,13 @@ // ===================================================================================== use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::ExecutorProvider; +use sc_client_api::{BlockBackend, ExecutorProvider}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; @@ -66,6 +65,7 @@ type FullClient = type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; +#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -89,7 +89,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) } let telemetry = config @@ -107,11 +107,12 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, )?; @@ -139,7 +140,7 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { @@ -150,7 +151,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -178,7 +179,7 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &String) -> Result, &'static str> { +fn remote_keystore(_url: &str) -> Result, &'static str> { // FIXME: here would the concrete keystore be built, // must return a concrete type (NOT `LocalKeystore`) that // implements `CryptoStore` and `SyncCryptoStore` @@ -209,8 +210,27 @@ pub fn new_full(mut config: Configuration) -> Result }; } - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); + // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change + // anything in terms of behaviour, but makes the logs more consistent with the other + // Substrate nodes. + let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); + config + .network + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + + let beefy_protocol_name = beefy_gadget::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); + config + .network + .extra_sets + .push(beefy_gadget::beefy_peers_set_config(beefy_protocol_name.clone())); + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -244,8 +264,10 @@ pub fn new_full(mut config: Configuration) -> Result let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let shared_voter_state = SharedVoterState::empty(); - let (signed_commitment_sender, signed_commitment_stream) = - beefy_gadget::notification::BeefySignedCommitmentStream::channel(); + let (beefy_commitment_link, beefy_commitment_stream) = + beefy_gadget::notification::BeefySignedCommitmentStream::::channel(); + let (beefy_best_block_link, beefy_best_block_stream) = + beefy_gadget::notification::BeefyBestBlockStream::::channel(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -286,10 +308,12 @@ pub fn new_full(mut config: Configuration) -> Result finality_proof_provider.clone(), ))); io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( - beefy_gadget_rpc::BeefyRpcHandler::new( - signed_commitment_stream.clone(), + beefy_gadget_rpc::BeefyRpcHandler::::new( + beefy_commitment_stream.clone(), + beefy_best_block_stream.clone(), subscription_executor, - ), + ) + .map_err(|e| sc_service::Error::Other(format!("{}", e)))?, )); io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new( client.clone(), @@ -324,7 +348,6 @@ pub fn new_full(mut config: Configuration) -> Result sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let raw_slot_duration = slot_duration.slot_duration(); let aura = sc_consensus_aura::start_aura::( StartAuraParams { @@ -337,9 +360,9 @@ pub fn new_full(mut config: Configuration) -> Result let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - raw_slot_duration, + slot_duration, ); Ok((timestamp, slot)) @@ -373,9 +396,11 @@ pub fn new_full(mut config: Configuration) -> Result backend, key_store: keystore.clone(), network: network.clone(), - signed_commitment_sender, + signed_commitment_sender: beefy_commitment_link, + beefy_best_block_sender: beefy_best_block_link, min_block_delta: 4, prometheus_registry: prometheus_registry.clone(), + protocol_name: beefy_protocol_name, }; // Start the BEEFY bridge gadget. @@ -394,6 +419,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore, local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, }; if enable_grandpa { diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 13195b95194b..162404b77e7d 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -2,20 +2,22 @@ name = "millau-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } +bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } @@ -63,6 +65,10 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +static_assertions = "1.1" + [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -71,6 +77,7 @@ default = ["std"] std = [ "beefy-primitives/std", "bp-header-chain/std", + "bp-message-dispatch/std", "bp-messages/std", "bp-millau/std", "bp-rialto/std", @@ -116,8 +123,12 @@ std = [ "sp-version/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "bridge-runtime-common/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "libsecp256k1", + "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-token-swap/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 288ff9a47d60..d2da5affb235 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -21,8 +21,6 @@ #![recursion_limit = "256"] // Runtime-generated enums #![allow(clippy::large_enum_variant)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] // From construct_runtime macro #![allow(clippy::from_over_into)] @@ -52,7 +50,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -138,6 +136,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 0, }; /// The version information used to identify this runtime when compiled natively. @@ -204,6 +203,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} @@ -374,12 +374,26 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; +} - // Number of headers to keep. - // - // Assuming the worst case of every header being finalized, we will keep headers for at least a - // week. - pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + /// Number of headers to keep in benchmarks. + /// + /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that + /// pruning is taken into account. + /// + /// Note: This is lower than regular value, to speed up benchmarking setup. + pub const HeadersToKeep: u32 = 1024; +} + +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + /// Number of headers to keep. + /// + /// Assuming the worst case of every header being finalized, we will keep headers at least for a + /// week. + pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } pub type RialtoGrandpaInstance = (); @@ -388,8 +402,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; @@ -398,8 +411,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -407,9 +419,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Millau => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -422,8 +434,7 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -443,10 +454,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithRialtoMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = @@ -512,7 +522,7 @@ construct_runtime!( BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event}, + BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event, Origin}, // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, @@ -531,6 +541,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -551,7 +562,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_runtime_apis! { @@ -653,7 +664,7 @@ impl_runtime_apis! { } impl beefy_primitives::BeefyApi for Runtime { - fn validator_set() -> ValidatorSet { + fn validator_set() -> Option> { Beefy::validator_set() } } @@ -731,10 +742,6 @@ impl_runtime_apis! { let header = BridgeRialtoGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_rialto::Hash) -> bool { - BridgeRialtoGrandpa::is_known_header(hash) - } } impl bp_westend::WestendFinalityApi for Runtime { @@ -742,20 +749,18 @@ impl_runtime_apis! { let header = BridgeWestendGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_westend::Hash) -> bool { - BridgeWestendGrandpa::is_known_header(hash) - } } impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToRialtoMessagePayload, + rialto_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + rialto_to_this_conversion_rate, ).ok() } @@ -770,28 +775,6 @@ impl_runtime_apis! { WithRialtoMessageBridge, >(lane, begin, end) } - - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::outbound_latest_received_nonce(lane) - } - - fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::outbound_latest_generated_nonce(lane) - } - } - - impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::inbound_latest_received_nonce(lane) - } - - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::inbound_latest_confirmed_nonce(lane) - } - - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { - BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) - } } #[cfg(feature = "runtime-benchmarks")] @@ -803,9 +786,13 @@ impl_runtime_apis! { use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; + use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; + let mut list = Vec::::new(); list_benchmark!(list, extra, pallet_bridge_token_swap, BridgeRialtoTokenSwap); + list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); + list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); let storage_info = AllPalletsWithSystem::storage_info(); @@ -833,6 +820,74 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); + use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof, prepare_outbound_message}; + use bridge_runtime_common::messages; + use pallet_bridge_messages::benchmarking::{ + Pallet as MessagesBench, + Config as MessagesConfig, + MessageDeliveryProofParams, + MessageParams, + MessageProofParams, + }; + use rialto_messages::WithRialtoMessageBridge; + + impl MessagesConfig for Runtime { + fn maximal_message_size() -> u32 { + messages::source::maximal_message_size::() + } + + fn bridged_relayer_id() -> Self::InboundRelayer { + [0u8; 32].into() + } + + fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { + pallet_balances::Pallet::::free_balance(account) + } + + fn endow_account(account: &Self::AccountId) { + pallet_balances::Pallet::::make_free_balance_be( + account, + Balance::MAX / 100, + ); + } + + fn prepare_outbound_message( + params: MessageParams, + ) -> (rialto_messages::ToRialtoMessagePayload, Balance) { + (prepare_outbound_message::(params), Self::message_fee()) + } + + fn prepare_message_proof( + params: MessageProofParams, + ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { + prepare_message_proof::( + params, + &VERSION, + Balance::MAX / 100, + ) + } + + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> rialto_messages::ToRialtoMessagesDeliveryProof { + prepare_message_delivery_proof::( + params, + ) + } + + fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { + frame_system::Pallet::::events() + .into_iter() + .map(|event_record| event_record.event) + .any(|event| matches!( + event, + Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( + _, ([0, 0, 0, 0], nonce_from_event), _, + )) if nonce_from_event == nonce + )) + } + } + use pallet_bridge_token_swap::benchmarking::Config as TokenSwapConfig; impl TokenSwapConfig for Runtime { @@ -848,9 +903,15 @@ impl_runtime_apis! { } } + add_benchmark!( + params, + batches, + pallet_bridge_messages, + MessagesBench:: + ); + add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } @@ -883,52 +944,18 @@ where #[cfg(test)] mod tests { use super::*; - use bridge_runtime_common::messages; #[test] - fn ensure_millau_message_lane_weights_are_correct() { - // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type Weights = pallet_bridge_messages::weights::RialtoWeight; - - pallet_bridge_messages::ensure_weights_are_correct::( - bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); - - let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), - ), + fn call_size() { + const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, - ) - .unwrap_or(u32::MAX); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - DbWeight::get(), + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE ); - } - - #[test] - fn call_size() { const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 6d9677c45cf9..d925d805dd04 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -19,11 +19,11 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -64,10 +64,10 @@ pub type FromRialtoMessagePayload = pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Messages proof for Rialto -> Millau messages. -type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; +pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Millau -> Rialto messages. -type ToRialtoMessagesDeliveryProof = +pub type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; /// Call-dispatch based message dispatch for Rialto -> Millau messages. @@ -86,16 +86,19 @@ impl MessageBridge for WithRialtoMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; type BridgedChain = Rialto; - fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { - bp_millau::Balance::try_from( - RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_millau::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_rialto::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_millau::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| RialtoToMillauConversionRate::get()); + bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_millau::Balance::MAX) } } @@ -113,12 +116,23 @@ impl messages::ChainWithMessages for Millau { } impl messages::ThisChainWithMessages for Millau { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || - *lane == [0, 0, 0, 1] || - *lane == crate::TokenSwapMessagesLane::get() + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + // lanes 0x00000000 && 0x00000001 are accepting any paid messages, while + // `TokenSwapMessageLane` only accepts messages from token swap pallet + let token_swap_dedicated_lane = crate::TokenSwapMessagesLane::get(); + match *lane { + [0, 0, 0, 0] | [0, 0, 0, 1] => send_origin.linked_account().is_some(), + _ if *lane == token_swap_dedicated_lane => matches!( + send_origin.caller, + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { .. } + ) + ), + _ => false, + } } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -172,13 +186,13 @@ impl messages::ChainWithMessages for Rialto { impl messages::BridgedChainWithMessages for Rialto { fn maximal_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() + bp_rialto::Rialto::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` @@ -274,6 +288,25 @@ impl SourceHeaderChain for Rialto { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { + ref swap_account_at_this_chain, + .. + }, + ) => Some(swap_account_at_this_chain.clone()), + _ => None, + } + } +} + /// Millau -> Rialto message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum MillauToRialtoMessagesParameter { @@ -289,3 +322,107 @@ impl MessagesParameter for MillauToRialtoMessagesParameter { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{DbWeight, RialtoGrandpaInstance, Runtime, WithRialtoMessagesInstance}; + + use bp_runtime::Chain; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, + AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + }, + messages, + }; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + type Weights = pallet_bridge_messages::weights::MillauWeight; + + pallet_bridge_messages::ensure_weights_are_correct::( + bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), + ); + + let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), + ); + pallet_bridge_messages::ensure_able_to_receive_message::( + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), + max_incoming_message_proof_size, + messages::target::maximal_incoming_message_dispatch_weight( + bp_millau::Millau::max_extrinsic_weight(), + ), + ); + + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, + ) + .unwrap_or(u32::MAX); + pallet_bridge_messages::ensure_able_to_receive_confirmation::( + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + DbWeight::get(), + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: RialtoGrandpaInstance, + with_bridged_chain_messages_instance: WithRialtoMessagesInstance, + bridge: WithRialtoMessageBridge, + this_chain: bp_millau::Millau, + bridged_chain: bp_rialto::Rialto, + this_chain_account_id_converter: bp_millau::AccountIdConverter + ); + + assert_complete_bridge_constants::< + Runtime, + RialtoGrandpaInstance, + WithRialtoMessagesInstance, + WithRialtoMessageBridge, + bp_millau::Millau, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_millau::BlockLength::get(), + block_weights: bp_millau::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::RIALTO_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, + }, + }); + + assert_eq!( + RialtoToMillauConversionRate::key().to_vec(), + bp_runtime::storage_parameter_key( + bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME + ) + .0, + ); + } +} diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 8adc998e47ee..41021a35ed2b 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -2,7 +2,7 @@ name = "rialto-parachain-collator" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" @@ -18,10 +18,10 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] +clap = { version = "3.1", features = ["derive"] } derive_more = '0.99.2' log = '0.4.14' -codec = { package = 'parity-scale-codec', version = '2.0.0' } -structopt = '0.3.8' +codec = { package = 'parity-scale-codec', version = '3.0.0' } serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' @@ -80,6 +80,8 @@ cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } # Polkadot dependencies polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 52012423fb71..6a8e751677df 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -89,6 +89,7 @@ pub fn development_config(id: ParaId) -> ChainSpec { None, None, None, + None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: id.into(), @@ -133,6 +134,7 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { None, None, None, + None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: id.into(), @@ -155,7 +157,7 @@ fn testnet_genesis( balances: rialto_parachain_runtime::BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }, - sudo: rialto_parachain_runtime::SudoConfig { key: root_key }, + sudo: rialto_parachain_runtime::SudoConfig { key: Some(root_key) }, parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 78c05f90c880..89d049f022e3 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -15,18 +15,18 @@ // along with Parity Bridges Common. If not, see . use crate::chain_spec; +use clap::Parser; use std::path::PathBuf; -use structopt::StructOpt; /// Sub-commands supported by the collator. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Export the genesis state of the parachain. - #[structopt(name = "export-genesis-state")] + #[clap(name = "export-genesis-state")] ExportGenesisState(ExportGenesisStateCommand), /// Export the genesis wasm of the parachain. - #[structopt(name = "export-genesis-wasm")] + #[clap(name = "export-genesis-wasm")] ExportGenesisWasm(ExportGenesisWasmCommand), /// Build a chain specification. @@ -51,66 +51,66 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } /// Command for exporting the genesis state of the parachain -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisStateCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Id of the parachain this state is for. /// /// Default: 100 - #[structopt(long, conflicts_with = "chain")] + #[clap(long, conflicts_with = "chain")] pub parachain_id: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis state should be exported. - #[structopt(long, conflicts_with = "parachain-id")] + #[clap(long, conflicts_with = "parachain-id")] pub chain: Option, } /// Command for exporting the genesis wasm file. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisWasmCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis wasm file should be exported. - #[structopt(long)] + #[clap(long)] pub chain: Option, } -#[derive(Debug, StructOpt)] -#[structopt(settings = &[ - structopt::clap::AppSettings::GlobalVersion, - structopt::clap::AppSettings::ArgsNegateSubcommands, - structopt::clap::AppSettings::SubcommandsNegateReqs, -])] +#[derive(Debug, Parser)] +#[clap( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] pub struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Option, - #[structopt(long)] + #[clap(long)] pub parachain_id: Option, - #[structopt(flatten)] + #[clap(flatten)] pub run: cumulus_client_cli::RunCmd, /// Relaychain arguments - #[structopt(raw = true)] + #[clap(raw = true)] pub relaychain_args: Vec, } @@ -135,6 +135,6 @@ impl RelayChainCli { let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("rialto-bridge-node")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) } + Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } } } diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index e4f52cc026a7..c47e742675da 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -211,10 +211,12 @@ pub fn run() -> Result<()> { builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); let _ = builder.init(); - let block: Block = generate_genesis_block(&load_spec( + let spec = load_spec( ¶ms.chain.clone().unwrap_or_default(), params.parachain_id.expect("Missing ParaId").into(), - )?)?; + )?; + let state_version = Cli::native_runtime_version(&spec).state_version(); + let block: Block = generate_genesis_block(&spec, state_version)?; let raw_header = block.header().encode(); let output_buf = if params.raw { raw_header @@ -263,6 +265,7 @@ pub fn run() -> Result<()> { }, None => { let runner = cli.create_runner(&cli.run.normalize())?; + let collator_options = cli.run.collator_options(); runner.run_node_until_exit(|config| async move { let para_id = @@ -276,10 +279,12 @@ pub fn run() -> Result<()> { let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); let parachain_account = - AccountIdConversion::::into_account(&id); + AccountIdConversion::::into_account(&id); - let block: Block = - generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?; + let state_version = + RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); + let block: Block = generate_genesis_block(&config.chain_spec, state_version) + .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); let polkadot_config = SubstrateCli::create_configuration( @@ -294,7 +299,7 @@ pub fn run() -> Result<()> { info!("Parachain genesis state: {}", genesis_state); info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - crate::service::start_node(config, polkadot_config, id) + crate::service::start_node(config, polkadot_config, collator_options, id) .await .map(|r| r.0) .map_err(Into::into) @@ -357,11 +362,24 @@ impl CliConfiguration for RelayChainCli { self.base.base.rpc_ws(default_listen_port) } - fn prometheus_config(&self, default_listen_port: u16) -> Result> { - self.base.base.prometheus_config(default_listen_port) + fn prometheus_config( + &self, + default_listen_port: u16, + chain_spec: &Box, + ) -> Result> { + self.base.base.prometheus_config(default_listen_port, chain_spec) } - fn init(&self) -> Result<()> { + fn init( + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, + ) -> Result<()> + where + F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), + { unreachable!("PolkadotCli is never initialized; qed"); } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index bd3afca30744..a2299e17457d 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -14,22 +14,30 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Rialto parachain node service. +//! +//! The code is mostly copy of `polkadot-parachains/src/service.rs` file from Cumulus +//! repository with some parts removed. We have added two RPC extensions to the original +//! service: `pallet_transaction_payment_rpc::TransactionPaymentApi` and +//! `substrate_frame_rpc_system::SystemApi`. + // std -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; // Local Runtime Types use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports -use cumulus_client_consensus_aura::{ - build_aura_consensus, BuildAuraConsensusParams, SlotProportion, -}; +use cumulus_client_cli::CollatorOptions; +use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; use cumulus_client_consensus_common::ParachainConsensus; -use cumulus_client_network::build_block_announce_validator; +use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; +use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; // Substrate Imports use sc_client_api::ExecutorProvider; @@ -38,7 +46,6 @@ use sc_network::NetworkService; use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; use sp_api::ConstructRuntimeApi; -use sp_consensus::SlotData; use sp_keystore::SyncCryptoStorePtr; use sp_runtime::traits::BlakeTwo256; use substrate_prometheus_endpoint::Registry; @@ -134,6 +141,7 @@ where config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = @@ -187,6 +195,7 @@ where async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, + collator_options: CollatorOptions, id: ParaId, rpc_ext_builder: RB, build_import_queue: BIQ, @@ -212,7 +221,14 @@ where sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, Executor: NativeExecutionDispatch + 'static, RB: Fn( + sc_rpc_api::DenyUnsafe, Arc>>, + Arc< + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, + >, ) -> jsonrpc_core::IoHandler + Send + 'static, @@ -233,7 +249,7 @@ where Option<&Registry>, Option, &TaskManager, - &polkadot_service::NewFull, + Arc, Arc< sc_transaction_pool::FullPool< Block, @@ -254,27 +270,26 @@ where let params = new_partial::(¶chain_config, build_import_queue)?; let (mut telemetry, telemetry_worker_handle) = params.other; - let relay_chain_full_node = - cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle) - .map_err(|e| match e { - polkadot_service::Error::Sub(x) => x, - s => format!("{}", s).into(), - })?; + let mut task_manager = params.task_manager; + let (relay_chain_interface, collator_key) = build_inprocess_relay_chain( + polkadot_config, + ¶chain_config, + telemetry_worker_handle, + &mut task_manager, + ) + .map_err(|e| match e { + RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, + s => s.to_string().into(), + })?; let client = params.client.clone(); let backend = params.backend.clone(); - let block_announce_validator = build_block_announce_validator( - relay_chain_full_node.client.clone(), - id, - Box::new(relay_chain_full_node.network.clone()), - relay_chain_full_node.backend.clone(), - ); + let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id); let force_authoring = parachain_config.force_authoring; let validator = parachain_config.role.is_authority(); let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); - let mut task_manager = params.task_manager; let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); let (network, system_rpc_tx, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -283,12 +298,17 @@ where transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue: import_queue.clone(), - block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), + block_announce_validator_builder: Some(Box::new(|_| { + Box::new(block_announce_validator) + })), warp_sync: None, })?; let rpc_client = client.clone(); - let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone()))); + let rpc_transaction_pool = transaction_pool.clone(); + let rpc_extensions_builder = Box::new(move |deny_unsafe, _| { + Ok(rpc_ext_builder(deny_unsafe, rpc_client.clone(), rpc_transaction_pool.clone())) + }); sc_service::spawn_tasks(sc_service::SpawnTasksParams { rpc_extensions_builder, @@ -308,13 +328,15 @@ where Arc::new(move |hash, data| network.announce_block(hash, data)) }; + let relay_chain_slot_duration = Duration::from_secs(6); + if validator { let parachain_consensus = build_consensus( client.clone(), prometheus_registry.as_ref(), telemetry.as_ref().map(|t| t.handle()), &task_manager, - &relay_chain_full_node, + relay_chain_interface.clone(), transaction_pool, network, params.keystore_container.sync_keystore(), @@ -329,10 +351,12 @@ where announce_block, client: client.clone(), task_manager: &mut task_manager, - relay_chain_full_node, + relay_chain_interface, spawner, parachain_consensus, import_queue, + collator_key: collator_key.expect("Command line arguments do not allow this. qed"), + relay_chain_slot_duration, }; start_collator(params).await?; @@ -342,7 +366,10 @@ where announce_block, task_manager: &mut task_manager, para_id: id, - relay_chain_full_node, + relay_chain_interface, + relay_chain_slot_duration, + import_queue, + collator_options, }; start_full_node(params)?; @@ -384,9 +411,9 @@ pub fn parachain_build_import_queue( let time = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *time, - slot_duration.slot_duration(), + slot_duration, ); Ok((time, slot)) @@ -403,6 +430,7 @@ pub fn parachain_build_import_queue( pub async fn start_node( parachain_config: Configuration, polkadot_config: Configuration, + collator_options: CollatorOptions, id: ParaId, ) -> sc_service::error::Result<( TaskManager, @@ -411,14 +439,27 @@ pub async fn start_node( start_node_impl::( parachain_config, polkadot_config, + collator_options, id, - |_| Default::default(), + |deny_unsafe, client, pool| { + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + client.clone(), + pool, + deny_unsafe, + ))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); + io + }, parachain_build_import_queue, |client, prometheus_registry, telemetry, task_manager, - relay_chain_node, + relay_chain_interface, transaction_pool, sync_oracle, keystore, @@ -433,60 +474,47 @@ pub async fn start_node( telemetry.clone(), ); - let relay_chain_backend = relay_chain_node.backend.clone(); - let relay_chain_client = relay_chain_node.client.clone(); - Ok(build_aura_consensus::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - _, - _, - _, - >(BuildAuraConsensusParams { - proposer_factory, - create_inherent_data_providers: move |_, (relay_parent, validation_data)| { - let parachain_inherent = - cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client( + Ok(AuraConsensus::build::( + BuildAuraConsensusParams { + proposer_factory, + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let relay_chain_interface = relay_chain_interface.clone(); + async move { + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( relay_parent, - &relay_chain_client, - &*relay_chain_backend, + &relay_chain_interface, &validation_data, id, - ); - async move { - let time = sp_timestamp::InherentDataProvider::from_system_time(); + ).await; + let time = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *time, - slot_duration.slot_duration(), + slot_duration, ); - let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) - })?; - Ok((time, slot, parachain_inherent)) - } + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from( + "Failed to create parachain inherent", + ) + })?; + Ok((time, slot, parachain_inherent)) + } + }, + block_import: client.clone(), + para_client: client, + backoff_authoring_blocks: Option::<()>::None, + sync_oracle, + keystore, + force_authoring, + slot_duration, + // We got around 500ms for proposing + block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), + telemetry, + max_block_proposal_slot_portion: None, }, - block_import: client.clone(), - relay_chain_client: relay_chain_node.client.clone(), - relay_chain_backend: relay_chain_node.backend.clone(), - para_client: client, - backoff_authoring_blocks: Option::<()>::None, - sync_oracle, - keystore, - force_authoring, - slot_duration, - // We got around 500ms for proposing - block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), - telemetry, - max_block_proposal_slot_portion: None, - })) + )) }, ) .await diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 20ce70aba8f6..1d0870fcbcd8 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "rialto-parachain-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" @@ -11,9 +11,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } [dependencies] -codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']} +codec = { package = 'parity-scale-codec', version = '3.0.0', default-features = false, features = ['derive']} log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.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 depedencies diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5b71674b7fe9..646521f32939 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -42,7 +42,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ - construct_runtime, match_type, parameter_types, + construct_runtime, match_types, parameter_types, traits::{Everything, IsInVec, Randomness}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -50,7 +50,7 @@ pub use frame_support::{ }, StorageValue, }; -pub use frame_system::Call as SystemCall; +pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -70,7 +70,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, - ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; @@ -86,6 +86,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckGenesis, frame_system::CheckEra, @@ -103,7 +104,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_opaque_keys! { @@ -122,6 +123,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 0, }; /// This determines the average expected block time that we are targeting. @@ -209,6 +211,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The action to take on a Runtime Upgrade type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -267,7 +270,7 @@ parameter_types! { impl cumulus_pallet_parachain_system::Config for Runtime { type Event = Event; - type OnValidationData = (); + type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; type DmpMessageHandler = DmpQueue; @@ -294,7 +297,7 @@ parameter_types! { /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsDefault, + ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. @@ -348,7 +351,7 @@ parameter_types! { pub const MaxAuthorities: u32 = 100_000; } -match_type! { +match_types! { pub type ParentOrParentsUnitPlurality: impl Contains = { MultiLocation { parents: 1, interior: Here } | MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } @@ -420,6 +423,10 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; type VersionWrapper = (); + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -554,8 +561,8 @@ impl_runtime_apis! { } impl cumulus_primitives_core::CollectCollationInfo for Runtime { - fn collect_collation_info() -> cumulus_primitives_core::CollationInfo { - ParachainSystem::collect_collation_info() + fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) } } @@ -610,7 +617,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 2795f2eecaec..e44ceb45faa9 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -3,19 +3,19 @@ name = "rialto-bridge-node" description = "Substrate node compatible with Rialto runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +clap = { version = "3.1", features = ["derive"] } futures = "0.3" jsonrpc-core = "18.0" -kvdb = "0.10" -kvdb-rocksdb = "0.12" +kvdb = "0.11" +kvdb-rocksdb = "0.15" lru = "0.7" -structopt = "0.3.21" serde_json = "1.0.59" thiserror = "1.0" @@ -50,7 +50,6 @@ sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -#sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -77,37 +76,10 @@ substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate # Polkadot Dependencies -polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" } - -# Polkadot (parachain) Dependencies - -polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index fb18a35a6af0..10315e33c853 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,7 +16,7 @@ use beefy_primitives::crypto::AuthorityId as BeefyId; use bp_rialto::derive_account_from_millau_id; -use polkadot_primitives::v1::{AssignmentId, ValidatorId}; +use polkadot_primitives::v2::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, @@ -30,7 +30,8 @@ use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = + sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted @@ -96,23 +97,16 @@ impl Alternative { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - ], + endowed_accounts(), true, ) }, vec![], None, None, - properties, None, + properties, + Default::default(), ), Alternative::LocalTestnet => ChainSpec::from_genesis( "Rialto Local", @@ -128,61 +122,70 @@ impl Alternative { get_authority_keys_from_seed("Eve"), ], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("MillauMessagesOwner"), - get_account_id_from_seed::("WithMillauTokenSwap"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto::AccountId, - bp_rialto::AccountIdConverter, - >(), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), - ], + endowed_accounts(), true, ) }, vec![], None, None, - properties, None, + properties, + Default::default(), ), } } } +/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make +/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, +/// accounts used by relayers in our test deployments, accounts used for demonstration +/// purposes), are all available on these chains. +fn endowed_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("MillauMessagesOwner"), + get_account_id_from_seed::("WithMillauTokenSwap"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto::AccountId, + bp_rialto::AccountIdConverter, + >(), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), + ] +} + fn session_keys( babe: BabeId, beefy: BeefyId, @@ -221,7 +224,7 @@ fn testnet_genesis( }, beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, - sudo: SudoConfig { key: root_key }, + sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities .iter() @@ -247,25 +250,20 @@ fn testnet_genesis( // (see /node/service/src/chain_spec.rs:default_parachains_host_configuration) configuration: ConfigurationConfig { config: polkadot_runtime_parachains::configuration::HostConfiguration { - validation_upgrade_frequency: 1u32, - validation_upgrade_delay: 1, + validation_upgrade_cooldown: 2u32, + validation_upgrade_delay: 2, code_retention_period: 1200, - max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE, + max_code_size: polkadot_primitives::v2::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v2::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, chain_availability_period: 4, thread_availability_period: 4, max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, - max_downward_message_size: 1024, - // this is approximatelly 4ms. - // - // Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with - // an import since that's a made up number and should be replaced with a constant - // obtained by benchmarking anyway. - ump_service_total_weight: 4 * 1_000_000_000, - max_upward_message_size: 1024 * 1024, + max_downward_message_size: 1024 * 1024, + ump_service_total_weight: 100_000_000_000, + max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, hrmp_recipient_deposit: 0, @@ -283,6 +281,7 @@ fn testnet_genesis( needed_approvals: 2, relay_vrf_modulo_samples: 2, zeroth_delay_tranche_width: 0, + minimum_validation_upgrade_delay: 5, ..Default::default() }, }, diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 3f85a69a713f..bb7f54998dd5 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use clap::Parser; use sc_cli::RunCmd; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, @@ -27,9 +27,10 @@ pub struct Cli { } /// Possible subcommands of the main binary. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Key management CLI utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. @@ -69,16 +70,16 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. - #[structopt(name = "prepare-worker", setting = structopt::clap::AppSettings::Hidden)] + #[clap(name = "prepare-worker", hide = true)] PvfPrepareWorker(ValidationWorkerCommand), /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. - #[structopt(name = "execute-worker", setting = structopt::clap::AppSettings::Hidden)] + #[clap(name = "execute-worker", hide = true)] PvfExecuteWorker(ValidationWorkerCommand), } /// Validation worker command. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ValidationWorkerCommand { /// The path to the validation host's socket. pub socket_path: String, diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 7be615a57760..da92837f06c0 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -14,13 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - cli::{Cli, Subcommand}, - service::new_partial, -}; +use crate::cli::{Cli, Subcommand}; use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; -use sc_service::PartialComponents; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -67,6 +63,21 @@ impl SubstrateCli for Cli { } } +// Rialto native executor instance. +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + rialto_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + rialto_runtime::native_version() + } +} + /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); @@ -79,7 +90,7 @@ pub fn run() -> sc_cli::Result<()> { if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -98,32 +109,32 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, import_queue, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, config.database), task_manager)) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, import_queue, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -134,16 +145,14 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, backend, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, backend, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, backend), task_manager)) }) }, Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| { - cmd.run::(config) - }) + runner.sync_run(|config| cmd.run::(config)) }, Some(Subcommand::PvfPrepareWorker(cmd)) => { let mut builder = sc_cli::LoggerBuilder::new(""); @@ -170,15 +179,35 @@ pub fn run() -> sc_cli::Result<()> { // let no_beefy = true; // let telemetry_worker_handler = None; // let is_collator = crate::service::IsCollator::No; - let overseer_gen = crate::overseer::RealOverseerGen; + let overseer_gen = polkadot_service::overseer::RealOverseerGen; runner.run_node_until_exit(|config| async move { match config.role { Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other( "Light client is not supported by this node".into(), ))), - _ => crate::service::build_full(config, overseer_gen) - .map(|full| full.task_manager) - .map_err(service_error), + _ => { + let is_collator = polkadot_service::IsCollator::No; + let grandpa_pause = None; + let enable_beefy = true; + let jaeger_agent = None; + let telemetry_worker_handle = None; + let program_path = None; + let overseer_enable_anyways = false; + + polkadot_service::new_full::( + config, + is_collator, + grandpa_pause, + enable_beefy, + jaeger_agent, + telemetry_worker_handle, + program_path, + overseer_enable_anyways, + overseer_gen, + ) + .map(|full| full.task_manager) + .map_err(service_error) + }, } }) }, @@ -187,6 +216,6 @@ pub fn run() -> sc_cli::Result<()> { // We don't want to change 'service.rs' too much to ease future updates => it'll keep using // its own error enum like original polkadot service does. -fn service_error(err: crate::service::Error) -> sc_cli::Error { +fn service_error(err: polkadot_service::Error) -> sc_cli::Error { sc_cli::Error::Application(Box::new(err)) } diff --git a/bin/rialto/node/src/main.rs b/bin/rialto/node/src/main.rs index 824814224e54..6dea84a309b2 100644 --- a/bin/rialto/node/src/main.rs +++ b/bin/rialto/node/src/main.rs @@ -19,12 +19,8 @@ #![warn(missing_docs)] mod chain_spec; -#[macro_use] -mod service; mod cli; mod command; -mod overseer; -mod parachains_db; /// Run the Rialto Node fn main() -> sc_cli::Result<()> { diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs deleted file mode 100644 index 9a7025e77c9b..000000000000 --- a/bin/rialto/node/src/overseer.rs +++ /dev/null @@ -1,316 +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 is almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository. -//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. - -// this warning comes from `polkadot_overseer::AllSubsystems` type -#![allow(clippy::type_complexity)] - -use crate::service::{AuthorityDiscoveryApi, Error}; -use rialto_runtime::{opaque::Block, Hash}; - -use lru::LruCache; -use polkadot_availability_distribution::IncomingRequestReceivers; -use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; -use polkadot_node_core_av_store::Config as AvailabilityConfig; -use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; -use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; -use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver}; -use polkadot_overseer::{ - metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder, - OverseerConnector, OverseerHandle, -}; -use polkadot_primitives::v1::ParachainHost; -use sc_authority_discovery::Service as AuthorityDiscoveryService; -use sc_client_api::AuxStore; -use sc_keystore::LocalKeystore; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_consensus_babe::BabeApi; -use sp_core::traits::SpawnNamed; -use std::sync::Arc; -use substrate_prometheus_endpoint::Registry; - -pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem; -pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem; -pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem; -pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem; -pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide}; -pub use polkadot_dispute_distribution::DisputeDistributionSubsystem; -pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem; -pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem; -pub use polkadot_node_collation_generation::CollationGenerationSubsystem; -pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem; -pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem; -pub use polkadot_node_core_backing::CandidateBackingSubsystem; -pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem; -pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem; -pub use polkadot_node_core_chain_api::ChainApiSubsystem; -pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem; -pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem; -pub use polkadot_node_core_provisioner::ProvisionerSubsystem; -pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem; -pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem; - -/// Arguments passed for overseer construction. -pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> -where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, -{ - /// Set of initial relay chain leaves to track. - pub leaves: Vec, - /// The keystore to use for i.e. validator keys. - pub keystore: Arc, - /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. - pub runtime_client: Arc, - /// The underlying key value store for the parachains. - pub parachains_db: Arc, - /// Underlying network service implementation. - pub network_service: Arc>, - /// Underlying authority discovery service. - pub authority_discovery_service: AuthorityDiscoveryService, - /// POV request receiver - pub pov_req_receiver: IncomingRequestReceiver, - pub chunk_req_receiver: IncomingRequestReceiver, - pub collation_req_receiver: IncomingRequestReceiver, - pub available_data_req_receiver: - IncomingRequestReceiver, - pub statement_req_receiver: IncomingRequestReceiver, - pub dispute_req_receiver: IncomingRequestReceiver, - /// Prometheus registry, commonly used for production systems, less so for test. - pub registry: Option<&'a Registry>, - /// Task spawner to be used throughout the overseer and the APIs it provides. - pub spawner: Spawner, - /// Configuration for the approval voting subsystem. - pub approval_voting_config: ApprovalVotingConfig, - /// Configuration for the availability store subsystem. - pub availability_config: AvailabilityConfig, - /// Configuration for the candidate validation subsystem. - pub candidate_validation_config: CandidateValidationConfig, - /// Configuration for the chain selection subsystem. - pub chain_selection_config: ChainSelectionConfig, - /// Configuration for the dispute coordinator subsystem. - pub dispute_coordinator_config: DisputeCoordinatorConfig, -} - -/// Obtain a prepared `OverseerBuilder`, that is initialized -/// with all default values. -pub fn prepared_overseer_builder( - OverseerGenArgs { - leaves, - keystore, - runtime_client, - parachains_db, - network_service, - authority_discovery_service, - pov_req_receiver, - chunk_req_receiver, - collation_req_receiver: _, - available_data_req_receiver, - statement_req_receiver, - dispute_req_receiver, - registry, - spawner, - approval_voting_config, - availability_config, - candidate_validation_config, - chain_selection_config, - dispute_coordinator_config, - }: OverseerGenArgs<'_, Spawner, RuntimeClient>, -) -> Result< - OverseerBuilder< - Spawner, - Arc, - CandidateValidationSubsystem, - CandidateBackingSubsystem, - StatementDistributionSubsystem, - AvailabilityDistributionSubsystem, - AvailabilityRecoverySubsystem, - BitfieldSigningSubsystem, - BitfieldDistributionSubsystem, - ProvisionerSubsystem, - RuntimeApiSubsystem, - AvailabilityStoreSubsystem, - NetworkBridgeSubsystem< - Arc>, - AuthorityDiscoveryService, - >, - ChainApiSubsystem, - CollationGenerationSubsystem, - CollatorProtocolSubsystem, - ApprovalDistributionSubsystem, - ApprovalVotingSubsystem, - GossipSupportSubsystem, - DisputeCoordinatorSubsystem, - DisputeDistributionSubsystem, - ChainSelectionSubsystem, - >, - Error, -> -where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, -{ - use polkadot_node_subsystem_util::metrics::Metrics; - use std::iter::FromIterator; - - let metrics = ::register(registry)?; - - let builder = Overseer::builder() - .availability_distribution(AvailabilityDistributionSubsystem::new( - keystore.clone(), - IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, - Metrics::register(registry)?, - )) - .availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only( - available_data_req_receiver, - Metrics::register(registry)?, - )) - .availability_store(AvailabilityStoreSubsystem::new( - parachains_db.clone(), - availability_config, - Metrics::register(registry)?, - )) - .bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?)) - .bitfield_signing(BitfieldSigningSubsystem::new( - spawner.clone(), - keystore.clone(), - Metrics::register(registry)?, - )) - .candidate_backing(CandidateBackingSubsystem::new( - spawner.clone(), - keystore.clone(), - Metrics::register(registry)?, - )) - .candidate_validation(CandidateValidationSubsystem::with_config( - candidate_validation_config, - Metrics::register(registry)?, // candidate-validation metrics - Metrics::register(registry)?, // validation host metrics - )) - .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?)) - .collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?)) - .collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator { - keystore: keystore.clone(), - eviction_policy: Default::default(), - metrics: Metrics::register(registry)?, - })) - .network_bridge(NetworkBridgeSubsystem::new( - network_service.clone(), - authority_discovery_service.clone(), - Box::new(network_service.clone()), - Metrics::register(registry)?, - )) - .provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?)) - .runtime_api(RuntimeApiSubsystem::new( - runtime_client.clone(), - Metrics::register(registry)?, - spawner.clone(), - )) - .statement_distribution(StatementDistributionSubsystem::new( - keystore.clone(), - statement_req_receiver, - Metrics::register(registry)?, - )) - .approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?)) - .approval_voting(ApprovalVotingSubsystem::with_config( - approval_voting_config, - parachains_db.clone(), - keystore.clone(), - Box::new(network_service), - Metrics::register(registry)?, - )) - .gossip_support(GossipSupportSubsystem::new( - keystore.clone(), - authority_discovery_service.clone(), - )) - .dispute_coordinator(DisputeCoordinatorSubsystem::new( - parachains_db.clone(), - dispute_coordinator_config, - keystore.clone(), - Metrics::register(registry)?, - )) - .dispute_distribution(DisputeDistributionSubsystem::new( - keystore, - dispute_req_receiver, - authority_discovery_service, - Metrics::register(registry)?, - )) - .chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db)) - .leaves(Vec::from_iter( - leaves - .into_iter() - .map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)), - )) - .activation_external_listeners(Default::default()) - .span_per_active_leaf(Default::default()) - .active_leaves(Default::default()) - .supports_parachains(runtime_client) - .known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE)) - .metrics(metrics) - .spawner(spawner); - Ok(builder) -} - -/// Trait for the `fn` generating the overseer. -/// -/// Default behavior is to create an unmodified overseer, as `RealOverseerGen` -/// would do. -pub trait OverseerGen { - /// Overwrite the full generation of the overseer, including the subsystems. - fn generate( - &self, - connector: OverseerConnector, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, - ) -> Result<(Overseer>, OverseerHandle), Error> - where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, - { - let gen = RealOverseerGen; - RealOverseerGen::generate::(&gen, connector, args) - } - // It would be nice to make `create_subsystems` part of this trait, - // but the amount of generic arguments that would be required as - // as consequence make this rather annoying to implement and use. -} - -use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE; - -/// The regular set of subsystems. -pub struct RealOverseerGen; - -impl OverseerGen for RealOverseerGen { - fn generate( - &self, - connector: OverseerConnector, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, - ) -> Result<(Overseer>, OverseerHandle), Error> - where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, - { - prepared_overseer_builder(args)? - .build_with_connector(connector) - .map_err(|e| e.into()) - } -} diff --git a/bin/rialto/node/src/parachains_db.rs b/bin/rialto/node/src/parachains_db.rs deleted file mode 100644 index bf2052043c98..000000000000 --- a/bin/rialto/node/src/parachains_db.rs +++ /dev/null @@ -1,104 +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 is almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository. -//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. - -use kvdb::KeyValueDB; -use std::{io, path::PathBuf, sync::Arc}; - -mod columns { - pub const NUM_COLUMNS: u32 = 5; - - pub const COL_AVAILABILITY_DATA: u32 = 0; - pub const COL_AVAILABILITY_META: u32 = 1; - pub const COL_APPROVAL_DATA: u32 = 2; - pub const COL_CHAIN_SELECTION_DATA: u32 = 3; - pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4; -} - -/// Columns used by different subsystems. -#[derive(Debug, Clone)] -pub struct ColumnsConfig { - /// The column used by the av-store for data. - pub col_availability_data: u32, - /// The column used by the av-store for meta information. - pub col_availability_meta: u32, - /// The column used by approval voting for data. - pub col_approval_data: u32, - /// The column used by chain selection for data. - pub col_chain_selection_data: u32, - /// The column used by dispute coordinator for data. - pub col_dispute_coordinator_data: u32, -} - -/// The real columns used by the parachains DB. -pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig { - col_availability_data: columns::COL_AVAILABILITY_DATA, - col_availability_meta: columns::COL_AVAILABILITY_META, - col_approval_data: columns::COL_APPROVAL_DATA, - col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA, - col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA, -}; - -/// The cache size for each column, in megabytes. -#[derive(Debug, Clone)] -pub struct CacheSizes { - /// Cache used by availability data. - pub availability_data: usize, - /// Cache used by availability meta. - pub availability_meta: usize, - /// Cache used by approval data. - pub approval_data: usize, -} - -impl Default for CacheSizes { - fn default() -> Self { - CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 } - } -} - -fn other_io_error(err: String) -> io::Error { - io::Error::new(io::ErrorKind::Other, err) -} - -/// Open the database on disk, creating it if it doesn't exist. -pub fn open_creating(root: PathBuf, cache_sizes: CacheSizes) -> io::Result> { - use kvdb_rocksdb::{Database, DatabaseConfig}; - - let path = root.join("parachains").join("db"); - - let mut db_config = DatabaseConfig::with_columns(columns::NUM_COLUMNS); - - let _ = db_config - .memory_budget - .insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data); - let _ = db_config - .memory_budget - .insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta); - let _ = db_config - .memory_budget - .insert(columns::COL_APPROVAL_DATA, cache_sizes.approval_data); - - let path_str = path - .to_str() - .ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?; - - std::fs::create_dir_all(&path_str)?; - let db = Database::open(&db_config, path_str)?; - - Ok(Arc::new(db)) -} diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs deleted file mode 100644 index 3349b09edb9f..000000000000 --- a/bin/rialto/node/src/service.rs +++ /dev/null @@ -1,756 +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 . - -//! Rialto chain node service. -//! -//! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository -//! without optional functions, and with BEEFY added on top. - -use crate::overseer::{OverseerGen, OverseerGenArgs}; - -use polkadot_client::RuntimeApiCollection; -use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; -use polkadot_node_core_av_store::Config as AvailabilityConfig; -use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; -use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; -use polkadot_node_network_protocol::request_response::IncomingRequest; -use polkadot_overseer::{BlockInfo, OverseerConnector}; -use polkadot_primitives::v1::BlockId; -use rialto_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::ExecutorProvider; -use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; -use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; -use sc_service::{config::PrometheusConfig, Configuration, TaskManager}; -use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_api::{ConstructRuntimeApi, HeaderT}; -use sp_consensus::SelectChain; -use sp_runtime::traits::Block as BlockT; -use std::{sync::Arc, time::Duration}; -use substrate_prometheus_endpoint::Registry; - -pub use polkadot_overseer::Handle; -pub use polkadot_primitives::v1::ParachainHost; -pub use sc_client_api::AuxStore; -pub use sp_authority_discovery::AuthorityDiscoveryApi; -pub use sp_blockchain::HeaderBackend; -pub use sp_consensus_babe::BabeApi; - -pub type Executor = NativeElseWasmExecutor; - -// Our native executor instance. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - rialto_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - rialto_runtime::native_version() - } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Io(#[from] std::io::Error), - - #[error(transparent)] - Cli(#[from] sc_cli::Error), - - #[error(transparent)] - Blockchain(#[from] sp_blockchain::Error), - - #[error(transparent)] - Consensus(#[from] sp_consensus::Error), - - #[error(transparent)] - Service(#[from] sc_service::Error), - - #[error(transparent)] - Telemetry(#[from] sc_telemetry::Error), - - #[error("Failed to create an overseer")] - Overseer(#[from] polkadot_overseer::SubsystemError), - - #[error(transparent)] - Prometheus(#[from] substrate_prometheus_endpoint::PrometheusError), - - #[error("Authorities require the real overseer implementation")] - AuthoritiesRequireRealOverseer, - - #[error("Creating a custom database is required for validators")] - DatabasePathRequired, -} - -type FullClient = sc_service::TFullClient; -type FullBackend = sc_service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; -type FullGrandpaBlockImport = - sc_finality_grandpa::GrandpaBlockImport; -type FullTransactionPool = sc_transaction_pool::FullPool; -type FullBabeBlockImport = - sc_consensus_babe::BabeBlockImport; -type FullBabeLink = sc_consensus_babe::BabeLink; -type FullGrandpaLink = sc_finality_grandpa::LinkHalf; - -// If we're using prometheus, use a registry with a prefix of `polkadot`. -fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> { - if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() { - *registry = Registry::new_custom(Some("polkadot".into()), None)?; - } - - Ok(()) -} - -// Needed here for complex return type while `impl Trait` in type aliases is unstable. -#[allow(clippy::type_complexity)] -pub fn new_partial( - config: &mut Configuration, -) -> Result< - sc_service::PartialComponents< - FullClient, - FullBackend, - FullSelectChain, - sc_consensus::DefaultImportQueue, - FullTransactionPool, - ( - impl Fn( - sc_rpc::DenyUnsafe, - sc_rpc::SubscriptionTaskExecutor, - ) -> Result, sc_service::Error>, - ( - FullBabeBlockImport, - FullGrandpaLink, - FullBabeLink, - beefy_gadget::notification::BeefySignedCommitmentSender, - ), - sc_finality_grandpa::SharedVoterState, - std::time::Duration, - Option, - ), - >, - Error, -> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - set_prometheus_registry(config)?; - - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - ); - - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - let client = Arc::new(client); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let (grandpa_block_import, grandpa_link) = - sc_finality_grandpa::block_import_with_authority_set_hard_forks( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - Vec::new(), - telemetry.as_ref().map(|x| x.handle()), - )?; - let justification_import = grandpa_block_import.clone(); - - let babe_config = sc_consensus_babe::Config::get_or_compute(&*client)?; - let (block_import, babe_link) = - sc_consensus_babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?; - - let slot_duration = babe_link.config().slot_duration(); - let import_queue = sc_consensus_babe::import_queue( - babe_link.clone(), - block_import.clone(), - Some(Box::new(justification_import)), - client.clone(), - select_chain.clone(), - move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - telemetry.as_ref().map(|x| x.handle()), - )?; - - let justification_stream = grandpa_link.justification_stream(); - let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - - let (signed_commitment_sender, signed_commitment_stream) = - beefy_gadget::notification::BeefySignedCommitmentStream::channel(); - - let import_setup = (block_import, grandpa_link, babe_link, signed_commitment_sender); - let rpc_setup = shared_voter_state.clone(); - - let slot_duration = babe_config.slot_duration(); - - let rpc_extensions_builder = { - let client = client.clone(); - let transaction_pool = transaction_pool.clone(); - let backend = backend.clone(); - - move |deny_unsafe, - subscription_executor: sc_rpc::SubscriptionTaskExecutor| - -> Result, sc_service::Error> { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; - use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - - let backend = backend.clone(); - let client = client.clone(); - let pool = transaction_pool.clone(); - - let shared_voter_state = shared_voter_state.clone(); - - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( - backend, - Some(shared_authority_set.clone()), - ); - - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::to_delegate(FullSystem::new( - client.clone(), - pool, - deny_unsafe, - ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( - client.clone(), - ))); - io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( - shared_authority_set.clone(), - shared_voter_state, - justification_stream.clone(), - subscription_executor.clone(), - finality_proof_provider, - ))); - io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( - beefy_gadget_rpc::BeefyRpcHandler::new( - signed_commitment_stream.clone(), - subscription_executor, - ), - )); - io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new(client))); - - Ok(io) - } - }; - - Ok(sc_service::PartialComponents { - client, - backend, - task_manager, - keystore_container, - select_chain, - import_queue, - transaction_pool, - other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, telemetry), - }) -} - -pub struct NewFull { - pub task_manager: TaskManager, - pub client: C, - pub overseer_handle: Option, - pub network: Arc::Hash>>, - pub rpc_handlers: sc_service::RpcHandlers, - pub backend: Arc, -} - -/// The maximum number of active leaves we forward to the [`Overseer`] on start up. -const MAX_ACTIVE_LEAVES: usize = 4; - -/// Returns the active leaves the overseer should start with. -async fn active_leaves( - select_chain: &sc_consensus::LongestChain, - client: &FullClient, -) -> Result, Error> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - let best_block = select_chain.best_chain().await?; - - let mut leaves = select_chain - .leaves() - .await - .unwrap_or_default() - .into_iter() - .filter_map(|hash| { - let number = client.number(hash).ok()??; - - // Only consider leaves that are in maximum an uncle of the best block. - if number < best_block.number().saturating_sub(1) || hash == best_block.hash() { - return None - } - - let parent_hash = client.header(&BlockId::Hash(hash)).ok()??.parent_hash; - - Some(BlockInfo { hash, parent_hash, number }) - }) - .collect::>(); - - // Sort by block number and get the maximum number of leaves - leaves.sort_by_key(|b| b.number); - - leaves.push(BlockInfo { - hash: best_block.hash(), - parent_hash: *best_block.parent_hash(), - number: *best_block.number(), - }); - - Ok(leaves.into_iter().rev().take(MAX_ACTIVE_LEAVES).collect()) -} - -// Create a new full node. -pub fn new_full( - mut config: Configuration, - program_path: Option, - overseer_gen: impl OverseerGen, -) -> Result>, Error> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - let is_collator = false; - - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let backoff_authoring_blocks = - Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default()); - - let disable_grandpa = config.disable_grandpa; - let name = config.network.node_name.clone(); - - let sc_service::PartialComponents { - client, - backend, - mut task_manager, - keystore_container, - select_chain, - import_queue, - transaction_pool, - other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry), - } = new_partial(&mut config)?; - - let prometheus_registry = config.prometheus_registry().cloned(); - - let overseer_connector = OverseerConnector::default(); - - let shared_voter_state = rpc_setup; - let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; - - // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change - // anything in terms of behaviour, but makes the logs more consistent with the other - // Substrate nodes. - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - - config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); - - { - use polkadot_network_bridge::{peer_sets_info, IsAuthority}; - let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No }; - config.network.extra_sets.extend(peer_sets_info(is_authority)); - } - - let (pov_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (chunk_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (collation_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (available_data_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (statement_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (dispute_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - import_setup.1.shared_authority_set().clone(), - vec![], - )); - - let (network, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; - - if config.offchain_worker.enabled { - let _ = sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - } - - let parachains_db = crate::parachains_db::open_creating( - config.database.path().ok_or(Error::DatabasePathRequired)?.into(), - crate::parachains_db::CacheSizes::default(), - )?; - - let availability_config = AvailabilityConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_availability_data, - col_meta: crate::parachains_db::REAL_COLUMNS.col_availability_meta, - }; - - let approval_voting_config = ApprovalVotingConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_approval_data, - slot_duration_millis: slot_duration.as_millis() as u64, - }; - - let candidate_validation_config = CandidateValidationConfig { - artifacts_cache_path: config - .database - .path() - .ok_or(Error::DatabasePathRequired)? - .join("pvf-artifacts"), - program_path: match program_path { - None => std::env::current_exe()?, - Some(p) => p, - }, - }; - - let chain_selection_config = ChainSelectionConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_chain_selection_data, - stagnant_check_interval: polkadot_node_core_chain_selection::StagnantCheckInterval::never(), - }; - - let dispute_coordinator_config = DisputeCoordinatorConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_dispute_coordinator_data, - }; - - let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - config, - backend: backend.clone(), - client: client.clone(), - keystore: keystore_container.sync_keystore(), - network: network.clone(), - rpc_extensions_builder: Box::new(rpc_extensions_builder), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - system_rpc_tx, - telemetry: telemetry.as_mut(), - })?; - - let (block_import, link_half, babe_link, signed_commitment_sender) = import_setup; - - let overseer_client = client.clone(); - let spawner = task_manager.spawn_handle(); - let active_leaves = futures::executor::block_on(active_leaves(&select_chain, &*client))?; - - let authority_discovery_service = if role.is_authority() || is_collator { - use futures::StreamExt; - use sc_network::Event; - - let authority_discovery_role = if role.is_authority() { - sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore()) - } else { - // don't publish our addresses when we're only a collator - sc_authority_discovery::Role::Discover - }; - let dht_event_stream = - network.event_stream("authority-discovery").filter_map(|e| async move { - match e { - Event::Dht(e) => Some(e), - _ => None, - } - }); - let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( - sc_authority_discovery::WorkerConfig { - publish_non_global_ips: auth_disc_publish_non_global_ips, - ..Default::default() - }, - client.clone(), - network.clone(), - Box::pin(dht_event_stream), - authority_discovery_role, - prometheus_registry.clone(), - ); - - task_manager - .spawn_handle() - .spawn("authority-discovery-worker", None, worker.run()); - Some(service) - } else { - None - }; - - // we'd say let overseer_handler = - // authority_discovery_service.map(|authority_discovery_service|, ...), but in that case we - // couldn't use ? to propagate errors - let local_keystore = keystore_container.local_keystore(); - let maybe_params = - local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); - - let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params { - let (overseer, overseer_handle) = overseer_gen - .generate::( - overseer_connector, - OverseerGenArgs { - leaves: active_leaves, - keystore, - runtime_client: overseer_client.clone(), - parachains_db, - availability_config, - approval_voting_config, - network_service: network.clone(), - authority_discovery_service, - registry: prometheus_registry.as_ref(), - spawner, - candidate_validation_config, - available_data_req_receiver, - chain_selection_config, - chunk_req_receiver, - collation_req_receiver, - dispute_coordinator_config, - dispute_req_receiver, - pov_req_receiver, - statement_req_receiver, - }, - )?; - let handle = Handle::new(overseer_handle); - - { - let handle = handle.clone(); - task_manager.spawn_essential_handle().spawn_blocking( - "overseer", - None, - Box::pin(async move { - use futures::{pin_mut, select, FutureExt}; - - let forward = polkadot_overseer::forward_events(overseer_client, handle); - - let forward = forward.fuse(); - let overseer_fut = overseer.run().fuse(); - - pin_mut!(overseer_fut); - pin_mut!(forward); - - select! { - _ = forward => (), - _ = overseer_fut => (), - complete => (), - } - }), - ); - } - - Some(handle) - } else { - None - }; - - if role.is_authority() { - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - - let proposer = sc_basic_authorship::ProposerFactory::new( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|x| x.handle()), - ); - - let client_clone = client.clone(); - let overseer_handle = - overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone(); - let slot_duration = babe_link.config().slot_duration(); - let babe_config = sc_consensus_babe::BabeParams { - keystore: keystore_container.sync_keystore(), - client: client.clone(), - select_chain, - block_import, - env: proposer, - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - create_inherent_data_providers: move |parent, ()| { - let client_clone = client_clone.clone(); - let overseer_handle = overseer_handle.clone(); - async move { - let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create( - &*client_clone, - overseer_handle, - parent, - ) - .await - .map_err(Box::new)?; - - let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider( - &*client_clone, - parent, - )?; - - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot, uncles, parachain)) - } - }, - force_authoring, - backoff_authoring_blocks, - babe_link, - can_author_with, - block_proposal_slot_portion: sc_consensus_babe::SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - let babe = sc_consensus_babe::start_babe(babe_config)?; - task_manager.spawn_essential_handle().spawn_blocking("babe", None, babe); - } - - // if the node isn't actively participating in consensus then it doesn't - // need a keystore, regardless of which protocol we use below. - let keystore_opt = - if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; - - let beefy_params = beefy_gadget::BeefyParams { - client: client.clone(), - backend: backend.clone(), - key_store: keystore_opt.clone(), - network: network.clone(), - signed_commitment_sender, - min_block_delta: 2, - prometheus_registry: prometheus_registry.clone(), - }; - - // Start the BEEFY bridge gadget. - task_manager.spawn_essential_handle().spawn_blocking( - "beefy-gadget", - None, - beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params), - ); - - let config = sc_finality_grandpa::Config { - // FIXME substrate#1578 make this available through chainspec - gossip_duration: Duration::from_millis(1000), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: keystore_opt, - local_role: role, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - let enable_grandpa = !disable_grandpa; - if enable_grandpa { - // start the full GRANDPA voter - // NOTE: unlike in substrate we are currently running the full - // GRANDPA voter protocol for all full nodes (regardless of whether - // they're validators or not). at this point the full voter should - // provide better guarantees of block and vote data availability than - // the observer. - - // add a custom voting rule to temporarily stop voting for new blocks - // after the given pause block is finalized and restarting after the - // given delay. - let builder = sc_finality_grandpa::VotingRulesBuilder::default(); - - let voting_rule = builder.build(); - let grandpa_config = sc_finality_grandpa::GrandpaParams { - config, - link: link_half, - network: network.clone(), - voting_rule, - prometheus_registry, - shared_voter_state, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_essential_handle().spawn_blocking( - "grandpa-voter", - None, - sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, - ); - } - - network_starter.start_network(); - - Ok(NewFull { task_manager, client, overseer_handle, network, rpc_handlers, backend }) -} - -pub fn build_full( - config: Configuration, - overseer_gen: impl OverseerGen, -) -> Result>, Error> { - new_full(config, None, overseer_gen) -} diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 3c4ec1ebce1c..59b9a8e9b575 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -2,17 +2,17 @@ name = "rialto-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.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 @@ -73,7 +73,9 @@ polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", bran polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } libsecp256k1 = { version = "0.7", features = ["hmac"] } +static_assertions = "1.1" [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -135,7 +137,7 @@ std = [ ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "libsecp256k1", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0987184c73aa..87cddf5e268d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -21,8 +21,6 @@ #![recursion_limit = "256"] // Runtime-generated enums #![allow(clippy::large_enum_variant)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] // From construct_runtime macro #![allow(clippy::from_over_into)] @@ -53,7 +51,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -142,6 +140,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 1, }; /// The version information used to identify this runtime when compiled natively. @@ -208,6 +207,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } /// The BABE epoch configuration at genesis. @@ -399,21 +399,7 @@ parameter_types! { /// Note that once this is hit the pallet will essentially throttle incoming requests down to one /// call per block. pub const MaxRequests: u32 = 50; -} -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - /// Number of headers to keep in benchmarks. - /// - /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that - /// pruning is taken into account. - /// - /// Note: This is lower than regular value, to speed up benchmarking setup. - pub const HeadersToKeep: u32 = 1024; -} - -#[cfg(not(feature = "runtime-benchmarks"))] -parameter_types! { /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a @@ -426,7 +412,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -434,9 +420,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -449,7 +435,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -469,10 +455,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithMillauMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -547,6 +532,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -567,7 +553,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_runtime_apis! { @@ -619,7 +605,7 @@ impl_runtime_apis! { } impl beefy_primitives::BeefyApi for Runtime { - fn validator_set() -> ValidatorSet { + fn validator_set() -> Option> { Beefy::validator_set() } } @@ -662,10 +648,6 @@ impl_runtime_apis! { let header = BridgeMillauGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_millau::Hash) -> bool { - BridgeMillauGrandpa::is_known_header(hash) - } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { @@ -733,64 +715,56 @@ impl_runtime_apis! { } } - impl polkadot_primitives::v1::ParachainHost for Runtime { - fn validators() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v1::validators::() + impl polkadot_primitives::v2::ParachainHost for Runtime { + fn validators() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v2::validators::() } - fn validator_groups() -> ( - Vec>, - polkadot_primitives::v1::GroupRotationInfo, - ) { - polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::() + fn validator_groups() -> (Vec>, polkadot_primitives::v2::GroupRotationInfo) { + polkadot_runtime_parachains::runtime_api_impl::v2::validator_groups::() } - fn availability_cores() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::() + fn availability_cores() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::availability_cores::() } - fn persisted_validation_data( - para_id: polkadot_primitives::v1::Id, - assumption: polkadot_primitives::v1::OccupiedCoreAssumption, - ) - -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::(para_id, assumption) + fn persisted_validation_data(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::persisted_validation_data::(para_id, assumption) } fn assumed_validation_data( - para_id: polkadot_primitives::v1::Id, + para_id: polkadot_primitives::v2::Id, expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::v1::PersistedValidationData, polkadot_primitives::v1::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::(para_id, expected_persisted_validation_data_hash) + ) -> Option<(polkadot_primitives::v2::PersistedValidationData, polkadot_primitives::v2::ValidationCodeHash)> { + polkadot_runtime_parachains::runtime_api_impl::v2::assumed_validation_data::( + para_id, + expected_persisted_validation_data_hash, + ) } fn check_validation_outputs( - para_id: polkadot_primitives::v1::Id, - outputs: polkadot_primitives::v1::CandidateCommitments, + para_id: polkadot_primitives::v2::Id, + outputs: polkadot_primitives::v2::CandidateCommitments, ) -> bool { - polkadot_runtime_parachains::runtime_api_impl::v1::check_validation_outputs::(para_id, outputs) + polkadot_runtime_parachains::runtime_api_impl::v2::check_validation_outputs::(para_id, outputs) } - fn session_index_for_child() -> polkadot_primitives::v1::SessionIndex { - polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::() + fn session_index_for_child() -> polkadot_primitives::v2::SessionIndex { + polkadot_runtime_parachains::runtime_api_impl::v2::session_index_for_child::() } - fn validation_code( - para_id: polkadot_primitives::v1::Id, - assumption: polkadot_primitives::v1::OccupiedCoreAssumption, - ) - -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::(para_id, assumption) + fn validation_code(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code::(para_id, assumption) } - fn candidate_pending_availability( - para_id: polkadot_primitives::v1::Id, - ) -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::(para_id) + fn candidate_pending_availability(para_id: polkadot_primitives::v2::Id) -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::candidate_pending_availability::(para_id) } - fn candidate_events() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::candidate_events::(|ev| { + fn candidate_events() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::candidate_events::(|ev| { match ev { Event::Inclusion(ev) => { Some(ev) @@ -800,36 +774,46 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::session_info::(index) + fn session_info(index: polkadot_primitives::v2::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::session_info::(index) } - fn dmq_contents( - recipient: polkadot_primitives::v1::Id, - ) -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::(recipient) + fn dmq_contents(recipient: polkadot_primitives::v2::Id) -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::dmq_contents::(recipient) } fn inbound_hrmp_channels_contents( - recipient: polkadot_primitives::v1::Id - ) -> BTreeMap>> { - polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::(recipient) + recipient: polkadot_primitives::v2::Id + ) -> BTreeMap>> { + polkadot_runtime_parachains::runtime_api_impl::v2::inbound_hrmp_channels_contents::(recipient) + } + + fn validation_code_by_hash(hash: polkadot_primitives::v2::ValidationCodeHash) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_by_hash::(hash) + } + + fn on_chain_votes() -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::on_chain_votes::() + } + + fn submit_pvf_check_statement(stmt: polkadot_primitives::v2::PvfCheckStatement, signature: polkadot_primitives::v2::ValidatorSignature) { + polkadot_runtime_parachains::runtime_api_impl::v2::submit_pvf_check_statement::(stmt, signature) } - fn validation_code_by_hash( - hash: polkadot_primitives::v1::ValidationCodeHash, - ) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::(hash) + fn pvfs_require_precheck() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v2::pvfs_require_precheck::() } - fn on_chain_votes() -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::() + fn validation_code_hash(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option + { + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_hash::(para_id, assumption) } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { fn authorities() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v1::relevant_authority_ids::() + polkadot_runtime_parachains::runtime_api_impl::v2::relevant_authority_ids::() } } @@ -896,10 +880,12 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToMillauMessagePayload, + millau_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithMillauMessageBridge::RELAYER_FEE_PERCENT, + millau_to_this_conversion_rate, ).ok() } @@ -914,249 +900,6 @@ impl_runtime_apis! { WithMillauMessageBridge, >(lane, begin, end) } - - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::outbound_latest_received_nonce(lane) - } - - fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::outbound_latest_generated_nonce(lane) - } - } - - impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::inbound_latest_received_nonce(lane) - } - - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::inbound_latest_confirmed_nonce(lane) - } - - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { - BridgeMillauMessages::inbound_unrewarded_relayers_state(lane) - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(extra: bool) -> ( - Vec, - Vec, - ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; - use frame_support::traits::StorageInfoTrait; - - use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; - - let mut list = Vec::::new(); - - list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); - list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa); - - let storage_info = AllPalletsWithSystem::storage_info(); - - return (list, storage_info) - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig, - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; - - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - // Caller 0 Account - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), - ]; - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - - use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; - use bp_runtime::messages::DispatchFeePayment; - use bridge_runtime_common::messages; - use pallet_bridge_messages::benchmarking::{ - Pallet as MessagesBench, - Config as MessagesConfig, - MessageDeliveryProofParams, - MessageParams, - MessageProofParams, - ProofSize as MessagesProofSize, - }; - - impl MessagesConfig for Runtime { - fn maximal_message_size() -> u32 { - messages::source::maximal_message_size::() - } - - fn bridged_relayer_id() -> Self::InboundRelayer { - Default::default() - } - - fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { - pallet_balances::Pallet::::free_balance(account) - } - - fn endow_account(account: &Self::AccountId) { - pallet_balances::Pallet::::make_free_balance_be( - account, - Balance::MAX / 100, - ); - } - - fn prepare_outbound_message( - params: MessageParams, - ) -> (millau_messages::ToMillauMessagePayload, Balance) { - let message_payload = vec![0; params.size as usize]; - let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount( - params.sender_account, - ); - - let message = ToMillauMessagePayload { - spec_version: 0, - weight: params.size as _, - origin: dispatch_origin, - call: message_payload, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }; - (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) - } - - fn prepare_message_proof( - params: MessageProofParams, - ) -> (millau_messages::FromMillauMessagesProof, Weight) { - use crate::millau_messages::WithMillauMessageBridge; - use bp_messages::MessageKey; - use bridge_runtime_common::{ - messages::MessageBridge, - messages_benchmarking::{ed25519_sign, prepare_message_proof}, - }; - use codec::Encode; - use frame_support::weights::GetDispatchInfo; - use pallet_bridge_messages::storage_keys; - use sp_runtime::traits::{Header, IdentifyAccount}; - - let remark = match params.size { - MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }; - let call = Call::System(SystemCall::remark { remark }); - let call_weight = call.get_dispatch_info().weight; - - let millau_account_id: bp_millau::AccountId = Default::default(); - let (rialto_raw_public, rialto_raw_signature) = ed25519_sign( - &call, - &millau_account_id, - VERSION.spec_version, - bp_runtime::MILLAU_CHAIN_ID, - bp_runtime::RIALTO_CHAIN_ID, - ); - let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public)); - let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( - rialto_raw_signature, - )); - - if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { - Self::endow_account(&rialto_public.clone().into_account()); - } - - let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &message_key.lane_id, message_key.nonce, - ).0; - let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0; - - let make_millau_header = |state_root| bp_millau::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ); - - let dispatch_fee_payment = params.dispatch_fee_payment.clone(); - prepare_message_proof::( - params, - make_millau_message_key, - make_millau_outbound_lane_data_key, - make_millau_header, - call_weight, - bp_message_dispatch::MessagePayload { - spec_version: VERSION.spec_version, - weight: call_weight, - origin: bp_message_dispatch::CallOrigin::< - bp_millau::AccountId, - MultiSigner, - Signature, - >::TargetAccount( - millau_account_id, - rialto_public, - rialto_signature, - ), - dispatch_fee_payment, - call: call.encode(), - }.encode(), - ) - } - - fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams, - ) -> millau_messages::ToMillauMessagesDeliveryProof { - use crate::millau_messages::WithMillauMessageBridge; - use bridge_runtime_common::{messages_benchmarking::prepare_message_delivery_proof}; - use sp_runtime::traits::Header; - - prepare_message_delivery_proof::( - params, - |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0, - |state_root| bp_millau::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ), - ) - } - - fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { - frame_system::Pallet::::events() - .into_iter() - .map(|event_record| event_record.event) - .any(|event| matches!( - event, - Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( - _, ([0, 0, 0, 0], nonce_from_event), _, - )) if nonce_from_event == nonce - )) - } - } - - add_benchmark!( - params, - batches, - pallet_bridge_messages, - MessagesBench:: - ); - add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeMillauGrandpa); - - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } - Ok(batches) - } } } @@ -1187,55 +930,22 @@ where #[cfg(test)] mod tests { use super::*; - use bridge_runtime_common::messages; #[test] - fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::RialtoWeight; - - pallet_bridge_messages::ensure_weights_are_correct::( - bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); - - let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), - ), + fn call_size() { + const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, - ) - .unwrap_or(u32::MAX); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - DbWeight::get(), + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE ); - } - - #[test] - fn call_size() { - const DOT_MAX_CALL_SZ: usize = 230; - assert!(core::mem::size_of::>() <= DOT_MAX_CALL_SZ); - // FIXME: get this down to 230. https://github.com/paritytech/grandpa-bridge-gadget/issues/359 - const BEEFY_MAX_CALL_SZ: usize = 232; - assert!(core::mem::size_of::>() <= BEEFY_MAX_CALL_SZ); + // Largest inner Call is `pallet_session::Call` with a size of 224 bytes. This size is a + // result of large `SessionKeys` struct. + // Total size of Rialto runtime Call is 232. + const MAX_CALL_SIZE: usize = 232; + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 13a1c6b06ec2..44348383f1d5 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -19,11 +19,11 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -86,16 +86,19 @@ impl MessageBridge for WithMillauMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; type BridgedChain = Millau; - fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { - bp_rialto::Balance::try_from( - MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_rialto::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_millau::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_rialto::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| MillauToRialtoConversionRate::get()); + bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_rialto::Balance::MAX) } } @@ -113,10 +116,11 @@ impl messages::ChainWithMessages for Rialto { } impl messages::ThisChainWithMessages for Rialto { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -170,13 +174,13 @@ impl messages::ChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau { fn maximal_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() + bp_millau::Millau::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` @@ -272,6 +276,19 @@ impl SourceHeaderChain for Millau { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + _ => None, + } + } +} + /// Rialto -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoToMillauMessagesParameter { @@ -291,15 +308,23 @@ impl MessagesParameter for RialtoToMillauMessagesParameter { #[cfg(test)] mod tests { use super::*; - use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION}; + use crate::{ + AccountId, Call, DbWeight, ExistentialDeposit, MillauGrandpaInstance, Runtime, SystemCall, + SystemConfig, WithMillauMessagesInstance, VERSION, + }; use bp_message_dispatch::CallOrigin; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, }; - use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount}; - use bridge_runtime_common::messages::target::{ - FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload, + use bp_runtime::{derive_account_id, messages::DispatchFeePayment, Chain, SourceAccount}; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, + AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + }, + messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}, }; use frame_support::{ traits::Currency, @@ -316,7 +341,7 @@ mod tests { SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { let bridge = MILLAU_CHAIN_ID; - let call: Call = SystemCall::remark { remark: vec![] }.into(); + let call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); let dispatch_weight = call.get_dispatch_info().weight; let dispatch_fee = ::WeightToFee::calc( &dispatch_weight, @@ -377,4 +402,157 @@ mod tests { ); }); } + + #[test] + fn ensure_rialto_message_lane_weights_are_correct() { + type Weights = pallet_bridge_messages::weights::MillauWeight; + + pallet_bridge_messages::ensure_weights_are_correct::( + bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), + ); + + let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), + ); + pallet_bridge_messages::ensure_able_to_receive_message::( + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), + max_incoming_message_proof_size, + messages::target::maximal_incoming_message_dispatch_weight( + bp_rialto::Rialto::max_extrinsic_weight(), + ), + ); + + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, + ) + .unwrap_or(u32::MAX); + pallet_bridge_messages::ensure_able_to_receive_confirmation::( + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + DbWeight::get(), + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: MillauGrandpaInstance, + with_bridged_chain_messages_instance: WithMillauMessagesInstance, + bridge: WithMillauMessageBridge, + this_chain: bp_rialto::Rialto, + bridged_chain: bp_millau::Millau, + this_chain_account_id_converter: bp_rialto::AccountIdConverter + ); + + assert_complete_bridge_constants::< + Runtime, + MillauGrandpaInstance, + WithMillauMessagesInstance, + WithMillauMessageBridge, + bp_rialto::Rialto, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_rialto::BlockLength::get(), + block_weights: bp_rialto::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::MILLAU_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + }, + }); + + assert_eq!( + MillauToRialtoConversionRate::key().to_vec(), + bp_runtime::storage_parameter_key( + bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME + ) + .0, + ); + } + + #[test] + #[ignore] + fn no_stack_overflow_when_decoding_nested_call_during_dispatch() { + // this test is normally ignored, because it only makes sense to run it in release mode + + let mut ext: sp_io::TestExternalities = + SystemConfig::default().build_storage::().unwrap().into(); + ext.execute_with(|| { + let bridge = MILLAU_CHAIN_ID; + + let mut call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); + + for _i in 0..3000 { + call = Call::Sudo(pallet_sudo::Call::sudo { call: Box::new(call) }); + } + + let dispatch_weight = 500; + let dispatch_fee = ::WeightToFee::calc( + &dispatch_weight, + ); + assert!(dispatch_fee > 0); + + // create relayer account with minimal balance + let relayer_account: AccountId = [1u8; 32].into(); + let initial_amount = ExistentialDeposit::get(); + let _ = as Currency>::deposit_creating( + &relayer_account, + initial_amount, + ); + + // create dispatch account with minimal balance + dispatch fee + let dispatch_account = derive_account_id::< + ::SourceChainAccountId, + >(bridge, SourceAccount::Root); + let dispatch_account = + ::AccountIdConverter::convert( + dispatch_account, + ); + let _ = as Currency>::deposit_creating( + &dispatch_account, + initial_amount + dispatch_fee, + ); + + // dispatch message with intention to pay dispatch fee at the target chain + // + // this is where the stack overflow has happened before the fix has been applied + FromMillauMessageDispatch::dispatch( + &relayer_account, + DispatchMessage { + key: MessageKey { lane_id: Default::default(), nonce: 0 }, + data: DispatchMessageData { + payload: Ok(FromBridgedChainMessagePayload:: { + spec_version: VERSION.spec_version, + weight: dispatch_weight, + origin: CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: FromBridgedChainEncodedMessageCall::new(call.encode()), + }), + fee: 1, + }, + }, + ); + }); + } } diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 332a3387ac69..20a9aeb28c0d 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -16,11 +16,14 @@ //! Parachains support in Rialto runtime. -use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots}; +use crate::{ + AccountId, Babe, Balance, Balances, BlockNumber, Call, Event, Origin, Registrar, Runtime, + Slots, UncheckedExtrinsic, +}; use frame_support::{parameter_types, weights::Weight}; use frame_system::EnsureRoot; -use polkadot_primitives::v1::ValidatorIndex; +use polkadot_primitives::v2::ValidatorIndex; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp, @@ -29,6 +32,15 @@ use polkadot_runtime_parachains::{ paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump, }; +use sp_runtime::transaction_validity::TransactionPriority; + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + Call: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = Call; +} /// Special `RewardValidators` that does nothing ;) pub struct RewardValidators; @@ -49,6 +61,7 @@ impl parachains_hrmp::Config for Runtime { type Event = Event; type Origin = Origin; type Currency = Balances; + type WeightInfo = parachains_hrmp::TestWeightInfo; } impl parachains_inclusion::Config for Runtime { @@ -65,10 +78,15 @@ impl parachains_initializer::Config for Runtime { impl parachains_origin::Config for Runtime {} +parameter_types! { + pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); +} + impl parachains_paras::Config for Runtime { - type Origin = Origin; type Event = Event; type WeightInfo = parachains_paras::TestWeightInfo; + type UnsignedPriority = ParasUnsignedPriority; + type NextSessionRotation = Babe; } impl parachains_paras_inherent::Config for Runtime { @@ -90,6 +108,7 @@ impl parachains_ump::Config for Runtime { type UmpSink = (); type FirstMessageFactorPercent = FirstMessageFactorPercent; type ExecuteOverweightOrigin = EnsureRoot; + type WeightInfo = parachains_ump::TestWeightInfo; } // required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing @@ -120,6 +139,7 @@ impl slots::Config for Runtime { type LeasePeriod = LeasePeriod; type WeightInfo = slots::TestWeightInfo; type LeaseOffset = (); + type ForceOrigin = EnsureRoot; } impl paras_sudo_wrapper::Config for Runtime {} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 0ae642ba5589..abd84364ce2c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -2,16 +2,17 @@ name = "bridge-runtime-common" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +static_assertions = { version = "1.1", optional = true } # Bridge dependencies @@ -25,12 +26,16 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [features] default = ["std"] @@ -40,12 +45,14 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "frame-system/std", "hash-db/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-transaction-payment/std", "scale-info/std", + "sp-api/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", @@ -54,7 +61,12 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", + "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "sp-state-machine", + "sp-version", +] +integrity-test = [ + "static_assertions", ] diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index 38a47bfdcc9d..5f2298cd787d 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -62,8 +62,11 @@ corresponding chain. There is single exception, though (it may be changed in the This trait represents this chain from bridge point of view. Let's review every method of this trait: -- `ThisChainWithMessages::is_outbound_lane_enabled`: is used to check whether given lane accepts - outbound messages. +- `ThisChainWithMessages::is_message_accepted`: is used to check whether given lane accepts + messages. The send-message origin is passed to the function, so you may e.g. verify that only + given pallet is able to send messages over selected lane. **IMPORTANT**: if you assume that the + message must be paid by the sender, you must ensure that the sender origin has linked the account + for paying message delivery and dispatch fee. - `ThisChainWithMessages::maximal_pending_messages_at_outbound_lane`: you should return maximal number of pending (undelivered) messages from this function. Returning small values would require diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs new file mode 100644 index 000000000000..ab517566a0fe --- /dev/null +++ b/bin/runtime-common/src/integrity.rs @@ -0,0 +1,331 @@ +// 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/lib.rs b/bin/runtime-common/src/lib.rs index 66f2c6c3a01f..c7fb98aba767 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -21,3 +21,6 @@ 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 b34cbb85540d..250b68ceffe2 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -22,7 +22,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_messages::{ - source_chain::{LaneMessageVerifier, Sender}, + source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; @@ -30,7 +30,7 @@ use bp_runtime::{ messages::{DispatchFeePayment, MessageDispatchResult}, ChainId, Size, StorageProofChecker, }; -use codec::{Decode, Encode}; +use codec::{Decode, DecodeLimit, Encode}; use frame_support::{ traits::{Currency, ExistenceRequirement}, weights::{Weight, WeightToFeePolynomial}, @@ -70,6 +70,7 @@ pub trait MessageBridge { /// 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>; } @@ -110,11 +111,13 @@ pub struct MessageTransaction { /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { + /// Call origin on the chain. + type Origin; /// Call type on the chain. type Call: Encode + Decode; - /// Are we accepting any messages to the given lane? - fn is_outbound_lane_enabled(lane: &LaneId) -> bool; + /// Do we accept message sent by given origin to given lane? + fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool; /// Maximal number of pending (not yet delivered) messages at This chain. /// @@ -172,11 +175,13 @@ pub type SignatureOf = ::Signature; pub type WeightOf = ::Weight; /// Type of balances that is used on the chain. pub type BalanceOf = ::Balance; +/// Type of origin that is used on the chain. +pub type OriginOf = ::Origin; /// Type of call that is used on this chain. pub type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). -type RawStorageProof = Vec>; +pub type RawStorageProof = Vec>; /// Compute fee of transaction at runtime where regular transaction payment pallet is being used. /// @@ -269,7 +274,8 @@ pub mod source { pub struct FromThisChainMessageVerifier(PhantomData); /// The error message returned from LaneMessageVerifier when outbound lane is disabled. - pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; + pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = + "The outbound message lane has rejected the message."; /// The error message returned from LaneMessageVerifier when too many pending messages at the /// lane. pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; @@ -280,26 +286,30 @@ pub mod source { impl LaneMessageVerifier< + OriginOf>, AccountIdOf>, FromThisChainMessagePayload, BalanceOf>, > for FromThisChainMessageVerifier where B: MessageBridge, + // matches requirements from the `frame_system::Config::Origin` + OriginOf>: Clone + + Into>>, OriginOf>>>, AccountIdOf>: PartialEq + Clone, { type Error = &'static str; fn verify_message( - submitter: &Sender>>, + submitter: &OriginOf>, delivery_and_dispatch_fee: &BalanceOf>, lane: &LaneId, lane_outbound_data: &OutboundLaneData, payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { // reject message if lane is blocked - if !ThisChain::::is_outbound_lane_enabled(lane) { - return Err(OUTBOUND_LANE_DISABLED) + if !ThisChain::::is_message_accepted(submitter, lane) { + return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) } // reject message if there are too many pending messages at this lane @@ -313,11 +323,29 @@ pub mod source { // Do the dispatch-specific check. We assume that the target chain uses // `Dispatch`, so we verify the message accordingly. - pallet_bridge_dispatch::verify_message_origin(submitter, payload) - .map_err(|_| BAD_ORIGIN)?; + let raw_origin_or_err: Result< + frame_system::RawOrigin>>, + OriginOf>, + > = submitter.clone().into(); + match raw_origin_or_err { + Ok(raw_origin) => + pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) + .map(drop) + .map_err(|_| BAD_ORIGIN)?, + Err(_) => { + // so what it means that we've failed to convert origin to the + // `frame_system::RawOrigin`? now it means that the custom pallet origin has + // been used to send the message. Do we need to verify it? The answer is no, + // because pallet may craft any origin (e.g. root) && we can't verify whether it + // is valid, or not. + }, + }; - let minimal_fee_in_this_tokens = - estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; + let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( + payload, + B::RELAYER_FEE_PERCENT, + None, + )?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { @@ -371,6 +399,7 @@ pub mod source { 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 // @@ -391,8 +420,11 @@ pub mod source { 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) - .checked_add(&confirmation_transaction_fee); + 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 @@ -428,7 +460,7 @@ pub mod source { // Messages delivery proof is just proof of single storage key read => any error // is fatal. let storage_inbound_lane_data_key = - pallet_bridge_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); + 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")? @@ -513,7 +545,11 @@ pub mod target { for Result { fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) + DecodedCall::decode_with_depth_limit( + sp_api::MAX_EXTRINSIC_DEPTH, + &mut &encoded_call.encoded_call[..], + ) + .map_err(drop) } } @@ -674,16 +710,15 @@ pub mod target { B: MessageBridge, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { - let storage_outbound_lane_data_key = - pallet_bridge_messages::storage_keys::outbound_lane_data_key( - B::BRIDGED_MESSAGES_PALLET_NAME, - lane_id, - ); + let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + lane_id, + ); self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_bridge_messages::storage_keys::message_key( + let storage_message_key = bp_messages::storage_keys::message_key( B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, message_key.nonce, @@ -799,8 +834,12 @@ mod tests { fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, + bridged_to_this_conversion_rate_override: Option, ) -> ThisChainBalance { - ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) + 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) } } @@ -818,7 +857,10 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { + fn bridged_balance_to_this_balance( + _this_balance: ThisChainBalance, + _bridged_to_this_conversion_rate_override: Option, + ) -> BridgedChainBalance { unreachable!() } } @@ -836,6 +878,18 @@ mod tests { #[codec(index = 84)] Mint, } + #[derive(Clone, Debug)] + struct ThisChainOrigin(Result, ()>); + + impl From + for Result, ThisChainOrigin> + { + fn from( + origin: ThisChainOrigin, + ) -> Result, ThisChainOrigin> { + origin.clone().0.map_err(|_| origin) + } + } #[derive(Debug, PartialEq, Decode, Encode)] struct BridgedChainAccountId(u32); @@ -845,6 +899,18 @@ mod tests { struct BridgedChainSignature(u32); #[derive(Debug, PartialEq, Decode, Encode)] enum BridgedChainCall {} + #[derive(Clone, Debug)] + struct BridgedChainOrigin; + + impl From + for Result, BridgedChainOrigin> + { + fn from( + _origin: BridgedChainOrigin, + ) -> Result, BridgedChainOrigin> { + unreachable!() + } + } macro_rules! impl_wrapped_balance { ($name:ident) => { @@ -922,9 +988,10 @@ mod tests { } impl ThisChainWithMessages for ThisChain { + type Origin = ThisChainOrigin; type Call = ThisChainCall; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { lane == TEST_LANE_ID } @@ -982,9 +1049,10 @@ mod tests { } impl ThisChainWithMessages for BridgedChain { + type Origin = BridgedChainOrigin; type Call = BridgedChainCall; - fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool { unreachable!() } @@ -1096,6 +1164,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ), Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); @@ -1107,6 +1176,7 @@ mod tests { 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", @@ -1121,7 +1191,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1130,7 +1200,7 @@ mod tests { Err(source::TOO_LOW_FEE) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1153,7 +1223,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1163,7 +1233,7 @@ mod tests { ); assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::None, + &ThisChainOrigin(Ok(frame_system::RawOrigin::None)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1172,7 +1242,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1195,7 +1265,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1204,7 +1274,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(1)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1217,13 +1287,13 @@ mod tests { fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), b"dsbl", &test_lane_outbound_data(), ®ular_outbound_message_payload(), ), - Err(source::OUTBOUND_LANE_DISABLED) + Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) ); } @@ -1231,7 +1301,7 @@ mod tests { fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &OutboundLaneData { @@ -1573,4 +1643,21 @@ mod tests { 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_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 217560e11434..7c9f50e8ea0c 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -20,162 +20,188 @@ #![cfg(feature = "runtime-benchmarks")] use crate::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BalanceOf, BridgedChain, HashOf, MessageBridge, ThisChain, + source::{FromBridgedChainMessagesDeliveryProof, FromThisChainMessagePayload}, + target::FromBridgedChainMessagesProof, + AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, RawStorageProof, + SignatureOf, SignerOf, ThisChain, }; -use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; -use bp_runtime::ChainId; +use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; +use bp_runtime::{messages::DispatchFeePayment, ChainId}; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; -use frame_support::weights::Weight; +use frame_support::{ + traits::Currency, + weights::{GetDispatchInfo, Weight}, +}; use pallet_bridge_messages::benchmarking::{ - MessageDeliveryProofParams, MessageProofParams, ProofSize, + MessageDeliveryProofParams, MessageParams, MessageProofParams, ProofSize, }; use sp_core::Hasher; -use sp_runtime::traits::Header; -use sp_std::prelude::*; -use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; +use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; +use sp_std::{fmt::Debug, prelude::*}; +use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_version::RuntimeVersion; -/// Generate ed25519 signature to be used in -/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. -/// -/// Returns public key of the signer and the signature itself. -pub fn ed25519_sign( - target_call: &impl Encode, - source_account_id: &impl Encode, - target_spec_version: u32, - source_chain_id: ChainId, - target_chain_id: ChainId, -) -> ([u8; 32], [u8; 64]) { +/// Return this chain account, used to dispatch message. +pub fn dispatch_account() -> AccountIdOf> +where + B: MessageBridge, + SignerOf>: + From + IdentifyAccount>>, +{ + let this_raw_public = PublicKey::from(&dispatch_account_secret()); + let this_public: SignerOf> = + sp_core::ed25519::Public::from_raw(this_raw_public.to_bytes()).into(); + this_public.into_account() +} + +/// Return public key of this chain account, used to dispatch message. +pub fn dispatch_account_secret() -> SecretKey { // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) - let target_secret = SecretKey::from_bytes(&[ + SecretKey::from_bytes(&[ 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, ]) - .expect("harcoded key is valid"); - let target_public: PublicKey = (&target_secret).into(); - - let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; - target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); - target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); - let target_pair = - ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); + .expect("harcoded key is valid") +} - let signature_message = pallet_bridge_dispatch::account_ownership_digest( - target_call, - source_account_id, - target_spec_version, - source_chain_id, - target_chain_id, - ); - let target_origin_signature = target_pair - .try_sign(&signature_message) - .expect("Ed25519 try_sign should not fail in benchmarks"); +/// Prepare outbound message for the `send_message` call. +pub fn prepare_outbound_message( + params: MessageParams>>, +) -> FromThisChainMessagePayload +where + B: MessageBridge, + BalanceOf>: From, +{ + let message_payload = vec![0; params.size as usize]; + let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount(params.sender_account); - (target_public.to_bytes(), target_origin_signature.to_bytes()) + FromThisChainMessagePayload:: { + spec_version: 0, + weight: params.size as _, + origin: dispatch_origin, + call: message_payload, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + } } /// Prepare proof of messages for the `receive_messages_proof` call. -pub fn prepare_message_proof( +/// +/// In addition to returning valid messages proof, environment is prepared to verify this message +/// proof. +pub fn prepare_message_proof( params: MessageProofParams, - make_bridged_message_storage_key: MM, - make_bridged_outbound_lane_data_key: ML, - make_bridged_header: MH, - message_dispatch_weight: Weight, - message_payload: MessagePayload, + version: &RuntimeVersion, + endow_amount: BalanceOf>, ) -> (FromBridgedChainMessagesProof>>, Weight) where + R: frame_system::Config>> + + pallet_balances::Config>> + + pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain
, B: MessageBridge, - H: Hasher, - R: pallet_bridge_grandpa::Config, + BI: 'static, FI: 'static, - ::Hash: Into>>, - MM: Fn(MessageKey) -> Vec, - ML: Fn(LaneId) -> Vec, - MH: Fn(H::Out) -> ::Header, + BH: Header>>, + BHH: Hasher>>, + AccountIdOf>: PartialEq + sp_std::fmt::Debug, + AccountIdOf>: From<[u8; 32]>, + BalanceOf>: Debug + MaybeSerializeDeserialize, + CallOf>: From> + GetDispatchInfo, + HashOf>: Copy + Default, + SignatureOf>: From, + SignerOf>: Clone + + From + + IdentifyAccount>>, { - // prepare Bridged chain storage with messages and (optionally) outbound lane state - let message_count = - params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; - let mut storage_keys = Vec::with_capacity(message_count as usize + 1); - let mut root = Default::default(); - let mut mdb = MemoryDB::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + // we'll be dispatching the same call at This chain + let remark = match params.size { + ProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }; + let call: CallOf> = frame_system::Call::remark { remark }.into(); + let call_weight = call.get_dispatch_info().weight; - // insert messages - for nonce in params.message_nonces.clone() { - let message_key = MessageKey { lane_id: params.lane, nonce }; - let message_data = MessageData { - fee: BalanceOf::>::from(0), - payload: message_payload.clone(), - }; - let storage_key = make_bridged_message_storage_key(message_key); - trie.insert(&storage_key, &message_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } + // message payload needs to be signed, because we use `TargetAccount` call origin + // (which is 'heaviest' to verify) + let bridged_account_id: AccountIdOf> = [0u8; 32].into(); + let (this_raw_public, this_raw_signature) = ed25519_sign( + &call, + &bridged_account_id, + version.spec_version, + B::BRIDGED_CHAIN_ID, + B::THIS_CHAIN_ID, + ); + let this_public: SignerOf> = + sp_core::ed25519::Public::from_raw(this_raw_public).into(); + let this_signature: SignatureOf> = + sp_core::ed25519::Signature::from_raw(this_raw_signature).into(); - // insert outbound lane state - if let Some(outbound_lane_data) = params.outbound_lane_data { - let storage_key = make_bridged_outbound_lane_data_key(params.lane); - trie.insert(&storage_key, &outbound_lane_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } + // if dispatch fee is paid at this chain, endow relayer account + if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { + assert_eq!(this_public.clone().into_account(), dispatch_account::()); + pallet_balances::Pallet::::make_free_balance_be( + &this_public.clone().into_account(), + endow_amount, + ); } - root = grow_trie(root, &mut mdb, params.size); - // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + // prepare message payload that is stored in the Bridged chain storage + let message_payload = bp_message_dispatch::MessagePayload { + spec_version: version.spec_version, + weight: call_weight, + origin: bp_message_dispatch::CallOrigin::< + AccountIdOf>, + SignerOf>, + SignatureOf>, + >::TargetAccount(bridged_account_id, this_public, this_signature), + dispatch_fee_payment: params.dispatch_fee_payment.clone(), + call: call.encode(), + } + .encode(); - // prepare Bridged chain header and insert it into the Substrate pallet - let bridged_header = make_bridged_header(root); - let bridged_header_hash = bridged_header.hash(); - pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + // finally - prepare storage proof and update environment + let (state_root, storage_proof) = + prepare_messages_storage_proof::(¶ms, message_payload); + let bridged_header_hash = insert_bridged_chain_header::(state_root); ( FromBridgedChainMessagesProof { - bridged_header_hash: bridged_header_hash.into(), + bridged_header_hash, storage_proof, lane: params.lane, nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - message_dispatch_weight - .checked_mul(message_count) + call_weight + .checked_mul( + params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1, + ) .expect("too many messages requested by benchmark"), ) } /// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. -pub fn prepare_message_delivery_proof( +pub fn prepare_message_delivery_proof( params: MessageDeliveryProofParams>>, - make_bridged_inbound_lane_data_key: ML, - make_bridged_header: MH, ) -> FromBridgedChainMessagesDeliveryProof>> where - B: MessageBridge, - H: Hasher, R: pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain
, FI: 'static, - ::Hash: Into>>, - ML: Fn(LaneId) -> Vec, - MH: Fn(H::Out) -> ::Header, + B: MessageBridge, + BH: Header>>, + BHH: Hasher>>, + HashOf>: Copy + Default, { // prepare Bridged chain storage with inbound lane state - let storage_key = make_bridged_inbound_lane_data_key(params.lane); + let storage_key = + storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane).0; let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -183,16 +209,14 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - // prepare Bridged chain header and insert it into the Substrate pallet - let bridged_header = make_bridged_header(root); - let bridged_header_hash = bridged_header.hash(); - pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + // finally insert header with given state root to our storage + let bridged_header_hash = insert_bridged_chain_header::(root); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), @@ -201,6 +225,127 @@ where } } +/// Prepare storage proof of given messages. +/// +/// Returns state trie root and nodes with prepared messages. +fn prepare_messages_storage_proof( + params: &MessageProofParams, + message_payload: MessagePayload, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, + BHH: Hasher>>, + HashOf>: Copy + Default, +{ + // prepare Bridged chain storage with messages and (optionally) outbound lane state + let message_count = + params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; + let mut storage_keys = Vec::with_capacity(message_count as usize + 1); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); + + // insert messages + for nonce in params.message_nonces.clone() { + let message_key = MessageKey { lane_id: params.lane, nonce }; + let message_data = MessageData { + fee: BalanceOf::>::from(0), + payload: message_payload.clone(), + }; + let storage_key = storage_keys::message_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &message_key.lane_id, + message_key.nonce, + ) + .0; + trie.insert(&storage_key, &message_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + + // insert outbound lane state + if let Some(ref outbound_lane_data) = params.outbound_lane_data { + let storage_key = + storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane) + .0; + trie.insert(&storage_key, &outbound_lane_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + } + root = grow_trie(root, &mut mdb, params.size); + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + (root, storage_proof) +} + +/// Insert Bridged chain header with given state root into storage of GRANDPA pallet at This chain. +fn insert_bridged_chain_header( + state_root: HashOf>, +) -> HashOf> +where + R: pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain
, + FI: 'static, + B: MessageBridge, + BH: Header>>, + HashOf>: Default, +{ + let bridged_header = BH::new( + Zero::zero(), + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + let bridged_header_hash = bridged_header.hash(); + pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + bridged_header_hash +} + +/// Generate ed25519 signature to be used in +/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. +/// +/// Returns public key of the signer and the signature itself. +fn ed25519_sign( + target_call: &impl Encode, + source_account_id: &impl Encode, + target_spec_version: u32, + source_chain_id: ChainId, + target_chain_id: ChainId, +) -> ([u8; 32], [u8; 64]) { + let target_secret = dispatch_account_secret(); + let target_public: PublicKey = (&target_secret).into(); + + let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; + target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); + target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); + let target_pair = + ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); + + let signature_message = pallet_bridge_dispatch::account_ownership_digest( + target_call, + source_account_id, + target_spec_version, + source_chain_id, + target_chain_id, + ); + let target_origin_signature = target_pair + .try_sign(&signature_message) + .expect("Ed25519 try_sign should not fail in benchmarks"); + + (target_public.to_bytes(), target_origin_signature.to_bytes()) +} + /// Populate trie with dummy keys+values until trie has at least given size. fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { let (iterations, leaf_size, minimal_trie_size) = match trie_size { @@ -213,7 +358,7 @@ fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: Proo loop { // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(mdb, &root, &mut proof_recorder) + record_all_keys::, _>(mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); @@ -221,9 +366,9 @@ fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: Proo return root } - let mut trie = TrieDBMut::::from_existing(mdb, &mut root) - .map_err(|_| "TrieDBMut::from_existing has failed") - .expect("TrieDBMut::from_existing should not fail in benchmarks"); + let mut trie = TrieDBMutV1::::from_existing(mdb, &mut root) + .map_err(|_| "TrieDBMutV1::from_existing has failed") + .expect("TrieDBMutV1::from_existing should not fail in benchmarks"); for _ in 0..iterations { trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) .map_err(|_| "TrieMut::insert has failed") diff --git a/ci.Dockerfile b/ci.Dockerfile index eec619a79831..b419f6be54d2 100644 --- a/ci.Dockerfile +++ b/ci.Dockerfile @@ -1,7 +1,7 @@ # This file is a "runtime" part from a builder-pattern in Dockerfile, it's used in CI. # The only different part is that the compilation happens externally, # so COPY has a different source. -FROM ubuntu:20.04 +FROM docker.io/library/ubuntu:20.04 # show backtraces ENV RUST_BACKTRACE 1 diff --git a/deny.toml b/deny.toml index d22897182af2..e5281e0e8491 100644 --- a/deny.toml +++ b/deny.toml @@ -48,21 +48,17 @@ notice = "warn" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ - # yaml-rust < clap. Not feasible to upgrade and also not possible to trigger in practice. - "RUSTSEC-2018-0006", "RUSTSEC-2020-0070", # Comes from honggfuzz via storage-proof-fuzzer: 'memmap' "RUSTSEC-2020-0077", - # Comes from time: 'stweb' (will be fixed in upcoming time 0.3) - "RUSTSEC-2020-0056", # net2 (origin: Substrate RPC crates) "RUSTSEC-2020-0016", - # Wasmtime (origin: Substrate executor crates) - "RUSTSEC-2021-0110", # time (origin: Substrate RPC + benchmarking crates) "RUSTSEC-2020-0071", # chrono (origin: Substrate benchmarking + cli + ...) "RUSTSEC-2020-0159", + # lru 0.6.6 (origin: libp2p) + "RUSTSEC-2021-0130", ] # Threshold for security vulnerabilities, any vulnerability with a CVSS score # lower than the range specified will be ignored. Note that ignored advisories diff --git a/deployments/BridgeDeps.Dockerfile b/deployments/BridgeDeps.Dockerfile index a18a94a7155a..6d3b3fa17048 100644 --- a/deployments/BridgeDeps.Dockerfile +++ b/deployments/BridgeDeps.Dockerfile @@ -2,7 +2,7 @@ # # This image is meant to be used as a building block when building images for # the various components in the bridge repo, such as nodes and relayers. -FROM ubuntu:20.04 +FROM docker.io/library/ubuntu:20.04 ENV LAST_DEPS_UPDATE 2021-04-01 ENV DEBIAN_FRONTEND=noninteractive diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json index 32f3e53d6671..abce8bbc29ae 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/relay-millau-to-rialto-messages-dashboard.json @@ -64,11 +64,18 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_00000000_best_block_numbers{type=~\"target|target_at_source\"}, \"type\", \"At Rialto\", \"type\", \"target\"), \"type\", \"At Millau\", \"type\", \"target_at_source\")", + "expr": "Millau_to_Rialto_MessageLane_00000000_best_target_block_number", "instant": false, "interval": "", - "legendFormat": "{{type}}", + "legendFormat": "At Rialto", "refId": "A" + }, + { + "expr": "Millau_to_Rialto_MessageLane_00000000_best_target_at_source_block_number", + "instant": false, + "interval": "", + "legendFormat": "At Millau", + "refId": "B" } ], "thresholds": [], @@ -158,10 +165,16 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Millau_to_Rialto_MessageLane_00000000_best_block_numbers{type=~\"source|source_at_target\"}, \"type\", \"At Millau\", \"type\", \"source\"), \"type\", \"At Rialto\", \"type\", \"source_at_target\")", + "expr": "Millau_to_Rialto_MessageLane_00000000_best_source_block_number", "interval": "", - "legendFormat": "{{type}}", + "legendFormat": "At Millau", "refId": "A" + }, + { + "expr": "Millau_to_Rialto_MessageLane_00000000_best_source_at_target_block_number", + "interval": "", + "legendFormat": "At Rialto", + "refId": "B" } ], "thresholds": [], @@ -531,7 +544,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_00000000_lane_state_nonces{type=\"target_latest_received\"}[1m])", + "expr": "increase(Millau_to_Rialto_MessageLane_00000000_lane_state_nonces{type=\"target_latest_received\"}[1m]) OR on() vector(0)", "interval": "", "legendFormat": "Messages delivered to Rialto in last 1m", "refId": "B" @@ -954,7 +967,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_00000001_lane_state_nonces{type=\"target_latest_received\"}[10m])", + "expr": "increase(Millau_to_Rialto_MessageLane_00000001_lane_state_nonces{type=\"target_latest_received\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes", @@ -1097,7 +1110,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_00000001_lane_state_nonces{type=\"source_latest_confirmed\"}[10m])", + "expr": "increase(Millau_to_Rialto_MessageLane_00000001_lane_state_nonces{type=\"source_latest_confirmed\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "", @@ -1241,7 +1254,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"target_latest_received\"}[20m])", + "expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"target_latest_received\"}[20m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes", @@ -1349,7 +1362,7 @@ "refId": "A" }, { - "expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"source_latest_confirmed\"}[10m])", + "expr": "increase(Millau_to_Rialto_MessageLane_73776170_lane_state_nonces{type=\"source_latest_confirmed\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "", diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json index eaca8610aec7..4e3d314a3f45 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/relay-rialto-to-millau-messages-dashboard.json @@ -64,11 +64,18 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_00000000_best_block_numbers{type=~\"target|target_at_source\"}, \"type\", \"At Millau\", \"type\", \"target\"), \"type\", \"At Rialto\", \"type\", \"target_at_source\")", + "expr": "Rialto_to_Millau_MessageLane_00000000_best_target_block_number", "instant": false, "interval": "", - "legendFormat": "{{type}}", + "legendFormat": "At Millau", "refId": "A" + }, + { + "expr": "Rialto_to_Millau_MessageLane_00000000_best_target_at_source_block_number", + "instant": false, + "interval": "", + "legendFormat": "At Rialto", + "refId": "B" } ], "thresholds": [], @@ -158,10 +165,16 @@ "steppedLine": false, "targets": [ { - "expr": "label_replace(label_replace(Rialto_to_Millau_MessageLane_00000000_best_block_numbers{type=~\"source|source_at_target\"}, \"type\", \"At Rialto\", \"type\", \"source\"), \"type\", \"At Millau\", \"type\", \"source_at_target\")", + "expr": "Rialto_to_Millau_MessageLane_00000000_best_source_block_number", "interval": "", - "legendFormat": "{{type}}", + "legendFormat": "At Rialto", "refId": "A" + }, + { + "expr": "Rialto_to_Millau_MessageLane_00000000_best_source_at_target_block_number", + "interval": "", + "legendFormat": "At Millau", + "refId": "B" } ], "thresholds": [], @@ -522,7 +535,7 @@ "refId": "A" }, { - "expr": "increase(Rialto_to_Millau_MessageLane_00000000_lane_state_nonces{type=\"target_latest_received\"}[1m])", + "expr": "increase(Rialto_to_Millau_MessageLane_00000000_lane_state_nonces{type=\"target_latest_received\"}[1m]) OR on() vector(0)", "interval": "", "legendFormat": "Messages delivered to Millau in last 1m", "refId": "B" @@ -945,7 +958,7 @@ "refId": "A" }, { - "expr": "increase(Rialto_to_Millau_MessageLane_00000001_lane_state_nonces{type=\"target_latest_received\"}[10m])", + "expr": "increase(Rialto_to_Millau_MessageLane_00000001_lane_state_nonces{type=\"target_latest_received\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "Messages generated in last 5 minutes", @@ -1089,7 +1102,7 @@ "refId": "A" }, { - "expr": "increase(Rialto_to_Millau_MessageLane_00000001_lane_state_nonces{type=\"source_latest_confirmed\"}[10m])", + "expr": "increase(Rialto_to_Millau_MessageLane_00000001_lane_state_nonces{type=\"source_latest_confirmed\"}[10m]) OR on() vector(0)", "hide": true, "interval": "", "legendFormat": "", diff --git a/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json b/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json index 5280da748502..225e46fae3ac 100644 --- a/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json +++ b/deployments/bridges/rialto-millau/dashboard/grafana/rialto-millau-maintenance-dashboard.json @@ -15,7 +15,6 @@ "editable": true, "gnetId": null, "graphTooltip": 0, - "id": 9, "links": [], "panels": [ { @@ -25,7 +24,9 @@ "dashes": false, "datasource": "Prometheus", "fieldConfig": { - "defaults": {}, + "defaults": { + "custom": {} + }, "overrides": [] }, "fill": 1, @@ -54,7 +55,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.3", + "pluginVersion": "7.1.3", "pointradius": 2, "points": false, "renderer": "flot", @@ -129,7 +130,9 @@ "dashes": false, "datasource": "Prometheus", "fieldConfig": { - "defaults": {}, + "defaults": { + "custom": {} + }, "overrides": [] }, "fill": 1, @@ -158,7 +161,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.3", + "pluginVersion": "7.1.3", "pointradius": 2, "points": false, "renderer": "flot", @@ -169,7 +172,7 @@ "targets": [ { "exemplar": true, - "expr": "kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'}", + "expr": "polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'}", "interval": "", "legendFormat": "Outside of runtime (actually Polkadot -> Kusama)", "refId": "A" @@ -233,7 +236,9 @@ "dashes": false, "datasource": "Prometheus", "fieldConfig": { - "defaults": {}, + "defaults": { + "custom": {} + }, "overrides": [] }, "fill": 1, @@ -262,7 +267,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.3", + "pluginVersion": "7.1.3", "pointradius": 2, "points": false, "renderer": "flot", @@ -337,7 +342,9 @@ "dashes": false, "datasource": "Prometheus", "fieldConfig": { - "defaults": {}, + "defaults": { + "custom": {} + }, "overrides": [] }, "fill": 1, @@ -366,7 +373,7 @@ "alertThreshold": true }, "percentage": false, - "pluginVersion": "7.5.3", + "pluginVersion": "7.1.3", "pointradius": 2, "points": false, "renderer": "flot", @@ -377,7 +384,7 @@ "targets": [ { "exemplar": true, - "expr": "polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'}", + "expr": "kusama_to_base_conversion_rate{instance='relay-millau-rialto:9616'} / polkadot_to_base_conversion_rate{instance='relay-millau-rialto:9616'}", "interval": "", "legendFormat": "Outside of runtime (actually Kusama -> Polkadot)", "refId": "A" @@ -433,22 +440,620 @@ "align": false, "alignLevel": null } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1000 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + }, + { + "evaluator": { + "params": [ + 1000 + ], + "type": "lt" + }, + "operator": { + "type": "or" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "At-Rialto relay balances are too low", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "at_Rialto_relay_balance", + "interval": "", + "legendFormat": "Relay account balance", + "refId": "A" + }, + { + "expr": "at_Rialto_messages_pallet_owner_balance", + "interval": "", + "legendFormat": "Messages pallet owner balance", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "lt", + "value": 1000 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Rialto relay balances", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1000 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + }, + { + "evaluator": { + "params": [ + 1000 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "At-Millau relay balances are too low", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "hiddenSeries": false, + "id": 9, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "at_Millau_relay_balance", + "interval": "", + "legendFormat": "Relay account balance", + "refId": "A" + }, + { + "expr": "at_Millau_messages_pallet_owner_balance", + "interval": "", + "legendFormat": "Messages pallet owner balance", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "lt", + "value": 1000 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Millau relay balances", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Whether with-Rialto-grandpa-pallet and Rialto itself are on different forks alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "Rialto_to_Millau_MessageLane_00000000_is_source_and_source_at_target_using_different_forks", + "interval": "", + "legendFormat": "On different forks?", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Whether with-Rialto-grandpa-pallet and Rialto itself are on different forks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Whether with-Rialto-grandpa-pallet and Rialto itself are on different forks alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "Millau_to_Rialto_MessageLane_00000000_is_source_and_source_at_target_using_different_forks", + "interval": "", + "legendFormat": "On different forks?", + "refId": "A" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Whether with-Millau-grandpa-pallet and Millau itself are on different forks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } } ], "refresh": "10s", - "schemaVersion": 27, + "schemaVersion": 26, "style": "dark", "tags": [], "templating": { "list": [] }, "time": { - "from": "now-1h", + "from": "now-15m", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Rialto+Millau maintenance dashboard", "uid": "7AuyrjlMz", - "version": 2 + "version": 1 } diff --git a/deployments/bridges/rialto-millau/docker-compose.yml b/deployments/bridges/rialto-millau/docker-compose.yml index 1ff93869de1c..5d774a578025 100644 --- a/deployments/bridges/rialto-millau/docker-compose.yml +++ b/deployments/bridges/rialto-millau/docker-compose.yml @@ -108,6 +108,7 @@ services: LETSENCRYPT_EMAIL: admin@parity.io volumes: - ./bridges/rialto-millau/dashboard/grafana:/etc/grafana/dashboards/rialto-millau:ro + - ./networks/dashboard/grafana/beefy-dashboard.json:/etc/grafana/dashboards/beefy.json prometheus-metrics: volumes: diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-messages-millau-to-rialto-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-messages-millau-to-rialto-entrypoint.sh index 758dce2515aa..743cc47f07e7 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-messages-millau-to-rialto-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-messages-millau-to-rialto-entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -xeu -sleep 60 -curl -v http://millau-node-bob:9933/health -curl -v http://rialto-node-bob:9933/health +sleep 15 MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000} diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-messages-rialto-to-millau-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-messages-rialto-to-millau-entrypoint.sh index e0731e9058d1..2b536dbd8171 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-messages-rialto-to-millau-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-messages-rialto-to-millau-entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -xeu -sleep 60 -curl -v http://millau-node-bob:9933/health -curl -v http://rialto-node-bob:9933/health +sleep 15 MESSAGE_LANE=${MSG_EXCHANGE_GEN_LANE:-00000000} diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-millau-generator-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-millau-generator-entrypoint.sh index b8d051a13122..e20b3da7df80 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-millau-generator-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-millau-generator-entrypoint.sh @@ -34,16 +34,13 @@ LARGE_MESSAGES_TIME=0 # start sending message packs in a hour BUNCH_OF_MESSAGES_TIME=3600 -# give conversion rate updater some time to update Millau->Rialto conversion rate in Rialto -# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value) -sleep 180 - while true do rand_sleep echo "Sending Remark from Rialto to Millau using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ remark @@ -51,6 +48,7 @@ do echo "Sending Remark from Rialto to Millau using Target Origin using secondary lane: $SECONDARY_MESSAGE_LANE" $SEND_MESSAGE \ --lane $SECONDARY_MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-fee-payment at-target-chain \ remark @@ -60,6 +58,7 @@ do echo "Sending Transfer from Rialto to Millau using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ transfer \ --amount 1000000000 \ @@ -69,6 +68,7 @@ do echo "Sending Remark from Rialto to Millau using Source Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Source \ remark @@ -76,6 +76,7 @@ do echo "Sending Transfer from Rialto to Millau using Source Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Source \ transfer \ --amount 1000000000 \ @@ -89,6 +90,7 @@ do echo "Sending Maximal Size Remark from Rialto to Millau using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ remark \ --remark-size=max @@ -97,6 +99,7 @@ do echo "Sending Maximal Dispatch Weight Remark from Rialto to Millau using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-weight=max \ remark @@ -105,6 +108,7 @@ do echo "Sending Maximal Size and Dispatch Weight Remark from Rialto to Millau using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-weight=max \ remark \ @@ -116,10 +120,21 @@ do if [ $SECONDS -ge $BUNCH_OF_MESSAGES_TIME ]; then BUNCH_OF_MESSAGES_TIME=$((SECONDS + 7200)) + SEND_MESSAGE_OUTPUT=`$SEND_MESSAGE --lane $MESSAGE_LANE --conversion-rate-override metric --origin Target remark 2>&1` + echo $SEND_MESSAGE_OUTPUT + ACTUAL_CONVERSION_RATE_REGEX="conversion rate override: ([0-9\.]+)" + if [[ $SEND_MESSAGE_OUTPUT =~ $ACTUAL_CONVERSION_RATE_REGEX ]]; then + ACTUAL_CONVERSION_RATE=${BASH_REMATCH[1]} + else + echo "Unable to find conversion rate in send-message output" + exit 1 + fi + for i in $(seq 1 $MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE); do $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override $ACTUAL_CONVERSION_RATE \ --origin Target \ remark done diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-generator-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-generator-entrypoint.sh index 0365ebe1d8b4..a8e032bbdfdd 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-generator-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-generator-entrypoint.sh @@ -34,16 +34,13 @@ LARGE_MESSAGES_TIME=0 # start sending message packs in a hour BUNCH_OF_MESSAGES_TIME=3600 -# give conversion rate updater some time to update Rialto->Millau conversion rate in Millau -# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value) -sleep 180 - while true do rand_sleep echo "Sending Remark from Millau to Rialto using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ remark @@ -51,6 +48,7 @@ do echo "Sending Remark from Millau to Rialto using Target Origin using secondary lane: $SECONDARY_MESSAGE_LANE" $SEND_MESSAGE \ --lane $SECONDARY_MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-fee-payment at-target-chain \ remark @@ -60,6 +58,7 @@ do echo "Sending Transfer from Millau to Rialto using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ transfer \ --amount 1000000000 \ @@ -69,6 +68,7 @@ do echo "Sending Remark from Millau to Rialto using Source Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Source \ remark @@ -76,6 +76,7 @@ do echo "Sending Transfer from Millau to Rialto using Source Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Source \ transfer \ --amount 1000000000 \ @@ -89,6 +90,7 @@ do echo "Sending Maximal Size Remark from Millau to Rialto using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ remark \ --remark-size=max @@ -97,6 +99,7 @@ do echo "Sending Maximal Dispatch Weight Remark from Millau to Rialto using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-weight=max \ remark @@ -105,6 +108,7 @@ do echo "Sending Maximal Size and Dispatch Weight Remark from Millau to Rialto using Target Origin" $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override metric \ --origin Target \ --dispatch-weight=max \ remark \ @@ -116,10 +120,21 @@ do if [ $SECONDS -ge $BUNCH_OF_MESSAGES_TIME ]; then BUNCH_OF_MESSAGES_TIME=$((SECONDS + 7200)) - for i in $(seq 1 $MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE); + SEND_MESSAGE_OUTPUT=`$SEND_MESSAGE --lane $MESSAGE_LANE --conversion-rate-override metric --origin Target remark 2>&1` + echo $SEND_MESSAGE_OUTPUT + ACTUAL_CONVERSION_RATE_REGEX="conversion rate override: ([0-9\.]+)" + if [[ $SEND_MESSAGE_OUTPUT =~ $ACTUAL_CONVERSION_RATE_REGEX ]]; then + ACTUAL_CONVERSION_RATE=${BASH_REMATCH[1]} + else + echo "Unable to find conversion rate in send-message output" + exit 1 + fi + + for i in $(seq 2 $MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE); do $SEND_MESSAGE \ --lane $MESSAGE_LANE \ + --conversion-rate-override $ACTUAL_CONVERSION_RATE \ --origin Target \ remark done diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-resubmitter-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-resubmitter-entrypoint.sh index ca4c9f03a8bb..068560e15021 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-resubmitter-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-messages-to-rialto-resubmitter-entrypoint.sh @@ -1,8 +1,7 @@ #!/bin/bash set -xeu -sleep 20 -curl -v http://millau-node-alice:9933/health +sleep 15 # //Dave is signing Millau -> Rialto message-send transactions, which are causing problems. # diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh index c87591fb6dbb..bab0e1c4af3e 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-millau-rialto-entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -xeu -sleep 60 -curl -v http://millau-node-alice:9933/health -curl -v http://rialto-node-alice:9933/health +sleep 15 /home/user/substrate-relay init-bridge millau-to-rialto \ --source-host millau-node-alice \ @@ -27,10 +25,12 @@ sleep 6 --millau-port 9944 \ --millau-signer //Charlie \ --millau-messages-pallet-owner=//RialtoMessagesOwner \ + --millau-transactions-mortality=64 \ --rialto-host rialto-node-alice \ --rialto-port 9944 \ --rialto-signer //Charlie \ --rialto-messages-pallet-owner=//MillauMessagesOwner \ + --rialto-transactions-mortality=64 \ --lane=00000000 \ --lane=73776170 \ --prometheus-host=0.0.0.0 diff --git a/deployments/bridges/rialto-millau/entrypoints/relay-token-swap-generator-entrypoint.sh b/deployments/bridges/rialto-millau/entrypoints/relay-token-swap-generator-entrypoint.sh index 95bbe1e38fb2..010c0572d50e 100755 --- a/deployments/bridges/rialto-millau/entrypoints/relay-token-swap-generator-entrypoint.sh +++ b/deployments/bridges/rialto-millau/entrypoints/relay-token-swap-generator-entrypoint.sh @@ -23,10 +23,6 @@ rand_sleep() { echo "Woke up at $NOW" } -# give conversion rate updater some time to update Rialto->Millau conversion rate in Millau -# (initially rate=1 and rational relayer won't deliver any messages if it'll be changed to larger value) -sleep 180 - while true do rand_sleep @@ -42,6 +38,8 @@ do --target-port $TARGET_PORT \ --target-signer //WithMillauTokenSwap \ --target-balance 200000 \ + --target-to-source-conversion-rate-override metric \ + --source-to-target-conversion-rate-override metric \ lock-until-block \ --blocks-before-expire 32 done diff --git a/deployments/bridges/westend-millau/dashboard/grafana/relay-westend-to-millau-headers-dashboard.json b/deployments/bridges/westend-millau/dashboard/grafana/relay-westend-to-millau-headers-dashboard.json index 1a3603512fdf..682ac2c77867 100644 --- a/deployments/bridges/westend-millau/dashboard/grafana/relay-westend-to-millau-headers-dashboard.json +++ b/deployments/bridges/westend-millau/dashboard/grafana/relay-westend-to-millau-headers-dashboard.json @@ -99,7 +99,7 @@ "steppedLine": false, "targets": [ { - "expr": "max(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}) - max(Westend_to_Millau_Sync_best_block_numbers{node=\"target\"})", + "expr": "max(Westend_to_Millau_Sync_best_source_block_number) - max(Westend_to_Millau_Sync_best_source_at_target_block_number)", "format": "table", "instant": false, "interval": "", @@ -237,7 +237,7 @@ "steppedLine": false, "targets": [ { - "expr": "max_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[10m])-min_over_time(Westend_to_Millau_Sync_best_block_numbers{node=\"source\"}[10m])", + "expr": "max_over_time(Westend_to_Millau_Sync_best_source_block_number[10m])-min_over_time(Westend_to_Millau_Sync_best_source_block_number[10m])", "interval": "", "legendFormat": "Number of new Headers on Westend (Last 10 Mins)", "refId": "A" @@ -341,13 +341,22 @@ "pluginVersion": "7.1.3", "targets": [ { - "expr": "Westend_to_Millau_Sync_best_block_numbers", + "expr": "Westend_to_Millau_Sync_best_source_block_number", "format": "time_series", "instant": true, "interval": "", "intervalFactor": 1, - "legendFormat": "Best Known Header on {{node}} Node", + "legendFormat": "Best Known Westend Header at Westend", "refId": "A" + }, + { + "expr": "Westend_to_Millau_Sync_best_source_at_target_block_number", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Best Known Westend Header at Millau", + "refId": "B" } ], "timeFrom": null, @@ -513,61 +522,139 @@ "type": "gauge" }, { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Whether with-Westend-grandpa-pallet and Westend itself are on different forks alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, "datasource": "Prometheus", - "description": "", "fieldConfig": { "defaults": { - "custom": {}, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } + "custom": {} }, "overrides": [] }, + "fill": 1, + "fillGradient": 0, "gridPos": { "h": 10, "w": 12, "x": 0, "y": 14 }, - "id": 4, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showUnfilled": true + "hiddenSeries": false, + "id": 18, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, "targets": [ { - "expr": "Westend_to_Millau_Sync_blocks_in_state", - "instant": true, + "expr": "Westend_to_Millau_Sync_is_source_and_source_at_target_using_different_forks", "interval": "", - "legendFormat": "{{state}}", + "legendFormat": "On different forks?", "refId": "A" } ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0 + } + ], "timeFrom": null, + "timeRegions": [], "timeShift": null, - "title": "Queued Headers in Relay", - "type": "bargauge" + "title": "Whether with-Westend-grandpa-pallet and Westend itself are on different forks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } }, { "aliasColors": {}, diff --git a/deployments/bridges/westend-millau/entrypoints/relay-headers-westend-to-millau-entrypoint.sh b/deployments/bridges/westend-millau/entrypoints/relay-headers-westend-to-millau-entrypoint.sh index d3b6932983fb..f37ee69915cd 100755 --- a/deployments/bridges/westend-millau/entrypoints/relay-headers-westend-to-millau-entrypoint.sh +++ b/deployments/bridges/westend-millau/entrypoints/relay-headers-westend-to-millau-entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -xeu -sleep 60 -curl -v http://millau-node-alice:9933/health -curl -v https://westend-rpc.polkadot.io:443/health +sleep 15 /home/user/substrate-relay init-bridge westend-to-millau \ --source-host westend-rpc.polkadot.io \ diff --git a/deployments/local-scripts/relay-messages-millau-to-rialto.sh b/deployments/local-scripts/relay-messages-millau-to-rialto.sh index d420dc56c263..36673d31be8c 100755 --- a/deployments/local-scripts/relay-messages-millau-to-rialto.sh +++ b/deployments/local-scripts/relay-messages-millau-to-rialto.sh @@ -10,6 +10,7 @@ RIALTO_PORT="${RIALTO_PORT:-9944}" RUST_LOG=bridge=debug \ ./target/debug/substrate-relay relay-messages millau-to-rialto \ + --relayer-mode=altruistic \ --lane 00000000 \ --source-host localhost \ --source-port $MILLAU_PORT \ diff --git a/deployments/local-scripts/relay-messages-rialto-to-millau.sh b/deployments/local-scripts/relay-messages-rialto-to-millau.sh index 0cd73c00454d..89e2b8182455 100755 --- a/deployments/local-scripts/relay-messages-rialto-to-millau.sh +++ b/deployments/local-scripts/relay-messages-rialto-to-millau.sh @@ -10,6 +10,7 @@ RIALTO_PORT="${RIALTO_PORT:-9944}" RUST_LOG=bridge=debug \ ./target/debug/substrate-relay relay-messages rialto-to-millau \ + --relayer-mode=altruistic \ --lane 00000000 \ --source-host localhost \ --source-port $RIALTO_PORT \ diff --git a/deployments/local-scripts/relay-millau-to-rialto.sh b/deployments/local-scripts/relay-millau-to-rialto.sh index 8b18cff2b53c..35d88d1a643b 100755 --- a/deployments/local-scripts/relay-millau-to-rialto.sh +++ b/deployments/local-scripts/relay-millau-to-rialto.sh @@ -15,6 +15,8 @@ RUST_LOG=bridge=debug \ --target-host localhost \ --target-port $RIALTO_PORT \ --target-signer //Alice \ + --source-version-mode Bundle \ + --target-version-mode Bundle sleep 5 RUST_LOG=bridge=debug \ diff --git a/deployments/monitoring/GrafanaMatrix.Dockerfile b/deployments/monitoring/GrafanaMatrix.Dockerfile index 420e134716a6..df80f7002159 100644 --- a/deployments/monitoring/GrafanaMatrix.Dockerfile +++ b/deployments/monitoring/GrafanaMatrix.Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:alpine +FROM docker.io/library/ruby:alpine RUN apk add --no-cache git diff --git a/deployments/networks/dashboard/grafana/beefy-dashboard.json b/deployments/networks/dashboard/grafana/beefy-dashboard.json new file mode 100644 index 000000000000..0216e145548e --- /dev/null +++ b/deployments/networks/dashboard/grafana/beefy-dashboard.json @@ -0,0 +1,539 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 1 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "C", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Beefy best blocks not advancing", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": { + "align": null + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 14, + "w": 12, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "polkadot_beefy_best_block", + "legendFormat": "Rialto(Charlie)", + "refId": "A" + }, + { + "expr": "substrate_beefy_best_block", + "legendFormat": "Millau(Charlie)", + "refId": "B" + }, + { + "expr": "max_over_time(substrate_beefy_best_block[5m]) - min_over_time(substrate_beefy_best_block[5m])", + "hide": true, + "legendFormat": "Millau Best Beefy blocks count in last 5 minutes", + "refId": "C" + }, + { + "expr": "max_over_time(polkadot_beefy_best_block[5m]) - min_over_time(polkadot_beefy_best_block[5m])", + "hide": true, + "legendFormat": "Rialto Best Beefy blocks count in last 5 minutes", + "refId": "D" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "lt", + "value": 1 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Beefy Best block", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "yellow", + "value": null + }, + { + "color": "yellow", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 11, + "x": 12, + "y": 0 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.1.3", + "targets": [ + { + "expr": "polkadot_beefy_should_vote_on", + "legendFormat": "Rialto(Charlie) Should-Vote-On", + "refId": "C" + }, + { + "expr": "polkadot_beefy_round_concluded", + "legendFormat": "Rialto(Charlie) Round-Concluded", + "refId": "A" + }, + { + "expr": "substrate_beefy_should_vote_on", + "legendFormat": "Millau(Charlie) Should-Vote-On", + "refId": "D" + }, + { + "expr": "substrate_beefy_round_concluded", + "legendFormat": "Millau(Charlie) Round-Concluded", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Beefy Voting Rounds", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 18, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "polkadot_beefy_votes_sent", + "legendFormat": "Rialto (node Charlie)", + "refId": "A" + }, + { + "expr": "substrate_beefy_votes_sent", + "legendFormat": "Millau (node Charlie)", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Beefy Votes Sent", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0 + ], + "type": "gt" + }, + "operator": { + "type": "or" + }, + "query": { + "params": [ + "B", + "5m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "5m", + "frequency": "1m", + "handler": 1, + "name": "Beefy Skipped Sessions alert", + "noDataState": "no_data", + "notifications": [] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": { + "align": null + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 1 + } + ] + } + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 5, + "x": 18, + "y": 14 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "percentage": false, + "pluginVersion": "7.1.3", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "polkadot_beefy_skipped_sessions", + "legendFormat": "Rialto(Charlie)", + "refId": "A" + }, + { + "expr": "substrate_beefy_skipped_sessions", + "legendFormat": "Millau(Charlie)", + "refId": "B" + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Beefy Skipped Sessions", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Beefy", + "uid": "j6cRDRh7z", + "version": 1 +} diff --git a/deployments/networks/dashboard/prometheus/millau-targets.yml b/deployments/networks/dashboard/prometheus/millau-targets.yml new file mode 100644 index 000000000000..c7a06509276f --- /dev/null +++ b/deployments/networks/dashboard/prometheus/millau-targets.yml @@ -0,0 +1,2 @@ +- targets: + - millau-node-charlie:9615 diff --git a/deployments/networks/dashboard/prometheus/rialto-targets.yml b/deployments/networks/dashboard/prometheus/rialto-targets.yml new file mode 100644 index 000000000000..9de26b9a2d7f --- /dev/null +++ b/deployments/networks/dashboard/prometheus/rialto-targets.yml @@ -0,0 +1,2 @@ +- targets: + - rialto-node-charlie:9615 diff --git a/deployments/networks/entrypoints/rialto-parachain-registrar-entrypoint.sh b/deployments/networks/entrypoints/rialto-parachain-registrar-entrypoint.sh index 172502327c9a..519ab228e932 100755 --- a/deployments/networks/entrypoints/rialto-parachain-registrar-entrypoint.sh +++ b/deployments/networks/entrypoints/rialto-parachain-registrar-entrypoint.sh @@ -1,9 +1,7 @@ #!/bin/bash set -xeu -sleep 60 -curl -v http://rialto-node-alice:9933/health -curl -v http://rialto-parachain-collator-alice:9933/health +sleep 15 /home/user/substrate-relay register-parachain rialto-parachain \ --parachain-host rialto-parachain-collator-alice \ diff --git a/deployments/networks/millau.yml b/deployments/networks/millau.yml index d42c1d7d07cb..13ac8d487726 100644 --- a/deployments/networks/millau.yml +++ b/deployments/networks/millau.yml @@ -17,6 +17,7 @@ services: - --alice - --node-key=0f900c89f4e626f4a217302ab8c7d213737d00627115f318ad6fb169717ac8e0 - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external environment: @@ -35,6 +36,7 @@ services: - --bob - --node-key=db383639ff2905d79f8e936fd5dc4416ef46b514b2f83823ec3c42753d7557bb - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: @@ -50,11 +52,14 @@ services: - --bootnodes=/dns4/millau-node-alice/tcp/30333/p2p/12D3KooWFqiV73ipQ1jpfVmCfLqBCp8G9PLH3zPkY9EhmdrSGA4H - --charlie - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external + - --prometheus-external ports: - "20133:9933" - "20144:9944" + - "20615:9615" millau-node-dave: <<: *millau-bridge-node @@ -65,6 +70,7 @@ services: - --bootnodes=/dns4/millau-node-alice/tcp/30333/p2p/12D3KooWFqiV73ipQ1jpfVmCfLqBCp8G9PLH3zPkY9EhmdrSGA4H - --dave - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: @@ -80,8 +86,16 @@ services: - --bootnodes=/dns4/millau-node-alice/tcp/30333/p2p/12D3KooWFqiV73ipQ1jpfVmCfLqBCp8G9PLH3zPkY9EhmdrSGA4H - --eve - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: - "20333:9933" - "20344:9944" + + # Note: These are being overridden from the top level `monitoring` compose file. + prometheus-metrics: + volumes: + - ./networks/dashboard/prometheus/millau-targets.yml:/etc/prometheus/targets-millau-nodes.yml + depends_on: + - millau-node-charlie diff --git a/deployments/networks/rialto.yml b/deployments/networks/rialto.yml index 0a484b2dad75..40e881a37c19 100644 --- a/deployments/networks/rialto.yml +++ b/deployments/networks/rialto.yml @@ -17,6 +17,7 @@ services: - --alice - --node-key=79cf382988364291a7968ae7825c01f68c50d679796a8983237d07fe0ccf363b - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external environment: @@ -35,6 +36,7 @@ services: - --bob - --node-key=4f9d0146dd9b7b3bf5a8089e3880023d1df92057f89e96e07bb4d8c2ead75bbd - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: @@ -50,11 +52,14 @@ services: - --bootnodes=/dns4/rialto-node-alice/tcp/30333/p2p/12D3KooWMF6JvV319a7kJn5pqkKbhR3fcM2cvK5vCbYZHeQhYzFE - --charlie - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external + - --prometheus-external ports: - "10133:9933" - "10144:9944" + - "10615:9615" rialto-node-dave: <<: *rialto-bridge-node @@ -65,6 +70,7 @@ services: - --bootnodes=/dns4/rialto-node-alice/tcp/30333/p2p/12D3KooWMF6JvV319a7kJn5pqkKbhR3fcM2cvK5vCbYZHeQhYzFE - --dave - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: @@ -80,6 +86,7 @@ services: - --bootnodes=/dns4/rialto-node-alice/tcp/30333/p2p/12D3KooWMF6JvV319a7kJn5pqkKbhR3fcM2cvK5vCbYZHeQhYzFE - --eve - --rpc-cors=all + - --enable-offchain-indexing=true - --unsafe-rpc-external - --unsafe-ws-external ports: @@ -93,6 +100,13 @@ services: - ./networks/entrypoints:/entrypoints - rialto-share:/rialto-share:z + # Note: These are being overridden from the top level `monitoring` compose file. + prometheus-metrics: + volumes: + - ./networks/dashboard/prometheus/rialto-targets.yml:/etc/prometheus/targets-rialto-nodes.yml + depends_on: + - rialto-node-charlie + # we're using `/rialto-share` to expose Rialto chain spec to those who are interested. Right # now it is Rialto Parachain collator nodes. Local + tmpfs combination allows sharing writable # in-memory volumes, which are dropped when containers are stopped. diff --git a/fuzz/storage-proof/Cargo.toml b/fuzz/storage-proof/Cargo.toml index c4da57b255c8..b406054bc6e4 100644 --- a/fuzz/storage-proof/Cargo.toml +++ b/fuzz/storage-proof/Cargo.toml @@ -2,7 +2,7 @@ name = "storage-proof-fuzzer" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -19,6 +19,7 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/fuzz/storage-proof/src/main.rs b/fuzz/storage-proof/src/main.rs index 42636a65c3dc..185d0e336c4d 100644 --- a/fuzz/storage-proof/src/main.rs +++ b/fuzz/storage-proof/src/main.rs @@ -31,13 +31,13 @@ fn craft_known_storage_proof(input_vec: Vec<(Vec, Vec)>) -> (H256, Stora let storage_proof_vec = vec![(None, input_vec.iter().map(|x| (x.0.clone(), Some(x.1.clone()))).collect())]; log::info!("Storage proof vec {:?}", storage_proof_vec); - let backend = >::from(storage_proof_vec); - let root = backend.storage_root(std::iter::empty()).0; + let state_version = sp_runtime::StateVersion::default(); + let backend = >::from((storage_proof_vec, state_version)); + let root = backend.storage_root(std::iter::empty(), state_version).0; let vector_element_proof = StorageProof::new( prove_read(backend, input_vec.iter().map(|x| x.0.as_slice())) .unwrap() - .iter_nodes() - .collect(), + .iter_nodes(), ); (root, vector_element_proof) } diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 7a8a34ab4c0e..833d5cca77a7 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -3,13 +3,13 @@ name = "pallet-bridge-dispatch" description = "A Substrate Runtime module that dispatches a bridge message, treating it simply as encoded Call" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index f467bab0d946..1e030b733205 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -64,8 +64,7 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaybeDisplay - + Ord - + Default; + + Ord; /// Type of account public key on target chain. type TargetChainAccountPublic: Parameter + IdentifyAccount; /// Type of signature that may prove that the message has been signed by @@ -520,6 +519,7 @@ mod tests { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for TestRuntime { @@ -649,11 +649,11 @@ mod tests { fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(frame_system::Call::remark { remark: vec![1, 2, 3] }); + let call = Call::System(frame_system::Call::set_heap_pages { pages: 42 }); let call_weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = 7; - assert!(call_weight != 7, "needed for test to actually trigger a weight mismatch"); + assert!(call_weight > 7, "needed for test to actually trigger a weight mismatch"); System::set_block_number(1); let result = Dispatch::dispatch( diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index e36b43585b9b..eac80375da12 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -2,17 +2,17 @@ name = "pallet-bridge-grandpa" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -finality-grandpa = { version = "0.14.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -58,5 +58,5 @@ std = [ ] runtime-benchmarks = [ "bp-test-utils", - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index cbc85da30259..947bfdc7f634 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -101,6 +101,7 @@ pub mod pallet { } #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] @@ -299,7 +300,7 @@ pub mod pallet { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). #[pallet::storage] - pub(super) type PalletOwner, I: 'static = ()> = + pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; /// If true, all pallet transactions are failed immediately. @@ -626,7 +627,10 @@ mod tests { JustificationGeneratorParams, ALICE, BOB, }; use codec::Encode; - use frame_support::{assert_err, assert_noop, assert_ok, weights::PostDispatchInfo}; + use frame_support::{ + assert_err, assert_noop, assert_ok, storage::generator::StorageValue, + weights::PostDispatchInfo, + }; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { @@ -1145,4 +1149,17 @@ mod tests { ); }) } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + IsHalted::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::is_halted_key("Grandpa").0, + ); + + assert_eq!( + BestFinalized::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::best_finalized_hash_key("Grandpa").0, + ); + } } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index f8b5e269323f..bfc749d5230c 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -77,6 +77,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -106,6 +107,13 @@ impl Chain for TestBridgedChain { type Balance = u64; type Index = u64; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index c0cce2c5258d..2c4660160a00 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -16,14 +16,14 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/rialto-bridge-node +// target/release/millau-bridge-node // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/grandpa/src/weights.rs -// --template=./.maintain/rialto-weight-template.hbs +// --template=./.maintain/millau-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] @@ -51,13 +51,13 @@ pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; } -/// Weights for `pallet_bridge_grandpa` using the Rialto node and recommended hardware. -pub struct RialtoWeight(PhantomData); -impl WeightInfo for RialtoWeight { +/// Weights for `pallet_bridge_grandpa` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (0 as Weight) - .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) + (115_651_000 as Weight) + .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -66,9 +66,9 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (0 as Weight) - .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) + (115_651_000 as Weight) + .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 6d52b899ea2b..804f323f10b6 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -3,15 +3,15 @@ name = "pallet-bridge-messages" description = "Module that allows bridged chains to exchange messages using lane concept." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +bitvec = { version = "1", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -30,8 +30,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -hex = "0.4" -hex-literal = "0.3" sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -53,5 +51,5 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/modules/messages/README.md b/modules/messages/README.md index 062a966fad70..2dc562968424 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -294,9 +294,8 @@ Where: *\* - In all benchmarks all received messages are dispatched and their dispatch cost is near to zero* *\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof -by including more trie nodes. That's because according to `receive_message_proofs_with_large_leaf` -and `receive_message_proofs_with_extra_nodes` benchmarks, increasing proof by including more nodes -has slightly larger impact on performance than increasing values stored in leafs*. +by including more trie nodes. That's because according to our additioal benchmarks, increasing proof +by including more nodes has slightly larger impact on performance than increasing values stored in leafs*. #### Weight formula diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 788ccc070310..46a8150d034b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -30,15 +30,7 @@ use bp_runtime::messages::DispatchFeePayment; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; -use sp_std::{ - collections::{btree_map::BTreeMap, vec_deque::VecDeque}, - convert::TryInto, - ops::RangeInclusive, - prelude::*, -}; - -/// Fee paid by submitter for single message delivery. -pub const MESSAGE_FEE: u64 = 100_000_000_000; +use sp_std::{collections::vec_deque::VecDeque, convert::TryInto, ops::RangeInclusive, prelude::*}; const SEED: u32 = 0; @@ -46,6 +38,7 @@ const SEED: u32 = 0; pub struct Pallet, I: 'static>(crate::Pallet); /// Proof size requirements. +#[derive(Clone, Copy, Debug)] pub enum ProofSize { /// The proof is expected to be minimal. If value size may be changed, then it is expected to /// have given size. @@ -59,6 +52,7 @@ pub enum ProofSize { } /// Benchmark-specific message parameters. +#[derive(Debug)] pub struct MessageParams { /// Size of the message payload. pub size: u32, @@ -67,6 +61,7 @@ pub struct MessageParams { } /// Benchmark-specific message proof parameters. +#[derive(Debug)] pub struct MessageProofParams { /// Id of the lane. pub lane: LaneId, @@ -81,6 +76,7 @@ pub struct MessageProofParams { } /// Benchmark-specific message delivery proof parameters. +#[derive(Debug)] pub struct MessageDeliveryProofParams { /// Id of the lane. pub lane: LaneId, @@ -104,6 +100,10 @@ pub trait Config: crate::Config { fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); + /// Fee paid by submitter for single message delivery. + fn message_fee() -> Self::OutboundMessageFee { + 100_000_000_000_000.into() + } /// Prepare message to send over lane. fn prepare_outbound_message( params: MessageParams, @@ -139,8 +139,10 @@ benchmarks_instance_pallet! { // added. send_minimal_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -155,7 +157,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -170,8 +172,10 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_1_kb_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -192,7 +196,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -207,8 +211,10 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_16_kb_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -229,7 +235,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -240,8 +246,10 @@ benchmarks_instance_pallet! { // // Result of this benchmark is directly used by weight formula of the call. maximal_increase_message_fee { + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -259,8 +267,10 @@ benchmarks_instance_pallet! { increase_message_fee { let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -283,6 +293,7 @@ benchmarks_instance_pallet! { receive_single_message_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -297,7 +308,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -317,6 +328,7 @@ benchmarks_instance_pallet! { receive_two_messages_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -331,7 +343,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 22, ); assert!(T::is_message_dispatched(22)); @@ -351,6 +363,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_with_outbound_lane_state { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -368,14 +381,9 @@ benchmarks_instance_pallet! { }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { - assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), - 21, - ); - assert_eq!( - crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), - 20, - ); + let lane_state = crate::InboundLanes::::get(&T::bench_lane_id()); + assert_eq!(lane_state.last_delivered_nonce(), 21); + assert_eq!(lane_state.last_confirmed_nonce, 20); assert!(T::is_message_dispatched(21)); } @@ -391,6 +399,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_1_kb { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -405,7 +414,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -425,6 +434,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_16_kb { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -439,7 +449,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -458,6 +468,7 @@ benchmarks_instance_pallet! { receive_single_prepaid_message_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -472,7 +483,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -512,7 +523,7 @@ benchmarks_instance_pallet! { verify { assert_eq!( T::account_balance(&relayer_id), - relayer_balance + MESSAGE_FEE.into(), + relayer_balance + T::message_fee(), ); } @@ -602,310 +613,16 @@ benchmarks_instance_pallet! { ensure_relayer_rewarded::(&relayer1_id, &relayer1_balance); ensure_relayer_rewarded::(&relayer2_id, &relayer2_balance); } - - // - // Benchmarks for manual checks. - // - - // Benchmark `send_message` extrinsic with following conditions: - // * outbound lane already has state, so it needs to be read and decoded; - // * relayers fund account does not exists (in practice it needs to exist in production environment); - // * maximal number of messages is being pruned during the call; - // * message size varies from minimal to maximal for the target chain. - // - // Results of this benchmark may be used to check how message size affects `send_message` performance. - send_messages_of_various_lengths { - let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); - - let lane_id = T::bench_lane_id(); - let sender = account("sender", 0, SEED); - T::endow_account(&sender); - - // 'send' messages that are to be pruned when our message is sent - for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { - send_regular_message::(); - } - confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - - let (payload, fee) = T::prepare_outbound_message(MessageParams { - size: i as _, - sender_account: sender.clone(), - }); - }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) - verify { - assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), - T::MaxMessagesToPruneAtOnce::get() + 1, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // This benchmarks gives us an approximation of single message delivery weight. It is similar to the - // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. So it may be used - // to verify that the other approximation is correct. - receive_multiple_messages_proof { - let i in 1..64; - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = i as _; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=(20 + i as MessageNonce), - outbound_lane_data: None, - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), - 20 + i as MessageNonce, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // Results of this benchmark may be used to check how proof size affects `receive_message_proof` performance. - receive_message_proofs_with_extra_nodes { - let i in 0..T::maximal_message_size(); - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = 1u32; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: ProofSize::HasExtraNodes(i as _), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), - 21, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // Results of this benchmark may be used to check how message size affects `receive_message_proof` performance. - receive_message_proofs_with_large_leaf { - let i in 0..T::maximal_message_size(); - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = 1u32; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: ProofSize::HasLargeLeaf(i as _), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), - 21, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: - // * proof includes outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // This benchmarks gives us an approximation of outbound lane state delivery weight. It is similar to the - // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. - // So it may be used to verify that the other approximation is correct. - receive_multiple_messages_proof_with_outbound_lane_state { - let i in 1..128; - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = i as _; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=20 + i as MessageNonce, - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 21, - latest_received_nonce: 20, - latest_generated_nonce: 21, - }), - size: ProofSize::Minimal(0), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), - 20 + i as MessageNonce, - ); - assert_eq!( - crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), - 20, - ); - } - - // Benchmark `receive_messages_delivery_proof` extrinsic where single relayer delivers multiple messages. - receive_delivery_proof_for_multiple_messages_by_single_relayer { - // there actually should be used value of `MaxUnrewardedRelayerEntriesAtInboundLane` from the bridged - // chain, but we're more interested in additional weight/message than in max weight - let i in 1..T::MaxUnrewardedRelayerEntriesAtInboundLane::get() - .try_into() - .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); - - let relayers_fund_id = crate::relayer_fund_account_id::(); - let relayer_id: T::AccountId = account("relayer", 0, SEED); - let relayer_balance = T::account_balance(&relayer_id); - T::endow_account(&relayers_fund_id); - - // send messages that we're going to confirm - for _ in 1..=i { - send_regular_message::(); - } - - let relayers_state = UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - messages_in_oldest_entry: 1, - total_messages: i as MessageNonce, - }; - let mut delivered_messages = DeliveredMessages::new(1, true); - for nonce in 2..=i { - delivered_messages.note_dispatched_message(true); - } - let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: T::bench_lane_id(), - inbound_lane_data: InboundLaneData { - relayers: vec![UnrewardedRelayer { - relayer: relayer_id.clone(), - messages: delivered_messages, - }].into_iter().collect(), - last_confirmed_nonce: 0, - }, - size: ProofSize::Minimal(0), - }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) - verify { - ensure_relayer_rewarded::(&relayer_id, &relayer_balance); - } - - // Benchmark `receive_messages_delivery_proof` extrinsic where every relayer delivers single messages. - receive_delivery_proof_for_multiple_messages_by_multiple_relayers { - // there actually should be used value of `MaxUnconfirmedMessagesAtInboundLane` from the bridged - // chain, but we're more interested in additional weight/message than in max weight - let i in 1..T::MaxUnconfirmedMessagesAtInboundLane::get() - .try_into() - .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); - - let relayers_fund_id = crate::relayer_fund_account_id::(); - let confirmation_relayer_id = account("relayer", 0, SEED); - let relayers: BTreeMap = (1..=i) - .map(|j| { - let relayer_id = account("relayer", j + 1, SEED); - let relayer_balance = T::account_balance(&relayer_id); - (relayer_id, relayer_balance) - }) - .collect(); - T::endow_account(&relayers_fund_id); - - // send messages that we're going to confirm - for _ in 1..=i { - send_regular_message::(); - } - - let relayers_state = UnrewardedRelayersState { - unrewarded_relayer_entries: i as MessageNonce, - messages_in_oldest_entry: 1, - total_messages: i as MessageNonce, - }; - let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: T::bench_lane_id(), - inbound_lane_data: InboundLaneData { - relayers: relayers - .keys() - .enumerate() - .map(|(j, relayer)| UnrewardedRelayer { - relayer: relayer.clone(), - messages: DeliveredMessages::new(j as MessageNonce + 1, true), - }) - .collect(), - last_confirmed_nonce: 0, - }, - size: ProofSize::Minimal(0), - }); - }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) - verify { - for (relayer_id, prev_balance) in relayers { - ensure_relayer_rewarded::(&relayer_id, &prev_balance); - } - } } fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload: vec![], fee: MESSAGE_FEE.into() }); + outbound_lane.send_message(MessageData { payload: vec![], fee: T::message_fee() }); } fn send_regular_message_with_payload, I: 'static>(payload: Vec) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload, fee: MESSAGE_FEE.into() }); + outbound_lane.send_message(MessageData { payload, fee: T::message_fee() }); } fn confirm_message_delivery, I: 'static>(nonce: MessageNonce) { diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index c145687af994..2a620a952225 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -22,7 +22,7 @@ use crate::OutboundMessages; use bp_messages::{ - source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, + source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, SenderOrigin}, LaneId, MessageKey, MessageNonce, UnrewardedRelayer, }; use codec::Encode; @@ -31,6 +31,10 @@ use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::Saturating; use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; +/// Error that occurs when message fee is non-zero, but payer is not defined. +const NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE: &str = + "Non-zero message fee can't be paid by "; + /// Instant message payments made in given currency. /// /// The balance is initially reserved in a special `relayers-fund` account, and transferred @@ -44,42 +48,50 @@ use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee)>, } -impl - MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments +impl + MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments where T: frame_system::Config + crate::Config, I: 'static, + T::Origin: SenderOrigin, Currency: CurrencyT, Currency::Balance: From, GetConfirmationFee: Get, - RootAccount: Get>, { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &T::Origin, fee: &Currency::Balance, relayer_fund_account: &T::AccountId, ) -> Result<(), Self::Error> { + let submitter_account = match submitter.linked_account() { + Some(submitter_account) => submitter_account, + None if !fee.is_zero() => { + // if we'll accept some message that has declared that the `fee` has been paid but + // it isn't actually paid, then it'll lead to problems with delivery confirmation + // payments (see `pay_relayer_rewards` && `confirmation_relayer` in particular) + return Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE) + }, + None => { + // message lane verifier has accepted the message before, so this message + // is unpaid **by design** + // => let's just do nothing + return Ok(()) + }, + }; + if !frame_system::Pallet::::account_exists(relayer_fund_account) { return Err("The relayer fund account must exist for the message lanes pallet to work correctly."); } - let root_account = RootAccount::get(); - let account = match submitter { - Sender::Signed(submitter) => submitter, - Sender::Root | Sender::None => root_account - .as_ref() - .ok_or("Sending messages using Root or None origin is disallowed.")?, - }; - Currency::transfer( - account, + &submitter_account, relayer_fund_account, *fee, // it's fine for the submitter to go below Existential Deposit and die. @@ -145,7 +157,7 @@ fn pay_relayers_rewards( relayer_fund_account: &AccountId, confirmation_fee: Currency::Balance, ) where - AccountId: Debug + Default + Encode + PartialEq, + AccountId: Debug + Encode + PartialEq, Currency: CurrencyT, Currency::Balance: From, { @@ -226,7 +238,9 @@ fn pay_relayer_reward( #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; + use crate::mock::{ + run_test, AccountId as TestAccountId, Balance as TestBalance, Origin, TestRuntime, + }; use bp_messages::source_chain::RelayerRewards; type Balances = pallet_balances::Pallet; @@ -245,6 +259,48 @@ mod tests { .collect() } + #[test] + fn pay_delivery_and_dispatch_fee_fails_on_non_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &100, + &RELAYERS_FUND_ACCOUNT, + ); + assert_eq!(result, Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE)); + }); + } + + #[test] + fn pay_delivery_and_dispatch_succeeds_on_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &0, + &RELAYERS_FUND_ACCOUNT, + ); + assert!(result.is_ok()); + }); + } + #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 119869d81e98..a344cedae241 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -170,12 +170,14 @@ pub mod pallet { type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier< + Self::Origin, Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee, >; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< + Self::Origin, Self::AccountId, Self::OutboundMessageFee, >; @@ -209,6 +211,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::call] @@ -275,16 +278,12 @@ pub mod pallet { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResultWithPostInfo { - crate::send_message::( - origin.into().map_err(|_| BadOrigin)?, - lane_id, - payload, - delivery_and_dispatch_fee, + crate::send_message::(origin, lane_id, payload, delivery_and_dispatch_fee).map( + |sent_message| PostDispatchInfo { + actual_weight: Some(sent_message.weight), + pays_fee: Pays::Yes, + }, ) - .map(|sent_message| PostDispatchInfo { - actual_weight: Some(sent_message.weight), - pays_fee: Pays::Yes, - }) } /// Pay additional fee for the message. @@ -312,17 +311,15 @@ pub mod pallet { ); // withdraw additional fee from submitter - let submitter = origin.into().map_err(|_| BadOrigin)?; T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &submitter, + &origin, &additional_fee, &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", - submitter, + "Submitter can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", additional_fee, lane_id, nonce, @@ -763,67 +760,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), - } - } - } -} - -/// Getting storage keys for messages and lanes states. These keys are normally used when building -/// messages and lanes states proofs. -pub mod storage_keys { - use super::*; - use sp_core::storage::StorageKey; - - /// Storage key of the outbound message in the runtime storage. - pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat( - pallet_prefix, - "OutboundMessages", - &MessageKey { lane_id: *lane, nonce }.encode(), - ) - } - - /// Storage key of the outbound message lane state in the runtime storage. - pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "OutboundLanes", lane) - } - - /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "InboundLanes", lane) } } @@ -840,6 +776,7 @@ pub fn relayer_fund_account_id bp_messages::source_chain::MessagesBridge< + T::Origin, T::AccountId, T::OutboundMessageFee, T::OutboundPayload, @@ -851,7 +788,7 @@ where type Error = sp_runtime::DispatchErrorWithPostInfo; fn send_message( - sender: bp_messages::source_chain::Sender, + sender: T::Origin, lane: LaneId, message: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -862,7 +799,7 @@ where /// Function that actually sends message. fn send_message, I: 'static>( - submitter: bp_messages::source_chain::Sender, + submitter: T::Origin, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -916,9 +853,8 @@ fn send_message, I: 'static>( .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", + "Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}", lane_id, - submitter, delivery_and_dispatch_fee, err, ); @@ -1159,9 +1095,12 @@ mod tests { REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; - use frame_support::{assert_noop, assert_ok, weights::Weight}; + use frame_support::{ + assert_noop, assert_ok, + storage::generator::{StorageMap, StorageValue}, + weights::Weight, + }; use frame_system::{EventRecord, Pallet as System, Phase}; - use hex_literal::hex; use sp_runtime::DispatchError; fn get_ready_for_events() { @@ -1169,6 +1108,20 @@ mod tests { System::::reset_events(); } + 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), + } + } + fn send_regular_message() -> Weight { get_ready_for_events(); @@ -1613,7 +1566,7 @@ mod tests { }, ); assert_eq!( - Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, @@ -1648,7 +1601,7 @@ mod tests { }, ); assert_eq!( - Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, @@ -1889,45 +1842,6 @@ mod tests { }); } - #[test] - fn storage_message_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted messages proofs. - let storage_key = storage_keys::message_key("BridgeMessages", &*b"test", 42).0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - - #[test] - fn outbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted outbound lane state proofs. - let storage_key = storage_keys::outbound_lane_data_key("BridgeMessages", &*b"test").0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - - #[test] - fn inbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted inbound lane state proofs. - let storage_key = storage_keys::inbound_lane_data_key("BridgeMessages", &*b"test").0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - #[test] fn actual_dispatch_weight_does_not_overlow() { run_test(|| { @@ -2198,6 +2112,7 @@ mod tests { #[test] #[should_panic] + #[cfg(debug_assertions)] fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { TestOnDeliveryConfirmed1::set_consumed_weight_per_message( @@ -2330,6 +2245,7 @@ mod tests { #[test] #[should_panic] + #[cfg(debug_assertions)] fn message_accepted_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { TestOnMessageAccepted::set_consumed_weight_per_message( @@ -2359,4 +2275,30 @@ mod tests { ); }); } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + PalletOperatingMode::::storage_value_final_key().to_vec(), + bp_messages::storage_keys::operating_mode_key("Messages").0, + ); + + assert_eq!( + OutboundMessages::::storage_map_final_key(MessageKey { + lane_id: TEST_LANE_ID, + nonce: 42 + }), + bp_messages::storage_keys::message_key("Messages", &TEST_LANE_ID, 42).0, + ); + + assert_eq!( + OutboundLanes::::storage_map_final_key(TEST_LANE_ID), + bp_messages::storage_keys::outbound_lane_data_key("Messages", &TEST_LANE_ID).0, + ); + + assert_eq!( + InboundLanes::::storage_map_final_key(TEST_LANE_ID), + bp_messages::storage_keys::inbound_lane_data_key("Messages", &TEST_LANE_ID).0, + ); + } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index a333c95bb58b..75dcce8df044 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -23,7 +23,7 @@ use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, Sender, TargetHeaderChain, + OnMessageAccepted, SenderOrigin, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -125,6 +125,7 @@ impl frame_system::Config for TestRuntime { type DbWeight = DbWeight; type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -193,6 +194,16 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } +impl SenderOrigin for Origin { + fn linked_account(&self) -> Option { + match self.caller { + OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + _ => None, + } + } +} + impl Size for TestPayload { fn size_hint(&self) -> u32 { 16 + self.extra.len() as u32 @@ -293,11 +304,13 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier + for TestLaneMessageVerifier +{ type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &Origin, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, @@ -323,8 +336,8 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - frame_support::storage::unhashed::get(b":message-fee:") == - Some((Sender::Signed(submitter), fee)) + let raw_origin: Result, _> = Origin::signed(submitter).into(); + frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee)) } /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is @@ -335,13 +348,13 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &Origin, fee: &TestMessageFee, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { @@ -349,7 +362,8 @@ impl MessageDeliveryAndDispatchPayment return Err(TEST_ERROR) } - frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); + let raw_origin: Result, _> = submitter.clone().into(); + frame_support::storage::unhashed::put(b":message-fee:", &(raw_origin.unwrap(), fee)); Ok(()) } @@ -529,7 +543,7 @@ pub fn unrewarded_relayer( begin, end, dispatch_results: if end >= begin { - bitvec![Msb0, u8; 1; (end - begin + 1) as _] + bitvec![u8, Msb0; 1; (end - begin + 1) as _] } else { Default::default() }, diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index c05437596db8..cfdc81acc315 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -260,7 +260,7 @@ mod tests { DeliveredMessages { begin: *nonces.start(), end: *nonces.end(), - dispatch_results: bitvec![Msb0, u8; 1; (nonces.end() - nonces.start() + 1) as _], + dispatch_results: bitvec![u8, Msb0; 1; (nonces.end() - nonces.start() + 1) as _], } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 9dce11168fbb..462f768a08b3 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -16,14 +16,14 @@ //! Autogenerated weights for `pallet_bridge_messages` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/rialto-bridge-node +// target/release/millau-bridge-node // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/messages/src/weights.rs -// --template=./.maintain/rialto-weight-template.hbs +// --template=./.maintain/millau-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] @@ -62,252 +62,155 @@ pub trait WeightInfo { fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; - fn send_messages_of_various_lengths(i: u32) -> Weight; - fn receive_multiple_messages_proof(i: u32) -> Weight; - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight; - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight; - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } -/// Weights for `pallet_bridge_messages` using the Rialto node and recommended hardware. -pub struct RialtoWeight(PhantomData); -impl WeightInfo for RialtoWeight { +/// Weights for `pallet_bridge_messages` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { fn send_minimal_message_worst_case() -> Weight { - (159_305_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (117_480_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (164_394_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (128_391_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (223_521_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (149_149_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_781_470_000 as Weight) + (6_015_058_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn increase_message_fee(i: u32) -> Weight { - (114_963_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (206_769_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (179_892_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (343_982_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (291_793_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (223_738_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (192_191_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (235_369_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (202_104_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (510_338_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (357_144_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (141_536_000 as Weight) + (122_648_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (128_805_000 as Weight) + (107_631_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_143_000 as Weight) + (113_885_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (193_108_000 as Weight) + (155_151_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - fn send_messages_of_various_lengths(i: u32) -> Weight { - (133_632_000 as Weight) - .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) - } - fn receive_multiple_messages_proof(i: u32) -> Weight { - (0 as Weight) - .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (486_301_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (178_139_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (113_140_000 as Weight) - .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (97_424_000 as Weight) - .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) - } } // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (159_305_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (117_480_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (164_394_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (128_391_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (223_521_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (149_149_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_781_470_000 as Weight) + (6_015_058_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn increase_message_fee(i: u32) -> Weight { - (114_963_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (206_769_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (179_892_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (343_982_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (291_793_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (223_738_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (192_191_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (235_369_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (202_104_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (510_338_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (357_144_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (141_536_000 as Weight) + (122_648_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (128_805_000 as Weight) + (107_631_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_143_000 as Weight) + (113_885_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (193_108_000 as Weight) + (155_151_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - fn send_messages_of_various_lengths(i: u32) -> Weight { - (133_632_000 as Weight) - .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) - } - fn receive_multiple_messages_proof(i: u32) -> Weight { - (0 as Weight) - .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (486_301_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (178_139_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (113_140_000 as Weight) - .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (97_424_000 as Weight) - .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) - } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index fef09c6cebe5..483a22eda1d6 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -390,7 +390,7 @@ impl WeightInfoExt for () { } } -impl WeightInfoExt for crate::weights::RialtoWeight { +impl WeightInfoExt for crate::weights::MillauWeight { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 9e3e15fddf89..30a5618b115f 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -3,12 +3,12 @@ name = "pallet-shift-session-manager" description = "A Substrate Runtime module that selects 2/3 of initial validators for every session" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 06d0b3fb0f8d..9cf84412575a 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -35,6 +35,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] @@ -162,6 +163,7 @@ mod tests { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index a6103f688c42..aad395fb7a30 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -3,13 +3,13 @@ name = "pallet-bridge-token-swap" description = "An Substrate pallet that allows parties on different chains (bridged using messages pallet) to swap their tokens" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -55,5 +55,5 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs index bbc544a8b91d..878cb20993a9 100644 --- a/modules/token-swap/src/benchmarking.rs +++ b/modules/token-swap/src/benchmarking.rs @@ -18,19 +18,19 @@ use crate::{ swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, - BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, + BridgedAccountSignatureOf, BridgedBalanceOf, Call, Origin, Pallet, ThisChainBalance, TokenSwapCreationOf, TokenSwapOf, }; use bp_token_swap::{TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType}; -use codec::Encode; +use codec::{Decode, Encode}; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Currency, Parameter}; use frame_system::RawOrigin; use sp_core::H256; use sp_io::hashing::blake2_256; -use sp_runtime::traits::Bounded; -use sp_std::vec::Vec; +use sp_runtime::traits::{Bounded, TrailingZeroInput}; +use sp_std::{boxed::Box, vec::Vec}; const SEED: u32 = 0; @@ -43,8 +43,9 @@ pub trait Config: crate::Config { benchmarks_instance_pallet! { where_clause { where - BridgedAccountPublicOf: Default + Parameter, - BridgedAccountSignatureOf: Default, + Origin: Into, + BridgedAccountPublicOf: Decode + Parameter, + BridgedAccountSignatureOf: Decode, } // @@ -138,8 +139,8 @@ fn test_swap_hash, I: 'static>(sender: T::AccountId, is_create: boo /// Returns test token swap creation params. fn test_swap_creation, I: 'static>() -> TokenSwapCreationOf where - BridgedAccountPublicOf: Default, - BridgedAccountSignatureOf: Default, + BridgedAccountPublicOf: Decode, + BridgedAccountSignatureOf: Decode, { TokenSwapCreation { target_public_at_bridged_chain: target_public_at_bridged_chain::(), @@ -176,20 +177,22 @@ fn target_balance_to_swap, I: 'static>() -> BridgedBalanceOf /// Public key of `target_account_at_bridged_chain`. fn target_public_at_bridged_chain, I: 'static>() -> BridgedAccountPublicOf where - BridgedAccountPublicOf: Default, + BridgedAccountPublicOf: Decode, { - Default::default() + BridgedAccountPublicOf::::decode(&mut TrailingZeroInput::zeroes()) + .expect("failed to decode `BridgedAccountPublicOf` from zeroes") } /// Signature of `target_account_at_bridged_chain` over message. fn bridged_currency_transfer_signature, I: 'static>() -> BridgedAccountSignatureOf where - BridgedAccountSignatureOf: Default, + BridgedAccountSignatureOf: Decode, { - Default::default() + BridgedAccountSignatureOf::::decode(&mut TrailingZeroInput::zeroes()) + .expect("failed to decode `BridgedAccountSignatureOf` from zeroes") } /// Account at the bridged chain that is participating in the swap. fn target_account_at_bridged_chain, I: 'static>() -> BridgedAccountIdOf { - Default::default() + account("target_account_at_bridged_chain", 0, SEED) } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 43fa13ba4bdb..e46a4bc2dd03 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -70,16 +70,18 @@ use bp_runtime::{messages::DispatchFeePayment, ChainId}; use bp_token_swap::{ RawBridgedTransferCall, TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType, }; -use codec::Encode; +use codec::{Decode, Encode}; use frame_support::{ fail, traits::{Currency, ExistenceRequirement}, weights::PostDispatchInfo, + RuntimeDebug, }; +use scale_info::TypeInfo; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; -use sp_std::boxed::Box; +use sp_std::{boxed::Box, marker::PhantomData}; use weights::WeightInfo; pub use weights_ext::WeightInfoExt; @@ -98,6 +100,21 @@ pub use pallet::*; /// Name of the `PendingSwaps` storage map. pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; +/// Origin for the token swap pallet. +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] +pub enum RawOrigin { + /// The call is originated by the token swap account. + TokenSwap { + /// Id of the account that has started the swap. + source_account_at_this_chain: AccountId, + /// Id of the account that holds the funds during this swap. The message fee is paid from + /// this account funds. + swap_account_at_this_chain: AccountId, + }, + /// Dummy to manage the fact we have instancing. + _Phantom(PhantomData), +} + // comes from #[pallet::event] #[allow(clippy::unused_unit)] #[frame_support::pallet] @@ -126,6 +143,7 @@ pub mod pallet { type OutboundMessageLaneId: Get; /// Messages bridge with Bridged chain. type MessagesBridge: MessagesBridge< + Self::Origin, Self::AccountId, >::Balance, MessagePayloadOf, @@ -182,6 +200,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] @@ -191,6 +210,7 @@ pub mod pallet { impl, I: 'static> Pallet where BridgedAccountPublicOf: Parameter, + Origin: Into, { /// Start token swap procedure. /// @@ -312,7 +332,11 @@ pub mod pallet { // `Currency::transfer` call on the bridged chain, but no checks are made - it is // the transaction submitter to ensure it is valid. let send_message_result = T::MessagesBridge::send_message( - bp_messages::source_chain::Sender::from(Some(swap_account.clone())), + RawOrigin::TokenSwap { + source_account_at_this_chain: swap.source_account_at_this_chain.clone(), + swap_account_at_this_chain: swap_account.clone(), + } + .into(), T::OutboundMessageLaneId::get(), bp_message_dispatch::MessagePayload { spec_version: bridged_chain_spec_version, @@ -515,6 +539,10 @@ pub mod pallet { InvalidClaimant, } + /// Origin for the token swap pallet. + #[pallet::origin] + pub type Origin = RawOrigin<::AccountId, I>; + /// Pending token swaps states. #[pallet::storage] pub type PendingSwaps, I: 'static = ()> = @@ -639,7 +667,7 @@ pub mod pallet { mod tests { use super::*; use crate::mock::*; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap}; const CAN_START_BLOCK_NUMBER: u64 = 10; const CAN_CLAIM_BLOCK_NUMBER: u64 = CAN_START_BLOCK_NUMBER + 1; @@ -687,7 +715,7 @@ mod tests { fn start_test_swap() { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(TokenSwapCreation { target_public_at_bridged_chain: bridged_chain_account_public(), @@ -712,7 +740,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), Box::new(test_swap_creation()), ), @@ -728,7 +756,7 @@ mod tests { swap.source_balance_at_this_chain = ExistentialDeposit::get() - 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -744,7 +772,7 @@ mod tests { swap.source_balance_at_this_chain = THIS_CHAIN_ACCOUNT_BALANCE + 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -762,7 +790,7 @@ mod tests { swap_creation.bridged_currency_transfer = transfer; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(swap_creation), ), @@ -775,14 +803,14 @@ mod tests { fn create_swap_fails_if_swap_is_active() { run_test(|| { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -797,7 +825,7 @@ mod tests { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER + 1); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -811,7 +839,7 @@ mod tests { run_test(|| { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -825,7 +853,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -857,7 +885,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed( + mock::Origin::signed( 1 + target_account_at_this_chain::(&test_swap()) ), test_swap(), @@ -874,7 +902,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsPending @@ -889,7 +919,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsFailed @@ -902,7 +934,9 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsInactive @@ -918,7 +952,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::FailedToTransferFromSwapAccount @@ -936,7 +972,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsTemporaryLocked @@ -954,7 +992,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::(&test_swap())), test_swap(), )); @@ -990,7 +1028,7 @@ mod tests { assert_noop!( Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap() ), Error::::MismatchedSwapSourceOrigin @@ -1004,7 +1042,10 @@ mod tests { start_test_swap(); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsPending ); }); @@ -1017,7 +1058,10 @@ mod tests { receive_test_swap_confirmation(true); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsConfirmed ); }); @@ -1027,7 +1071,10 @@ mod tests { fn cancel_swap_fails_if_swap_is_inactive() { run_test(|| { assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsInactive ); }); @@ -1044,7 +1091,10 @@ mod tests { ); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::FailedToTransferFromSwapAccount ); }); @@ -1060,7 +1110,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap() )); @@ -1130,4 +1180,12 @@ mod tests { ); }); } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + PendingSwaps::::storage_map_final_key(test_swap_hash()), + bp_token_swap::storage_keys::pending_swaps_key("TokenSwap", test_swap_hash()).0, + ); + } } diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 63edb323e1a4..ece7b16acc91 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -56,7 +56,7 @@ frame_support::construct_runtime! { { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Event}, - TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event}, + TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event, Origin}, } } @@ -91,6 +91,7 @@ impl frame_system::Config for TestRuntime { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } frame_support::parameter_types! { @@ -142,22 +143,34 @@ impl bp_runtime::Chain for BridgedChain { type Balance = BridgedBalance; type Index = u64; type Signature = BridgedAccountSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub struct TestMessagesBridge; -impl MessagesBridge> for TestMessagesBridge { +impl MessagesBridge> + for TestMessagesBridge +{ type Error = (); fn send_message( - sender: frame_system::RawOrigin, + sender: Origin, lane: LaneId, message: MessagePayloadOf, delivery_and_dispatch_fee: Balance, ) -> Result { - assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT)); assert_eq!(lane, OutboundMessageLaneId::get()); assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); + match sender.caller { + OriginCaller::TokenSwap(_) => (), + _ => panic!("unexpected origin"), + } match message.call[0] { OK_TRANSFER_CALL => Ok(SendMessageArtifacts { nonce: MESSAGE_NONCE, weight: 0 }), BAD_TRANSFER_CALL => Err(()), diff --git a/modules/token-swap/src/weights.rs b/modules/token-swap/src/weights.rs index 06cb6b85cf33..51c5d99de9c5 100644 --- a/modules/token-swap/src/weights.rs +++ b/modules/token-swap/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_token_swap` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-10-06, STEPS: 50, REPEAT: 20 +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -57,17 +57,17 @@ pub trait WeightInfo { pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn create_swap() -> Weight { - (116_040_000 as Weight) + (90_368_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn claim_swap() -> Weight { - (102_882_000 as Weight) + (88_397_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn cancel_swap() -> Weight { - (99_434_000 as Weight) + (91_253_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -76,17 +76,17 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn create_swap() -> Weight { - (116_040_000 as Weight) + (90_368_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn claim_swap() -> Weight { - (102_882_000 as Weight) + (88_397_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn cancel_swap() -> Weight { - (99_434_000 as Weight) + (91_253_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 6ff860357c7c..a676b565c33d 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-kusama" description = "Primitives of Kusama runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 9a6eb66d2286..a0a5990ca08a 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -17,13 +17,12 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +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; @@ -37,10 +36,11 @@ 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: 9100, + spec_version: 9180, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 5, + transaction_version: 11, + state_version: 0, }; // NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. @@ -81,17 +81,22 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; -/// Name of the With-Polkadot messages pallet instance in the Kusama runtime. -pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; +/// 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 `KusamaFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_header"; /// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -99,22 +104,6 @@ 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"; -/// Name of the `ToKusamaOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = - "ToKusamaOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToKusamaOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromKusamaInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromKusamaInboundLaneApi_latest_received_nonce"; -/// Name of the `FromKusamaInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromKusamaInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromKusamaInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = - "FromKusamaInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Kusama headers. @@ -124,8 +113,6 @@ sp_api::decl_runtime_apis! { pub trait KusamaFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Kusama chain. @@ -145,6 +132,7 @@ sp_api::decl_runtime_apis! { 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. @@ -156,22 +144,5 @@ sp_api::decl_runtime_apis! { 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 Kusama chain. - /// - /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the - /// Kusama runtime itself. - pub trait FromKusamaInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index f1e17fe96f5a..0aaeb5b6bf9d 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-millau" description = "Primitives of Millau runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -14,10 +14,10 @@ bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -impl-codec = { version = "0.5.1", default-features = false } +impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.10", default-features = false, features = ["primitive-types"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-util-mem = { version = "0.11", default-features = false, features = ["primitive-types"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 0092f7092bc0..ff8d53859535 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -17,12 +17,10 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] mod millau_hash; -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -30,13 +28,13 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_core::Hasher as HasherT; +use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; -use sp_trie::{trie_types::Layout, TrieConfiguration}; +use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -68,11 +66,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unrewarded relayer entries in Millau confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unconfirmed messages in Millau confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; /// Weight of single regular message delivery transaction on Millau chain. /// @@ -103,7 +101,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// 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; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// The target length of a session (how often authorities change) on Millau measured in of number of /// blocks. @@ -172,6 +170,17 @@ impl Chain for Millau { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. @@ -195,12 +204,18 @@ impl sp_core::Hasher for BlakeTwoAndKeccak256 { impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { type Output = MillauHash; - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - Layout::::trie_root(input) + fn trie_root(input: Vec<(Vec, Vec)>, state_version: StateVersion) -> Self::Output { + match state_version { + StateVersion::V0 => LayoutV0::::trie_root(input), + StateVersion::V1 => LayoutV1::::trie_root(input), + } } - fn ordered_trie_root(input: Vec>) -> Self::Output { - Layout::::ordered_trie_root(input) + fn ordered_trie_root(input: Vec>, state_version: StateVersion) -> Self::Output { + match state_version { + StateVersion::V0 => LayoutV0::::ordered_trie_root(input), + StateVersion::V1 => LayoutV1::::ordered_trie_root(input), + } } } @@ -246,21 +261,14 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} +/// Name of the With-Millau GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_MILLAU_GRANDPA_PALLET_NAME: &str = "BridgeMillauGrandpa"; +/// Name of the With-Millau messages pallet instance that is deployed at bridged chains. +pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} +/// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. +pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the With-Rialto messages pallet instance in the Millau runtime. -pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; /// Name of the With-Rialto token swap pallet instance in the Millau runtime. pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; @@ -273,22 +281,6 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; -/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToMillauOutboundLaneApi_latest_received_nonce"; -/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = - "ToMillauOutboundLaneApi_latest_generated_nonce"; - -/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromMillauInboundLaneApi_latest_received_nonce"; -/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromMillauInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = - "FromMillauInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Millau headers. @@ -298,8 +290,6 @@ sp_api::decl_runtime_apis! { pub trait MillauFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Millau chain. @@ -319,6 +309,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + millau_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. @@ -330,23 +321,6 @@ sp_api::decl_runtime_apis! { 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 Millau chain. - /// - /// This API is implemented by runtimes that are receiving messages from Millau chain, not the - /// Millau runtime itself. - pub trait FromMillauInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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; } } @@ -358,9 +332,9 @@ mod tests { #[test] fn maximal_account_size_does_not_overflow_constant() { assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::default().encode().len(), + AccountId::from([0u8; 32]).encode().len(), MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, ); } diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 917c7f974783..738899b658cd 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-polkadot" description = "Primitives of Polkadot runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 26bad1ea8656..d95e29c8b0ce 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -17,13 +17,12 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +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; @@ -37,10 +36,11 @@ 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: 9100, + spec_version: 9180, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 7, + transaction_version: 12, + state_version: 0, }; // NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. @@ -81,17 +81,22 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; -/// Name of the With-Kusama messages pallet instance in the Polkadot runtime. -pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; +/// 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 KSM->DOT conversion rate stored in the Polkadot runtime. +/// 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 `PolkadotFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_header"; /// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -99,22 +104,6 @@ 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"; -/// Name of the `ToPolkadotOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = - "ToPolkadotOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToPolkadotOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromPolkadotInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromPolkadotInboundLaneApi_latest_received_nonce"; -/// Name of the `FromPolkadotInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromPolkadotInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = - "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Polkadot headers. @@ -124,8 +113,6 @@ sp_api::decl_runtime_apis! { pub trait PolkadotFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Polkadot chain. @@ -145,6 +132,7 @@ sp_api::decl_runtime_apis! { 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. @@ -156,22 +144,5 @@ sp_api::decl_runtime_apis! { 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 Polkadot chain. - /// - /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the - /// Polkadot runtime itself. - pub trait FromPolkadotInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index 034188631b8c..a15c40929579 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-rialto-parachain" description = "Primitives of Rialto parachain runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 826f6d39bd7f..f3f449c7af3e 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_runtime::Chain; use frame_support::{ @@ -92,6 +90,17 @@ impl Chain for RialtoParachain { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } frame_support::parameter_types! { @@ -113,16 +122,3 @@ frame_support::parameter_types! { .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); } - -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index d16ac59484fb..663f9076657d 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-rialto" description = "Primitives of Rialto runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 6c4e48301e3b..4bf20489bc85 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -17,10 +17,8 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -30,7 +28,7 @@ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -59,11 +57,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unconfirmed messages in Rialto confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Rialto chain. /// @@ -94,7 +92,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// 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; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// The target length of a session (how often authorities change) on Rialto measured in of number of /// blocks. @@ -171,6 +169,17 @@ impl Chain for Rialto { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. @@ -215,21 +224,13 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} +/// Name of the With-Rialto GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_GRANDPA_PALLET_NAME: &str = "BridgeRialtoGrandpa"; +/// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} - -/// Name of the With-Millau messages pallet instance in the Rialto runtime. -pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; +/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime. +pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; /// Name of the parachain registrar pallet in the Rialto runtime. pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; @@ -246,22 +247,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToRialtoOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToRialtoOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromRialtoInboundLaneApi_latest_received_nonce"; -/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromRialtoInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = - "FromRialtoInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rialto headers. @@ -271,8 +256,6 @@ sp_api::decl_runtime_apis! { pub trait RialtoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Rialto chain. @@ -292,6 +275,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + rialto_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. @@ -303,23 +287,6 @@ sp_api::decl_runtime_apis! { 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 Rialto chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the - /// Rialto runtime itself. - pub trait FromRialtoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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; } } @@ -331,9 +298,9 @@ mod tests { #[test] fn maximal_account_size_does_not_overflow_constant() { assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::default().encode().len(), + AccountId::from([0u8; 32]).encode().len(), MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, ); } diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 6e1189b05f36..814cd09bf170 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -3,11 +3,11 @@ name = "bp-rococo" description = "Primitives of Rococo runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index b3bbc91976da..127e75d5f8b2 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -17,13 +17,12 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +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; @@ -32,22 +31,23 @@ pub use bp_polkadot_core::*; /// Rococo Chain pub type Rococo = PolkadotLike; -/// The target length of a session (how often authorities change) on Westend measured in of number +/// The target length of a session (how often authorities change) on Rococo 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 = 10 * time_units::MINUTES; +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-v1.6"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 9100, + 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. @@ -74,13 +74,13 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Wococo messages pallet instance in the Rococo runtime. -pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; +/// 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 `RococoFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_header"; /// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -88,22 +88,9 @@ 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"; -/// Name of the `ToRococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToRococoOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToRococoOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromRococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromRococoInboundLaneApi_latest_received_nonce"; -/// Name of the `FromRococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromRococoInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = - "FromRococoInboundLaneApi_unrewarded_relayers_state"; + +/// 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. /// @@ -122,8 +109,6 @@ sp_api::decl_runtime_apis! { pub trait RococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Rococo chain. @@ -143,6 +128,7 @@ sp_api::decl_runtime_apis! { 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. @@ -154,22 +140,5 @@ sp_api::decl_runtime_apis! { 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 Rococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the - /// Rococo runtime itself. - pub trait FromRococoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 4fd1652744ed..ee6e2b9be99a 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -3,18 +3,17 @@ name = "bp-westend" description = "Primitives of Westend runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -30,7 +29,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master default = ["std"] std = [ "bp-header-chain/std", - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 8beb897f59a1..c7ebe4b00fd5 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -17,10 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -56,10 +53,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("westend"), impl_name: sp_version::create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 51, + spec_version: 9140, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 5, + transaction_version: 8, + state_version: 0, }; /// Westend Runtime `Call` enum. @@ -88,33 +86,11 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Westend GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; + /// Name of the `WestendFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; -/// Name of the `WestendFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_header"; - -/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_WESTEND_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToWestendOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWestendOutboundLaneApi::message_details` runtime method. -pub const TO_WESTEND_MESSAGE_DETAILS_METHOD: &str = "ToWestendOutboundLaneApi_message_details"; -/// Name of the `ToWestendOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = - "ToWestendOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToWestendOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToWestendOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromWestendInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromWestendInboundLaneApi_latest_received_nonce"; -/// Name of the `FromWestendInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromWestendInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromWestendInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = - "FromWestendInboundLaneApi_unrewarded_relayers_state"; /// The target length of a session (how often authorities change) on Westend measured in of number /// of blocks. @@ -131,54 +107,5 @@ sp_api::decl_runtime_apis! { pub trait WestendFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; - } - - /// Outbound message lane API for messages that are sent to Westend chain. - /// - /// This API is implemented by runtimes that are sending messages to Westend chain, not the - /// Westend runtime itself. - pub trait ToWestendOutboundLaneApi { - /// 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 Westend 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, - ) -> 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>; - /// 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 Westend chain. - /// - /// This API is implemented by runtimes that are receiving messages from Westend chain, not the - /// Westend runtime itself. - pub trait FromWestendInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index d99783695ad3..633cdd15c1f5 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -3,11 +3,11 @@ name = "bp-wococo" description = "Primitives of Wococo runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index fe2ce3a309a6..f39543114c78 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -17,19 +17,25 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +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, PAY_INBOUND_DISPATCH_FEE_WEIGHT, SESSION_LENGTH, VERSION}; +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 { @@ -37,13 +43,13 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Rococo messages pallet instance in the Wococo runtime. -pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; +/// 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 `WococoFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header"; /// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -51,22 +57,6 @@ 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"; -/// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToWococoOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToWococoOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromWococoInboundLaneApi_latest_received_nonce"; -/// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromWococoInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = - "FromWococoInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Wococo headers. @@ -76,8 +66,6 @@ sp_api::decl_runtime_apis! { pub trait WococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Wococo chain. @@ -97,6 +85,7 @@ sp_api::decl_runtime_apis! { 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. @@ -108,22 +97,5 @@ sp_api::decl_runtime_apis! { 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 Wococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the - /// Wococo runtime itself. - pub trait FromWococoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the 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/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index b75a41a4b2e5..7cd688d0d819 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -3,15 +3,19 @@ name = "bp-header-chain" description = "A common interface for describing what a bridge pallet should be able to do." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -finality-grandpa = { version = "0.14.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } +# Bridge dependencies + +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -23,10 +27,13 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] assert_matches = "1.5" bp-test-utils = { path = "../test-utils" } +hex = "0.4" +hex-literal = "0.3" [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "finality-grandpa/std", "serde/std", diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5feb30aec3ee..28949f28de5d 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -29,6 +29,7 @@ use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT, Runtime use sp_std::boxed::Box; pub mod justification; +pub mod storage_keys; /// A type that can be used as a parameter in a dispatchable function. /// diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs new file mode 100644 index 000000000000..e123703eed50 --- /dev/null +++ b/primitives/header-chain/src/storage_keys.rs @@ -0,0 +1,78 @@ +// 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 . + +//! Storage keys of bridge GRANDPA pallet. + +/// Name of the `IsHalted` storage value. +pub const IS_HALTED_VALUE_NAME: &str = "IsHalted"; +/// Name of the `BestFinalized` storage value. +pub const BEST_FINALIZED_VALUE_NAME: &str = "BestFinalized"; + +use sp_core::storage::StorageKey; + +/// Storage key of the `IsHalted` flag in the runtime storage. +pub fn is_halted_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + IS_HALTED_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + +/// Storage key of the best finalized header hash value in the runtime storage. +pub fn best_finalized_hash_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + BEST_FINALIZED_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn is_halted_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // compatibility with previous pallet. + let storage_key = is_halted_key("BridgeGrandpa").0; + assert_eq!( + storage_key, + hex!("0b06f475eddb98cf933a12262e0388de9611a984bbd04e2fd39f97bbc006115f").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn best_finalized_hash_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // compatibility with previous pallet. + let storage_key = best_finalized_hash_key("BridgeGrandpa").0; + assert_eq!( + storage_key, + hex!("0b06f475eddb98cf933a12262e0388dea4ebafdd473c549fdb24c5c991c5591c").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 85846c6d50f9..5b4981a0f69a 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -136,7 +136,8 @@ fn justification_with_invalid_commit_rejected() { #[test] fn justification_with_invalid_authority_signature_rejected() { let mut justification = make_default_justification::(&test_header(1)); - justification.commit.precommits[0].signature = Default::default(); + justification.commit.precommits[0].signature = + sp_core::crypto::UncheckedFrom::unchecked_from([1u8; 64]); assert_eq!( verify_justification::( diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 9897b3199781..39b2d00111e1 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -3,13 +3,13 @@ name = "bp-message-dispatch" description = "Primitives of bridge messages dispatch modules." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 95dca2bea67b..2a84f74d225b 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -3,14 +3,14 @@ name = "bp-messages" description = "Primitives of messages module." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "bit-vec"] } +bitvec = { version = "1", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "1.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -21,16 +21,23 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +hex = "0.4" +hex-literal = "0.3" + [features] default = ["std"] std = [ + "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", "scale-info/std", "serde", + "sp-core/std", "sp-std/std" ] diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index abefe8d789b8..a4f204d238f7 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -30,6 +30,7 @@ use scale_info::TypeInfo; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; +pub mod storage_keys; pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. @@ -193,7 +194,7 @@ pub struct MessageDetails { } /// Bit vector of message dispatch results. -pub type DispatchResultsBitVec = BitVec; +pub type DispatchResultsBitVec = BitVec; /// Unrewarded relayer entry stored in the inbound lane data. /// @@ -224,11 +225,9 @@ impl DeliveredMessages { /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given /// dispatch result. pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { - DeliveredMessages { - begin: nonce, - end: nonce, - dispatch_results: bitvec![Msb0, u8; if dispatch_result { 1 } else { 0 }], - } + let mut dispatch_results = BitVec::with_capacity(1); + dispatch_results.push(if dispatch_result { true } else { false }); + DeliveredMessages { begin: nonce, end: nonce, dispatch_results } } /// Return total count of delivered messages. @@ -367,7 +366,7 @@ mod tests { messages: DeliveredMessages::new(i as _, true), }; entry.messages.dispatch_results = bitvec![ - Msb0, u8; + u8, Msb0; 1; (messages_count / relayer_entries) as _ ]; @@ -393,7 +392,7 @@ mod tests { #[test] fn message_dispatch_result_works() { let delivered_messages = - DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![Msb0, u8; 1; 151] }; + DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![u8, Msb0; 1; 151] }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 1ff05abf131e..fa7b3bb85ed0 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -28,7 +28,21 @@ use sp_std::{ }; /// The sender of the message on the source chain. -pub type Sender = frame_system::RawOrigin; +pub trait SenderOrigin { + /// Return id of the account that is sending this message. + /// + /// In regular messages configuration, when regular message is sent you'll always get `Some(_)` + /// from this call. This is the account that is paying send costs. However, there are some + /// examples when `None` may be returned from the call: + /// + /// - if the send-message call origin is either `frame_system::RawOrigin::Root` or + /// `frame_system::RawOrigin::None` and your configuration forbids such messages; + /// - if your configuration allows 'unpaid' messages sent by pallets. Then the pallet may just + /// use its own defined origin (not linked to any account) and the message will be accepted. + /// This may be useful for pallets that are sending important system-wide information (like + /// update of runtime version). + fn linked_account(&self) -> Option; +} /// Relayers rewards, grouped by relayer account id. pub type RelayersRewards = BTreeMap>; @@ -82,14 +96,14 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the /// lane. fn verify_message( - submitter: &Sender, + submitter: &SenderOrigin, delivery_and_dispatch_fee: &Fee, lane: &LaneId, outbound_data: &OutboundLaneData, @@ -110,14 +124,14 @@ pub trait LaneMessageVerifier { /// So to be sure that any non-altruist relayer would agree to deliver message, submitter /// should set `delivery_and_dispatch_fee` to at least (equivalent of): sum of fees from (2) /// to (4) above, plus some interest for the relayer. -pub trait MessageDeliveryAndDispatchPayment { +pub trait MessageDeliveryAndDispatchPayment { /// Error type. type Error: Debug + Into<&'static str>; /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &SenderOrigin, fee: &Balance, relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; @@ -145,7 +159,7 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; @@ -153,7 +167,7 @@ pub trait MessagesBridge { /// /// Returns unique message nonce or error if send has failed. fn send_message( - sender: Sender, + sender: SenderOrigin, lane: LaneId, message: Payload, delivery_and_dispatch_fee: Balance, @@ -164,13 +178,13 @@ pub trait MessagesBridge { #[derive(RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl MessagesBridge - for NoopMessagesBridge +impl + MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message( - _sender: Sender, + _sender: SenderOrigin, _lane: LaneId, _message: Payload, _delivery_and_dispatch_fee: Balance, @@ -245,13 +259,13 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier - for ForbidOutboundMessages +impl + LaneMessageVerifier for ForbidOutboundMessages { type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &SenderOrigin, _delivery_and_dispatch_fee: &Fee, _lane: &LaneId, _outbound_data: &OutboundLaneData, @@ -261,13 +275,13 @@ impl LaneMessageVerifier } } -impl MessageDeliveryAndDispatchPayment - for ForbidOutboundMessages +impl + MessageDeliveryAndDispatchPayment for ForbidOutboundMessages { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - _submitter: &Sender, + _submitter: &SenderOrigin, _fee: &Balance, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs new file mode 100644 index 000000000000..19494b8b8527 --- /dev/null +++ b/primitives/messages/src/storage_keys.rs @@ -0,0 +1,128 @@ +// 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 . + +//! Storage keys of bridge messages pallet. + +/// Name of the `OPERATING_MODE_VALUE_NAME` storage value. +pub const OPERATING_MODE_VALUE_NAME: &str = "PalletOperatingMode"; +/// Name of the `OutboundMessages` storage map. +pub const OUTBOUND_MESSAGES_MAP_NAME: &str = "OutboundMessages"; +/// Name of the `OutboundLanes` storage map. +pub const OUTBOUND_LANES_MAP_NAME: &str = "OutboundLanes"; +/// Name of the `InboundLanes` storage map. +pub const INBOUND_LANES_MAP_NAME: &str = "InboundLanes"; + +use crate::{LaneId, MessageKey, MessageNonce}; + +use codec::Encode; +use frame_support::Blake2_128Concat; +use sp_core::storage::StorageKey; + +/// Storage key of the `PalletOperatingMode` value in the runtime storage. +pub fn operating_mode_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + OPERATING_MODE_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + +/// Storage key of the outbound message in the runtime storage. +pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + OUTBOUND_MESSAGES_MAP_NAME, + &MessageKey { lane_id: *lane, nonce }.encode(), + ) +} + +/// Storage key of the outbound message lane state in the runtime storage. +pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + OUTBOUND_LANES_MAP_NAME, + lane, + ) +} + +/// Storage key of the inbound message lane state in the runtime storage. +pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + INBOUND_LANES_MAP_NAME, + lane, + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn operating_mode_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is possibly + // breaking all existing message relays. + let storage_key = operating_mode_key("BridgeMessages").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed010f4cf0917788d791142ff6c1f216e7b3").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn storage_message_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted messages proofs. + let storage_key = message_key("BridgeMessages", &*b"test", 42).0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn outbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted outbound lane state proofs. + let storage_key = outbound_lane_data_key("BridgeMessages", &*b"test").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn inbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted inbound lane state proofs. + let storage_key = inbound_lane_data_key("BridgeMessages", &*b"test").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index f05edd0d91ba..1542a784ef56 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -3,12 +3,12 @@ name = "bp-polkadot-core" description = "Primitives of Polkadot-like runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 38e43d312b5d..79db07b82cbb 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; -use bp_runtime::Chain; +use bp_runtime::{Chain, EncodedOrDecodedCall}; use frame_support::{ dispatch::Dispatchable, parameter_types, @@ -33,7 +33,8 @@ use scale_info::{StaticTypeInfo, TypeInfo}; use sp_core::Hasher as HasherT; use sp_runtime::{ generic, - traits::{BlakeTwo256, IdentifyAccount, Verify}, + traits::{BlakeTwo256, DispatchInfoOf, IdentifyAccount, Verify}, + transaction_validity::TransactionValidityError, MultiAddress, MultiSignature, OpaqueExtrinsic, }; use sp_std::prelude::Vec; @@ -115,31 +116,17 @@ parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can -/// use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Polkadot-like chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} - // TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; /// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; // TODO [#438] should be selected keeping in mind: // finality delay on both chains + reward payout cost + messages throughput. /// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; // One important thing about weight-related constants here is that actually we may have // different weights on different Polkadot-like chains. But now all deployments are @@ -241,25 +228,34 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic>; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< + AccountAddress, + EncodedOrDecodedCall, + Signature, + SignedExtensions, +>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; /// A type of the data encoded as part of the transaction. -pub type SignedExtra = ((), (), (), sp_runtime::generic::Era, Compact, (), Compact); +pub type SignedExtra = + ((), (), (), (), sp_runtime::generic::Era, Compact, (), Compact); /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). -pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); +pub type AdditionalSigned = ((), u32, u32, Hash, Hash, (), (), ()); /// A simplified version of signed extensions meant for producing signed transactions /// and signed payload in the client code. #[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] pub struct SignedExtensions { encode_payload: SignedExtra, - additional_signed: AdditionalSigned, + // It may be set to `None` if extensions are decoded. We are never reconstructing transactions + // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to + // read fields of `encode_payload`. And when resigning transaction, we're reconstructing + // `SignedExtensions` from the scratch. + additional_signed: Option, _data: sp_std::marker::PhantomData, } @@ -271,15 +267,20 @@ impl parity_scale_codec::Encode for SignedExtensions { impl parity_scale_codec::Decode for SignedExtensions { fn decode( - _input: &mut I, + input: &mut I, ) -> Result { - unimplemented!("SignedExtensions are never meant to be decoded, they are only used to create transaction"); + SignedExtra::decode(input).map(|encode_payload| SignedExtensions { + encode_payload, + additional_signed: None, + _data: Default::default(), + }) } } impl SignedExtensions { pub fn new( - version: sp_version::RuntimeVersion, + spec_version: u32, + transaction_version: u32, era: bp_runtime::TransactionEraOf, genesis_hash: Hash, nonce: Nonce, @@ -287,6 +288,7 @@ impl SignedExtensions { ) -> Self { Self { encode_payload: ( + (), // non-zero sender (), // spec version (), // tx version (), // genesis @@ -295,15 +297,16 @@ impl SignedExtensions { (), // Check weight tip.into(), // transaction payment / tip (compact encoding) ), - additional_signed: ( - version.spec_version, - version.transaction_version, + additional_signed: Some(( + (), + spec_version, + transaction_version, genesis_hash, era.signed_payload(genesis_hash), (), (), (), - ), + )), _data: Default::default(), } } @@ -312,12 +315,12 @@ impl SignedExtensions { impl SignedExtensions { /// Return signer nonce, used to craft transaction. pub fn nonce(&self) -> Nonce { - self.encode_payload.4.into() + self.encode_payload.5.into() } /// Return transaction tip. pub fn tip(&self) -> Balance { - self.encode_payload.6.into() + self.encode_payload.7.into() } } @@ -343,7 +346,23 @@ where fn additional_signed( &self, ) -> Result { - Ok(self.additional_signed) + // we shall not ever see this error in relay, because we are never signing decoded + // transactions. Instead we're constructing and signing new transactions. So the error code + // is kinda random here + self.additional_signed + .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( + frame_support::unsigned::UnknownTransaction::Custom(0xFF), + )) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) } } @@ -361,6 +380,17 @@ impl Chain for PolkadotLike { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. @@ -401,7 +431,7 @@ mod tests { #[test] fn maximal_encoded_account_id_size_is_correct() { - let actual_size = AccountId::default().encode().len(); + let actual_size = AccountId::from([0u8; 32]).encode().len(); assert!( actual_size <= MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize, "Actual size of encoded account id for Polkadot-like chains ({}) is larger than expected {}", diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7cc165fb4e9c..085cfb9dbc6d 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -3,14 +3,14 @@ name = "bp-runtime" description = "Primitives that may be used at (bridges) runtime level." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index e24694bf8b0f..5a7fafe9f67c 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use frame_support::Parameter; -use num_traits::{AsPrimitive, Bounded, CheckedSub, SaturatingAdd, Zero}; +use codec::{Decode, Encode}; +use frame_support::{weights::Weight, Parameter}; +use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ traits::{ AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, @@ -23,7 +24,69 @@ use sp_runtime::{ }, FixedPointOperand, }; -use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr}; +use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec}; + +/// Chain call, that is either SCALE-encoded, or decoded. +#[derive(Debug, Clone, PartialEq)] +pub enum EncodedOrDecodedCall { + /// The call that is SCALE-encoded. + /// + /// This variant is used when we the chain runtime is not bundled with the relay, but + /// we still need the represent call in some RPC calls or transactions. + Encoded(Vec), + /// The decoded call. + Decoded(ChainCall), +} + +impl EncodedOrDecodedCall { + /// Returns decoded call. + pub fn to_decoded(&self) -> Result { + match self { + Self::Encoded(ref encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()), + } + } + + /// Converts self to decoded call. + pub fn into_decoded(self) -> Result { + match self { + Self::Encoded(encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(decoded_call) => Ok(decoded_call), + } + } +} + +impl From for EncodedOrDecodedCall { + fn from(call: ChainCall) -> EncodedOrDecodedCall { + EncodedOrDecodedCall::Decoded(call) + } +} + +impl Decode for EncodedOrDecodedCall { + fn decode(input: &mut I) -> Result { + // having encoded version is better than decoded, because decoding isn't required + // everywhere and for mocked calls it may lead to **unneeded** errors + match input.remaining_len()? { + Some(remaining_len) => { + let mut encoded_call = vec![0u8; remaining_len]; + input.read(&mut encoded_call)?; + Ok(EncodedOrDecodedCall::Encoded(encoded_call)) + }, + None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)), + } + } +} + +impl Encode for EncodedOrDecodedCall { + fn encode(&self) -> Vec { + match *self { + Self::Encoded(ref encoded_call) => encoded_call.clone(), + Self::Decoded(ref decoded_call) => decoded_call.encode(), + } + } +} /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { @@ -46,6 +109,7 @@ pub trait Chain: Send + Sync + 'static { + MaybeMallocSizeOf + AsPrimitive + Default + + Saturating // original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but // `sp_runtime::generic::Era` requires block number -> `u64` conversion. + Into; @@ -82,13 +146,7 @@ pub trait Chain: Send + Sync + 'static { + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. - type AccountId: Parameter - + Member - + MaybeSerializeDeserialize - + Debug - + MaybeDisplay - + Ord - + Default; + type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord; /// Balance of an account in native tokens. /// /// The chain may support multiple tokens, but this particular type is for token that is used @@ -119,6 +177,11 @@ pub trait Chain: Send + Sync + 'static { + Copy; /// Signature type, used on this chain. type Signature: Parameter + Verify; + + /// Get the maximum size (in bytes) of a Normal extrinsic at this chain. + fn max_extrinsic_size() -> u32; + /// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use. + fn max_extrinsic_weight() -> Weight; } /// Block number used by the chain. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 051dc1f43c00..1d8a40339ab0 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -22,11 +22,11 @@ use codec::Encode; use frame_support::{RuntimeDebug, StorageHasher}; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; -use sp_std::{convert::TryFrom, vec::Vec}; +use sp_std::{convert::TryFrom, vec, vec::Vec}; pub use chain::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, - IndexOf, SignatureOf, TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, + HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; @@ -201,47 +201,22 @@ impl, BlockHash: Copy> TransactionEra( pallet_prefix: &str, map_name: &str, key: &[u8], ) -> StorageKey { - storage_map_final_key_identity( - pallet_prefix, - map_name, - &frame_support::Blake2_128Concat::hash(key), - ) -} - -/// -pub fn storage_map_final_key_twox64_concat( - pallet_prefix: &str, - map_name: &str, - key: &[u8], -) -> StorageKey { - storage_map_final_key_identity(pallet_prefix, map_name, &frame_support::Twox64Concat::hash(key)) -} - -/// This is a copy of the -/// `frame_support::storage::generator::StorageMap::storage_map_final_key` for `Identity` maps. -/// -/// We're using it because to call `storage_map_final_key` directly, we need access to the runtime -/// and pallet instance, which (sometimes) is impossible. -pub fn storage_map_final_key_identity( - pallet_prefix: &str, - map_name: &str, - key_hashed: &[u8], -) -> StorageKey { + let key_hashed = H::hash(key); let pallet_prefix_hashed = frame_support::Twox128::hash(pallet_prefix.as_bytes()); let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes()); let mut final_key = Vec::with_capacity( - pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len(), + pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(), ); final_key.extend_from_slice(&pallet_prefix_hashed[..]); @@ -254,7 +229,7 @@ pub fn storage_map_final_key_identity( /// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false; /// }`) is computed. /// -/// Copied from `frame_support::parameter_types` macro +/// Copied from `frame_support::parameter_types` macro. pub fn storage_parameter_key(parameter_name: &str) -> StorageKey { let mut buffer = Vec::with_capacity(1 + parameter_name.len() + 1); buffer.push(b':'); @@ -263,6 +238,20 @@ pub fn storage_parameter_key(parameter_name: &str) -> StorageKey { StorageKey(sp_io::hashing::twox_128(&buffer).to_vec()) } +/// This is how a storage key of storage value is computed. +/// +/// Copied from `frame_support::storage::storage_prefix`. +pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey { + let pallet_hash = sp_io::hashing::twox_128(pallet_prefix.as_bytes()); + let storage_hash = sp_io::hashing::twox_128(value_name.as_bytes()); + + let mut final_key = vec![0u8; 32]; + final_key[..16].copy_from_slice(&pallet_hash); + final_key[16..].copy_from_slice(&storage_hash); + + StorageKey(final_key) +} + #[cfg(test)] mod tests { use super::*; @@ -274,4 +263,17 @@ mod tests { StorageKey(hex_literal::hex!("58942375551bb0af1682f72786b59d04").to_vec()), ); } + + #[test] + fn storage_value_key_works() { + assert_eq!( + storage_value_key("PalletTransactionPayment", "NextFeeMultiplier"), + StorageKey( + hex_literal::hex!( + "f0e954dfcca51a255ab12c60c789256a3f2edf3bdf381debe331ab7446addfdc" + ) + .to_vec() + ), + ); + } } diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 9cc5b48ebd91..4a99ab6210f4 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -19,7 +19,7 @@ use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; -use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof}; +use sp_trie::{read_trie_value, LayoutV1, MemoryDB, StorageProof}; /// This struct is used to read storage values from a subset of a Merklized database. The "proof" /// is a subset of the nodes in the Merkle structure of the database, so that it provides @@ -52,7 +52,8 @@ where /// Reads a value from the available subset of storage. If the value cannot be read due to an /// incomplete or otherwise invalid proof, this returns an error. pub fn read_value(&self, key: &[u8]) -> Result>, Error> { - read_trie_value::, _>(&self.db, &self.root, key) + // LayoutV1 or LayoutV0 is identical for proof that only read values. + read_trie_value::, _>(&self.db, &self.root, key) .map_err(|_| Error::StorageValueUnavailable) } } @@ -70,20 +71,24 @@ pub enum Error { pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; + let state_version = sp_runtime::StateVersion::default(); + // construct storage proof - let backend = >::from(vec![ - (None, vec![(b"key1".to_vec(), Some(b"value1".to_vec()))]), - (None, vec![(b"key2".to_vec(), Some(b"value2".to_vec()))]), - (None, vec![(b"key3".to_vec(), Some(b"value3".to_vec()))]), - // Value is too big to fit in a branch node - (None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]), - ]); - let root = backend.storage_root(std::iter::empty()).0; + let backend = >::from(( + vec![ + (None, vec![(b"key1".to_vec(), Some(b"value1".to_vec()))]), + (None, vec![(b"key2".to_vec(), Some(b"value2".to_vec()))]), + (None, vec![(b"key3".to_vec(), Some(b"value3".to_vec()))]), + // Value is too big to fit in a branch node + (None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]), + ], + state_version, + )); + let root = backend.storage_root(std::iter::empty(), state_version).0; let proof = StorageProof::new( prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) .unwrap() - .iter_nodes() - .collect(), + .iter_nodes(), ); (root, proof) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 3876f0200a9e..6da5c7c0f4b5 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -2,14 +2,14 @@ name = "bp-test-utils" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } -codec = { package = "parity-scale-codec", version = "2.2.0", 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.14.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 059d6eb5be4f..2436d7933923 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -19,7 +19,6 @@ use codec::Encode; use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; -use sp_application_crypto::Public; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; @@ -70,7 +69,7 @@ impl Account { impl From for AuthorityId { fn from(p: Account) -> Self { - AuthorityId::from_slice(&p.public().to_bytes()) + sp_application_crypto::UncheckedFrom::unchecked_from(p.public().to_bytes()) } } diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 4b16c3567ea6..9097856f853a 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -3,25 +3,36 @@ name = "bp-token-swap" description = "Primitives of the pallet-bridge-token-swap pallet" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } + +# Bridge Dependencies + +bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +hex = "0.4" +hex-literal = "0.3" + [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "frame-support/std", "scale-info/std", "sp-core/std", + "sp-io/std", "sp-std/std", ] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index d46389e86891..79363e5477a4 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -16,10 +16,13 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub mod storage_keys; + use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; -use sp_core::U256; +use sp_core::{H256, U256}; +use sp_io::hashing::blake2_256; use sp_std::vec::Vec; /// Pending token swap state. @@ -85,6 +88,18 @@ pub struct TokenSwap + TokenSwap +where + TokenSwap: + Encode, +{ + /// Returns hash, used to identify this token swap. + pub fn hash(&self) -> H256 { + self.using_encoded(blake2_256).into() + } +} + /// SCALE-encoded `Currency::transfer` call on the bridged chain. pub type RawBridgedTransferCall = Vec; diff --git a/primitives/token-swap/src/storage_keys.rs b/primitives/token-swap/src/storage_keys.rs new file mode 100644 index 000000000000..d0aafc0d5c27 --- /dev/null +++ b/primitives/token-swap/src/storage_keys.rs @@ -0,0 +1,51 @@ +// 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 . + +//! Storage keys of bridge token swap pallet. + +use frame_support::Identity; +use sp_core::{storage::StorageKey, H256}; + +/// Name of the `PendingSwaps` storage map. +pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; + +/// Storage key of `PendingSwaps` value with given token swap hash. +pub fn pending_swaps_key(pallet_prefix: &str, token_swap_hash: H256) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + PENDING_SWAPS_MAP_NAME, + token_swap_hash.as_ref(), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn pending_swaps_key_computed_properly() { + // If this test fails, then something has been changed in module storage that may break + // all previous swaps. + let storage_key = pending_swaps_key("BridgeTokenSwap", [42u8; 32].into()).0; + assert_eq!( + storage_key, + hex!("76276da64e7a4f454760eedeb4bad11adca2227fef56ad07cc424f1f5d128b9a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a28c61262f40..fb8ff467d047 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "substrate-relay" -version = "0.1.0" +version = "1.0.1" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" async-std = "1.9.0" -codec = { package = "parity-scale-codec", version = "2.2.0" } +async-trait = "0.1.42" +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" hex = "0.4" log = "0.4.14" @@ -30,15 +31,16 @@ bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } -bp-token-swap = { path = "../../primitives/token-swap" } -bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } +bp-token-swap = { path = "../../primitives/token-swap" } bp-westend = { path = "../../primitives/chain-westend" } +bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-token-swap = { path = "../../modules/token-swap" } relay-kusama-client = { path = "../client-kusama" } @@ -72,8 +74,9 @@ polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", bran polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } [dev-dependencies] +bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.2" -finality-grandpa = { version = "0.14.0" } +finality-grandpa = { version = "0.15.0" } diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index b12d23f2a56d..9cdc6cd125e0 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -14,17 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Kusama. @@ -33,21 +36,16 @@ use crate::cli::{ /// calls in the future. But since it is used only in tests (and on test chains), this is ok. pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; -/// Id of Kusama token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "kusama"; - impl CliEncodeCall for Kusama { - fn max_extrinsic_size() -> u32 { - bp_kusama::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::KUSAMA_TO_POLKADOT_INDEX => { @@ -57,6 +55,7 @@ impl CliEncodeCall for Kusama { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -67,13 +66,11 @@ impl CliEncodeCall for Kusama { }) } - fn get_dispatch_info( - call: &relay_kusama_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_kusama_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -87,30 +84,52 @@ impl CliChain for Kusama { const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_kusama::AccountId, + bp_polkadot::AccountPublic, + bp_polkadot::Signature, + Vec, + >; fn ss58_format() -> u16 { - 42 - } - - fn max_extrinsic_weight() -> Weight { - bp_kusama::max_extrinsic_weight() + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::KusamaAccount, + ) + .into() } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Kusama is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Kusama's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Kusama; + type Target = relay_polkadot_client::Polkadot; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::KUSAMA_TO_POLKADOT_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Polkadot call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } - -/// Storage key and initial value of Polkadot -> Kusama conversion rate. -pub(crate) fn polkadot_to_kusama_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index ce631ef41e0a..0c0ba2272c7e 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -16,95 +16,52 @@ //! Kusama-to-Polkadot headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_kusama_client::{Kusama, SyncHeader as KusamaSyncHeader}; -use relay_polkadot_client::{Polkadot, SigningParams as PolkadotSigningParams}; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use async_trait::async_trait; +use relay_polkadot_client::Polkadot; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. /// /// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 -/// DOT, but let's round up to 30 DOT here. -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000; - -/// Kusama-to-Polkadot finality sync pipeline. -pub(crate) type FinalityPipelineKusamaFinalityToPolkadot = - SubstrateFinalityToSubstrate; - +/// DOT, and initial value of this constant was rounded up to 30 DOT. But for actual Kusama <> +/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory +/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against +/// relay/deployment issues, let's limit it so something that is much larger than this estimation - +/// e.g. to 100 DOT. +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100 * 10_000_000_000; + +/// Description of Kusama -> Polkadot finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct KusamaFinalityToPolkadot { - finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot, -} - -impl KusamaFinalityToPolkadot { - pub fn new(target_client: Client, target_sign: PolkadotSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new( - target_client, - target_sign, - ), - } - } -} - +pub struct KusamaFinalityToPolkadot; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + KusamaFinalityToPolkadot, + KusamaFinalityToPolkadotCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa, + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof +); + +#[async_trait] impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { - type FinalitySyncPipeline = FinalityPipelineKusamaFinalityToPolkadot; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - + type SourceChain = relay_kusama_client::Kusama; type TargetChain = Polkadot; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn start_relay_guards(&self) { - relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), - bp_polkadot::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder; + type TransactionSignScheme = Polkadot; + + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } - - fn transactions_author(&self) -> bp_polkadot::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: KusamaSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) + ) + .await } } @@ -132,7 +89,7 @@ pub(crate) mod tests { // differ from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is // the same. type GrandpaPalletWeights = - pallet_bridge_grandpa::weights::RialtoWeight; + pallet_bridge_grandpa::weights::MillauWeight; // The following formula shall not be treated as super-accurate - guard is to protect from // mad relays, not to protect from over-average loses. diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 32133adc3e54..9a71fbe3c621 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -16,316 +16,64 @@ //! Kusama-to-Polkadot messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; use frame_support::weights::Weight; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; -/// Kusama-to-Polkadot message lane. -pub type MessageLaneKusamaMessagesToPolkadot = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct KusamaMessagesToPolkadot { - message_lane: MessageLaneKusamaMessagesToPolkadot, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Kusama -> Polkadot messages bridge. +#[derive(Clone, Debug)] +pub struct KusamaMessagesToPolkadot; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof +); +substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( + Kusama, + KusamaMessagesToPolkadotUpdateConversionRateCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter, + relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate +); impl SubstrateMessageLane for KusamaMessagesToPolkadot { - type MessageLane = MessageLaneKusamaMessagesToPolkadot; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); type SourceChain = Kusama; type TargetChain = Polkadot; - fn source_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: PolkadotHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama confirmation transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: KusamaHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; + type SourceTransactionSignScheme = Kusama; + type TargetTransactionSignScheme = Polkadot; - let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot delivery transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Kusama node as messages source. -type KusamaSourceClient = SubstrateMessagesSource; - -/// Polkadot node as messages target. -type PolkadotTargetClient = SubstrateMessagesTarget; - -/// Run Kusama-to-Polkadot messages sync. -pub async fn run( - params: MessagesRelayParams< - Kusama, - KusamaSigningParams, - Polkadot, - PolkadotSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Kusama::AVERAGE_BLOCK_INTERVAL, - Polkadot::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = KusamaMessagesToPolkadot { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_kusama, - }, - }; + type ReceiveMessagesProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder; - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_polkadot::max_extrinsic_size() / 3; - // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_polkadot::max_extrinsic_weight(), - bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Kusama -> Polkadot messages relay.\n\t\ - Kusama relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Kusama::AVERAGE_BLOCK_INTERVAL, - target_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - KusamaSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - PolkadotTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Kusama -> Polkadot messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - ) -} + type TargetToSourceChainConversionRateUpdateBuilder = + KusamaMessagesToPolkadotUpdateConversionRateCallBuilder; -/// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. -pub(crate) async fn update_polkadot_to_kusama_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( - Kusama::sign_transaction( - genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter( - relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ) - ) - ), - transaction_nonce, - ), - ) - .encode(), - ) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 755d7cc4430a..1fc1e8308ef4 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -25,37 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::kusama::TOKEN_ID; - impl CliEncodeCall for Millau { - fn max_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer { dest: recipient.raw_id(), value: amount.cast(), - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::MILLAU_TO_RIALTO_INDEX => { @@ -67,6 +57,7 @@ impl CliEncodeCall for Millau { delivery_and_dispatch_fee: fee.cast(), }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -76,8 +67,8 @@ impl CliEncodeCall for Millau { }) } - fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -96,10 +87,6 @@ impl CliChain for Millau { millau_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_millau::max_extrinsic_weight() - } - // TODO [#854|#843] support multiple bridges? fn encode_message( message: encode_message::MessagePayload, @@ -107,7 +94,7 @@ impl CliChain for Millau { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Millau's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Millau; type Target = relay_rialto_client::Rialto; @@ -119,11 +106,13 @@ impl CliChain for Millau { bridge::MILLAU_TO_RIALTO_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, @@ -132,11 +121,3 @@ impl CliChain for Millau { } } } - -/// Storage key and initial value of Rialto -> Millau conversion rate. -pub(crate) fn rialto_to_millau_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), - millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, - ) -} diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 14a0430f6a91..584f0a9bb1d8 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -16,65 +16,22 @@ //! Millau-to-Rialto headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Millau-to-Rialto finality sync pipeline. -pub(crate) type FinalityPipelineMillauToRialto = - SubstrateFinalityToSubstrate; - +/// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct MillauFinalityToRialto { - finality_pipeline: FinalityPipelineMillauToRialto, -} - -impl MillauFinalityToRialto { - pub fn new(target_client: Client, target_sign: RialtoSigningParams) -> Self { - Self { finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign) } - } -} +pub struct MillauFinalityToRialto; impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { - type FinalitySyncPipeline = FinalityPipelineMillauToRialto; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - - type TargetChain = Rialto; - - fn transactions_author(&self) -> bp_rialto::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: MillauSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_millau_client::Millau; + type TargetChain = relay_rialto_client::Rialto; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::MillauGrandpaInstance, + >; + type TransactionSignScheme = relay_rialto_client::Rialto; } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index c4179eea330f..f20669e6c7a5 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,310 +16,55 @@ //! Millau-to-Rialto messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Millau-to-Rialto message lane. -pub type MessageLaneMillauMessagesToRialto = - SubstrateMessageLaneToSubstrate; -#[derive(Clone)] -pub struct MillauMessagesToRialto { - message_lane: MessageLaneMillauMessagesToRialto, -} +/// Description of Millau -> Rialto messages bridge. +#[derive(Clone, Debug)] +pub struct MillauMessagesToRialto; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + Millau, + MillauMessagesToRialtoUpdateConversionRateCallBuilder, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate +); impl SubstrateMessageLane for MillauMessagesToRialto { - type MessageLane = MessageLaneMillauMessagesToRialto; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; type SourceChain = Millau; type TargetChain = Rialto; - fn source_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: RialtoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: millau_runtime::Call = - millau_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } + type SourceTransactionSignScheme = Millau; + type TargetTransactionSignScheme = Rialto; - fn target_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; - fn make_messages_delivery_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: MillauHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; - -/// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; - -/// Run Millau-to-Rialto messages sync. -pub async fn run( - params: MessagesRelayParams< - Millau, - MillauSigningParams, - Rialto, - RialtoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Millau::AVERAGE_BLOCK_INTERVAL, - Rialto::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = MillauMessagesToRialto { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_millau, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3; - // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_rialto::max_extrinsic_weight(), - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Millau -> Rialto messages relay.\n\t\ - Millau relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Millau::AVERAGE_BLOCK_INTERVAL, - target_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - MillauSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RialtoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Millau -> Rialto messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - ) -} + type TargetToSourceChainConversionRateUpdateBuilder = + MillauMessagesToRialtoUpdateConversionRateCallBuilder; -/// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. -pub(crate) async fn update_rialto_to_millau_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( - Millau::sign_transaction( - genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - millau_runtime::MessagesCall::update_pallet_parameter { - parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - } - .into(), - transaction_nonce, - ), - ) - .encode(), - ) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index e9cb2d9b737f..16901143e19f 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -39,27 +39,16 @@ mod rococo; mod westend; mod wococo; -use relay_utils::metrics::{MetricsParams, StandaloneMetric}; - -pub(crate) fn add_polkadot_kusama_price_metrics( - params: MetricsParams, -) -> anyhow::Result { - substrate_relay_helper::helpers::token_price_metric(polkadot::TOKEN_ID)? - .register_and_spawn(¶ms.registry)?; - substrate_relay_helper::helpers::token_price_metric(kusama::TOKEN_ID)? - .register_and_spawn(¶ms.registry)?; - Ok(params) -} - #[cfg(test)] mod tests { use crate::cli::{encode_call, send_message}; use bp_messages::source_chain::TargetHeaderChain; + use bp_runtime::Chain as _; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; use relay_rialto_client::Rialto; - use relay_substrate_client::{TransactionSignScheme, UnsignedTransaction}; + use relay_substrate_client::{SignParam, TransactionSignScheme, UnsignedTransaction}; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -114,8 +103,8 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_size(), ); let call: millau_runtime::Call = @@ -147,8 +136,8 @@ mod tests { fn maximal_size_remark_to_rialto_is_generated_correctly() { assert!( bridge_runtime_common::messages::target::maximal_incoming_message_size( - bp_rialto::max_extrinsic_size() - ) > bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size() + ) > bp_millau::Millau::max_extrinsic_size(), "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", ) } @@ -158,7 +147,7 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark { remark: vec![] }.into(); @@ -187,7 +176,7 @@ mod tests { use millau_runtime::rialto_messages::Rialto; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark { remark: vec![] }.into(); @@ -215,12 +204,15 @@ mod tests { fn rialto_tx_extra_bytes_constant_is_correct() { let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); - let rialto_tx = Rialto::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(rialto_call.clone(), 0), - ); + let rialto_tx = Rialto::sign_transaction(SignParam { + spec_version: 1, + transaction_version: 1, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(rialto_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, @@ -234,12 +226,15 @@ mod tests { fn millau_tx_extra_bytes_constant_is_correct() { let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); - let millau_tx = Millau::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(millau_call.clone(), 0), - ); + let millau_tx = Millau::sign_transaction(SignParam { + spec_version: 0, + transaction_version: 0, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(millau_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 7b6256d1749f..7ae1cbc47777 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -14,17 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Polkadot. @@ -33,21 +36,16 @@ use crate::cli::{ /// calls in the future. But since it is used only in tests (and on test chains), this is ok. pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; -/// Id of Polkadot token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "polkadot"; - impl CliEncodeCall for Polkadot { - fn max_extrinsic_size() -> u32 { - bp_polkadot::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::POLKADOT_TO_KUSAMA_INDEX => { @@ -57,6 +55,7 @@ impl CliEncodeCall for Polkadot { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -67,13 +66,11 @@ impl CliEncodeCall for Polkadot { }) } - fn get_dispatch_info( - call: &relay_polkadot_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_polkadot_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -87,30 +84,52 @@ impl CliChain for Polkadot { const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_polkadot::AccountId, + bp_kusama::AccountPublic, + bp_kusama::Signature, + Vec, + >; fn ss58_format() -> u16 { - 42 - } - - fn max_extrinsic_weight() -> Weight { - bp_polkadot::max_extrinsic_weight() + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::PolkadotAccount, + ) + .into() } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Polkadot is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Polkadot's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Polkadot; + type Target = relay_kusama_client::Kusama; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::POLKADOT_TO_KUSAMA_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Kusama call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } - -/// Storage key and initial value of Kusama -> Polkadot conversion rate. -pub(crate) fn kusama_to_polkadot_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index b1948b234cc3..6d118b07caa5 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -16,95 +16,52 @@ //! Polkadot-to-Kusama headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_kusama_client::{Kusama, SigningParams as KusamaSigningParams}; -use relay_polkadot_client::{Polkadot, SyncHeader as PolkadotSyncHeader}; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use async_trait::async_trait; +use relay_kusama_client::Kusama; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. /// /// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 -/// KSM, but let's round up to 0.1 KSM here. -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000; - -/// Polkadot-to-Kusama finality sync pipeline. -pub(crate) type FinalityPipelinePolkadotFinalityToKusama = - SubstrateFinalityToSubstrate; - +/// KSM, and initial value of this constant was rounded up to 0.1 KSM. But for actual Kusama <> +/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory +/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against +/// relay/deployment issues, let's limit it so something that is much larger than this estimation - +/// e.g. to 2 KSM. +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_kusama::Balance = 2 * 1_000_000_000_000; + +/// Description of Polkadot -> Kusama finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct PolkadotFinalityToKusama { - finality_pipeline: FinalityPipelinePolkadotFinalityToKusama, -} - -impl PolkadotFinalityToKusama { - pub fn new(target_client: Client, target_sign: KusamaSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new( - target_client, - target_sign, - ), - } - } -} - +pub struct PolkadotFinalityToKusama; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + PolkadotFinalityToKusama, + PolkadotFinalityToKusamaCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotGrandpa, + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof +); + +#[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { - type FinalitySyncPipeline = FinalityPipelinePolkadotFinalityToKusama; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - + type SourceChain = relay_polkadot_client::Polkadot; type TargetChain = Kusama; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn start_relay_guards(&self) { - relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), - bp_kusama::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder; + type TransactionSignScheme = Kusama; + + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } - - fn transactions_author(&self) -> bp_kusama::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: PolkadotSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) + ) + .await } } diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index bc7f22243092..9c4a4640eb99 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -16,315 +16,63 @@ //! Polkadot-to-Kusama messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Polkadot-to-Kusama message lane. -pub type MessageLanePolkadotMessagesToKusama = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct PolkadotMessagesToKusama { - message_lane: MessageLanePolkadotMessagesToKusama, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Polkadot -> Kusama messages bridge. +#[derive(Clone, Debug)] +pub struct PolkadotMessagesToKusama; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof +); +substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( + Polkadot, + PolkadotMessagesToKusamaUpdateConversionRateCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter, + relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate +); impl SubstrateMessageLane for PolkadotMessagesToKusama { - type MessageLane = MessageLanePolkadotMessagesToKusama; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); type SourceChain = Polkadot; type TargetChain = Kusama; - fn source_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: KusamaHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot confirmation transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: PolkadotHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; + type SourceTransactionSignScheme = Polkadot; + type TargetTransactionSignScheme = Kusama; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama delivery transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Polkadot node as messages source. -type PolkadotSourceClient = SubstrateMessagesSource; - -/// Kusama node as messages target. -type KusamaTargetClient = SubstrateMessagesTarget; - -/// Run Polkadot-to-Kusama messages sync. -pub async fn run( - params: MessagesRelayParams< - Polkadot, - PolkadotSigningParams, - Kusama, - KusamaSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Polkadot::AVERAGE_BLOCK_INTERVAL, - Kusama::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = PolkadotMessagesToKusama { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_polkadot, - }, - }; + type ReceiveMessagesProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder; - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_kusama::max_extrinsic_size() / 3; - // we don't know exact weights of the Kusama runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_kusama::max_extrinsic_weight(), - bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Polkadot -> Kusama messages relay.\n\t\ - Polkadot relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, - target_tick: Kusama::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - PolkadotSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - KusamaTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Polkadot -> Kusama messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - ) -} + type TargetToSourceChainConversionRateUpdateBuilder = + PolkadotMessagesToKusamaUpdateConversionRateCallBuilder; -/// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. -pub(crate) async fn update_kusama_to_polkadot_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( - Polkadot::sign_transaction( - genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter( - relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ) - ) - ), - transaction_nonce, - ), - ) - .encode(), - ) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 2d873a24ba7a..8f26a64a4e32 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -25,37 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::polkadot::TOKEN_ID; - impl CliEncodeCall for Rialto { - fn max_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::RIALTO_TO_MILLAU_INDEX => { @@ -67,6 +57,7 @@ impl CliEncodeCall for Rialto { delivery_and_dispatch_fee: fee.0, }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -76,8 +67,8 @@ impl CliEncodeCall for Rialto { }) } - fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -96,17 +87,13 @@ impl CliChain for Rialto { rialto_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto::max_extrinsic_weight() - } - fn encode_message( message: encode_message::MessagePayload, ) -> anyhow::Result { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Rialto's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Rialto; type Target = relay_millau_client::Millau; @@ -118,11 +105,13 @@ impl CliChain for Rialto { bridge::RIALTO_TO_MILLAU_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, @@ -131,11 +120,3 @@ impl CliChain for Rialto { } } } - -/// Storage key and initial value of Millau -> Rialto conversion rate. -pub(crate) fn millau_to_rialto_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), - rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, - ) -} diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 7e76f403c55a..a433f3562a70 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -16,73 +16,22 @@ //! Rialto-to-Millau headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Rialto-to-Millau finality sync pipeline. -pub(crate) type FinalityPipelineRialtoFinalityToMillau = - SubstrateFinalityToSubstrate; - +/// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] -pub struct RialtoFinalityToMillau { - finality_pipeline: FinalityPipelineRialtoFinalityToMillau, -} - -impl RialtoFinalityToMillau { - pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new( - target_client, - target_sign, - ), - } - } -} +pub struct RialtoFinalityToMillau; impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { - type FinalitySyncPipeline = FinalityPipelineRialtoFinalityToMillau; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - - type TargetChain = Millau; - - fn transactions_author(&self) -> bp_millau::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: RialtoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_rialto_client::Rialto; + type TargetChain = relay_millau_client::Millau; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::RialtoGrandpaInstance, + >; + type TransactionSignScheme = relay_millau_client::Millau; } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 774da017df0c..d34f47146449 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,309 +16,55 @@ //! Rialto-to-Millau messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Rialto-to-Millau message lane. -pub type MessageLaneRialtoMessagesToMillau = - SubstrateMessageLaneToSubstrate; -#[derive(Clone)] -pub struct RialtoMessagesToMillau { - message_lane: MessageLaneRialtoMessagesToMillau, -} +/// Description of Rialto -> Millau messages bridge. +#[derive(Clone, Debug)] +pub struct RialtoMessagesToMillau; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + Rialto, + RialtoMessagesToMillauUpdateConversionRateCallBuilder, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate +); impl SubstrateMessageLane for RialtoMessagesToMillau { - type MessageLane = MessageLaneRialtoMessagesToMillau; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; type SourceChain = Rialto; type TargetChain = Millau; - fn source_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: MillauHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: rialto_runtime::Call = - rialto_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } + type SourceTransactionSignScheme = Rialto; + type TargetTransactionSignScheme = Millau; - fn target_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; - fn make_messages_delivery_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: RialtoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource; - -/// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget; - -/// Run Rialto-to-Millau messages sync. -pub async fn run( - params: MessagesRelayParams< - Rialto, - RialtoSigningParams, - Millau, - MillauSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rialto::AVERAGE_BLOCK_INTERVAL, - Millau::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = RialtoMessagesToMillau { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_rialto, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3; - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Rialto -> Millau messages relay.\n\t\ - Rialto relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - target_tick: Millau::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - RialtoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - MillauTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Rialto -> Millau messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - ) -} + type TargetToSourceChainConversionRateUpdateBuilder = + RialtoMessagesToMillauUpdateConversionRateCallBuilder; -/// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. -pub(crate) async fn update_millau_to_rialto_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( - Rialto::sign_transaction( - genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - rialto_runtime::MessagesCall::update_pallet_parameter { - parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - } - .into(), - transaction_nonce, - ), - ) - .encode(), - ) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index edd4ca362854..0ed39faa543b 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -21,37 +21,37 @@ use crate::cli::{ encode_message, CliChain, }; use bp_message_dispatch::MessagePayload; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; impl CliEncodeCall for RialtoParachain { - fn max_extrinsic_size() -> u32 { - bp_rialto_parachain::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( rialto_parachain_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), }, - ), + ) + .into(), Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( rialto_parachain_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, }, - ), - Call::BridgeSendMessage { .. } => - anyhow::bail!("Bridge messages are not (yet) supported here",), + ) + .into(), + Call::BridgeSendMessage { .. } => { + anyhow::bail!("Bridge messages are not (yet) supported here",) + }, }) } - fn get_dispatch_info(call: &rialto_parachain_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -70,10 +70,6 @@ impl CliChain for RialtoParachain { rialto_parachain_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto_parachain::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 4df60f89faa2..ceef4c1f532c 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; @@ -22,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Rococo. @@ -33,26 +37,25 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Rococo { - fn max_extrinsic_size() -> u32 { - bp_rococo::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::ROCOCO_TO_WOCOCO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; - relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message( + relay_rococo_client::runtime::Call::BridgeWococoMessages( + relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -63,13 +66,11 @@ impl CliEncodeCall for Rococo { }) } - fn get_dispatch_info( - call: &relay_rococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_rococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -83,19 +84,49 @@ impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountPublic, + bp_wococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Rococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Rococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Rococo; + type Target = relay_wococo_client::Wococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::ROCOCO_TO_WOCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Wococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index ec98cec1ec1e..bb66a7422d37 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -16,89 +16,41 @@ //! Rococo-to-Wococo headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; - use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; -/// Rococo-to-Wococo finality sync pipeline. -pub(crate) type FinalityPipelineRococoFinalityToWococo = - SubstrateFinalityToSubstrate; +use async_trait::async_trait; +use relay_wococo_client::Wococo; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; +/// Description of Rococo -> Wococo finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct RococoFinalityToWococo { - finality_pipeline: FinalityPipelineRococoFinalityToWococo, -} - -impl RococoFinalityToWococo { - pub fn new(target_client: Client, target_sign: WococoSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineRococoFinalityToWococo::new( - target_client, - target_sign, - ), - } - } -} - +pub struct RococoFinalityToWococo; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + RococoFinalityToWococo, + RococoFinalityToWococoCallBuilder, + relay_wococo_client::runtime::Call::BridgeGrandpaRococo, + relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof +); + +#[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { - type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - + type SourceChain = relay_rococo_client::Rococo; type TargetChain = Wococo; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn start_relay_guards(&self) { - relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), - bp_wococo::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder; + type TransactionSignScheme = Wococo; + + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } - - fn transactions_author(&self) -> bp_wococo::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: RococoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) + ) + .await } } diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index d6c9040e1277..4e67c87fa8c4 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -16,280 +16,48 @@ //! Rococo-to-Wococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Rococo-to-Wococo message lane. -pub type MessageLaneRococoMessagesToWococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct RococoMessagesToWococo { - message_lane: MessageLaneRococoMessagesToWococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Rococo -> Wococo messages bridge. +#[derive(Clone, Debug)] +pub struct RococoMessagesToWococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for RococoMessagesToWococo { - type MessageLane = MessageLaneRococoMessagesToWococo; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; type SourceChain = Rococo; type TargetChain = Wococo; - fn source_transactions_author(&self) -> bp_rococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: WococoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", - bp_rococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_rococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } + type SourceTransactionSignScheme = Rococo; + type TargetTransactionSignScheme = Wococo; - fn target_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type ReceiveMessagesProofCallBuilder = RococoMessagesToWococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder; - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: RococoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - - let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", - bp_wococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_wococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Rococo node as messages source. -type RococoSourceClient = SubstrateMessagesSource; - -/// Wococo node as messages target. -type WococoTargetClient = SubstrateMessagesTarget; - -/// Run Rococo-to-Wococo messages sync. -pub async fn run( - params: MessagesRelayParams< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rococo::AVERAGE_BLOCK_INTERVAL, - Wococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = RococoMessagesToWococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_rococo, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3; - // we don't know exact weights of the Wococo runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_wococo::max_extrinsic_weight(), - bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Rococo -> Wococo messages relay.\n\t\ - Rococo relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Rococo::AVERAGE_BLOCK_INTERVAL, - target_tick: Wococo::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - RococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - WococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type TargetToSourceChainConversionRateUpdateBuilder = (); -/// Create standalone metrics for the Rococo -> Wococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index a42e4805512c..8d3b5db9ab37 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -18,7 +18,6 @@ use crate::cli::{encode_message, CliChain}; use anyhow::anyhow; -use frame_support::weights::Weight; use relay_westend_client::Westend; use sp_version::RuntimeVersion; @@ -29,11 +28,10 @@ impl CliChain for Westend { type MessagePayload = (); fn ss58_format() -> u16 { - 42 - } - - fn max_extrinsic_weight() -> Weight { - 0 + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::SubstrateAccount, + ) + .into() } fn encode_message( diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 211aa9da9bfe..2ec20a027ff5 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -16,78 +16,22 @@ //! Westend-to-Millau headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Westend-to-Millau finality sync pipeline. -pub(crate) type FinalityPipelineWestendFinalityToMillau = - SubstrateFinalityToSubstrate; - +/// Description of Westend -> Millau finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct WestendFinalityToMillau { - finality_pipeline: FinalityPipelineWestendFinalityToMillau, -} - -impl WestendFinalityToMillau { - pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineWestendFinalityToMillau::new( - target_client, - target_sign, - ), - } - } -} +pub struct WestendFinalityToMillau; impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { - type FinalitySyncPipeline = FinalityPipelineWestendFinalityToMillau; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - - type TargetChain = Millau; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn transactions_author(&self) -> bp_millau::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: WestendSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_westend_client::Westend; + type TargetChain = relay_millau_client::Millau; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WestendGrandpaInstance, + >; + type TransactionSignScheme = relay_millau_client::Millau; } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 328397d14ba7..46dec2a3c90e 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -15,38 +15,41 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; impl CliEncodeCall for Wococo { - fn max_extrinsic_size() -> u32 { - bp_wococo::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::WOCOCO_TO_ROCOCO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; - relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message( + relay_wococo_client::runtime::Call::BridgeRococoMessages( + relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -57,18 +60,16 @@ impl CliEncodeCall for Wococo { }) } - fn get_dispatch_info( - call: &relay_wococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_wococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, }), - _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + _ => anyhow::bail!("Unsupported Wococo call: {:?}", call), } } } @@ -77,19 +78,49 @@ impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_wococo::AccountId, + bp_rococo::AccountPublic, + bp_rococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Wococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Wococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Wococo; + type Target = relay_rococo_client::Rococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::WOCOCO_TO_ROCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Rococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index fe17976d06a8..a7bff5951882 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -16,17 +16,9 @@ //! Wococo-to-Rococo headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use async_trait::async_trait; +use relay_rococo_client::Rococo; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -35,76 +27,36 @@ use substrate_relay_helper::finality_pipeline::{ /// Note that this is in plancks, so this corresponds to `1500 UNITS`. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; -/// Wococo-to-Rococo finality sync pipeline. -pub(crate) type FinalityPipelineWococoFinalityToRococo = - SubstrateFinalityToSubstrate; - +/// Description of Wococo -> Rococo finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct WococoFinalityToRococo { - finality_pipeline: FinalityPipelineWococoFinalityToRococo, -} - -impl WococoFinalityToRococo { - pub fn new(target_client: Client, target_sign: RococoSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineWococoFinalityToRococo::new( - target_client, - target_sign, - ), - } - } -} - +pub struct WococoFinalityToRococo; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + WococoFinalityToRococo, + WococoFinalityToRococoCallBuilder, + relay_rococo_client::runtime::Call::BridgeGrandpaWococo, + relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof +); + +#[async_trait] impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { - type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - + type SourceChain = relay_wococo_client::Wococo; type TargetChain = Rococo; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn start_relay_guards(&self) { - relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), - bp_rococo::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder; + type TransactionSignScheme = Rococo; + + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } - - fn transactions_author(&self) -> bp_rococo::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: WococoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) + ) + .await } } diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index dcba89e43f05..2c44803f2c06 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -16,279 +16,49 @@ //! Wococo-to-Rococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; -/// Wococo-to-Rococo message lane. -pub type MessageLaneWococoMessagesToRococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct WococoMessagesToRococo { - message_lane: MessageLaneWococoMessagesToRococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Wococo -> Rococo messages bridge. +#[derive(Clone, Debug)] +pub struct WococoMessagesToRococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for WococoMessagesToRococo { - type MessageLane = MessageLaneWococoMessagesToRococo; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; type SourceChain = Wococo; type TargetChain = Rococo; - fn source_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: RococoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", - bp_wococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_wococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_rococo::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type SourceTransactionSignScheme = Wococo; + type TargetTransactionSignScheme = Rococo; - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: WococoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; + type ReceiveMessagesProofCallBuilder = WococoMessagesToRococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder; - let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", - bp_rococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_rococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Wococo node as messages source. -type WococoSourceClient = SubstrateMessagesSource; - -/// Rococo node as messages target. -type RococoTargetClient = SubstrateMessagesTarget; - -/// Run Wococo-to-Rococo messages sync. -pub async fn run( - params: MessagesRelayParams< - Wococo, - WococoSigningParams, - Rococo, - RococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Wococo::AVERAGE_BLOCK_INTERVAL, - Rococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = WococoMessagesToRococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_wococo, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3; - // we don't know exact weights of the Rococo runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_rococo::max_extrinsic_weight(), - bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Wococo -> Rococo messages relay.\n\t\ - Wococo relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Wococo::AVERAGE_BLOCK_INTERVAL, - target_tick: Rococo::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - WococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type TargetToSourceChainConversionRateUpdateBuilder = (); -/// Create standalone metrics for the Wococo -> Rococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 1af6142c53ec..2eb836a84a75 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -68,7 +68,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::millau_messages_to_rialto::run as relay_messages; + use crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -90,7 +90,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rialto_messages_to_millau::run as relay_messages; + use crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -113,7 +113,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rococo_messages_to_wococo::run as relay_messages; + use crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -135,7 +135,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::wococo_messages_to_rococo::run as relay_messages; + use crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -157,7 +157,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::kusama_messages_to_polkadot::run as relay_messages; + use crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -179,7 +179,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::polkadot_messages_to_kusama::run as relay_messages; + use crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index e17854662e5c..e288e2c13d6c 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -20,6 +20,7 @@ use crate::{ }, select_full_bridge, }; +use bp_runtime::EncodedOrDecodedCall; use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -84,14 +85,11 @@ pub enum Call { } pub trait CliEncodeCall: Chain { - /// Maximal size (in bytes) of any extrinsic (from the runtime). - fn max_extrinsic_size() -> u32; - /// Encode a CLI call. - fn encode_call(call: &Call) -> anyhow::Result; + fn encode_call(call: &Call) -> anyhow::Result>; /// Get dispatch info for the call. - fn get_dispatch_info(call: &Self::Call) -> anyhow::Result; + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result; } impl EncodeCall { @@ -103,7 +101,10 @@ impl EncodeCall { let encoded = HexBytes::encode(&call); log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call) + .map(|dispatch_info| format!("{}", dispatch_info.weight)) + .unwrap_or_else(|_| "".to_string()) + ); log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); Ok(encoded) @@ -311,8 +312,8 @@ mod tests { ); } - #[test] - fn should_encode_bridge_send_message_call() { + #[async_std::test] + async fn should_encode_bridge_send_message_call() { // given let encode_message = SendMessage::from_iter(vec![ "send-message", @@ -328,6 +329,7 @@ mod tests { "remark", ]) .encode_payload() + .await .unwrap(); let mut encode_call = EncodeCall::from_iter(vec![ @@ -345,7 +347,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x0f030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x0f030000000001000000000000000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 98e1269aa68e..677fc29ef153 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -18,6 +18,7 @@ use crate::{ cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}, select_full_bridge, }; +use frame_support::weights::Weight; use structopt::StructOpt; use strum::VariantNames; @@ -37,6 +38,12 @@ pub enum MessagePayload { /// SS58 encoded Source account that will send the payload. #[structopt(long)] sender: AccountId, + /// Weight of the call. + /// + /// It must be specified if the chain runtime is not bundled with the relay, or if + /// you want to override bundled weight. + #[structopt(long)] + dispatch_weight: Option, }, } @@ -97,6 +104,8 @@ mod tests { "call", "--sender", &sender, + "--dispatch-weight", + "42", "remark", "--remark-size", "12", @@ -106,6 +115,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x0100000010f108000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x010000002a0000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index d063ce544cd2..bab625314e82 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -15,17 +15,22 @@ // along with Parity Bridges Common. If not, see . use crate::{ - cli::{bridge::FullBridge, Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}, + cli::{ + bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, + }, select_full_bridge, }; use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; +use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; +use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; /// Estimate Delivery & Dispatch Fee command. -#[derive(StructOpt, Debug, PartialEq, Eq)] +#[derive(StructOpt, Debug, PartialEq)] pub struct EstimateFee { /// A bridge instance to encode call for. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] @@ -35,15 +40,44 @@ pub struct EstimateFee { /// Hex-encoded id of lane that will be delivering the message. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + /// A way to override conversion rate between bridge tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + conversion_rate_override: Option, /// Payload to send over the bridge. #[structopt(flatten)] payload: crate::cli::encode_message::MessagePayload, } +/// A way to override conversion rate between bridge tokens. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ConversionRateOverride { + /// The actual conversion rate is computed in the same way how rate metric works. + Metric, + /// The actual conversion rate is specified explicitly. + Explicit(f64), +} + +impl std::str::FromStr for ConversionRateOverride { + type Err = String; + + fn from_str(s: &str) -> Result { + if s.to_lowercase() == "metric" { + return Ok(ConversionRateOverride::Metric) + } + + f64::from_str(s) + .map(ConversionRateOverride::Explicit) + .map_err(|e| format!("Failed to parse '{:?}'. Expected 'metric' or explicit value", e)) + } +} + impl EstimateFee { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - let Self { source, bridge, lane, payload } = self; + let Self { source, bridge, lane, conversion_rate_override, payload } = self; select_full_bridge!(bridge, { let source_client = source.to_client::().await?; @@ -51,8 +85,9 @@ impl EstimateFee { let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee: BalanceOf = estimate_message_delivery_and_dispatch_fee( + let fee = estimate_message_delivery_and_dispatch_fee::( &source_client, + conversion_rate_override, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload, @@ -66,16 +101,114 @@ impl EstimateFee { } } -pub(crate) async fn estimate_message_delivery_and_dispatch_fee( - client: &relay_substrate_client::Client, +/// The caller may provide target to source tokens conversion rate override to use in fee +/// computation. +pub(crate) async fn estimate_message_delivery_and_dispatch_fee< + Source: Chain, + Target: Chain, + P: Clone + Encode, +>( + client: &relay_substrate_client::Client, + conversion_rate_override: Option, + estimate_fee_method: &str, + lane: bp_messages::LaneId, + payload: P, +) -> anyhow::Result> { + // actual conversion rate CAN be lesser than the rate stored in the runtime. So we may try to + // pay lesser fee for the message delivery. But in this case, message may be rejected by the + // lane. So we MUST use the larger of two fees - one computed with stored fee and the one + // computed with actual fee. + + let conversion_rate_override = + match (conversion_rate_override, Source::TOKEN_ID, Target::TOKEN_ID) { + (Some(ConversionRateOverride::Explicit(v)), _, _) => { + let conversion_rate_override = FixedU128::from_float(v); + log::info!( + target: "bridge", + "{} -> {} conversion rate override: {:?} (explicit)", + Target::NAME, + Source::NAME, + conversion_rate_override.to_float(), + ); + Some(conversion_rate_override) + }, + ( + Some(ConversionRateOverride::Metric), + Some(source_token_id), + Some(target_token_id), + ) => { + let conversion_rate_override = + tokens_conversion_rate_from_metrics(target_token_id, source_token_id).await?; + // So we have current actual conversion rate and rate that is stored in the runtime. + // And we may simply choose the maximal of these. But what if right now there's + // rate update transaction on the way, that is updating rate to 10 seconds old + // actual rate, which is bigger than the current rate? Then our message will be + // rejected. + // + // So let's increase the actual rate by the same value that the conversion rate + // updater is using. + let increased_conversion_rate_override = FixedU128::from_float( + conversion_rate_override * (1.0 + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO), + ); + log::info!( + target: "bridge", + "{} -> {} conversion rate override: {} (value from metric - {})", + Target::NAME, + Source::NAME, + increased_conversion_rate_override.to_float(), + conversion_rate_override, + ); + Some(increased_conversion_rate_override) + }, + _ => None, + }; + + let without_override = do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), + None, + ) + .await?; + let with_override = do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), + conversion_rate_override, + ) + .await?; + let maximal_fee = std::cmp::max(without_override, with_override); + + log::info!( + target: "bridge", + "Estimated message fee: {:?} = max of {:?} (without rate override) and {:?} (with override to {:?})", + maximal_fee, + without_override, + with_override, + conversion_rate_override, + ); + + Ok(maximal_fee) +} + +/// Estimate message delivery and dispatch fee with given conversion rate override. +async fn do_estimate_message_delivery_and_dispatch_fee( + client: &relay_substrate_client::Client, estimate_fee_method: &str, lane: bp_messages::LaneId, payload: P, -) -> anyhow::Result { + conversion_rate_override: Option, +) -> anyhow::Result> { let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .state_call( + estimate_fee_method.into(), + (lane, payload, conversion_rate_override).encode().into(), + None, + ) .await?; - let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) + let decoded_response: Option> = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?; let fee = decoded_response.ok_or_else(|| { anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())) @@ -86,7 +219,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee().await?; let target_sign = self.target_sign.to_keypair::()?; + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; substrate_relay_helper::headers_initialize::initialize( source_client, target_client.clone(), target_sign.public().into(), move |transaction_nonce, initialization_data| { - Bytes( - Target::sign_transaction( - *target_client.genesis_hash(), - &target_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - encode_init_bridge(initialization_data), + Ok(Bytes( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *target_client.genesis_hash(), + signer: target_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + encode_init_bridge(initialization_data).into(), transaction_nonce, ), - ) + })? .encode(), - ) + )) }, ) .await; diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index f1180059b994..df57537f588e 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -18,11 +18,13 @@ use std::convert::TryInto; -use bp_messages::LaneId; use codec::{Decode, Encode}; -use frame_support::weights::Weight; +use relay_substrate_client::ChainRuntimeVersion; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +use strum::{EnumString, EnumVariantNames}; + +use bp_messages::LaneId; pub(crate) mod bridge; pub(crate) mod encode_call; @@ -33,6 +35,7 @@ pub(crate) mod send_message; mod derive_account; mod init_bridge; mod register_parachain; +mod reinit_bridge; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; @@ -69,6 +72,11 @@ pub enum Command { /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. InitBridge(init_bridge::InitBridge), + /// Reinitialize on-chain bridge pallet with current header data. + /// + /// Sends all missing mandatory headers to bootstrap the bridge with current finalized block + /// data. + ReinitBridge(reinit_bridge::ReinitBridge), /// Send custom message over the bridge. /// /// Allows interacting with the bridge by sending messages over `Messages` component. @@ -124,6 +132,7 @@ impl Command { Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, + Self::ReinitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?, Self::EncodeMessage(arg) => arg.run().await?, @@ -238,7 +247,7 @@ impl AccountId { /// /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { - /// Chain's current version of the runtime. + /// Current version of the chain runtime, known to relay. const RUNTIME_VERSION: sp_version::RuntimeVersion; /// Crypto KeyPair type used to send messages. @@ -258,9 +267,6 @@ pub trait CliChain: relay_substrate_client::Chain { fn encode_message( message: crate::cli::encode_message::MessagePayload, ) -> anyhow::Result; - - /// Maximal extrinsic weight (from the runtime). - fn max_extrinsic_weight() -> Weight; } /// Lane id. @@ -368,6 +374,17 @@ where } } +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + /// Create chain-specific set of configuration objects: connection parameters, /// signing parameters and bridge initialization parameters. #[macro_export] @@ -381,11 +398,28 @@ macro_rules! declare_chain_options { #[structopt(long, default_value = "127.0.0.1")] pub [<$chain_prefix _host>]: String, #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long)] + #[structopt(long, default_value = "9944")] pub [<$chain_prefix _port>]: u16, #[doc = "Use secure websocket connection."] #[structopt(long)] pub [<$chain_prefix _secure>]: bool, + #[doc = "Custom runtime version"] + #[structopt(flatten)] + pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], + } + + #[doc = $chain " runtime version params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] + pub struct [<$chain RuntimeVersionParams>] { + #[doc = "The type of runtime version for chain " $chain] + #[structopt(long, default_value = "Bundle")] + pub [<$chain_prefix _version_mode>]: RuntimeVersionType, + #[doc = "The custom sepc_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _spec_version>]: Option, + #[doc = "The custom transaction_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _transaction_version>]: Option, } #[doc = $chain " signing params."] @@ -501,18 +535,82 @@ macro_rules! declare_chain_options { } impl [<$chain ConnectionParams>] { + /// Returns `true` if version guard can be started. + /// + /// There's no reason to run version guard when version mode is set to `Auto`. It can + /// lead to relay shutdown when chain is upgraded, even though we have explicitly + /// said that we don't want to shutdown. + #[allow(dead_code)] + pub fn can_start_version_guard(&self) -> bool { + self.[<$chain_prefix _runtime_version>].[<$chain_prefix _version_mode>] != RuntimeVersionType::Auto + } + /// Convert connection params into Substrate client. pub async fn to_client( &self, ) -> anyhow::Result> { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], secure: self.[<$chain_prefix _secure>], + chain_runtime_version, }) .await ) } + + /// Return selected `chain_spec` version. + /// + /// This function only connects to the node if version mode is set to `Auto`. + #[allow(dead_code)] + pub async fn selected_chain_spec_version( + &self, + ) -> anyhow::Result { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; + Ok(match chain_runtime_version { + ChainRuntimeVersion::Auto => self + .to_client::() + .await? + .simple_runtime_version() + .await? + .0, + ChainRuntimeVersion::Custom(spec_version, _) => spec_version, + }) + } + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let except_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let except_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + except_spec_version, + except_transaction_version + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom( + runtime_version.spec_version, + runtime_version.transaction_version + ), + None => ChainRuntimeVersion::Auto + }, + }) + } } } }; @@ -525,9 +623,10 @@ declare_chain_options!(Parachain, parachain); #[cfg(test)] mod tests { - use sp_core::Pair; use std::str::FromStr; + use sp_core::Pair; + use super::*; #[test] diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index fecc431148eb..c761a5dd1a60 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -20,6 +20,7 @@ use crate::cli::{ }; use codec::Encode; +use frame_support::Twox64Concat; use num_traits::Zero; use polkadot_parachain::primitives::{ HeadData as ParaHeadData, Id as ParaId, ValidationCode as ParaValidationCode, @@ -29,7 +30,7 @@ use polkadot_runtime_common::{ }; use polkadot_runtime_parachains::paras::ParaLifecycle; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, Client, SignParam, TransactionSignScheme, UnsignedTransaction, }; use rialto_runtime::SudoCall; use sp_core::{ @@ -106,8 +107,8 @@ impl RegisterParachain { let para_id: ParaId = relay_client .storage_value(StorageKey(para_id_key.to_vec()), None) .await? - .unwrap_or(polkadot_primitives::v1::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v1::LOWEST_PUBLIC_ID); + .unwrap_or(polkadot_primitives::v2::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v2::LOWEST_PUBLIC_ID); log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id @@ -116,23 +117,26 @@ impl RegisterParachain { let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve {}.into(); let reserve_parachain_signer = relay_sign.clone(); + let (spec_version, transaction_version) = relay_client.simple_runtime_version().await?; wait_until_transaction_is_finalized::( relay_client .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - &reserve_parachain_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - reserve_parachain_id_call, + Ok(Bytes( + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: reserve_parachain_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + reserve_parachain_id_call.into(), transaction_nonce, ), - ) + })? .encode(), - ) + )) }, ) .await?, @@ -168,18 +172,20 @@ impl RegisterParachain { .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - ®ister_parathread_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - register_parathread_call, + Ok(Bytes( + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: register_parathread_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + register_parathread_call.into(), transaction_nonce, ), - ) + })? .encode(), - ) + )) }, ) .await?, @@ -188,7 +194,7 @@ impl RegisterParachain { log::info!(target: "bridge", "Registered parachain: {:?}. Waiting for onboarding", para_id); // wait until parathread is onboarded - let para_state_key = bp_runtime::storage_map_final_key_twox64_concat( + let para_state_key = bp_runtime::storage_map_final_key::( PARAS_PALLET_NAME, PARAS_LIFECYCLES_STORAGE_NAME, ¶_id.encode(), @@ -228,15 +234,20 @@ impl RegisterParachain { let force_lease_signer = relay_sign.clone(); relay_client .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - &force_lease_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(force_lease_call, transaction_nonce), - ) + Ok(Bytes( + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: force_lease_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + force_lease_call.into(), + transaction_nonce, + ), + })? .encode(), - ) + )) }) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); @@ -292,6 +303,9 @@ async fn wait_para_state( #[cfg(test)] mod tests { use super::*; + use crate::cli::{ + ParachainRuntimeVersionParams, RelaychainRuntimeVersionParams, RuntimeVersionType, + }; #[test] fn register_rialto_parachain() { @@ -327,6 +341,11 @@ mod tests { relaychain_host: "127.0.0.1".into(), relaychain_port: 9944, relaychain_secure: false, + relaychain_runtime_version: RelaychainRuntimeVersionParams { + relaychain_version_mode: RuntimeVersionType::Bundle, + relaychain_spec_version: None, + relaychain_transaction_version: None, + } }, relay_sign: RelaychainSigningParams { relaychain_signer: Some("//Alice".into()), @@ -339,6 +358,11 @@ mod tests { parachain_host: "127.0.0.1".into(), parachain_port: 11949, parachain_secure: false, + parachain_runtime_version: ParachainRuntimeVersionParams { + parachain_version_mode: RuntimeVersionType::Bundle, + parachain_spec_version: None, + parachain_transaction_version: None, + } }, } ); diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs new file mode 100644 index 000000000000..89470872cb2e --- /dev/null +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -0,0 +1,553 @@ +// 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::{ + chains::{ + kusama_headers_to_polkadot::KusamaFinalityToPolkadot, + polkadot_headers_to_kusama::PolkadotFinalityToKusama, + }, + cli::{ + swap_tokens::wait_until_transaction_is_finalized, SourceConnectionParams, + TargetConnectionParams, TargetSigningParams, + }, +}; +use bp_header_chain::justification::GrandpaJustification; +use bp_runtime::Chain; +use codec::Encode; +use finality_relay::{SourceClient, SourceHeader}; +use frame_support::weights::Weight; +use num_traits::One; +use pallet_bridge_grandpa::weights::WeightInfo; +use relay_substrate_client::{ + AccountIdOf, BlockNumberOf, Chain as _, Client, Error as SubstrateError, HeaderOf, SignParam, + SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; +use sp_core::{Bytes, Pair}; +use std::convert::{TryFrom, TryInto}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::{ + finality_pipeline::SubstrateFinalitySyncPipeline, finality_source::SubstrateFinalitySource, + finality_target::SubstrateFinalityTarget, messages_source::read_client_state, + TransactionParams, +}; + +/// Reinitialize bridge pallet. +#[derive(Debug, PartialEq, StructOpt)] +pub struct ReinitBridge { + /// A bridge instance to reinitialize. + #[structopt(possible_values = ReinitBridgeName::VARIANTS, case_insensitive = true)] + bridge: ReinitBridgeName, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, +} + +#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] +#[strum(serialize_all = "kebab_case")] +/// Bridge to initialize. +pub enum ReinitBridgeName { + KusamaToPolkadot, + PolkadotToKusama, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + ReinitBridgeName::KusamaToPolkadot => { + use relay_polkadot_client::runtime; + + type Finality = KusamaFinalityToPolkadot; + type Call = runtime::Call; + + fn submit_finality_proof_call( + header_and_proof: HeaderAndProof, + ) -> runtime::Call { + runtime::Call::BridgeKusamaGrandpa( + runtime::BridgeKusamaGrandpaCall::submit_finality_proof( + Box::new(header_and_proof.0.into_inner()), + header_and_proof.1, + ), + ) + } + + fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { + runtime::Call::BridgeKusamaGrandpa( + runtime::BridgeKusamaGrandpaCall::set_operational(operational), + ) + } + + fn batch_all_call(calls: Vec) -> runtime::Call { + runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) + } + + $generic + }, + ReinitBridgeName::PolkadotToKusama => { + use relay_kusama_client::runtime; + + type Finality = PolkadotFinalityToKusama; + type Call = runtime::Call; + + fn submit_finality_proof_call( + header_and_proof: HeaderAndProof, + ) -> runtime::Call { + runtime::Call::BridgePolkadotGrandpa( + runtime::BridgePolkadotGrandpaCall::submit_finality_proof( + Box::new(header_and_proof.0.into_inner()), + header_and_proof.1, + ), + ) + } + + fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { + runtime::Call::BridgePolkadotGrandpa( + runtime::BridgePolkadotGrandpaCall::set_operational(operational), + ) + } + + fn batch_all_call(calls: Vec) -> runtime::Call { + runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) + } + + $generic + }, + } + }; +} + +impl ReinitBridge { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + type Source = ::SourceChain; + type Target = ::TargetChain; + + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; + let transaction_params = TransactionParams { + signer: target_sign, + mortality: self.target_sign.target_transactions_mortality, + }; + + let finality_source = + SubstrateFinalitySource::::new(source_client.clone(), None); + let finality_target = SubstrateFinalityTarget::::new( + target_client.clone(), + transaction_params.clone(), + ); + + // this subcommand assumes that the pallet at the target chain is halted + ensure_pallet_operating_mode(&finality_target, false).await?; + + // we can't call `finality_target.best_finalized_source_block_id()`, because pallet is + // halted and the call will fail => just use what it uses internally + let current_number = + best_source_block_number_at_target::(&target_client).await?; + let target_number = finality_source.best_finalized_block_number().await?; + log::info!( + target: "bridge", + "Best finalized {} header: at {}: {}, at {}: {}", + Source::NAME, + Source::NAME, + target_number, + Target::NAME, + current_number, + ); + + // prepare list of mandatory headers from the range `(current_number; target_number]` + let headers_to_submit = find_mandatory_headers_in_range( + &finality_source, + (current_number + 1, target_number), + ) + .await?; + let latest_andatory_header_number = headers_to_submit.last().map(|(h, _)| h.number()); + log::info!( + target: "bridge", + "Missing {} mandatory {} headers at {}", + headers_to_submit.len(), + Source::NAME, + Target::NAME, + ); + + // split all mandatory headers into batches + let headers_batches = + make_mandatory_headers_batches::(headers_to_submit, |(_, proof)| { + // we don't have an access to the Kusama/Polkadot chain runtimes here, so we'll + // be using Millau weights. It isn't super-critical, unless real weights are + // magnitude higher or so + pallet_bridge_grandpa::weights::MillauWeight::::submit_finality_proof( + proof.commit.precommits.len().try_into().unwrap_or(u32::MAX), + proof.votes_ancestries.len().try_into().unwrap_or(u32::MAX), + ) + }); + log::info!( + target: "bridge", + "We're going to submit {} transactions to {} node", + headers_batches.len(), + Target::NAME, + ); + + // each batch is submitted as a separate transaction + let signer_account_id: AccountIdOf = transaction_params.signer.public().into(); + let genesis_hash = *target_client.genesis_hash(); + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; + let last_batch_index = headers_batches.len() - 1; + for (i, headers_batch) in headers_batches.into_iter().enumerate() { + let is_last_batch = i == last_batch_index; + let expected_number = + headers_batch.last().expect("all batches are non-empty").0.number(); + let transaction_params = transaction_params.clone(); + log::info!( + target: "bridge", + "Going to submit transaction that updates best {} header at {} to {}", + Source::NAME, + Target::NAME, + expected_number, + ); + + // prepare `batch_all` call + let mut batch_calls = Vec::with_capacity(headers_batch.len() + 2); + // the first call is always resumes pallet operation + batch_calls.push(set_pallet_operation_mode_call(true)); + // followed by submit-finality-proofs calls + for header_and_proof in headers_batch { + batch_calls.push(submit_finality_proof_call(header_and_proof)); + } + // if it isn't the last batch, we shall halt pallet again + if !is_last_batch { + batch_calls.push(set_pallet_operation_mode_call(false)); + } + let submit_batch_call = batch_all_call(batch_calls); + + let batch_transaction_events = target_client + .submit_and_watch_signed_extrinsic( + signer_account_id.clone(), + move |best_block_id, transaction_nonce| { + Ok(Bytes( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer.clone(), + era: TransactionEra::new( + best_block_id, + transaction_params.mortality, + ), + unsigned: UnsignedTransaction::new( + submit_batch_call.into(), + transaction_nonce, + ), + })? + .encode(), + )) + }, + ) + .await?; + wait_until_transaction_is_finalized::(batch_transaction_events).await?; + + // verify that the best finalized header at target has been updated + let current_number = + best_source_block_number_at_target::(&target_client).await?; + if current_number != expected_number { + return Err(anyhow::format_err!( + "Transaction has failed to update best {} header at {} to {}. It is {}", + Source::NAME, + Target::NAME, + expected_number, + current_number, + )) + } + + // verify that the pallet is still halted (or operational if it is the last batch) + ensure_pallet_operating_mode(&finality_target, is_last_batch).await?; + } + + if let Some(latest_andatory_header_number) = latest_andatory_header_number { + log::info!( + target: "bridge", + "Successfully updated best {} header at {} to {}. Pallet is now operational", + Source::NAME, + Target::NAME, + latest_andatory_header_number, + ); + } + + Ok(()) + }) + } +} + +/// Mandatory header and its finality proof. +type HeaderAndProof

= ( + SyncHeader::SourceChain>>, + GrandpaJustification::SourceChain>>, +); +/// Vector of mandatory headers and their finality proofs. +type HeadersAndProofs

= Vec>; + +/// Returns best finalized source header number known to the bridge GRANDPA pallet at the target +/// chain. +/// +/// This function works even if bridge GRANDPA pallet at the target chain is halted. +async fn best_source_block_number_at_target( + target_client: &Client, +) -> anyhow::Result> { + Ok(read_client_state::( + target_client, + None, + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) + .await? + .best_finalized_peer_at_best_self + .0) +} + +/// Verify that the bridge GRANDPA pallet at the target chain is either halted, or operational. +async fn ensure_pallet_operating_mode( + finality_target: &SubstrateFinalityTarget

, + operational: bool, +) -> anyhow::Result<()> { + match (operational, finality_target.ensure_pallet_active().await) { + (true, Ok(())) => Ok(()), + (false, Err(SubstrateError::BridgePalletIsHalted)) => Ok(()), + _ => + return Err(anyhow::format_err!( + "Bridge GRANDPA pallet at {} is expected to be {}, but it isn't", + P::TargetChain::NAME, + if operational { "operational" } else { "halted" }, + )), + } +} + +/// Returns list of all mandatory headers in given range. +async fn find_mandatory_headers_in_range( + finality_source: &SubstrateFinalitySource

, + range: (BlockNumberOf, BlockNumberOf), +) -> anyhow::Result> { + let mut mandatory_headers = Vec::new(); + let mut current = range.0; + while current <= range.1 { + let (header, proof) = finality_source.header_and_finality_proof(current).await?; + if header.is_mandatory() { + match proof { + Some(proof) => mandatory_headers.push((header, proof)), + None => + return Err(anyhow::format_err!( + "Missing GRANDPA justification for {} header {}", + P::SourceChain::NAME, + current, + )), + } + } + + current += One::one(); + } + + Ok(mandatory_headers) +} + +/// Given list of mandatory headers, prepare batches of headers, so that every batch may fit into +/// single transaction. +fn make_mandatory_headers_batches< + P: SubstrateFinalitySyncPipeline, + F: Fn(&HeaderAndProof

) -> Weight, +>( + mut headers_to_submit: HeadersAndProofs

, + submit_header_weight: F, +) -> Vec> { + // now that we have all mandatory headers, let's prepare transactions + // (let's keep all our transactions below 2/3 of max tx size/weight to have some reserve + // for utility overhead + for halting transaction) + let maximal_tx_size = P::TargetChain::max_extrinsic_size() * 2 / 3; + let maximal_tx_weight = P::TargetChain::max_extrinsic_weight() * 2 / 3; + let mut current_batch_size: u32 = 0; + let mut current_batch_weight: Weight = 0; + let mut batches = Vec::new(); + let mut i = 0; + while i < headers_to_submit.len() { + let header_and_proof_size = + headers_to_submit[i].0.encode().len() + headers_to_submit[i].1.encode().len(); + let header_and_proof_weight = submit_header_weight(&headers_to_submit[i]); + + let new_batch_size = current_batch_size + .saturating_add(u32::try_from(header_and_proof_size).unwrap_or(u32::MAX)); + let new_batch_weight = current_batch_weight.saturating_add(header_and_proof_weight); + + let is_exceeding_tx_size = new_batch_size > maximal_tx_size; + let is_exceeding_tx_weight = new_batch_weight > maximal_tx_weight; + let is_new_batch_required = is_exceeding_tx_size || is_exceeding_tx_weight; + + if is_new_batch_required { + // if `i` is 0 and we're here, it is a weird situation: even single header submission is + // larger than we've planned for a bunch of headers. Let's be optimistic and hope that + // the tx will still succeed. + let spit_off_index = std::cmp::max(i, 1); + let remaining_headers_to_submit = headers_to_submit.split_off(spit_off_index); + batches.push(headers_to_submit); + + // we'll reiterate the same header again => so set `current_*` to zero + current_batch_size = 0; + current_batch_weight = 0; + headers_to_submit = remaining_headers_to_submit; + i = 0; + } else { + current_batch_size = new_batch_size; + current_batch_weight = new_batch_weight; + i += 1; + } + } + if !headers_to_submit.is_empty() { + batches.push(headers_to_submit); + } + batches +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; + use bp_test_utils::{make_default_justification, test_header}; + use relay_polkadot_client::Polkadot; + use sp_runtime::{traits::Header as _, DigestItem}; + + fn make_header_and_justification( + i: u32, + size: u32, + ) -> (SyncHeader, GrandpaJustification) { + let size = size as usize; + let mut header: bp_kusama::Header = test_header(i); + let justification = make_default_justification(&header); + let actual_size = header.encode().len() + justification.encode().len(); + // additional digest means some additional bytes, so let's decrease `additional_digest_size` + // a bit + let additional_digest_size = size.saturating_sub(actual_size).saturating_sub(100); + header.digest_mut().push(DigestItem::Other(vec![0u8; additional_digest_size])); + let justification = make_default_justification(&header); + println!("{} {}", size, header.encode().len() + justification.encode().len()); + (header.into(), justification) + } + + #[test] + fn should_parse_cli_options() { + // when + let res = ReinitBridge::from_iter(vec![ + "reinit-bridge", + "kusama-to-polkadot", + "--source-host", + "127.0.0.1", + "--source-port", + "42", + "--target-host", + "127.0.0.1", + "--target-port", + "43", + "--target-signer", + "//Alice", + ]); + + // then + assert_eq!( + res, + ReinitBridge { + bridge: ReinitBridgeName::KusamaToPolkadot, + source: SourceConnectionParams { + source_host: "127.0.0.1".into(), + source_port: 42, + source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } + }, + target: TargetConnectionParams { + target_host: "127.0.0.1".into(), + target_port: 43, + target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } + }, + target_sign: TargetSigningParams { + target_signer: Some("//Alice".into()), + target_signer_password: None, + target_signer_file: None, + target_signer_password_file: None, + target_transactions_mortality: None, + }, + } + ); + } + + #[test] + fn make_mandatory_headers_batches_and_empty_headers() { + let batches = make_mandatory_headers_batches::(vec![], |_| 0); + assert!(batches.is_empty()); + } + + #[test] + fn make_mandatory_headers_batches_with_single_batch() { + let headers_to_submit = + vec![make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3)]; + let batches = + make_mandatory_headers_batches::(headers_to_submit, |_| 0); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![1],); + } + + #[test] + fn make_mandatory_headers_batches_group_by_size() { + let headers_to_submit = vec![ + make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3), + make_header_and_justification(20, Polkadot::max_extrinsic_size() / 3), + make_header_and_justification(30, Polkadot::max_extrinsic_size() * 2 / 3), + make_header_and_justification(40, Polkadot::max_extrinsic_size()), + ]; + let batches = + make_mandatory_headers_batches::(headers_to_submit, |_| 0); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); + } + + #[test] + fn make_mandatory_headers_batches_group_by_weight() { + let headers_to_submit = vec![ + make_header_and_justification(10, 0), + make_header_and_justification(20, 0), + make_header_and_justification(30, 0), + make_header_and_justification(40, 0), + ]; + let batches = make_mandatory_headers_batches::( + headers_to_submit, + |(header, _)| { + if header.number() == 10 || header.number() == 20 { + Polkadot::max_extrinsic_weight() / 3 + } else if header.number() == 30 { + Polkadot::max_extrinsic_weight() * 2 / 3 + } else { + Polkadot::max_extrinsic_weight() + } + }, + ); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 82c55965a991..45034aba4b5e 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -121,18 +121,26 @@ impl RelayHeaders { let target_client = self.target.to_client::().await?; let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; - let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; + + let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - let finality = Finality::new(target_client.clone(), target_sign); - finality.start_relay_guards(); + let target_transactions_params = substrate_relay_helper::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; + Finality::start_relay_guards( + &target_client, + &target_transactions_params, + self.target.can_start_version_guard(), + ) + .await?; - substrate_relay_helper::finality_pipeline::run( - finality, + substrate_relay_helper::finality_pipeline::run::( source_client, target_client, self.only_mandatory_headers, - target_transactions_mortality, + target_transactions_params, metrics_params, ) .await diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 9d76a0296fb2..4ff6ee0947cb 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -29,16 +29,18 @@ use strum::VariantNames; use codec::Encode; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ - AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, ChainRuntimeVersion, Client, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, on_demand_headers::OnDemandHeadersRelay, + finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, + on_demand_headers::OnDemandHeadersRelay, TransactionParams, }; use crate::{ - cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}, + cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, RuntimeVersionType}, declare_chain_options, }; @@ -48,7 +50,7 @@ use crate::{ /// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), /// then rational relayers may stop relaying messages because they were submitted using /// lesser conversion rate. -const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; +pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; /// Start headers+messages relayer process. #[derive(StructOpt)] @@ -131,21 +133,9 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = - bp_millau::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = - bp_rialto::SESSION_LENGTH; - use crate::chains::{ - millau_messages_to_rialto::{ - standalone_metrics as left_to_right_standalone_metrics, - run as left_to_right_messages, - update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, - }, - rialto_messages_to_millau::{ - run as right_to_left_messages, - update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, - }, + millau_messages_to_rialto::MillauMessagesToRialto as LeftToRightMessageLane, + rialto_messages_to_millau::RialtoMessagesToMillau as RightToLeftMessageLane, }; async fn left_create_account( @@ -180,51 +170,45 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = - bp_rococo::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = - bp_wococo::SESSION_LENGTH; - use crate::chains::{ - rococo_messages_to_wococo::{ - standalone_metrics as left_to_right_standalone_metrics, - run as left_to_right_messages, - }, - wococo_messages_to_rococo::{ - run as right_to_left_messages, - }, + rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, + wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, }; - async fn update_right_to_left_conversion_rate( - _client: Client, - _signer: ::AccountKeyPair, - _updated_rate: f64, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) - } - - async fn update_left_to_right_conversion_rate( - _client: Client, - _signer: ::AccountKeyPair, - _updated_rate: f64, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) - } - async fn left_create_account( - _left_client: Client, - _left_sign: ::AccountKeyPair, - _account_id: AccountIdOf, + left_client: Client, + left_sign: ::AccountKeyPair, + account_id: AccountIdOf, ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) + submit_signed_extrinsic( + left_client, + left_sign, + relay_rococo_client::runtime::Call::Balances( + relay_rococo_client::runtime::BalancesCall::transfer( + bp_rococo::AccountAddress::Id(account_id), + bp_rococo::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } async fn right_create_account( - _right_client: Client, - _right_sign: ::AccountKeyPair, - _account_id: AccountIdOf, + right_client: Client, + right_sign: ::AccountKeyPair, + account_id: AccountIdOf, ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) + submit_signed_extrinsic( + right_client, + right_sign, + relay_wococo_client::runtime::Call::Balances( + relay_wococo_client::runtime::BalancesCall::transfer( + bp_wococo::AccountAddress::Id(account_id), + bp_wococo::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } $generic @@ -243,21 +227,9 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = - bp_kusama::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = - bp_polkadot::SESSION_LENGTH; - use crate::chains::{ - kusama_messages_to_polkadot::{ - standalone_metrics as left_to_right_standalone_metrics, - run as left_to_right_messages, - update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, - }, - polkadot_messages_to_kusama::{ - run as right_to_left_messages, - update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, - }, + kusama_messages_to_polkadot::KusamaMessagesToPolkadot as LeftToRightMessageLane, + polkadot_messages_to_kusama::PolkadotMessagesToKusama as RightToLeftMessageLane, }; async fn left_create_account( @@ -265,29 +237,17 @@ macro_rules! select_bridge { left_sign: ::AccountKeyPair, account_id: AccountIdOf, ) -> anyhow::Result<()> { - let left_genesis_hash = *left_client.genesis_hash(); - left_client - .submit_signed_extrinsic( - left_sign.public().into(), - move |_, transaction_nonce| { - Bytes( - Left::sign_transaction(left_genesis_hash, &left_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_kusama_client::runtime::Call::Balances( - relay_kusama_client::runtime::BalancesCall::transfer( - bp_kusama::AccountAddress::Id(account_id), - bp_kusama::EXISTENTIAL_DEPOSIT.into(), - ), - ), - transaction_nonce, - ), - ).encode() - ) - }, - ) - .await - .map(drop) - .map_err(|e| anyhow::format_err!("{}", e)) + submit_signed_extrinsic( + left_client, + left_sign, + relay_kusama_client::runtime::Call::Balances( + relay_kusama_client::runtime::BalancesCall::transfer( + bp_kusama::AccountAddress::Id(account_id), + bp_kusama::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } async fn right_create_account( @@ -295,29 +255,17 @@ macro_rules! select_bridge { right_sign: ::AccountKeyPair, account_id: AccountIdOf, ) -> anyhow::Result<()> { - let right_genesis_hash = *right_client.genesis_hash(); - right_client - .submit_signed_extrinsic( - right_sign.public().into(), - move |_, transaction_nonce| { - Bytes( - Right::sign_transaction(right_genesis_hash, &right_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_polkadot_client::runtime::Call::Balances( - relay_polkadot_client::runtime::BalancesCall::transfer( - bp_polkadot::AccountAddress::Id(account_id), - bp_polkadot::EXISTENTIAL_DEPOSIT.into(), - ), - ), - transaction_nonce, - ), - ).encode() - ) - }, - ) - .await - .map(drop) - .map_err(|e| anyhow::format_err!("{}", e)) + submit_signed_extrinsic( + right_client, + right_sign, + relay_polkadot_client::runtime::Call::Balances( + relay_polkadot_client::runtime::BalancesCall::transfer( + bp_polkadot::AccountAddress::Id(account_id), + bp_polkadot::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } $generic @@ -363,11 +311,13 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); let left_to_right_metrics = - left_to_right_standalone_metrics(left_client.clone(), right_client.clone())?; + substrate_relay_helper::messages_metrics::standalone_metrics::< + LeftToRightMessageLane, + >(left_client.clone(), right_client.clone())?; let right_to_left_metrics = left_to_right_metrics.clone().reverse(); // start conversion rate update loops for left/right chains - if let Some(left_messages_pallet_owner) = left_messages_pallet_owner { + if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { let left_client = left_client.clone(); let format_err = || { anyhow::format_err!( @@ -376,7 +326,15 @@ impl RelayHeadersAndMessages { Left::NAME ) }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + LeftToRightMessageLane, + Left, + >( + left_client.clone(), + TransactionParams { + signer: left_messages_pallet_owner.clone(), + mortality: left_transactions_mortality, + }, left_to_right_metrics .target_to_source_conversion_rate .as_ref() @@ -393,24 +351,9 @@ impl RelayHeadersAndMessages { .ok_or_else(format_err)? .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - move |new_rate| { - log::info!( - target: "bridge", - "Going to update {} -> {} (on {}) conversion rate to {}.", - Right::NAME, - Left::NAME, - Left::NAME, - new_rate, - ); - update_right_to_left_conversion_rate( - left_client.clone(), - left_messages_pallet_owner.clone(), - new_rate, - ) - }, ); } - if let Some(right_messages_pallet_owner) = right_messages_pallet_owner { + if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { let right_client = right_client.clone(); let format_err = || { anyhow::format_err!( @@ -419,38 +362,31 @@ impl RelayHeadersAndMessages { Right::NAME ) }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + RightToLeftMessageLane, + Right, + >( + right_client.clone(), + TransactionParams { + signer: right_messages_pallet_owner.clone(), + mortality: right_transactions_mortality, + }, right_to_left_metrics .target_to_source_conversion_rate .as_ref() .ok_or_else(format_err)? .shared_value_ref(), - left_to_right_metrics - .source_to_base_conversion_rate + right_to_left_metrics + .target_to_base_conversion_rate .as_ref() .ok_or_else(format_err)? .shared_value_ref(), - left_to_right_metrics - .target_to_base_conversion_rate + right_to_left_metrics + .source_to_base_conversion_rate .as_ref() .ok_or_else(format_err)? .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - move |new_rate| { - log::info!( - target: "bridge", - "Going to update {} -> {} (on {}) conversion rate to {}.", - Left::NAME, - Right::NAME, - Right::NAME, - new_rate, - ); - update_left_to_right_conversion_rate( - right_client.clone(), - right_messages_pallet_owner.clone(), - new_rate, - ) - }, ); } @@ -493,21 +429,55 @@ impl RelayHeadersAndMessages { } } + // add balance-related metrics + let metrics_params = + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + left_client.clone(), + metrics_params, + Some(left_sign.public().into()), + left_messages_pallet_owner.map(|kp| kp.public().into()), + ) + .await?; + let metrics_params = + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + right_client.clone(), + metrics_params, + Some(right_sign.public().into()), + right_messages_pallet_owner.map(|kp| kp.public().into()), + ) + .await?; + // start on-demand header relays - let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( + let left_to_right_transaction_params = TransactionParams { + mortality: right_transactions_mortality, + signer: right_sign.clone(), + }; + let right_to_left_transaction_params = TransactionParams { + mortality: left_transactions_mortality, + signer: left_sign.clone(), + }; + LeftToRightFinality::start_relay_guards( + &right_client, + &left_to_right_transaction_params, + params.right.can_start_version_guard(), + ) + .await?; + RightToLeftFinality::start_relay_guards( + &left_client, + &right_to_left_transaction_params, + params.left.can_start_version_guard(), + ) + .await?; + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( left_client.clone(), right_client.clone(), - right_transactions_mortality, - LeftToRightFinality::new(right_client.clone(), right_sign.clone()), - MAX_MISSING_LEFT_HEADERS_AT_RIGHT, + left_to_right_transaction_params, params.shared.only_mandatory_headers, ); - let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( + let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( right_client.clone(), left_client.clone(), - left_transactions_mortality, - RightToLeftFinality::new(left_client.clone(), left_sign.clone()), - MAX_MISSING_RIGHT_HEADERS_AT_LEFT, + right_to_left_transaction_params, params.shared.only_mandatory_headers, ); @@ -515,13 +485,19 @@ impl RelayHeadersAndMessages { let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { let lane = lane.into(); - let left_to_right_messages = left_to_right_messages(MessagesRelayParams { + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< + LeftToRightMessageLane, + >(MessagesRelayParams { source_client: left_client.clone(), - source_sign: left_sign.clone(), - source_transactions_mortality: left_transactions_mortality, + source_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, target_client: right_client.clone(), - target_sign: right_sign.clone(), - target_transactions_mortality: right_transactions_mortality, + target_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, @@ -531,13 +507,19 @@ impl RelayHeadersAndMessages { }) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); - let right_to_left_messages = right_to_left_messages(MessagesRelayParams { + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< + RightToLeftMessageLane, + >(MessagesRelayParams { source_client: right_client.clone(), - source_sign: right_sign.clone(), - source_transactions_mortality: right_transactions_mortality, + source_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, target_client: left_client.clone(), - target_sign: left_sign.clone(), - target_transactions_mortality: left_transactions_mortality, + target_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, @@ -561,3 +543,34 @@ impl RelayHeadersAndMessages { }) } } + +/// Sign and submit transaction with given call to the chain. +async fn submit_signed_extrinsic>( + client: Client, + sign: C::AccountKeyPair, + call: CallOf, +) -> anyhow::Result<()> +where + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, + CallOf: Send, +{ + let genesis_hash = *client.genesis_hash(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; + client + .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { + Ok(Bytes( + C::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? + .encode(), + )) + }) + .await + .map(drop) + .map_err(|e| anyhow::format_err!("{}", e)) +} diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index e47abfc5d94e..45087fad5eb3 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -18,7 +18,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use substrate_relay_helper::messages_lane::MessagesRelayParams; +use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; use crate::{ cli::{ @@ -84,13 +84,17 @@ impl RelayMessages { let relayer_mode = self.relayer_mode.into(); let relay_strategy = MixStrategy::new(relayer_mode); - relay_messages(MessagesRelayParams { + substrate_relay_helper::messages_lane::run::(MessagesRelayParams { source_client, - source_sign, - source_transactions_mortality, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, target_client, - target_sign, - target_transactions_mortality, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 64663d7e8ec0..f92c035082cb 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -19,9 +19,10 @@ use crate::cli::{Balance, TargetConnectionParams, TargetSigningParams}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ - BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderOf, TransactionSignScheme, + BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, + SignParam, TransactionSignScheme, }; -use relay_utils::FailedClient; +use relay_utils::{FailedClient, HeaderId}; use sp_core::Bytes; use sp_runtime::{ traits::{Hash, Header as HeaderT}, @@ -29,6 +30,7 @@ use sp_runtime::{ }; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::TransactionParams; /// Start resubmit transactions process. #[derive(StructOpt)] @@ -115,13 +117,16 @@ impl ResubmitTransactions { select_bridge!(self.chain, { let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); let client = self.target.to_client::().await?; - let key_pair = self.target_sign.to_keypair::()?; + let transaction_params = TransactionParams { + signer: self.target_sign.to_keypair::()?, + mortality: self.target_sign.target_transactions_mortality, + }; relay_utils::relay_loop((), client) .run(relay_loop_name, move |_, client, _| { run_until_connection_lost::( client, - key_pair.clone(), + transaction_params.clone(), Context { strategy: self.strategy, best_header: HeaderOf::::new( @@ -212,13 +217,14 @@ impl Context { /// Run resubmit transactions loop. async fn run_until_connection_lost>( client: Client, - key_pair: S::AccountKeyPair, + transaction_params: TransactionParams, mut context: Context, ) -> Result<(), FailedClient> { loop { async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - let result = run_loop_iteration::(client.clone(), key_pair.clone(), context).await; + let result = + run_loop_iteration::(client.clone(), transaction_params.clone(), context).await; context = match result { Ok(context) => context, Err(error) => { @@ -237,20 +243,21 @@ async fn run_until_connection_lost /// Run single loop iteration. async fn run_loop_iteration>( client: Client, - key_pair: S::AccountKeyPair, + transaction_params: TransactionParams, mut context: Context, ) -> Result, SubstrateError> { // correct best header is required for all other actions context.best_header = client.best_header().await?; // check if there's queued transaction, signed by given author - let original_transaction = match lookup_signer_transaction::(&client, &key_pair).await? { - Some(original_transaction) => original_transaction, - None => { - log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); - return Ok(context) - }, - }; + let original_transaction = + match lookup_signer_transaction::(&client, &transaction_params.signer).await? { + Some(original_transaction) => original_transaction, + None => { + log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); + return Ok(context) + }, + }; let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); let context = context.notice_transaction(original_transaction_hash); @@ -280,8 +287,8 @@ async fn run_loop_iteration>( // update transaction tip let (is_updated, updated_transaction) = update_transaction_tip::( &client, - &key_pair, - context.best_header.hash(), + &transaction_params, + HeaderId(*context.best_header.number(), context.best_header.hash()), original_transaction, context.tip_step, context.tip_limit, @@ -397,20 +404,21 @@ fn select_transaction_from_queue( /// Try to find appropriate tip for transaction so that its priority is larger than given. async fn update_transaction_tip>( client: &Client, - key_pair: &S::AccountKeyPair, - at_block: C::Hash, + transaction_params: &TransactionParams, + at_block: HeaderIdOf, tx: S::SignedTransaction, tip_step: C::Balance, tip_limit: C::Balance, target_priority: TransactionPriority, ) -> Result<(bool, S::SignedTransaction), SubstrateError> { let stx = format!("{:?}", tx); - let mut current_priority = client.validate_transaction(at_block, tx.clone()).await??.priority; + let mut current_priority = client.validate_transaction(at_block.1, tx.clone()).await??.priority; let mut unsigned_tx = S::parse_transaction(tx).ok_or_else(|| { SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)) })?; let old_tip = unsigned_tx.tip; + let (spec_version, transaction_version) = client.simple_runtime_version().await?; while current_priority < target_priority { let next_tip = unsigned_tx.tip + tip_step; if next_tip > tip_limit { @@ -429,13 +437,15 @@ async fn update_transaction_tip>( unsigned_tx.tip = next_tip; current_priority = client .validate_transaction( - at_block, - S::sign_transaction( - *client.genesis_hash(), - key_pair, - relay_substrate_client::TransactionEra::immortal(), - unsigned_tx.clone(), - ), + at_block.1, + S::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: transaction_params.signer.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: unsigned_tx.clone(), + })?, ) .await?? .priority; @@ -451,12 +461,17 @@ async fn update_transaction_tip>( Ok(( old_tip != unsigned_tx.tip, - S::sign_transaction( - *client.genesis_hash(), - key_pair, - relay_substrate_client::TransactionEra::immortal(), - unsigned_tx, - ), + S::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: transaction_params.signer.clone(), + era: relay_substrate_client::TransactionEra::new( + at_block, + transaction_params.mortality, + ), + unsigned: unsigned_tx, + })?, )) } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 3e77ad834292..ddb1ff59b5d0 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -17,15 +17,15 @@ use crate::cli::{ bridge::FullBridge, encode_call::{self, CliEncodeCall}, - estimate_fee::estimate_message_delivery_and_dispatch_fee, - Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, - SourceSigningParams, TargetSigningParams, + estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, + Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::BalanceOf; +use bp_runtime::Chain as _; use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; use std::fmt::Debug; @@ -66,6 +66,12 @@ pub struct SendMessage { /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + /// A way to override conversion rate between bridge tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + conversion_rate_override: Option, /// Where dispatch fee is paid? #[structopt( long, @@ -88,10 +94,16 @@ pub struct SendMessage { /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] origin: Origins, + + // Normally we don't need to connect to the target chain to send message. But for testing + // we may want to use **actual** `spec_version` of the target chain when composing a message. + // Then we'll need to read version from the target chain node. + #[structopt(flatten)] + target: TargetConnectionParams, } impl SendMessage { - pub fn encode_payload( + pub async fn encode_payload( &mut self, ) -> anyhow::Result>> { crate::select_full_bridge!(self.bridge, { @@ -110,18 +122,23 @@ impl SendMessage { encode_call::preprocess_call::(message, bridge.bridge_instance_index()); let target_call = Target::encode_call(message)?; + let target_spec_version = self.target.selected_chain_spec_version::().await?; let payload = { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, - ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight), + || { + Ok(ExplicitOrMaximal::Explicit( + Target::get_dispatch_info(&target_call)?.weight, + )) + }, compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - ); + )?; let source_sender_public: MultiSigner = source_sign.public().into(); let source_account_id = source_sender_public.into_account(); message_payload( - Target::RUNTIME_VERSION.spec_version, + target_spec_version, target_call_weight, match origin { Origins::Source => CallOrigin::SourceAccount(source_account_id), @@ -130,7 +147,7 @@ impl SendMessage { let digest = account_ownership_digest( &target_call, source_account_id.clone(), - Target::RUNTIME_VERSION.spec_version, + target_spec_version, ); let target_origin_public = target_sign.public(); let digest_signature = target_sign.sign(&digest); @@ -152,17 +169,19 @@ impl SendMessage { /// Run the command. pub async fn run(mut self) -> anyhow::Result<()> { crate::select_full_bridge!(self.bridge, { - let payload = self.encode_payload()?; + let payload = self.encode_payload().await?; let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; let lane = self.lane.clone().into(); + let conversion_rate_override = self.conversion_rate_override; let fee = match self.fee { Some(fee) => fee, None => Balance( - estimate_message_delivery_and_dispatch_fee::, _, _>( + estimate_message_delivery_and_dispatch_fee::( &source_client, + conversion_rate_override, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), @@ -171,6 +190,7 @@ impl SendMessage { ), }; let dispatch_weight = payload.weight; + let payload_len = payload.encode().len(); let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage { bridge_instance_index: self.bridge.bridge_instance_index(), lane: self.lane, @@ -179,25 +199,31 @@ impl SendMessage { })?; let source_genesis_hash = *source_client.genesis_hash(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let estimated_transaction_fee = source_client .estimate_extrinsic_fee(Bytes( - Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(send_message_call.clone(), 0), - ) + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), + })? .encode(), )) .await?; source_client .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { - let signed_source_call = Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(send_message_call, transaction_nonce), - ) + let signed_source_call = Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), + })? .encode(); log::info!( @@ -205,7 +231,7 @@ impl SendMessage { "Sending message to {}. Lane: {:?}. Size: {}. Dispatch weight: {}. Fee: {}", Target::NAME, lane, - signed_source_call.len(), + payload_len, dispatch_weight, fee, ); @@ -225,7 +251,7 @@ impl SendMessage { HexBytes::encode(&signed_source_call) ); - Bytes(signed_source_call) + Ok(Bytes(signed_source_call)) }) .await?; }); @@ -236,12 +262,16 @@ impl SendMessage { fn prepare_call_dispatch_weight( user_specified_dispatch_weight: &Option>, - weight_from_pre_dispatch_call: ExplicitOrMaximal, + weight_from_pre_dispatch_call: impl Fn() -> anyhow::Result>, maximal_allowed_weight: Weight, -) -> Weight { - match user_specified_dispatch_weight.clone().unwrap_or(weight_from_pre_dispatch_call) { - ExplicitOrMaximal::Explicit(weight) => weight, - ExplicitOrMaximal::Maximal => maximal_allowed_weight, +) -> anyhow::Result { + match user_specified_dispatch_weight + .clone() + .map(Ok) + .unwrap_or_else(weight_from_pre_dispatch_call)? + { + ExplicitOrMaximal::Explicit(weight) => Ok(weight), + ExplicitOrMaximal::Maximal => Ok(maximal_allowed_weight), } } @@ -283,10 +313,11 @@ pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: #[cfg(test)] mod tests { use super::*; + use crate::cli::CliChain; use hex_literal::hex; - #[test] - fn send_remark_rialto_to_millau() { + #[async_std::test] + async fn send_remark_rialto_to_millau() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -295,20 +326,22 @@ mod tests { "1234", "--source-signer", "//Alice", + "--conversion-rate-override", + "0.75", "remark", "--remark-payload", "1234", ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!( payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 576000, + weight: 0, origin: CallOrigin::SourceAccount( sp_keyring::AccountKeyring::Alice.to_account_id() ), @@ -318,8 +351,8 @@ mod tests { ); } - #[test] - fn send_remark_millau_to_rialto() { + #[async_std::test] + async fn send_remark_millau_to_rialto() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -332,13 +365,15 @@ mod tests { "Target", "--target-signer", "//Bob", + "--conversion-rate-override", + "metric", "remark", "--remark-payload", "1234", ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then // Since signatures are randomized we extract it from here and only check the rest. @@ -350,7 +385,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 576000, + weight: 0, origin: CallOrigin::TargetAccount( sp_keyring::AccountKeyring::Alice.to_account_id(), sp_keyring::AccountKeyring::Bob.into(), @@ -382,8 +417,8 @@ mod tests { assert!(send_message.is_ok()); } - #[test] - fn accepts_non_default_dispatch_fee_payment() { + #[async_std::test] + async fn accepts_non_default_dispatch_fee_payment() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -398,7 +433,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!( diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index dbe46f469070..0758deddfd10 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -29,15 +29,15 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use frame_support::dispatch::GetDispatchInfo; use relay_substrate_client::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, - Client, Error as SubstrateError, HashOf, SignatureOf, Subscription, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, + Client, Error as SubstrateError, HashOf, SignParam, SignatureOf, Subscription, + TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, }; -use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, H256, U256}; +use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, U256}; use sp_runtime::traits::{Convert, Header as HeaderT}; use crate::cli::{ - Balance, CliChain, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, - TargetSigningParams, + estimate_fee::ConversionRateOverride, Balance, CliChain, SourceConnectionParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; /// Swap tokens. @@ -65,6 +65,18 @@ pub struct SwapTokens { /// Target chain balance that target signer wants to swap. #[structopt(long)] target_balance: Balance, + /// A way to override conversion rate from target to source tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + target_to_source_conversion_rate_override: Option, + /// A way to override conversion rate from source to target tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + source_to_target_conversion_rate_override: Option, } /// Token swap type. @@ -98,6 +110,8 @@ macro_rules! select_bridge { SwapTokensBridge::MillauToRialto => { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; + const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; + const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; @@ -114,9 +128,6 @@ macro_rules! select_bridge { const SOURCE_CHAIN_ID: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; const TARGET_CHAIN_ID: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; - const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; - const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; - const SOURCE_TO_TARGET_LANE_ID: bp_messages::LaneId = *b"swap"; const TARGET_TO_SOURCE_LANE_ID: bp_messages::LaneId = [0, 0, 0, 0]; @@ -134,6 +145,10 @@ impl SwapTokens { let source_sign = self.source_sign.to_keypair::()?; let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; + let target_to_source_conversion_rate_override = + self.target_to_source_conversion_rate_override; + let source_to_target_conversion_rate_override = + self.source_to_target_conversion_rate_override; // names of variables in this function are matching names used by the // `pallet-bridge-token-swap` @@ -199,9 +214,14 @@ impl SwapTokens { // prepare `create_swap` call let target_public_at_bridged_chain: AccountPublicOf = target_sign.public().into(); - let swap_delivery_and_dispatch_fee: BalanceOf = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + let swap_delivery_and_dispatch_fee = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< + Source, + Target, + _, + >( &source_client, + target_to_source_conversion_rate_override.clone(), ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, SOURCE_TO_TARGET_LANE_ID, bp_message_dispatch::MessagePayload { @@ -234,20 +254,27 @@ impl SwapTokens { // start tokens swap let source_genesis_hash = *source_client.genesis_hash(); let create_swap_signer = source_sign.clone(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let swap_created_at = wait_until_transaction_is_finalized::( source_client .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( - Source::sign_transaction( - source_genesis_hash, - &create_swap_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(create_swap_call, transaction_nonce), - ) + Ok(Bytes( + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: create_swap_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + create_swap_call.into(), + transaction_nonce, + ), + })? .encode(), - ) + )) }, ) .await?, @@ -255,11 +282,10 @@ impl SwapTokens { .await?; // read state of swap after it has been created - let token_swap_hash: H256 = token_swap.using_encoded(blake2_256).into(); - let token_swap_storage_key = bp_runtime::storage_map_final_key_identity( + let token_swap_hash = token_swap.hash(); + let token_swap_storage_key = bp_token_swap::storage_keys::pending_swaps_key( TOKEN_SWAP_PALLET_NAME, - pallet_bridge_token_swap::PENDING_SWAPS_MAP_NAME, - token_swap_hash.as_ref(), + token_swap_hash, ); match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key) .await? @@ -337,7 +363,7 @@ impl SwapTokens { // if is_transfer_succeeded { - log::info!(target: "bridge", "Claiming the swap swap"); + log::info!(target: "bridge", "Claiming the swap"); // prepare `claim_swap` message that will be sent over the bridge let claim_swap_call: CallOf = @@ -351,9 +377,14 @@ impl SwapTokens { dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: claim_swap_call.encode(), }; - let claim_swap_delivery_and_dispatch_fee: BalanceOf = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + let claim_swap_delivery_and_dispatch_fee = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< + Target, + Source, + _, + >( &target_client, + source_to_target_conversion_rate_override.clone(), ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, TARGET_TO_SOURCE_LANE_ID, claim_swap_message.clone(), @@ -369,23 +400,27 @@ impl SwapTokens { // send `claim_swap` message let target_genesis_hash = *target_client.genesis_hash(); + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; let _ = wait_until_transaction_is_finalized::( target_client .submit_and_watch_signed_extrinsic( accounts.target_account_at_bridged_chain.clone(), move |_, transaction_nonce| { - Bytes( - Target::sign_transaction( - target_genesis_hash, - &target_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - send_message_call, + Ok(Bytes( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: target_genesis_hash, + signer: target_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + send_message_call.into(), transaction_nonce, ), - ) + })? .encode(), - ) + )) }, ) .await?, @@ -409,23 +444,27 @@ impl SwapTokens { log::info!(target: "bridge", "Cancelling the swap"); let cancel_swap_call: CallOf = pallet_bridge_token_swap::Call::cancel_swap { swap: token_swap.clone() }.into(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let _ = wait_until_transaction_is_finalized::( source_client .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( - Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - cancel_swap_call, + Ok(Bytes( + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + cancel_swap_call.into(), transaction_nonce, ), - ) + })? .encode(), - ) + )) }, ) .await?, @@ -673,6 +712,7 @@ async fn read_token_swap_state( #[cfg(test)] mod tests { use super::*; + use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; #[test] fn swap_tokens_millau_to_rialto_no_lock() { @@ -706,6 +746,11 @@ mod tests { source_host: "127.0.0.1".into(), source_port: 9000, source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } }, source_sign: SourceSigningParams { source_signer: Some("//Alice".into()), @@ -718,6 +763,11 @@ mod tests { target_host: "127.0.0.1".into(), target_port: 9001, target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } }, target_sign: TargetSigningParams { target_signer: Some("//Bob".into()), @@ -729,6 +779,8 @@ mod tests { swap_type: TokenSwapType::NoLock, source_balance: Balance(8000000000), target_balance: Balance(9000000000), + target_to_source_conversion_rate_override: None, + source_to_target_conversion_rate_override: None, } ); } @@ -754,6 +806,10 @@ mod tests { "//Bob", "--target-balance", "9000000000", + "--target-to-source-conversion-rate-override", + "metric", + "--source-to-target-conversion-rate-override", + "84.56", "lock-until-block", "--blocks-before-expire", "1", @@ -767,6 +823,11 @@ mod tests { source_host: "127.0.0.1".into(), source_port: 9000, source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } }, source_sign: SourceSigningParams { source_signer: Some("//Alice".into()), @@ -779,6 +840,11 @@ mod tests { target_host: "127.0.0.1".into(), target_port: 9001, target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } }, target_sign: TargetSigningParams { target_signer: Some("//Bob".into()), @@ -793,6 +859,10 @@ mod tests { }, source_balance: Balance(8000000000), target_balance: Balance(9000000000), + target_to_source_conversion_rate_override: Some(ConversionRateOverride::Metric), + source_to_target_conversion_rate_override: Some(ConversionRateOverride::Explicit( + 84.56 + )), } ); } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index a48d82f641b7..35c24c1089e6 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -2,14 +2,14 @@ name = "relay-kusama-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index a93726620ff6..e228f2dc24de 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,10 +16,12 @@ //! 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, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,21 @@ impl ChainBase for Kusama { type Balance = bp_kusama::Balance; 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 { const NAME: &'static str = "Kusama"; + const TOKEN_ID: Option<&'static str> = Some("kusama"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -57,6 +70,24 @@ impl Chain for Kusama { type WeightToFee = bp_kusama::WeightToFee; } +impl ChainWithGrandpa for Kusama { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Kusama { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_kusama::account_info_storage_key(account_id)) @@ -68,34 +99,30 @@ impl TransactionSignScheme for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_kusama::SignedExtensions::new( - bp_kusama::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + 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| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - bp_kusama::UncheckedExtrinsic::new_signed( + Ok(bp_kusama::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index 6d0ab5462d7c..59a919e6cb97 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -70,6 +70,9 @@ pub enum Call { /// Balances pallet. #[codec(index = 4)] Balances(BalancesCall), + /// Utility pallet. + #[codec(index = 24)] + Utility(UtilityCall), /// Polkadot bridge pallet. #[codec(index = 110)] BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), @@ -102,6 +105,8 @@ pub enum BridgePolkadotGrandpaCall { ), #[codec(index = 1)] initialize(bp_header_chain::InitializationData<::Header>), + #[codec(index = 3)] + set_operational(bool), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -136,6 +141,13 @@ pub enum BridgePolkadotMessagesCall { ), } +#[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)] diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 49d9dade154c..989324334551 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -2,16 +2,17 @@ name = "relay-millau-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Supported Chains +bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 3f1aba1f3b37..eae9d9b4586a 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Millau-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -29,7 +31,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Millau chain definition. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Millau; impl ChainBase for Millau { @@ -42,10 +44,40 @@ impl ChainBase for Millau { type Balance = millau_runtime::Balance; type Index = millau_runtime::Index; type Signature = millau_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_millau::Millau::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_millau::Millau::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Millau { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Millau { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); } impl Chain for Millau { const NAME: &'static str = "Millau"; + // Rialto token has no value, but we associate it with KSM token + const TOKEN_ID: Option<&'static str> = Some("kusama"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -69,43 +101,40 @@ impl TransactionSignScheme for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( - unsigned.call, + param.unsigned.call.clone(), ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), + frame_system::CheckEra::::from(param.era.frame_era()), + frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( - millau_runtime::VERSION.spec_version, - millau_runtime::VERSION.transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), + (), + param.spec_version, + param.transaction_version, + param.genesis_hash, + param.era.signed_payload(param.genesis_hash), (), (), (), ), ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - millau_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(millau_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -124,9 +153,9 @@ impl TransactionSignScheme for Millau { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, - nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.6.encode()[..]) + call: tx.function.into(), + nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + tip: Compact::>::decode(&mut &extra.7.encode()[..]) .ok()? .into(), }) @@ -138,3 +167,32 @@ pub type SigningParams = sp_core::sr25519::Pair; /// Millau header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: millau_runtime::Call::System(millau_runtime::SystemCall::remark { + remark: b"Hello world!".to_vec(), + }) + .into(), + nonce: 777, + tip: 888, + }; + let signed_transaction = Millau::sign_transaction(SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 64].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + era: TransactionEra::immortal(), + unsigned: unsigned.clone(), + }) + .unwrap(); + let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index ff7748657941..96cfa2ce1bac 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -2,14 +2,14 @@ name = "relay-polkadot-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index e6ceabf583e0..d4ada45e36cc 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,10 +16,12 @@ //! 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, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,21 @@ impl ChainBase for Polkadot { type Balance = bp_polkadot::Balance; 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 { const NAME: &'static str = "Polkadot"; + const TOKEN_ID: Option<&'static str> = Some("polkadot"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -57,6 +70,25 @@ impl Chain for Polkadot { type WeightToFee = bp_polkadot::WeightToFee; } +impl ChainWithGrandpa for Polkadot { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Polkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_polkadot::account_info_storage_key(account_id)) @@ -68,34 +100,30 @@ impl TransactionSignScheme for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_polkadot::SignedExtensions::new( - bp_polkadot::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + 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| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - bp_polkadot::UncheckedExtrinsic::new_signed( + Ok(bp_polkadot::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index 8b125a37843c..fa45115a6b5c 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -70,6 +70,9 @@ pub enum Call { /// Balances pallet. #[codec(index = 5)] Balances(BalancesCall), + /// Utility pallet. + #[codec(index = 26)] + Utility(UtilityCall), /// Kusama bridge pallet. #[codec(index = 110)] BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), @@ -102,6 +105,8 @@ pub enum BridgeKusamaGrandpaCall { ), #[codec(index = 1)] initialize(bp_header_chain::InitializationData<::Header>), + #[codec(index = 3)] + set_operational(bool), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -136,6 +141,13 @@ pub enum BridgeKusamaMessagesCall { ), } +#[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)] diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index e4518c687765..ebc285606431 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-rialto-parachain-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index ca299a0eeb78..65bf46f660cc 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Rialto-Substrate chain. +use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase}; use std::time::Duration; @@ -37,10 +38,21 @@ impl ChainBase for RialtoParachain { type Balance = rialto_parachain_runtime::Balance; type Index = rialto_parachain_runtime::Index; type Signature = rialto_parachain_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; + const TOKEN_ID: Option<&'static str> = None; + // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 3132b26d27fc..37c55dd5f153 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -2,16 +2,17 @@ name = "relay-rialto-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bp-messages = { path = "../../primitives/messages" } bp-rialto = { path = "../../primitives/chain-rialto" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 42ed8bce3bd9..858227e8083f 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Rialto-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -29,7 +31,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Rialto chain definition -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Rialto; impl ChainBase for Rialto { @@ -42,10 +44,22 @@ impl ChainBase for Rialto { type Balance = rialto_runtime::Balance; type Index = rialto_runtime::Index; type Signature = rialto_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for Rialto { const NAME: &'static str = "Rialto"; + // Rialto token has no value, but we associate it with DOT token + const TOKEN_ID: Option<&'static str> = Some("polkadot"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -55,6 +69,24 @@ impl Chain for Rialto { type WeightToFee = bp_rialto::WeightToFee; } +impl ChainWithGrandpa for Rialto { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Rialto { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rialto { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; @@ -69,43 +101,40 @@ impl TransactionSignScheme for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( - unsigned.call, + param.unsigned.call.clone(), ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), + frame_system::CheckEra::::from(param.era.frame_era()), + frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( - rialto_runtime::VERSION.spec_version, - rialto_runtime::VERSION.transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), + (), + param.spec_version, + param.transaction_version, + param.genesis_hash, + param.era.signed_payload(param.genesis_hash), (), (), (), ), ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - rialto_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(rialto_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account().into(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -122,9 +151,9 @@ impl TransactionSignScheme for Rialto { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, - nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.6.encode()[..]) + call: tx.function.into(), + nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + tip: Compact::>::decode(&mut &extra.7.encode()[..]) .ok()? .into(), }) @@ -136,3 +165,32 @@ pub type SigningParams = sp_core::sr25519::Pair; /// Rialto header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { + remark: b"Hello world!".to_vec(), + }) + .into(), + nonce: 777, + tip: 888, + }; + let signed_transaction = Rialto::sign_transaction(SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + era: TransactionEra::immortal(), + unsigned: unsigned.clone(), + }) + .unwrap(); + let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 28e97d3bf0ce..2b78684a853c 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -2,14 +2,14 @@ name = "relay-rococo-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ad61e3cfd643..f63041df9edd 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,10 +16,12 @@ //! 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, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,21 @@ impl ChainBase for Rococo { type Balance = bp_rococo::Balance; 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 { const NAME: &'static str = "Rococo"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -60,6 +73,24 @@ impl Chain for Rococo { type WeightToFee = bp_rococo::WeightToFee; } +impl ChainWithGrandpa for Rococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Rococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_rococo::account_info_storage_key(account_id)) @@ -71,34 +102,30 @@ impl TransactionSignScheme for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_rococo::SignedExtensions::new( - bp_rococo::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + 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| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - bp_rococo::UncheckedExtrinsic::new_signed( + Ok(bp_rococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index effe6e5c60a9..b13808059964 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -17,9 +17,9 @@ //! Types that are specific to the Rococo runtime. use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::PolkadotLike; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; -use codec::{Decode, Encode}; +use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use scale_info::TypeInfo; @@ -66,12 +66,15 @@ 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)] - BridgeMessagesWococo(BridgeMessagesWococoCall), + BridgeWococoMessages(BridgeWococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -81,6 +84,13 @@ pub enum SystemCall { 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 { @@ -95,7 +105,7 @@ pub enum BridgeGrandpaWococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesWococoCall { +pub enum BridgeWococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 2eb07fdcde46..dad864965e29 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -2,25 +2,27 @@ name = "relay-substrate-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +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 = "2.2.0" } -jsonrpsee-proc-macros = "0.3.1" -jsonrpsee-ws-client = "0.3.1" +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" -tokio = "1.8" +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" } @@ -31,9 +33,10 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 75789ce37f30..60adfb0a88ac 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -14,10 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; +use bp_messages::MessageNonce; +use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; -use frame_support::weights::WeightToFeePolynomial; -use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; +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}; @@ -32,6 +33,18 @@ use std::{fmt::Debug, time::Duration}; 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 @@ -45,12 +58,54 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Dispatchable + Debug; + 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. @@ -58,7 +113,7 @@ pub type WeightToFeeOf = ::WeightToFee; /// Transaction status of the chain. pub type TransactionStatusOf = TransactionStatus, HashOf>; -/// Substrate-based chain with `frame_system::Config::AccountData` set to +/// 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. @@ -79,10 +134,10 @@ pub trait BlockWithJustification

{ } /// Transaction before it is signed. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedTransaction { /// Runtime call of this transaction. - pub call: C::Call, + pub call: EncodedOrDecodedCall, /// Transaction nonce. pub nonce: C::Index, /// Tip included into transaction. @@ -91,7 +146,7 @@ pub struct UnsignedTransaction { impl UnsignedTransaction { /// Create new unsigned transaction with given call, nonce and zero tip. - pub fn new(call: C::Call, nonce: C::Index) -> Self { + pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { Self { call, nonce, tip: Zero::zero() } } @@ -102,6 +157,9 @@ impl UnsignedTransaction { } } +/// 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. @@ -112,12 +170,9 @@ pub trait TransactionSignScheme { type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction; + fn sign_transaction(param: SignParam) -> Result + where + Self: Sized; /// Returns true if transaction is signed. fn is_signed(tx: &Self::SignedTransaction) -> bool; @@ -131,6 +186,22 @@ pub trait TransactionSignScheme { 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() diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 1902875c9381..1e48bc333966 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,8 +18,9 @@ use crate::{ chain::{Chain, ChainWithBalances, TransactionStatusOf}, - rpc::Substrate, - ConnectionParams, Error, HashOf, HeaderIdOf, Result, + rpc::SubstrateClient, + AccountIdOf, BlockNumberOf, ConnectionParams, Error, HashOf, HeaderIdOf, HeaderOf, IndexOf, + Result, }; use async_std::sync::{Arc, Mutex}; @@ -27,14 +28,12 @@ use async_trait::async_trait; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; -use jsonrpsee_ws_client::{ - types::{ - self as jsonrpsee_types, traits::SubscriptionClient, v2::params::JsonRpcParams, - DeserializeOwned, - }, - WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, +use jsonrpsee::{ + core::{client::SubscriptionClientT, DeserializeOwned}, + types::params::ParamsSer, + ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; -use num_traits::{Bounded, Zero}; +use num_traits::{Bounded, CheckedSub, One, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; @@ -60,6 +59,17 @@ 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. @@ -77,6 +87,8 @@ pub struct Client { /// 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] @@ -99,6 +111,7 @@ impl Clone for Client { 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(), } } } @@ -140,16 +153,26 @@ impl Client { let genesis_hash_client = client.clone(); let genesis_hash = tokio .spawn(async move { - Substrate::::chain_get_block_hash(&*genesis_hash_client, number).await + 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, }) } @@ -178,10 +201,31 @@ impl 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 = Substrate::::system_health(&*client).await?; + 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(()) @@ -200,7 +244,15 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { self.jsonrpsee_execute(|client| async move { - Ok(Substrate::::chain_get_finalized_head(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_finalized_head(&*client) + .await?) }) .await } @@ -216,7 +268,15 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(|client| async move { - Ok(Substrate::::chain_get_header(&*client, None).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_header(&*client, None) + .await?) }) .await } @@ -224,7 +284,15 @@ impl Client { /// 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(Substrate::::chain_get_block(&*client, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_block(&*client, block_hash) + .await?) }) .await } @@ -235,7 +303,15 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::chain_get_header(&*client, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_header(&*client, Some(block_hash)) + .await?) }) .await } @@ -243,7 +319,15 @@ impl Client { /// 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(Substrate::::chain_get_block_hash(&*client, number).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_block_hash(&*client, Some(number)) + .await?) }) .await } @@ -261,7 +345,15 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::state_runtime_version(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_runtime_version(&*client) + .await?) }) .await } @@ -287,7 +379,15 @@ impl Client { block_hash: Option, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::state_get_storage(&*client, storage_key, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_get_storage(&*client, storage_key, block_hash) + .await?) }) .await } @@ -299,10 +399,16 @@ impl Client { { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = - Substrate::::state_get_storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; + 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[..], ) @@ -317,7 +423,15 @@ impl Client { /// 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(Substrate::::system_account_next_index(&*client, account).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::system_account_next_index(&*client, account) + .await?) }) .await } @@ -327,7 +441,15 @@ impl Client { /// 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 = Substrate::::author_submit_extrinsic(&*client, transaction).await?; + 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) }) @@ -344,15 +466,33 @@ impl Client { pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + 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()); + + // 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 = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; + 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) }) @@ -364,7 +504,7 @@ impl Client { pub async fn submit_and_watch_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + 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?; @@ -372,13 +512,13 @@ impl Client { 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 extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = C::Hasher::hash(&extrinsic.0); let subscription = client .subscribe( "author_submitAndWatchExtrinsic", - JsonRpcParams::Array(vec![jsonrpsee_types::to_json_value(extrinsic) - .map_err(|e| Error::RpcError(e.into()))?]), + Some(ParamsSer::Array(vec![jsonrpsee::core::to_json_value(extrinsic) + .map_err(|e| Error::RpcError(e.into()))?])), "author_unwatchExtrinsic", ) .await?; @@ -399,7 +539,15 @@ impl Client { /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::author_pending_extrinsics(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::author_pending_extrinsics(&*client) + .await?) }) .await } @@ -414,8 +562,15 @@ impl Client { let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); let data = Bytes((TransactionSource::External, transaction, at_block).encode()); - let encoded_response = - Substrate::::state_call(&*client, call, data, Some(at_block)).await?; + 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)?; @@ -430,8 +585,15 @@ impl Client { transaction: Bytes, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - let fee_details = - Substrate::::payment_query_fee_details(&*client, transaction, None).await?; + 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 { @@ -463,8 +625,15 @@ impl Client { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = - Substrate::::state_call(&*client, call, data, Some(block)).await?; + 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) @@ -480,9 +649,16 @@ impl Client { at_block: Option, ) -> Result { self.jsonrpsee_execute(move |client| async move { - Substrate::::state_call(&*client, method, data, at_block) - .await - .map_err(Into::into) + SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_call(&*client, method, data, at_block) + .await + .map_err(Into::into) }) .await } @@ -494,10 +670,36 @@ impl Client { at_block: C::Hash, ) -> Result { self.jsonrpsee_execute(move |client| async move { - Substrate::::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) + 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 } @@ -509,7 +711,7 @@ impl Client { Ok(client .subscribe( "grandpa_subscribeJustifications", - JsonRpcParams::NoParams, + None, "grandpa_unsubscribeJustifications", ) .await?) @@ -549,32 +751,32 @@ impl Subscription { async fn background_worker( chain_name: String, item_type: String, - mut subscription: jsonrpsee_types::Subscription, + mut subscription: jsonrpsee::core::client::Subscription, mut sender: futures::channel::mpsc::Sender>, ) { loop { match subscription.next().await { - Ok(Some(item)) => + Some(Ok(item)) => if sender.send(Some(item)).await.is_err() { break }, - Ok(None) => { + Some(Err(e)) => { log::trace!( target: "bridge", - "{} {} subscription stream has returned None. Stream needs to be restarted.", + "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", chain_name, item_type, + e, ); let _ = sender.send(None).await; break }, - Err(e) => { + None => { log::trace!( target: "bridge", - "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", + "{} {} subscription stream has returned None. Stream needs to be restarted.", chain_name, item_type, - e, ); let _ = sender.send(None).await; break diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 33b9b22a03ef..e698f2596c5f 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,7 +16,7 @@ //! Substrate node RPC errors. -use jsonrpsee_ws_client::types::Error as RpcError; +use jsonrpsee::core::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; use sp_runtime::transaction_validity::TransactionValidityError; @@ -51,6 +51,9 @@ pub enum Error { /// 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), diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index a064e3623400..359a3f69d8a3 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -64,6 +64,13 @@ pub fn abort_on_spec_version_change( 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 { @@ -103,6 +110,14 @@ pub fn abort_when_account_balance_decreased( 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 { @@ -181,7 +196,7 @@ impl Environment for Client { #[cfg(test)] mod tests { use super::*; - use frame_support::weights::IdentityFee; + use frame_support::weights::{IdentityFee, Weight}; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, future::FutureExt, @@ -202,10 +217,19 @@ mod tests { type Balance = u32; 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 { const NAME: &'static str = "Test"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); const STORAGE_PROOF_OVERHEAD: u32 = 0; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 51ddf852b9b6..b3a7ec414190 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -24,7 +24,6 @@ mod error; mod rpc; mod sync_header; -pub mod finality_source; pub mod guard; pub mod metrics; @@ -32,10 +31,11 @@ use std::time::Duration; pub use crate::{ chain::{ - BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, + ChainWithGrandpa, ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, + UnsignedTransaction, WeightToFeeOf, }, - client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, + client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, sync_header::SyncHeader, }; @@ -56,11 +56,18 @@ pub struct ConnectionParams { 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 } + ConnectionParams { + host: "localhost".into(), + port: 9944, + secure: false, + chain_runtime_version: ChainRuntimeVersion::Auto, + } } } diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index 7dccf82b6f8e..7bb92693b38d 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -14,48 +14,84 @@ // 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}; +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::StorageKey; -use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; -use std::time::Duration; +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 { +pub struct FloatStorageValueMetric { + value_converter: V, client: Client, storage_key: StorageKey, - maybe_default_value: Option, metric: Gauge, shared_value_ref: F64SharedRef, + _phantom: PhantomData, } -impl FloatStorageValueMetric { +impl FloatStorageValueMetric { /// Create new metric. pub fn new( + value_converter: V, client: Client, storage_key: StorageKey, - maybe_default_value: Option, name: String, help: String, ) -> Result { let shared_value_ref = Arc::new(RwLock::new(None)); Ok(FloatStorageValueMetric { + value_converter, client, storage_key, - maybe_default_value, metric: Gauge::new(metric_name(None, &name), help)?, shared_value_ref, + _phantom: Default::default(), }) } @@ -65,20 +101,14 @@ impl FloatStorageValueMetric { } } -impl Metric for FloatStorageValueMetric -where - T: 'static + Decode + Send + Sync + FixedPointNumber, -{ +impl Metric for FloatStorageValueMetric { fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { register(self.metric.clone(), registry).map(drop) } } #[async_trait] -impl StandaloneMetric for FloatStorageValueMetric -where - T: 'static + Decode + Send + Sync + FixedPointNumber, -{ +impl StandaloneMetric for FloatStorageValueMetric { fn update_interval(&self) -> Duration { C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS } @@ -86,16 +116,18 @@ where async fn update(&self) { let value = self .client - .storage_value::(self.storage_key.clone(), None) + .raw_storage_value(self.storage_key.clone(), None) .await - .map(|maybe_storage_value| { - maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { - storage_value.into_inner().unique_saturated_into() as f64 / - T::DIV.unique_saturated_into() as f64 + .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(drop); - relay_utils::metrics::set_gauge_value(&self.metric, value); + .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 index 177e2a709cf2..3b63099e0003 100644 --- a/relays/client-substrate/src/metrics/mod.rs +++ b/relays/client-substrate/src/metrics/mod.rs @@ -16,7 +16,7 @@ //! Contains several Substrate-specific metrics that may be exposed by relay. -pub use float_storage_value::FloatStorageValueMetric; +pub use float_storage_value::{FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric}; pub use storage_proof_overhead::StorageProofOverheadMetric; mod float_storage_value; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index efd45ebe43f3..a0172d1e5501 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -16,8 +16,7 @@ //! The most generic Substrate node RPC interface. -use crate::chain::Chain; - +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::{ @@ -27,33 +26,51 @@ use sp_core::{ use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; -jsonrpsee_proc_macros::rpc_client_api! { - pub(crate) Substrate { - #[rpc(method = "system_health", positional_params)] - fn system_health() -> Health; - #[rpc(method = "chain_getHeader", positional_params)] - fn chain_get_header(block_hash: Option) -> C::Header; - #[rpc(method = "chain_getFinalizedHead", positional_params)] - fn chain_get_finalized_head() -> C::Hash; - #[rpc(method = "chain_getBlock", positional_params)] - fn chain_get_block(block_hash: Option) -> C::SignedBlock; - #[rpc(method = "chain_getBlockHash", positional_params)] - fn chain_get_block_hash(block_number: Option) -> C::Hash; - #[rpc(method = "system_accountNextIndex", positional_params)] - fn system_account_next_index(account_id: C::AccountId) -> C::Index; - #[rpc(method = "author_submitExtrinsic", positional_params)] - fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash; - #[rpc(method = "author_pendingExtrinsics", positional_params)] - fn author_pending_extrinsics() -> Vec; - #[rpc(method = "state_call", positional_params)] - fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; - #[rpc(method = "state_getStorage", positional_params)] - fn state_get_storage(key: StorageKey, at_block: Option) -> Option; - #[rpc(method = "state_getReadProof", positional_params)] - fn state_prove_storage(keys: Vec, hash: Option) -> ReadProof; - #[rpc(method = "state_getRuntimeVersion", positional_params)] - fn state_runtime_version() -> RuntimeVersion; - #[rpc(method = "payment_queryFeeDetails", positional_params)] - fn payment_query_fee_details(extrinsic: Bytes, at_block: Option) -> FeeDetails; - } +#[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 index ed3de6289ce0..e45e6b4197ab 100644 --- a/relays/client-substrate/src/sync_header.rs +++ b/relays/client-substrate/src/sync_header.rs @@ -44,7 +44,11 @@ impl
From
for SyncHeader
{ } } -impl FinalitySourceHeader for SyncHeader
{ +impl FinalitySourceHeader for SyncHeader
{ + fn hash(&self) -> Header::Hash { + self.0.hash() + } + fn number(&self) -> Header::Number { *self.0.number() } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 24b05c4f4836..d38aa1629945 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -2,11 +2,11 @@ name = "relay-westend-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -16,5 +16,6 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index c719d6ea5536..caf0c010c56a 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,7 +16,8 @@ //! Types used to connect to the Westend chain. -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; +use frame_support::weights::Weight; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -40,10 +41,21 @@ impl ChainBase for Westend { type Balance = bp_westend::Balance; type Index = bp_westend::Nonce; type Signature = bp_westend::Signature; + + fn max_extrinsic_size() -> u32 { + bp_westend::Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_westend::Westend::max_extrinsic_weight() + } } impl Chain for Westend { const NAME: &'static str = "Westend"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -53,6 +65,11 @@ impl Chain for Westend { type WeightToFee = bp_westend::WeightToFee; } +impl ChainWithGrandpa for Westend { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + bp_westend::WITH_WESTEND_GRANDPA_PALLET_NAME; +} + impl ChainWithBalances for Westend { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_westend::account_info_storage_key(account_id)) diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index ea46c3c898bb..6845ac34c84a 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -2,14 +2,14 @@ name = "relay-wococo-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge dependencies bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index d61915ec1237..485ca1bd62f4 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Wococo-Substrate chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,21 @@ impl ChainBase for Wococo { type Balance = bp_wococo::Balance; type Index = bp_wococo::Nonce; type Signature = bp_wococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_wococo::Wococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_wococo::Wococo::max_extrinsic_weight() + } } impl Chain for Wococo { const NAME: &'static str = "Wococo"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; @@ -60,6 +73,24 @@ impl Chain for Wococo { type WeightToFee = bp_wococo::WeightToFee; } +impl ChainWithGrandpa for Wococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_wococo::WITH_WOCOCO_GRANDPA_PALLET_NAME; +} + +impl ChainWithMessages for Wococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_wococo::account_info_storage_key(account_id)) @@ -71,34 +102,30 @@ impl TransactionSignScheme for Wococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_wococo::SignedExtensions::new( - bp_wococo::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + 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| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + 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(); - bp_wococo::UncheckedExtrinsic::new_signed( + Ok(bp_wococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index 91d32d1aa76f..b28e053086b1 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -17,9 +17,9 @@ //! Types that are specific to the Wococo runtime. use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::PolkadotLike; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; -use codec::{Decode, Encode}; +use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use scale_info::TypeInfo; @@ -66,12 +66,15 @@ pub enum Call { /// System pallet. #[codec(index = 0)] System(SystemCall), + /// Balances pallet. + #[codec(index = 4)] + Balances(BalancesCall), /// Rococo bridge pallet. #[codec(index = 40)] BridgeGrandpaRococo(BridgeGrandpaRococoCall), /// Rococo messages pallet. #[codec(index = 43)] - BridgeMessagesRococo(BridgeMessagesRococoCall), + BridgeRococoMessages(BridgeRococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -81,6 +84,13 @@ pub enum SystemCall { 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 BridgeGrandpaRococoCall { @@ -95,7 +105,7 @@ pub enum BridgeGrandpaRococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesRococoCall { +pub enum BridgeRococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 645ac10775ba..cc5ae54be339 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -2,7 +2,7 @@ name = "finality-relay" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 320b44d310f0..c29a5d5fec21 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -29,7 +29,7 @@ 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, - MaybeConnectionError, + HeaderId, MaybeConnectionError, }; use std::{ pin::Pin, @@ -87,7 +87,9 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Get best finalized source block number. - async fn best_finalized_source_block_number(&self) -> Result; + async fn best_finalized_source_block_id( + &self, + ) -> Result, Self::Error>; /// Submit header finality proof. async fn submit_finality_proof( @@ -114,7 +116,11 @@ pub async fn run( 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::

()))?)? + .loop_metric(SyncLoopMetrics::new( + Some(&metrics_prefix::

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

(), move |source_client, target_client, metrics| { @@ -169,7 +175,7 @@ where /// Information about transaction that we have submitted. #[derive(Debug, Clone)] -struct Transaction { +pub(crate) struct Transaction { /// Time when we have submitted this transaction. pub time: Instant, /// The number of the header we have submitted. @@ -181,7 +187,7 @@ pub(crate) struct RestartableFinalityProofsStream { /// Flag that the stream needs to be restarted. pub(crate) needs_restart: bool, /// The stream itself. - stream: Pin>, + pub(crate) stream: Pin>, } #[cfg(test)] @@ -192,15 +198,16 @@ impl From for RestartableFinalityProofsStream { } /// Finality synchronization loop state. -struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { +pub(crate) struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { /// Synchronization loop progress. - progress: &'a mut (Instant, Option), + pub(crate) progress: &'a mut (Instant, Option), /// Finality proofs stream. - finality_proofs_stream: &'a mut RestartableFinalityProofsStream, + pub(crate) finality_proofs_stream: + &'a mut RestartableFinalityProofsStream, /// Recent finality proofs that we have read from the stream. - recent_finality_proofs: &'a mut FinalityProofs

, + pub(crate) recent_finality_proofs: &'a mut FinalityProofs

, /// Last transaction that we have submitted to the target node. - last_transaction: Option>, + pub(crate) last_transaction: Option>, } async fn run_until_connection_lost( @@ -280,7 +287,7 @@ async fn run_until_connection_lost( } } -async fn run_loop_iteration( +pub(crate) async fn run_loop_iteration( source_client: &SC, target_client: &TC, state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, @@ -295,13 +302,31 @@ where // 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_number_at_target = target_client - .best_finalized_source_block_number() + 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::Target)?; + .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); @@ -427,6 +452,22 @@ where 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. diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 915b7ee6766e..478d8e1be652 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -20,10 +20,12 @@ use crate::{ finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run, - select_better_recent_finality_proof, select_header_to_submit, FinalityProofs, - FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, TargetClient, + 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, }; @@ -31,12 +33,18 @@ use async_trait::async_trait; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, +}; +use std::{ + collections::HashMap, + pin::Pin, + sync::Arc, + time::{Duration, Instant}, }; -use std::{collections::HashMap, pin::Pin, sync::Arc, time::Duration}; type IsMandatory = bool; type TestNumber = u64; +type TestHash = u64; #[derive(Debug, Clone)] enum TestError { @@ -56,16 +64,20 @@ impl FinalitySyncPipeline for TestFinalitySyncPipeline { const SOURCE_NAME: &'static str = "TestSource"; const TARGET_NAME: &'static str = "TestTarget"; - type Hash = u64; + type Hash = TestHash; type Number = TestNumber; type Header = TestSourceHeader; type FinalityProof = TestFinalityProof; } #[derive(Debug, Clone, PartialEq)] -struct TestSourceHeader(IsMandatory, TestNumber); +struct TestSourceHeader(IsMandatory, TestNumber, TestHash); + +impl SourceHeader for TestSourceHeader { + fn hash(&self) -> TestHash { + self.2 + } -impl SourceHeader for TestSourceHeader { fn number(&self) -> TestNumber { self.1 } @@ -90,7 +102,7 @@ struct ClientsData { source_headers: HashMap)>, source_proofs: Vec, - target_best_block_number: TestNumber, + target_best_block_id: HeaderId, target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, } @@ -152,10 +164,12 @@ impl RelayClient for TestTargetClient { #[async_trait] impl TargetClient for TestTargetClient { - async fn best_finalized_source_block_number(&self) -> Result { + 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_number) + Ok(data.target_best_block_id) } async fn submit_finality_proof( @@ -165,7 +179,7 @@ impl TargetClient for TestTargetClient { ) -> Result<(), TestError> { let mut data = self.data.lock(); (self.on_method_call)(&mut *data); - data.target_best_block_number = header.number(); + data.target_best_block_id = HeaderId(header.number(), header.hash()); data.target_headers.push((header, proof)); Ok(()) } @@ -187,7 +201,7 @@ fn prepare_test_clients( source_headers, source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], - target_best_block_number: 5, + target_best_block_id: HeaderId(5, 5), target_headers: vec![], })); ( @@ -199,6 +213,15 @@ fn prepare_test_clients( ) } +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 { @@ -207,21 +230,17 @@ fn run_sync_loop( exit_sender, state_function, vec![ - (6, (TestSourceHeader(false, 6), None)), - (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10), None)), + (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 = FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 1024, - stall_timeout: Duration::from_secs(1), - only_mandatory_headers: false, - }; + let sync_params = test_sync_params(); let clients_data = source_client.data.clone(); let _ = async_std::task::block_on(run( @@ -246,38 +265,38 @@ fn finality_sync_loop_works() { // // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from // the stream - if data.target_best_block_number == 9 { + if data.target_best_block_id.0 == 9 { data.source_best_block_number = 14; - data.source_headers.insert(11, (TestSourceHeader(false, 11), None)); + data.source_headers.insert(11, (TestSourceHeader(false, 11, 11), None)); data.source_headers - .insert(12, (TestSourceHeader(false, 12), Some(TestFinalityProof(12)))); - data.source_headers.insert(13, (TestSourceHeader(false, 13), None)); + .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), Some(TestFinalityProof(14)))); + .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_number == 14 { + if data.target_best_block_id.0 == 14 { data.source_best_block_number = 17; - data.source_headers.insert(15, (TestSourceHeader(false, 15), None)); + data.source_headers.insert(15, (TestSourceHeader(false, 15, 15), None)); data.source_headers - .insert(16, (TestSourceHeader(false, 16), Some(TestFinalityProof(16)))); - data.source_headers.insert(17, (TestSourceHeader(false, 17), None)); + .insert(16, (TestSourceHeader(false, 16, 16), Some(TestFinalityProof(16)))); + data.source_headers.insert(17, (TestSourceHeader(false, 17, 17), None)); } - data.target_best_block_number == 16 + 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), TestFinalityProof(8)), + (TestSourceHeader(true, 8, 8), TestFinalityProof(8)), // before adding 11..14: persistent finality proof for non-mandatory header#9 - (TestSourceHeader(false, 9), TestFinalityProof(9)), + (TestSourceHeader(false, 9, 9), TestFinalityProof(9)), // after adding 11..14: ephemeral finality proof for non-mandatory header#14 - (TestSourceHeader(false, 14), TestFinalityProof(14)), + (TestSourceHeader(false, 14, 14), TestFinalityProof(14)), // after adding 15..17: persistent finality proof for non-mandatory header#16 - (TestSourceHeader(false, 16), TestFinalityProof(16)), + (TestSourceHeader(false, 16, 16), TestFinalityProof(16)), ], ); } @@ -291,11 +310,11 @@ fn run_only_mandatory_headers_mode_test( exit_sender, |_| false, vec![ - (6, (TestSourceHeader(false, 6), Some(TestFinalityProof(6)))), - (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(has_mandatory_headers, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10), Some(TestFinalityProof(10)))), + (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(), @@ -322,7 +341,7 @@ fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_heade 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), TestFinalityProof(10))), + Some((TestSourceHeader(false, 10, 10), TestFinalityProof(10))), ); } @@ -330,11 +349,11 @@ fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_heade 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), TestFinalityProof(8))), + Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), ); assert_eq!( run_only_mandatory_headers_mode_test(false, true), - Some((TestSourceHeader(true, 8), TestFinalityProof(8))), + Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), ); } @@ -345,63 +364,74 @@ fn select_better_recent_finality_proof_works() { select_better_recent_finality_proof::( &[(5, TestFinalityProof(5))], &mut vec![], - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 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)], - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + &mut vec![TestSourceHeader(false, 5, 5)], + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 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), TestSourceHeader(false, 10)]; + 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), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 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), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; + 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), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ); assert_eq!( unjustified_headers, - vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)] + 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), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; + 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), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 9), TestFinalityProof(9))), + Some((TestSourceHeader(false, 9, 9), TestFinalityProof(9))), ); } @@ -475,3 +505,45 @@ fn prune_recent_finality_proofs_works() { 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 index 6421d13b787c..49be64ff74db 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -19,8 +19,9 @@ //! 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, +pub use crate::{ + finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}, + sync_loop_metrics::SyncLoopMetrics, }; use bp_header_chain::FinalityProof; @@ -42,13 +43,15 @@ pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers we're syncing are identified by this number. type Number: relay_utils::BlockNumberBase; /// Type of header that we're syncing. - type Header: SourceHeader; + 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 { +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. diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index 1f65dac17c05..a003a47d8909 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -16,49 +16,71 @@ //! Metrics for headers synchronization relay loop. -use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, -}; +use relay_utils::metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry}; /// Headers sync metrics. #[derive(Clone)] pub struct SyncLoopMetrics { - /// Best syncing headers at "source" and "target" nodes. - best_block_numbers: GaugeVec, + /// 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>) -> Result { + pub fn new( + prefix: Option<&str>, + at_source_chain_label: &str, + at_target_chain_label: &str, + ) -> Result { Ok(SyncLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best block numbers on source and target nodes", - ), - &["node"], + 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_block_numbers - .with_label_values(&["source"]) - .set(source_best_number.into()); + 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_block_numbers - .with_label_values(&["target"]) - .set(target_best_number.into()); + 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_block_numbers.clone(), registry)?; + 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/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5bee10856daa..e2cabf52f449 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-relay-helper" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -10,23 +10,23 @@ anyhow = "1.0" thiserror = "1.0.26" async-std = "1.9.0" async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" num-traits = "0.2" log = "0.4.14" - # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.14.0" } +finality-grandpa = { version = "0.15.0" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } messages-relay = { path = "../messages" } relay-substrate-client = { path = "../client-substrate" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } bp-runtime = { path = "../../primitives/runtime" } @@ -35,14 +35,18 @@ bp-messages = { path = "../../primitives/messages" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] bp-millau = { path = "../../primitives/chain-millau" } +bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } relay-rococo-client = { path = "../client-rococo" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index 93458457d34c..469bc5589932 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -16,39 +16,143 @@ //! Tools for updating conversion rate that is stored in the runtime storage. +use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; + +use codec::Encode; +use relay_substrate_client::{ + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam, + TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::metrics::F64SharedRef; -use std::{future::Future, time::Duration}; +use sp_core::{Bytes, Pair}; +use std::time::{Duration, Instant}; /// Duration between updater iterations. const SLEEP_DURATION: Duration = Duration::from_secs(60); +/// Duration which will almost never expire. Since changing conversion rate may require manual +/// intervention (e.g. if call is made through `multisig` pallet), we don't want relayer to +/// resubmit transaction often. +const ALMOST_NEVER_DURATION: Duration = Duration::from_secs(60 * 60 * 24 * 30); + /// Update-conversion-rate transaction status. #[derive(Debug, Clone, Copy, PartialEq)] enum TransactionStatus { /// We have not submitted any transaction recently. Idle, /// We have recently submitted transaction that should update conversion rate. - Submitted(f64), + Submitted(Instant, f64), +} + +/// Different ways of building 'update conversion rate' calls. +pub trait UpdateConversionRateCallBuilder { + /// Given conversion rate, build call that updates conversion rate in given chain runtime + /// storage. + fn build_update_conversion_rate_call(conversion_rate: f64) -> anyhow::Result>; +} + +impl UpdateConversionRateCallBuilder for () { + fn build_update_conversion_rate_call(_conversion_rate: f64) -> anyhow::Result> { + Err(anyhow::format_err!("Conversion rate update is not supported at {}", C::NAME)) + } +} + +/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when +/// you have a direct access to the source chain runtime. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_direct_update_conversion_rate_call_builder { + ( + $source_chain:ident, + $mocked_builder:ident, + $runtime:ty, + $instance:ty, + $parameter:path + ) => { + pub struct $mocked_builder; + + impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> + for $mocked_builder + { + fn build_update_conversion_rate_call( + conversion_rate: f64, + ) -> anyhow::Result> { + Ok(pallet_bridge_messages::Call::update_pallet_parameter::<$runtime, $instance> { + parameter: $parameter(sp_runtime::FixedU128::from_float(conversion_rate)), + }.into()) + } + } + }; +} + +/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when +/// you only have an access to the mocked version of source chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls, the "name" of +/// the variant for the `update_pallet_parameter` call within that first option and the name +/// of the conversion rate parameter itself. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_update_conversion_rate_call_builder { + ( + $source_chain:ident, + $mocked_builder:ident, + $bridge_messages:path, + $update_pallet_parameter:path, + $parameter:path + ) => { + pub struct $mocked_builder; + + impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> + for $mocked_builder + { + fn build_update_conversion_rate_call( + conversion_rate: f64, + ) -> anyhow::Result> { + Ok($bridge_messages($update_pallet_parameter($parameter( + sp_runtime::FixedU128::from_float(conversion_rate), + )))) + } + } + }; } /// Run infinite conversion rate updater loop. /// /// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * /// Rate`. -pub fn run_conversion_rate_update_loop< - SubmitConversionRateFuture: Future> + Send + 'static, ->( +pub fn run_conversion_rate_update_loop( + client: Client, + transaction_params: TransactionParams>, left_to_right_stored_conversion_rate: F64SharedRef, left_to_base_conversion_rate: F64SharedRef, right_to_base_conversion_rate: F64SharedRef, max_difference_ratio: f64, - submit_conversion_rate: impl Fn(f64) -> SubmitConversionRateFuture + Send + 'static, -) { +) where + Lane: SubstrateMessageLane, + Sign: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, +{ + let stall_timeout = transaction_stall_timeout( + transaction_params.mortality, + Lane::SourceChain::AVERAGE_BLOCK_INTERVAL, + ALMOST_NEVER_DURATION, + ); + + log::info!( + target: "bridge", + "Starting {} -> {} conversion rate (on {}) update loop. Stall timeout: {}s", + Lane::TargetChain::NAME, + Lane::SourceChain::NAME, + Lane::SourceChain::NAME, + stall_timeout.as_secs(), + ); + async_std::task::spawn(async move { let mut transaction_status = TransactionStatus::Idle; loop { async_std::task::sleep(SLEEP_DURATION).await; let maybe_new_conversion_rate = maybe_select_new_conversion_rate( + stall_timeout, &mut transaction_status, &left_to_right_stored_conversion_rate, &left_to_base_conversion_rate, @@ -57,13 +161,32 @@ pub fn run_conversion_rate_update_loop< ) .await; if let Some((prev_conversion_rate, new_conversion_rate)) = maybe_new_conversion_rate { - let submit_conversion_rate_future = submit_conversion_rate(new_conversion_rate); - match submit_conversion_rate_future.await { + log::info!( + target: "bridge", + "Going to update {} -> {} (on {}) conversion rate to {}.", + Lane::TargetChain::NAME, + Lane::SourceChain::NAME, + Lane::SourceChain::NAME, + new_conversion_rate, + ); + + let result = update_target_to_source_conversion_rate::( + client.clone(), + transaction_params.clone(), + new_conversion_rate, + ) + .await; + match result { Ok(()) => { - transaction_status = TransactionStatus::Submitted(prev_conversion_rate); + transaction_status = + TransactionStatus::Submitted(Instant::now(), prev_conversion_rate); }, Err(error) => { - log::trace!(target: "bridge", "Failed to submit conversion rate update transaction: {:?}", error); + log::error!( + target: "bridge", + "Failed to submit conversion rate update transaction: {:?}", + error, + ); }, } } @@ -73,6 +196,7 @@ pub fn run_conversion_rate_update_loop< /// Select new conversion rate to submit to the node. async fn maybe_select_new_conversion_rate( + stall_timeout: Duration, transaction_status: &mut TransactionStatus, left_to_right_stored_conversion_rate: &F64SharedRef, left_to_base_conversion_rate: &F64SharedRef, @@ -83,7 +207,18 @@ async fn maybe_select_new_conversion_rate( (*left_to_right_stored_conversion_rate.read().await)?; match *transaction_status { TransactionStatus::Idle => (), - TransactionStatus::Submitted(previous_left_to_right_stored_conversion_rate) => { + TransactionStatus::Submitted(submitted_at, _) + if Instant::now() - submitted_at > stall_timeout => + { + log::error!( + target: "bridge", + "Conversion rate update transaction has been lost and loop stalled. Restarting", + ); + + // we assume that our transaction has been lost + *transaction_status = TransactionStatus::Idle; + }, + TransactionStatus::Submitted(_, previous_left_to_right_stored_conversion_rate) => { // we can't compare float values from different sources directly, so we only care // whether the stored rate has been changed or not. If it has been changed, then we // assume that our proposal has been accepted. @@ -106,7 +241,7 @@ async fn maybe_select_new_conversion_rate( let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?; let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?; let actual_left_to_right_conversion_rate = - right_to_base_conversion_rate / left_to_base_conversion_rate; + left_to_base_conversion_rate / right_to_base_conversion_rate; let rate_difference = (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); @@ -118,11 +253,50 @@ async fn maybe_select_new_conversion_rate( Some((left_to_right_stored_conversion_rate, actual_left_to_right_conversion_rate)) } +/// Update Target -> Source tokens conversion rate, stored in the Source runtime storage. +pub async fn update_target_to_source_conversion_rate( + client: Client, + transaction_params: TransactionParams>, + updated_rate: f64, +) -> anyhow::Result<()> +where + Lane: SubstrateMessageLane, + Sign: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, +{ + let genesis_hash = *client.genesis_hash(); + let signer_id = transaction_params.signer.public().into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; + let call = + Lane::TargetToSourceChainConversionRateUpdateBuilder::build_update_conversion_rate_call( + updated_rate, + )?; + client + .submit_signed_extrinsic(signer_id, move |best_block_id, transaction_nonce| { + Ok(Bytes( + Sign::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer, + era: TransactionEra::new(best_block_id, transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce).into(), + })? + .encode(), + )) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} + #[cfg(test)] mod tests { use super::*; use async_std::sync::{Arc, RwLock}; + const TEST_STALL_TIMEOUT: Duration = Duration::from_secs(60); + fn test_maybe_select_new_conversion_rate( mut transaction_status: TransactionStatus, stored_conversion_rate: Option, @@ -134,6 +308,7 @@ mod tests { let left_to_base_conversion_rate = Arc::new(RwLock::new(left_to_base_conversion_rate)); let right_to_base_conversion_rate = Arc::new(RwLock::new(right_to_base_conversion_rate)); let result = async_std::task::block_on(maybe_select_new_conversion_rate( + TEST_STALL_TIMEOUT, &mut transaction_status, &stored_conversion_rate, &left_to_base_conversion_rate, @@ -145,15 +320,10 @@ mod tests { #[test] fn rate_is_not_updated_when_transaction_is_submitted() { + let status = TransactionStatus::Submitted(Instant::now(), 10.0); assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Submitted(10.0), - Some(10.0), - Some(1.0), - Some(1.0), - 0.0 - ), - (None, TransactionStatus::Submitted(10.0)), + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (None, status), ); } @@ -161,7 +331,7 @@ mod tests { fn transaction_state_is_changed_to_idle_when_stored_rate_shanges() { assert_eq!( test_maybe_select_new_conversion_rate( - TransactionStatus::Submitted(1.0), + TransactionStatus::Submitted(Instant::now(), 1.0), Some(10.0), Some(1.0), Some(1.0), @@ -229,15 +399,42 @@ mod tests { #[test] fn transaction_is_submitted_when_difference_is_above_threshold() { + let left_to_right_stored_conversion_rate = 1.0; + let left_to_base_conversion_rate = 18f64; + let right_to_base_conversion_rate = 180f64; + + assert!(left_to_base_conversion_rate < right_to_base_conversion_rate); + assert_eq!( test_maybe_select_new_conversion_rate( TransactionStatus::Idle, - Some(1.0), - Some(1.0), - Some(1.03), + Some(left_to_right_stored_conversion_rate), + Some(left_to_base_conversion_rate), + Some(right_to_base_conversion_rate), 0.02 ), - (Some((1.0, 1.03)), TransactionStatus::Idle), + ( + Some(( + left_to_right_stored_conversion_rate, + left_to_base_conversion_rate / right_to_base_conversion_rate, + )), + TransactionStatus::Idle + ), + ); + } + + #[test] + fn transaction_expires() { + let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT / 2, 10.0); + assert_eq!( + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (None, status), + ); + + let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT * 2, 10.0); + assert_eq!( + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (Some((10.0, 1.0)), TransactionStatus::Idle), ); } } diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index 802499503563..9402d55e3798 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -55,4 +55,7 @@ pub enum Error { /// Failed to retrieve header by the hash from the source chain. #[error("Failed to retrieve {0} header with hash {1}: {:?}")] RetrieveHeader(&'static str, Hash, client::Error), + /// Failed to retrieve best finalized source header hash from the target chain. + #[error("Failed to retrieve best finalized {0} header from the target chain: {1}")] + RetrieveBestFinalizedHeaderHash(&'static str, client::Error), } diff --git a/relays/lib-substrate-relay/src/finality_guards.rs b/relays/lib-substrate-relay/src/finality_guards.rs new file mode 100644 index 000000000000..a3e69afe1b1d --- /dev/null +++ b/relays/lib-substrate-relay/src/finality_guards.rs @@ -0,0 +1,48 @@ +// 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 for starting guards of finality relays. + +use crate::TransactionParams; + +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, ChainWithBalances, TransactionSignScheme, +}; +use sp_core::Pair; + +/// Start finality relay guards. +pub async fn start>( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + maximal_balance_decrease_per_day: C::Balance, +) -> relay_substrate_client::Result<()> +where + AccountIdOf: From< as Pair>::Public>, +{ + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.0, + ); + } + relay_substrate_client::guard::abort_when_account_balance_decreased( + target_client.clone(), + transaction_params.signer.public().into(), + maximal_balance_decrease_per_day, + ); + Ok(()) +} diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index cdfbb3354d27..3daf8d11440e 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -14,18 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Substrate-to-Substrate headers sync entrypoint. +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! finality proofs synchronization pipelines. -use crate::{finality_target::SubstrateFinalityTarget, STALL_TIMEOUT}; +use crate::{ + finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget, + TransactionParams, +}; +use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; -use bp_runtime::AccountIdOf; -use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; +use finality_relay::FinalitySyncPipeline; +use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, + ChainWithGrandpa, Client, HashOf, HeaderOf, SyncHeader, TransactionSignScheme, }; -use relay_utils::{metrics::MetricsParams, BlockNumberBase}; -use sp_core::Bytes; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; use std::{fmt::Debug, marker::PhantomData}; /// Default limit of recent finality proofs. @@ -34,130 +40,146 @@ use std::{fmt::Debug, marker::PhantomData}; /// Substrate+GRANDPA based chains (good to know). pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; -/// Headers sync pipeline for Substrate <-> Substrate relays. +/// Substrate -> Substrate finality proofs synchronization pipeline. +#[async_trait] pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { - /// Pipeline for syncing finalized Source chain headers to Target chain. - type FinalitySyncPipeline: FinalitySyncPipeline; - - /// Name of the runtime method that returns id of best finalized source header at target chain. - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; - - /// Chain with GRANDPA bridge pallet. + /// Headers of this chain are submitted to the `TargetChain`. + type SourceChain: ChainWithGrandpa; + /// Headers of the `SourceChain` are submitted to this chain. type TargetChain: Chain; - /// Customize metrics exposed by headers sync loop. - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - Ok(params) + /// How submit finality proof call is built? + type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; + /// Scheme used to sign target chain transactions. + type TransactionSignScheme: TransactionSignScheme; + + /// Add relay guards if required. + async fn start_relay_guards( + _target_client: &Client, + _transaction_params: &TransactionParams>, + _enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + Ok(()) } +} - /// Start finality relay guards. - /// - /// Different finality bridges may have different set of guards - e.g. on ephemeral chains we - /// don't need a version guards, on test chains we don't care that much about relayer account - /// balance, ... So the implementation is left to the specific bridges. - fn start_relay_guards(&self) {} - - /// Returns id of account that we're using to sign transactions at target chain. - fn transactions_author(&self) -> AccountIdOf; - - /// Make submit header transaction. - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: ::Header, - proof: ::FinalityProof, - ) -> Bytes; +/// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. +#[derive(Clone, Debug)] +pub struct FinalitySyncPipelineAdapter { + _phantom: PhantomData

, } -/// Substrate-to-Substrate finality proof pipeline. -#[derive(Clone)] -pub struct SubstrateFinalityToSubstrate { - /// Client for the target chain. - pub target_client: Client, - /// Data required to sign target chain transactions. - pub target_sign: TargetSign, - /// Unused generic arguments dump. - _marker: PhantomData, +impl FinalitySyncPipeline for FinalitySyncPipelineAdapter

{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = relay_substrate_client::SyncHeader>; + type FinalityProof = GrandpaJustification>; } -impl Debug - for SubstrateFinalityToSubstrate -{ - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("SubstrateFinalityToSubstrate") - .field("target_client", &self.target_client) - .finish() - } +/// Different ways of building `submit_finality_proof` calls. +pub trait SubmitFinalityProofCallBuilder { + /// Given source chain header and its finality proofs, build call of `submit_finality_proof` + /// function of bridge GRANDPA module at the target chain. + fn build_submit_finality_proof_call( + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> CallOf; } -impl - SubstrateFinalityToSubstrate -{ - /// Create new Substrate-to-Substrate headers pipeline. - pub fn new(target_client: Client, target_sign: TargetSign) -> Self { - SubstrateFinalityToSubstrate { target_client, target_sign, _marker: Default::default() } - } +/// Building `submit_finality_proof` call when you have direct access to the target +/// chain runtime. +pub struct DirectSubmitFinalityProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, } -impl FinalitySyncPipeline - for SubstrateFinalityToSubstrate +impl SubmitFinalityProofCallBuilder

for DirectSubmitFinalityProofCallBuilder where - SourceChain: Clone + Chain + Debug, - BlockNumberOf: BlockNumberBase, - TargetChain: Clone + Chain + Debug, - TargetSign: 'static + Clone + Send + Sync, + P: SubstrateFinalitySyncPipeline, + R: BridgeGrandpaConfig, + I: 'static, + R::BridgedChain: bp_runtime::Chain

>, + CallOf: From>, { - const SOURCE_NAME: &'static str = SourceChain::NAME; - const TARGET_NAME: &'static str = TargetChain::NAME; + fn build_submit_finality_proof_call( + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> CallOf { + BridgeGrandpaCall::::submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + } + .into() + } +} - type Hash = HashOf; - type Number = BlockNumberOf; - type Header = SyncHeader; - type FinalityProof = GrandpaJustification; +/// Macro that generates `SubmitFinalityProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge GRANDPA calls and the "name" of +/// the variant for the `submit_finality_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_submit_finality_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => { + pub struct $mocked_builder; + + impl $crate::finality_pipeline::SubmitFinalityProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_submit_finality_proof_call( + header: relay_substrate_client::SyncHeader< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + > + >, + proof: bp_header_chain::justification::GrandpaJustification< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + > + >, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::TargetChain + > { + $bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof)) + } + } + }; } -/// Run Substrate-to-Substrate finality sync. -pub async fn run( - pipeline: P, - source_client: Client, - target_client: Client, +/// Run Substrate-to-Substrate finality sync loop. +pub async fn run( + source_client: Client, + target_client: Client, only_mandatory_headers: bool, - transactions_mortality: Option, + transaction_params: TransactionParams>, metrics_params: MetricsParams, ) -> anyhow::Result<()> where - P: SubstrateFinalitySyncPipeline, - P::FinalitySyncPipeline: FinalitySyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Header = SyncHeader, - FinalityProof = GrandpaJustification, - >, - SourceChain: Clone + Chain, - BlockNumberOf: BlockNumberBase, - TargetChain: Clone + Chain, + AccountIdOf: From< as Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { log::info!( target: "bridge", "Starting {} -> {} finality proof relay", - SourceChain::NAME, - TargetChain::NAME, + P::SourceChain::NAME, + P::TargetChain::NAME, ); finality_relay::run( - FinalitySource::new(source_client, None), - SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality), - FinalitySyncParams { + SubstrateFinalitySource::

::new(source_client, None), + SubstrateFinalityTarget::

::new(target_client, transaction_params.clone()), + finality_relay::FinalitySyncParams { tick: std::cmp::max( - SourceChain::AVERAGE_BLOCK_INTERVAL, - TargetChain::AVERAGE_BLOCK_INTERVAL, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: relay_substrate_client::transaction_stall_timeout( - transactions_mortality, - TargetChain::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, + stall_timeout: transaction_stall_timeout( + transaction_params.mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + crate::STALL_TIMEOUT, ), only_mandatory_headers, }, diff --git a/relays/client-substrate/src/finality_source.rs b/relays/lib-substrate-relay/src/finality_source.rs similarity index 66% rename from relays/client-substrate/src/finality_source.rs rename to relays/lib-substrate-relay/src/finality_source.rs index 98526de178cb..804d3212930d 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/lib-substrate-relay/src/finality_source.rs @@ -16,49 +16,59 @@ //! Default generic implementation of finality source for basic Substrate client. -use crate::{ - chain::{BlockWithJustification, Chain}, - client::Client, - error::Error, - sync_header::SyncHeader, -}; +use crate::finality_pipeline::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; use codec::Decode; -use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader}; +use finality_relay::SourceClient; use futures::stream::{unfold, Stream, StreamExt}; +use relay_substrate_client::{ + BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf, +}; use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::traits::Header as HeaderT; -use std::{marker::PhantomData, pin::Pin}; +use std::pin::Pin; /// Shared updatable reference to the maximal header number that we want to sync from the source. pub type RequiredHeaderNumberRef = Arc::BlockNumber>>; +/// Substrate finality proofs stream. +pub type SubstrateFinalityProofsStream

= Pin< + Box< + dyn Stream< + Item = GrandpaJustification< + HeaderOf<

::SourceChain>, + >, + > + Send, + >, +>; + /// Substrate node as finality source. -pub struct FinalitySource { - client: Client, - maximal_header_number: Option>, - _phantom: PhantomData

, +pub struct SubstrateFinalitySource { + client: Client, + maximal_header_number: Option>, } -impl FinalitySource { +impl SubstrateFinalitySource

{ /// Create new headers source using given client. pub fn new( - client: Client, - maximal_header_number: Option>, + client: Client, + maximal_header_number: Option>, ) -> Self { - FinalitySource { client, maximal_header_number, _phantom: Default::default() } + SubstrateFinalitySource { client, maximal_header_number } } /// Returns reference to the underlying RPC client. - pub fn client(&self) -> &Client { + pub fn client(&self) -> &Client { &self.client } /// Returns best finalized block number. - pub async fn on_chain_best_finalized_block_number(&self) -> Result { + pub async fn on_chain_best_finalized_block_number( + &self, + ) -> Result, Error> { // we **CAN** continue to relay finality proofs if source node is out of sync, because // target node may be missing proofs that are already available at the source let finalized_header_hash = self.client.best_finalized_header_hash().await?; @@ -67,18 +77,17 @@ impl FinalitySource { } } -impl Clone for FinalitySource { +impl Clone for SubstrateFinalitySource

{ fn clone(&self) -> Self { - FinalitySource { + SubstrateFinalitySource { client: self.client.clone(), maximal_header_number: self.maximal_header_number.clone(), - _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for FinalitySource { +impl RelayClient for SubstrateFinalitySource

{ type Error = Error; async fn reconnect(&mut self) -> Result<(), Error> { @@ -87,21 +96,12 @@ impl RelayClient for FinalitySource { } #[async_trait] -impl SourceClient

for FinalitySource -where - C: Chain, - C::BlockNumber: relay_utils::BlockNumberBase, - P: FinalitySyncPipeline< - Hash = C::Hash, - Number = C::BlockNumber, - Header = SyncHeader, - FinalityProof = GrandpaJustification, - >, - P::Header: SourceHeader, +impl SourceClient> + for SubstrateFinalitySource

{ - type FinalityProofsStream = Pin> + Send>>; + type FinalityProofsStream = SubstrateFinalityProofsStream

; - async fn best_finalized_block_number(&self) -> Result { + async fn best_finalized_block_number(&self) -> Result, Error> { let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?; // never return block number larger than requested. This way we'll never sync headers // past `maximal_header_number` @@ -116,15 +116,23 @@ where async fn header_and_finality_proof( &self, - number: P::Number, - ) -> Result<(P::Header, Option), Error> { + number: BlockNumberOf, + ) -> Result< + ( + relay_substrate_client::SyncHeader>, + Option>>, + ), + Error, + > { let header_hash = self.client.block_hash_by_number(number).await?; let signed_block = self.client.get_block(Some(header_hash)).await?; let justification = signed_block .justification() .map(|raw_justification| { - GrandpaJustification::::decode(&mut raw_justification.as_slice()) + GrandpaJustification::>::decode( + &mut raw_justification.as_slice(), + ) }) .transpose() .map_err(Error::ResponseParseFailed)?; @@ -141,7 +149,7 @@ where log::error!( target: "bridge", "Failed to read justification target from the {} justifications stream: {:?}", - P::SOURCE_NAME, + P::SourceChain::NAME, err, ); }; @@ -153,7 +161,9 @@ where .ok()??; let decoded_justification = - GrandpaJustification::::decode(&mut &next_justification[..]); + GrandpaJustification::>::decode( + &mut &next_justification[..], + ); let justification = match decoded_justification { Ok(j) => j, diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index f50bd103f430..4c5814171049 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -15,96 +15,122 @@ // along with Parity Bridges Common. If not, see . //! Substrate client as Substrate finality proof target. The chain we connect to should have -//! runtime that implements `FinalityApi` to allow bridging with -//! chain. +//! bridge GRANDPA pallet deployed and provide `FinalityApi` to allow bridging +//! with chain. -use crate::finality_pipeline::SubstrateFinalitySyncPipeline; +use crate::{ + finality_pipeline::{ + FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + }, + TransactionParams, +}; use async_trait::async_trait; -use codec::Decode; -use finality_relay::{FinalitySyncPipeline, TargetClient}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError}; +use bp_header_chain::{justification::GrandpaJustification, storage_keys::is_halted_key}; +use codec::Encode; +use finality_relay::TargetClient; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithGrandpa, Client, Error, HeaderIdOf, HeaderOf, + SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::relay_loop::Client as RelayClient; +use sp_core::{Bytes, Pair}; /// Substrate client as Substrate finality target. -pub struct SubstrateFinalityTarget { - client: Client, - pipeline: P, - transactions_mortality: Option, +pub struct SubstrateFinalityTarget { + client: Client, + transaction_params: TransactionParams>, } -impl SubstrateFinalityTarget { +impl SubstrateFinalityTarget

{ /// Create new Substrate headers target. - pub fn new(client: Client, pipeline: P, transactions_mortality: Option) -> Self { - SubstrateFinalityTarget { client, pipeline, transactions_mortality } + pub fn new( + client: Client, + transaction_params: TransactionParams>, + ) -> Self { + SubstrateFinalityTarget { client, transaction_params } + } + + /// Ensure that the GRANDPA pallet at target chain is active. + pub async fn ensure_pallet_active(&self) -> Result<(), Error> { + let is_halted = self + .client + .storage_value(is_halted_key(P::SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME), None) + .await?; + if is_halted.unwrap_or(false) { + Err(Error::BridgePalletIsHalted) + } else { + Ok(()) + } } } -impl Clone for SubstrateFinalityTarget { +impl Clone for SubstrateFinalityTarget

{ fn clone(&self) -> Self { SubstrateFinalityTarget { client: self.client.clone(), - pipeline: self.pipeline.clone(), - transactions_mortality: self.transactions_mortality, + transaction_params: self.transaction_params.clone(), } } } #[async_trait] -impl RelayClient for SubstrateFinalityTarget { - type Error = SubstrateError; +impl RelayClient for SubstrateFinalityTarget

{ + type Error = Error; - async fn reconnect(&mut self) -> Result<(), SubstrateError> { + async fn reconnect(&mut self) -> Result<(), Error> { self.client.reconnect().await } } #[async_trait] -impl TargetClient for SubstrateFinalityTarget +impl TargetClient> + for SubstrateFinalityTarget

where - C: Chain, - P: SubstrateFinalitySyncPipeline, - ::Number: Decode, - ::Hash: Decode, + AccountIdOf: From< as Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { - async fn best_finalized_source_block_number( - &self, - ) -> Result<::Number, SubstrateError> { + async fn best_finalized_source_block_id(&self) -> Result, Error> { // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; + // we can't relay finality if GRANDPA pallet at target chain is halted + self.ensure_pallet_active().await?; - Ok(crate::messages_source::read_client_state::< - C, - ::Hash, - ::Number, - >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) + Ok(crate::messages_source::read_client_state::( + &self.client, + None, + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await? - .best_finalized_peer_at_best_self - .0) + .best_finalized_peer_at_best_self) } async fn submit_finality_proof( &self, - header: ::Header, - proof: ::FinalityProof, - ) -> Result<(), SubstrateError> { - let transactions_author = self.pipeline.transactions_author(); - let pipeline = self.pipeline.clone(); - let transactions_mortality = self.transactions_mortality; + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> Result<(), Error> { + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let call = + P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_signed_extrinsic( - transactions_author, + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - pipeline.make_submit_finality_proof_transaction( - relay_substrate_client::TransactionEra::new( - best_block_id, - transactions_mortality, - ), - transaction_nonce, - header, - proof, - ) + Ok(Bytes( + P::TransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer.clone(), + era: TransactionEra::new(best_block_id, transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? + .encode(), + )) }, ) .await diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 2e802c4cb215..0e1371c53c81 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -31,17 +31,22 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use relay_substrate_client::{Chain, Client}; +use relay_substrate_client::{ + BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, +}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. -pub async fn initialize( +pub async fn initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, ) { @@ -54,13 +59,14 @@ pub async fn initialize( .await; match result { - Ok(tx_hash) => log::info!( + Ok(Some(tx_hash)) => log::info!( target: "bridge", "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", SourceChain::NAME, TargetChain::NAME, tx_hash, ), + Ok(None) => (), Err(err) => log::error!( target: "bridge", "Failed to submit {}-headers bridge initialization transaction to {}: {:?}", @@ -72,14 +78,31 @@ pub async fn initialize( } /// Craft and submit initialization transaction, returning any error that may occur. -async fn do_initialize( +async fn do_initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, -) -> Result::Number>> { +) -> Result< + Option, + Error::Number>, +> { + let is_initialized = is_initialized::(&target_client).await?; + if is_initialized { + log::info!( + target: "bridge", + "{}-headers bridge at {} is already initialized. Skipping", + SourceChain::NAME, + TargetChain::NAME, + ); + return Ok(None) + } + let initialization_data = prepare_initialization_data(source_client).await?; log::info!( target: "bridge", @@ -95,7 +118,23 @@ async fn do_initialize( }) .await .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; - Ok(initialization_tx_hash) + Ok(Some(initialization_tx_hash)) +} + +/// Returns `Ok(true)` if bridge has already been initialized. +async fn is_initialized( + target_client: &Client, +) -> Result, BlockNumberOf>> { + Ok(target_client + .raw_storage_value( + bp_header_chain::storage_keys::best_finalized_hash_key( + SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME, + ), + None, + ) + .await + .map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))? + .is_some()) } /// Prepare initialization data for the GRANDPA verifier pallet. diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index f95a8e0aba3a..80359b1c2a98 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -16,14 +16,91 @@ //! Substrate relay helpers -use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError}; +use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, StandaloneMetric}; /// Creates standalone token price metric. pub fn token_price_metric(token_id: &str) -> Result { FloatJsonValueMetric::new( format!("https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", token_id), format!("$.{}.btc", token_id), - format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), + format!("{}_to_base_conversion_rate", token_id.replace('-', "_")), format!("Rate used to convert from {} to some BASE tokens", token_id.to_uppercase()), ) } + +/// Compute conversion rate between two tokens immediately, without spawning any metrics. +/// +/// Returned rate may be used in expression: `from_tokens * rate -> to_tokens`. +pub async fn tokens_conversion_rate_from_metrics( + from_token_id: &str, + to_token_id: &str, +) -> anyhow::Result { + let from_token_metric = token_price_metric(from_token_id)?; + from_token_metric.update().await; + let to_token_metric = token_price_metric(to_token_id)?; + to_token_metric.update().await; + + let from_token_value = *from_token_metric.shared_value_ref().read().await; + let to_token_value = *to_token_metric.shared_value_ref().read().await; + // `FloatJsonValueMetric` guarantees that the value is positive && normal, so no additional + // checks required here + match (from_token_value, to_token_value) { + (Some(from_token_value), Some(to_token_value)) => + Ok(tokens_conversion_rate(from_token_value, to_token_value)), + _ => Err(anyhow::format_err!( + "Failed to compute conversion rate from {} to {}", + from_token_id, + to_token_id, + )), + } +} + +/// Compute conversion rate between two tokens, given token prices. +/// +/// Returned rate may be used in expression: `from_tokens * rate -> to_tokens`. +/// +/// Both prices are assumed to be normal and non-negative. +pub fn tokens_conversion_rate(from_token_value: f64, to_token_value: f64) -> f64 { + from_token_value / to_token_value +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rialto_to_millau_conversion_rate_is_correct() { + let rialto_price = 18.18; + let millau_price = 136.35; + assert!(rialto_price < millau_price); + + let conversion_rate = tokens_conversion_rate(rialto_price, millau_price); + let rialto_amount = 100.0; + let millau_amount = rialto_amount * conversion_rate; + assert!( + rialto_amount > millau_amount, + "{} RLT * {} = {} MLU", + rialto_amount, + conversion_rate, + millau_amount, + ); + } + + #[test] + fn millau_to_rialto_conversion_rate_is_correct() { + let rialto_price = 18.18; + let millau_price = 136.35; + assert!(rialto_price < millau_price); + + let conversion_rate = tokens_conversion_rate(millau_price, rialto_price); + let millau_amount = 100.0; + let rialto_amount = millau_amount * conversion_rate; + assert!( + rialto_amount > millau_amount, + "{} MLU * {} = {} RLT", + millau_amount, + conversion_rate, + rialto_amount, + ); + } +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index cc066bf501ac..27d91147c2dd 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,11 +22,14 @@ use std::time::Duration; pub mod conversion_rate_update; pub mod error; +pub mod finality_guards; pub mod finality_pipeline; +pub mod finality_source; pub mod finality_target; pub mod headers_initialize; pub mod helpers; pub mod messages_lane; +pub mod messages_metrics; pub mod messages_source; pub mod messages_target; pub mod on_demand_headers; @@ -39,3 +42,12 @@ pub mod on_demand_headers; /// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine /// transaction, or remove it from the pool. pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); + +/// Transaction creation parameters. +#[derive(Clone, Debug)] +pub struct TransactionParams { + /// Transactions author. + pub signer: TS, + /// Transactions mortality. + pub mortality: Option, +} diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 6cadb64754a5..fadf5e62245a 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -17,194 +17,434 @@ //! Tools for supporting message lanes between two Substrate-based chains. use crate::{ - messages_source::SubstrateMessagesProof, messages_target::SubstrateMessagesReceivingProof, + conversion_rate_update::UpdateConversionRateCallBuilder, + messages_metrics::StandaloneMessagesMetrics, + messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, + messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, STALL_TIMEOUT, }; -use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, IndexOf}; -use frame_support::weights::Weight; -use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - relay_strategy::RelayStrategy, +use bp_runtime::{AccountIdOf, Chain as _}; +use bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; +use codec::Encode; +use frame_support::weights::{GetDispatchInfo, Weight}; +use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; +use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - BlockNumberOf, Chain, Client, HashOf, + transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, + ChainWithMessages, Client, HashOf, TransactionSignScheme, }; -use relay_utils::{ - metrics::{ - FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, - }, - BlockNumberBase, -}; -use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::FixedU128; -use std::ops::RangeInclusive; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; + +/// Substrate -> Substrate messages synchronization pipeline. +pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { + /// Name of the source -> target tokens conversion rate parameter. + /// + /// The parameter is stored at the target chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + /// Name of the target -> source tokens conversion rate parameter. + /// + /// The parameter is stored at the source chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + + /// Name of the source chain fee multiplier parameter. + /// + /// The parameter is stored at the target chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; + /// Name of the target chain fee multiplier parameter. + /// + /// The parameter is stored at the source chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; + + /// Name of the transaction payment pallet, deployed at the source chain. + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; + /// Name of the transaction payment pallet, deployed at the target chain. + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; + + /// Messages of this chain are relayed to the `TargetChain`. + type SourceChain: ChainWithMessages; + /// Messages from the `SourceChain` are dispatched on this chain. + type TargetChain: ChainWithMessages; + + /// Scheme used to sign source chain transactions. + type SourceTransactionSignScheme: TransactionSignScheme; + /// Scheme used to sign target chain transactions. + type TargetTransactionSignScheme: TransactionSignScheme; + + /// How receive messages proof call is built? + type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; + /// How receive messages delivery proof call is built? + type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; + + /// `TargetChain` tokens to `SourceChain` tokens conversion rate update builder. + /// + /// If not applicable to this bridge, you may use `()` here. + type TargetToSourceChainConversionRateUpdateBuilder: UpdateConversionRateCallBuilder< + Self::SourceChain, + >; + + /// Message relay strategy. + type RelayStrategy: RelayStrategy; +} + +/// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. +#[derive(Clone, Debug)] +pub(crate) struct MessageLaneAdapter { + _phantom: PhantomData

, +} + +impl MessageLane for MessageLaneAdapter

{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type MessagesProof = SubstrateMessagesProof; + type MessagesReceivingProof = SubstrateMessagesDeliveryProof; + + type SourceChainBalance = BalanceOf; + type SourceHeaderNumber = BlockNumberOf; + type SourceHeaderHash = HashOf; + + type TargetHeaderNumber = BlockNumberOf; + type TargetHeaderHash = HashOf; +} /// Substrate <-> Substrate messages relay parameters. -pub struct MessagesRelayParams { +pub struct MessagesRelayParams { /// Messages source client. - pub source_client: Client, - /// Sign parameters for messages source chain. - pub source_sign: SS, - /// Mortality of source transactions. - pub source_transactions_mortality: Option, + pub source_client: Client, + /// Source transaction params. + pub source_transaction_params: + TransactionParams>, /// Messages target client. - pub target_client: Client, - /// Sign parameters for messages target chain. - pub target_sign: TS, - /// Mortality of target transactions. - pub target_transactions_mortality: Option, + pub target_client: Client, + /// Target transaction params. + pub target_transaction_params: + TransactionParams>, /// Optional on-demand source to target headers relay. - pub source_to_target_headers_relay: Option>, + pub source_to_target_headers_relay: Option>, /// Optional on-demand target to source headers relay. - pub target_to_source_headers_relay: Option>, + pub target_to_source_headers_relay: Option>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, /// Metrics parameters. pub metrics_params: MetricsParams, /// Pre-registered standalone metrics. - pub standalone_metrics: Option>, - /// Relay strategy - pub relay_strategy: Strategy, + pub standalone_metrics: Option>, + /// Relay strategy. + pub relay_strategy: P::RelayStrategy, } -/// Message sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { - /// Underlying generic message lane. - type MessageLane: MessageLane; - - /// Name of the runtime method that returns dispatch weight of outbound messages at the source - /// chain. - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the runtime method that returns latest generated nonce at the source chain. - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest received (confirmed) nonce at the the source - /// chain. - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - - /// Name of the runtime method that returns latest received nonce at the target chain. - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the - /// target chain. - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; - /// Number of the runtime method that returns state of "unrewarded relayers" set at the target - /// chain. - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str; - - /// Name of the runtime method that returns id of best finalized source header at target chain. - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; - /// Name of the runtime method that returns id of best finalized target header at source chain. - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; - - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at source chain. - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str; - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain. - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str; - - /// Extra weight of the delivery transaction at the target chain, that is paid to cover - /// dispatch fee payment. - /// - /// If dispatch fee is paid at the source chain, then this weight is refunded by the - /// delivery transaction. - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight; - - /// Source chain. - type SourceChain: Chain; - /// Target chain. - type TargetChain: Chain; - - /// Returns id of account that we're using to sign transactions at target chain (messages - /// proof). - fn target_transactions_author(&self) -> AccountIdOf; - - /// Make messages delivery transaction. - fn make_messages_delivery_transaction( - &self, - best_block_id: TargetHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: SourceHeaderIdOf, - nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes; - - /// Returns id of account that we're using to sign transactions at source chain (delivery - /// proof). - fn source_transactions_author(&self) -> AccountIdOf; - - /// Make messages receiving proof transaction. - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: SourceHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, - ) -> Bytes; +/// Run Substrate-to-Substrate messages sync loop. +pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> +where + AccountIdOf: + From< as Pair>::Public>, + AccountIdOf: + From< as Pair>::Public>, + BalanceOf: TryFrom>, + P::SourceTransactionSignScheme: TransactionSignScheme, + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let source_client = params.source_client; + let target_client = params.target_client; + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transaction_params.mortality, + params.target_transaction_params.mortality, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + let relayer_id_at_source: AccountIdOf = + params.source_transaction_params.signer.public().into(); + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; + // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + crate::messages_lane::select_delivery_transaction_limits::< + ::WeightInfo, + >( + P::TargetChain::max_extrinsic_weight(), + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); + + let standalone_metrics = params.standalone_metrics.map(Ok).unwrap_or_else(|| { + crate::messages_metrics::standalone_metrics::

( + source_client.clone(), + target_client.clone(), + ) + })?; + + log::info!( + target: "bridge", + "Starting {} -> {} messages relay.\n\t\ + {} relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}\n\t\ + Tx mortality: {:?} (~{}m)/{:?} (~{}m)\n\t\ + Stall timeout: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME, + relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + params.source_transaction_params.mortality, + transaction_stall_timeout( + params.source_transaction_params.mortality, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ).as_secs_f64() / 60.0f64, + params.target_transaction_params.mortality, + transaction_stall_timeout( + params.target_transaction_params.mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ).as_secs_f64() / 60.0f64, + stall_timeout, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: params.lane_id, + source_tick: P::SourceChain::AVERAGE_BLOCK_INTERVAL, + target_tick: P::TargetChain::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_nonces_at_target: + P::SourceChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relay_strategy: params.relay_strategy, + }, + }, + SubstrateMessagesSource::

::new( + source_client.clone(), + target_client.clone(), + params.lane_id, + params.source_transaction_params, + params.target_to_source_headers_relay, + ), + SubstrateMessagesTarget::

::new( + target_client, + source_client, + params.lane_id, + relayer_id_at_source, + params.target_transaction_params, + standalone_metrics.clone(), + params.source_to_target_headers_relay, + ), + standalone_metrics.register_and_spawn(params.metrics_params)?, + futures::future::pending(), + ) + .await + .map_err(Into::into) } -/// Substrate-to-Substrate message lane. -#[derive(Debug)] -pub struct SubstrateMessageLaneToSubstrate< - Source: Chain, - SourceSignParams, - Target: Chain, - TargetSignParams, -> { - /// Client for the source Substrate chain. - pub source_client: Client, - /// Parameters required to sign transactions for source chain. - pub source_sign: SourceSignParams, - /// Source transactions mortality. - pub source_transactions_mortality: Option, - /// Client for the target Substrate chain. - pub target_client: Client, - /// Parameters required to sign transactions for target chain. - pub target_sign: TargetSignParams, - /// Target transactions mortality. - pub target_transactions_mortality: Option, - /// Account id of relayer at the source chain. - pub relayer_id_at_source: Source::AccountId, +/// Different ways of building `receive_messages_proof` calls. +pub trait ReceiveMessagesProofCallBuilder { + /// Given messages proof, build call of `receive_messages_proof` function of bridge + /// messages module at the target chain. + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf; } -impl Clone - for SubstrateMessageLaneToSubstrate +/// Building `receive_messages_proof` call when you have direct access to the target +/// chain runtime. +pub struct DirectReceiveMessagesProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} + +impl ReceiveMessagesProofCallBuilder

for DirectReceiveMessagesProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig>, + I: 'static, + R::SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< + R::InboundMessageFee, + MessagesProof = FromBridgedChainMessagesProof>, + >, + CallOf: From> + GetDispatchInfo, { - fn clone(&self) -> Self { - Self { - source_client: self.source_client.clone(), - source_sign: self.source_sign.clone(), - source_transactions_mortality: self.source_transactions_mortality, - target_client: self.target_client.clone(), - target_sign: self.target_sign.clone(), - target_transactions_mortality: self.target_transactions_mortality, - relayer_id_at_source: self.relayer_id_at_source.clone(), + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf { + let call: CallOf = BridgeMessagesCall::::receive_messages_proof { + relayer_id_at_bridged_chain: relayer_id_at_source, + proof: proof.1, + messages_count, + dispatch_weight, } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} messages delivery call. Weight: {}/{}, size: {}/{}", + P::SourceChain::NAME, + P::TargetChain::NAME, + call.get_dispatch_info().weight, + P::TargetChain::max_extrinsic_weight(), + call.encode().len(), + P::TargetChain::max_extrinsic_size(), + ); + } + call } } -impl MessageLane - for SubstrateMessageLaneToSubstrate -where - SourceSignParams: Clone + Send + Sync + 'static, - TargetSignParams: Clone + Send + Sync + 'static, - BlockNumberOf: BlockNumberBase, - BlockNumberOf: BlockNumberBase, -{ - const SOURCE_NAME: &'static str = Source::NAME; - const TARGET_NAME: &'static str = Target::NAME; +/// Macro that generates `ReceiveMessagesProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_proof_call( + relayer_id_at_source: relay_substrate_client::AccountIdOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + proof: $crate::messages_source::SubstrateMessagesProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + messages_count: u32, + dispatch_weight: Weight, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + > { + $bridge_messages($receive_messages_proof( + relayer_id_at_source, + proof.1, + messages_count, + dispatch_weight, + )) + } + } + }; +} - type MessagesProof = SubstrateMessagesProof; - type MessagesReceivingProof = SubstrateMessagesReceivingProof; +/// Different ways of building `receive_messages_delivery_proof` calls. +pub trait ReceiveMessagesDeliveryProofCallBuilder { + /// Given messages delivery proof, build call of `receive_messages_delivery_proof` function of + /// bridge messages module at the source chain. + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf; +} + +/// Building `receive_messages_delivery_proof` call when you have direct access to the source +/// chain runtime. +pub struct DirectReceiveMessagesDeliveryProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} - type SourceChainBalance = Source::Balance; - type SourceHeaderNumber = BlockNumberOf; - type SourceHeaderHash = HashOf; +impl ReceiveMessagesDeliveryProofCallBuilder

+ for DirectReceiveMessagesDeliveryProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig, + I: 'static, + R::TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain< + R::OutboundPayload, + R::AccountId, + MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>, + >, + CallOf: From> + GetDispatchInfo, +{ + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf { + let call: CallOf = + BridgeMessagesCall::::receive_messages_delivery_proof { + proof: proof.1, + relayers_state: proof.0, + } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} delivery confirmation transaction. Weight: {}/{}, size: {}/{}", + P::TargetChain::NAME, + P::SourceChain::NAME, + call.get_dispatch_info().weight, + P::SourceChain::max_extrinsic_weight(), + call.encode().len(), + P::SourceChain::max_extrinsic_size(), + ); + } + call + } +} - type TargetHeaderNumber = BlockNumberOf; - type TargetHeaderHash = HashOf; +/// Macro that generates `ReceiveMessagesDeliveryProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of source chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_delivery_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_delivery_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_delivery_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesDeliveryProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_delivery_proof_call( + proof: $crate::messages_target::SubstrateMessagesDeliveryProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + >, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + > { + $bridge_messages($receive_messages_delivery_proof(proof.1, proof.0)) + } + } + }; } /// Returns maximal number of messages and their maximal cumulative dispatch weight, based @@ -245,165 +485,20 @@ pub fn select_delivery_transaction_limits { - /// Global metrics. - pub global: GlobalMetrics, - /// Storage chain proof overhead metric. - pub source_storage_proof_overhead: StorageProofOverheadMetric, - /// Target chain proof overhead metric. - pub target_storage_proof_overhead: StorageProofOverheadMetric, - /// Source tokens to base conversion rate metric. - pub source_to_base_conversion_rate: Option, - /// Target tokens to base conversion rate metric. - pub target_to_base_conversion_rate: Option, - /// Source tokens to target tokens conversion rate metric. This rate is stored by the target - /// chain. - pub source_to_target_conversion_rate: - Option>, - /// Target tokens to source tokens conversion rate metric. This rate is stored by the source - /// chain. - pub target_to_source_conversion_rate: - Option>, -} - -impl StandaloneMessagesMetrics { - /// Swap source and target sides. - pub fn reverse(self) -> StandaloneMessagesMetrics { - StandaloneMessagesMetrics { - global: self.global, - source_storage_proof_overhead: self.target_storage_proof_overhead, - target_storage_proof_overhead: self.source_storage_proof_overhead, - source_to_base_conversion_rate: self.target_to_base_conversion_rate, - target_to_base_conversion_rate: self.source_to_base_conversion_rate, - source_to_target_conversion_rate: self.target_to_source_conversion_rate, - target_to_source_conversion_rate: self.source_to_target_conversion_rate, - } - } - - /// Register all metrics in the registry. - pub fn register_and_spawn( - self, - metrics: MetricsParams, - ) -> Result { - self.global.register_and_spawn(&metrics.registry)?; - self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - if let Some(m) = self.source_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_source_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - Ok(metrics) - } - - /// Return conversion rate from target to source tokens. - pub async fn target_to_source_conversion_rate(&self) -> Option { - Self::compute_target_to_source_conversion_rate( - *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - ) - } - - /// Return conversion rate from target to source tokens, given conversion rates from - /// target/source tokens to some base token. - fn compute_target_to_source_conversion_rate( - target_to_base_conversion_rate: Option, - source_to_base_conversion_rate: Option, - ) -> Option { - Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) - } -} - -/// Create standalone metrics for the message lane relay loop. -/// -/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) -/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). -pub fn standalone_metrics( - source_client: Client, - target_client: Client, - source_chain_token_id: Option<&str>, - target_chain_token_id: Option<&str>, - source_to_target_conversion_rate_params: Option<(StorageKey, FixedU128)>, - target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, -) -> anyhow::Result> { - Ok(StandaloneMessagesMetrics { - global: GlobalMetrics::new()?, - source_storage_proof_overhead: StorageProofOverheadMetric::new( - source_client.clone(), - format!("{}_storage_proof_overhead", SC::NAME.to_lowercase()), - format!("{} storage proof overhead", SC::NAME), - )?, - target_storage_proof_overhead: StorageProofOverheadMetric::new( - target_client.clone(), - format!("{}_storage_proof_overhead", TC::NAME.to_lowercase()), - format!("{} storage proof overhead", TC::NAME), - )?, - source_to_base_conversion_rate: source_chain_token_id - .map(|source_chain_token_id| { - crate::helpers::token_price_metric(source_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_base_conversion_rate: target_chain_token_id - .map(|target_chain_token_id| { - crate::helpers::token_price_metric(target_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - source_to_target_conversion_rate: source_to_target_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - target_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", TC::NAME, SC::NAME, TC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - SC::NAME, - TC::NAME, - TC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_source_conversion_rate: target_to_source_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - source_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", SC::NAME, TC::NAME, SC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - TC::NAME, - SC::NAME, - SC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - }) -} - #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; type RialtoToMillauMessagesWeights = - pallet_bridge_messages::weights::RialtoWeight; + pallet_bridge_messages::weights::MillauWeight; #[test] fn select_delivery_transaction_limits_works() { let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + bp_millau::Millau::max_extrinsic_weight(), + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, ); assert_eq!( (max_count, max_weight), @@ -412,15 +507,7 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (782, 216_583_333_334), - ); - } - - #[async_std::test] - async fn target_to_source_conversion_rate_works() { - assert_eq!( - StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), - Some(12.32 / 183.15), + (958, 216_583_333_334), ); } } diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs new file mode 100644 index 000000000000..b165892fda1d --- /dev/null +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -0,0 +1,389 @@ +// 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 for supporting message lanes between two Substrate-based chains. + +use crate::{helpers::tokens_conversion_rate, messages_lane::SubstrateMessageLane}; + +use codec::Decode; +use frame_system::AccountInfo; +use pallet_balances::AccountData; +use relay_substrate_client::{ + metrics::{ + FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric, StorageProofOverheadMetric, + }, + AccountIdOf, BalanceOf, Chain, ChainWithBalances, Client, Error as SubstrateError, IndexOf, +}; +use relay_utils::metrics::{ + FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, +}; +use sp_core::storage::StorageData; +use sp_runtime::{FixedPointNumber, FixedU128}; +use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; + +/// Name of the `NextFeeMultiplier` storage value within the transaction payment pallet. +const NEXT_FEE_MULTIPLIER_VALUE_NAME: &str = "NextFeeMultiplier"; + +/// Shared references to the standalone metrics of the message lane relay loop. +#[derive(Debug, Clone)] +pub struct StandaloneMessagesMetrics { + /// Global metrics. + pub global: GlobalMetrics, + /// Storage chain proof overhead metric. + pub source_storage_proof_overhead: StorageProofOverheadMetric, + /// Target chain proof overhead metric. + pub target_storage_proof_overhead: StorageProofOverheadMetric, + /// Source tokens to base conversion rate metric. + pub source_to_base_conversion_rate: Option, + /// Target tokens to base conversion rate metric. + pub target_to_base_conversion_rate: Option, + /// Source tokens to target tokens conversion rate metric. This rate is stored by the target + /// chain. + pub source_to_target_conversion_rate: Option>, + /// Target tokens to source tokens conversion rate metric. This rate is stored by the source + /// chain. + pub target_to_source_conversion_rate: Option>, + + /// Actual source chain fee multiplier. + pub source_fee_multiplier: Option>, + /// Source chain fee multiplier, stored at the target chain. + pub source_fee_multiplier_at_target: Option>, + /// Actual target chain fee multiplier. + pub target_fee_multiplier: Option>, + /// Target chain fee multiplier, stored at the target chain. + pub target_fee_multiplier_at_source: Option>, +} + +impl StandaloneMessagesMetrics { + /// Swap source and target sides. + pub fn reverse(self) -> StandaloneMessagesMetrics { + StandaloneMessagesMetrics { + global: self.global, + source_storage_proof_overhead: self.target_storage_proof_overhead, + target_storage_proof_overhead: self.source_storage_proof_overhead, + source_to_base_conversion_rate: self.target_to_base_conversion_rate, + target_to_base_conversion_rate: self.source_to_base_conversion_rate, + source_to_target_conversion_rate: self.target_to_source_conversion_rate, + target_to_source_conversion_rate: self.source_to_target_conversion_rate, + source_fee_multiplier: self.target_fee_multiplier, + source_fee_multiplier_at_target: self.target_fee_multiplier_at_source, + target_fee_multiplier: self.source_fee_multiplier, + target_fee_multiplier_at_source: self.source_fee_multiplier_at_target, + } + } + + /// Register all metrics in the registry. + pub fn register_and_spawn( + self, + metrics: MetricsParams, + ) -> Result { + self.global.register_and_spawn(&metrics.registry)?; + self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + if let Some(m) = self.source_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_source_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.source_fee_multiplier { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.source_fee_multiplier_at_target { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_fee_multiplier { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_fee_multiplier_at_source { + m.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) + } + + /// Return conversion rate from target to source tokens. + pub async fn target_to_source_conversion_rate(&self) -> Option { + let from_token_value = + (*self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; + let to_token_value = + (*self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; + Some(tokens_conversion_rate(from_token_value, to_token_value)) + } +} + +/// Create symmetric standalone metrics for the message lane relay loop. +/// +/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) +/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). +/// We assume that either conversion rate parameters have values in the storage, or they are +/// initialized with 1:1. +pub fn standalone_metrics( + source_client: Client, + target_client: Client, +) -> anyhow::Result> { + Ok(StandaloneMessagesMetrics { + global: GlobalMetrics::new()?, + source_storage_proof_overhead: StorageProofOverheadMetric::new( + source_client.clone(), + format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::SourceChain::NAME), + )?, + target_storage_proof_overhead: StorageProofOverheadMetric::new( + target_client.clone(), + format!("{}_storage_proof_overhead", P::TargetChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::TargetChain::NAME), + )?, + source_to_base_conversion_rate: P::SourceChain::TOKEN_ID + .map(|source_chain_token_id| { + crate::helpers::token_price_metric(source_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_base_conversion_rate: P::TargetChain::TOKEN_ID + .map(|target_chain_token_id| { + crate::helpers::token_price_metric(target_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + target_client.clone(), + key, + format!( + "{}_{}_to_{}_conversion_rate", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::TargetChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::TargetChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + source_client.clone(), + key, + format!( + "{}_{}_to_{}_conversion_rate", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::SourceChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + source_fee_multiplier: P::AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME + .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) + .map(|key| { + log::trace!(target: "bridge", "{}_fee_multiplier", P::SourceChain::NAME); + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + source_client.clone(), + key, + format!("{}_fee_multiplier", P::SourceChain::NAME,), + format!("{} fee multiplier", P::SourceChain::NAME,), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + source_fee_multiplier_at_target: P::SOURCE_FEE_MULTIPLIER_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + target_client.clone(), + key, + format!("{}_{}_fee_multiplier", P::TargetChain::NAME, P::SourceChain::NAME,), + format!( + "{} fee multiplier stored at {}", + P::SourceChain::NAME, + P::TargetChain::NAME, + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_fee_multiplier: P::AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME + .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) + .map(|key| { + log::trace!(target: "bridge", "{}_fee_multiplier", P::TargetChain::NAME); + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + target_client, + key, + format!("{}_fee_multiplier", P::TargetChain::NAME,), + format!("{} fee multiplier", P::TargetChain::NAME,), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_fee_multiplier_at_source: P::TARGET_FEE_MULTIPLIER_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + source_client, + key, + format!("{}_{}_fee_multiplier", P::SourceChain::NAME, P::TargetChain::NAME,), + format!( + "{} fee multiplier stored at {}", + P::TargetChain::NAME, + P::SourceChain::NAME, + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + }) +} + +/// Add relay accounts balance metrics. +pub async fn add_relay_balances_metrics( + client: Client, + metrics: MetricsParams, + relay_account_id: Option>, + messages_pallet_owner_account_id: Option>, +) -> anyhow::Result +where + BalanceOf: Into + std::fmt::Debug, +{ + if relay_account_id.is_none() && messages_pallet_owner_account_id.is_none() { + return Ok(metrics) + } + + // if `tokenDecimals` is missing from system properties, we'll be using + let token_decimals = client + .token_decimals() + .await? + .map(|token_decimals| { + log::info!(target: "bridge", "Read `tokenDecimals` for {}: {}", C::NAME, token_decimals); + token_decimals + }) + .unwrap_or_else(|| { + // turns out it is normal not to have this property - e.g. when polkadot binary is + // started using `polkadot-local` chain. Let's use minimal nominal here + log::info!(target: "bridge", "Using default (zero) `tokenDecimals` value for {}", C::NAME); + 0 + }); + let token_decimals = u32::try_from(token_decimals).map_err(|e| { + anyhow::format_err!( + "Token decimals value ({}) of {} doesn't fit into u32: {:?}", + token_decimals, + C::NAME, + e, + ) + })?; + if let Some(relay_account_id) = relay_account_id { + let relay_account_balance_metric = FloatStorageValueMetric::new( + FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + C::account_info_storage_key(&relay_account_id), + format!("at_{}_relay_balance", C::NAME), + format!("Balance of the relay account at the {}", C::NAME), + )?; + relay_account_balance_metric.register_and_spawn(&metrics.registry)?; + } + if let Some(messages_pallet_owner_account_id) = messages_pallet_owner_account_id { + let pallet_owner_account_balance_metric = FloatStorageValueMetric::new( + FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + C::account_info_storage_key(&messages_pallet_owner_account_id), + format!("at_{}_messages_pallet_owner_balance", C::NAME), + format!("Balance of the messages pallet owner at the {}", C::NAME), + )?; + pallet_owner_account_balance_metric.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) +} + +/// Adapter for `FloatStorageValueMetric` to decode account free balance. +#[derive(Clone, Debug)] +struct FreeAccountBalance { + token_decimals: u32, + _phantom: PhantomData, +} + +impl FloatStorageValue for FreeAccountBalance +where + C: Chain, + BalanceOf: Into, +{ + type Value = FixedU128; + + fn decode( + &self, + maybe_raw_value: Option, + ) -> Result, SubstrateError> { + maybe_raw_value + .map(|raw_value| { + AccountInfo::, AccountData>>::decode(&mut &raw_value.0[..]) + .map_err(SubstrateError::ResponseParseFailed) + .map(|account_data| { + convert_to_token_balance(account_data.data.free.into(), self.token_decimals) + }) + }) + .transpose() + } +} + +/// Convert from raw `u128` balance (nominated in smallest chain token units) to the float regular +/// tokens value. +fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 { + FixedU128::from_inner(balance.saturating_mul(FixedU128::DIV / 10u128.pow(token_decimals))) +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::storage::generator::StorageValue; + use sp_core::storage::StorageKey; + + #[test] + fn token_decimals_used_properly() { + let plancks = 425_000_000_000; + let token_decimals = 10; + let dots = convert_to_token_balance(plancks, token_decimals); + assert_eq!(dots, FixedU128::saturating_from_rational(425, 10)); + } + + #[test] + fn next_fee_multiplier_storage_key_is_correct() { + assert_eq!( + bp_runtime::storage_value_key("TransactionPayment", NEXT_FEE_MULTIPLIER_VALUE_NAME), + StorageKey(pallet_transaction_payment::NextFeeMultiplier::::storage_value_final_key().to_vec()), + ); + } +} diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 5f066296e7e7..77dd2aed05bc 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -19,12 +19,19 @@ //! chain. use crate::{ - messages_lane::SubstrateMessageLane, messages_target::SubstrateMessagesReceivingProof, + messages_lane::{ + MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, + }, + messages_target::SubstrateMessagesDeliveryProof, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{ + storage_keys::{operating_mode_key, outbound_lane_data_key}, + LaneId, MessageNonce, OperatingMode, OutboundLaneData, UnrewardedRelayersState, +}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -39,15 +46,13 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, - IndexOf, -}; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Header as HeaderT}, - DeserializeOwned, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionSignScheme, UnsignedTransaction, }; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything @@ -57,30 +62,60 @@ pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof { - client: Client, - lane: P, + source_client: Client, + target_client: Client, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, } impl SubstrateMessagesSource

{ /// Create new Substrate headers source. pub fn new( - client: Client, - lane: P, + source_client: Client, + target_client: Client, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, ) -> Self { - SubstrateMessagesSource { client, lane, lane_id, target_to_source_headers_relay } + SubstrateMessagesSource { + source_client, + target_client, + lane_id, + transaction_params, + target_to_source_headers_relay, + } + } + + /// Read outbound lane state from the on-chain storage at given block. + async fn outbound_lane_data( + &self, + id: SourceHeaderIdOf>, + ) -> Result, SubstrateError> { + self.source_client + .storage_value( + outbound_lane_data_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), + Some(id.1), + ) + .await + } + + /// Ensure that the messages pallet at source chain is active. + async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { + ensure_messages_pallet_active::(&self.source_client).await } } impl Clone for SubstrateMessagesSource

{ fn clone(&self) -> Self { Self { - client: self.client.clone(), - lane: self.lane.clone(), + source_client: self.source_client.clone(), + target_client: self.target_client.clone(), lane_id: self.lane_id, + transaction_params: self.transaction_params.clone(), target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), } } @@ -91,96 +126,71 @@ impl RelayClient for SubstrateMessagesSource

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await + self.source_client.reconnect().await?; + self.target_client.reconnect().await } } #[async_trait] -impl

SourceClient for SubstrateMessagesSource

+impl SourceClient> for SubstrateMessagesSource

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: Decode + Bounded, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: BlockNumberBase + Copy, - HeaderOf: DeserializeOwned, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::TargetHeaderNumber: Decode, - ::TargetHeaderHash: Decode, - ::SourceChainBalance: AtLeast32BitUnsigned, + AccountIdOf: + From< as Pair>::Public>, + P::SourceTransactionSignScheme: TransactionSignScheme, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver - self.client.ensure_synced().await?; - - read_client_state::< - _, - ::TargetHeaderHash, - ::TargetHeaderNumber, - >(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE) + self.source_client.ensure_synced().await?; + // we can't relay confirmations if messages pallet at source chain is halted + self.ensure_pallet_active().await?; + + read_client_state( + &self.source_client, + Some(&self.target_client), + P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await } async fn latest_generated_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let latest_generated_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { + // lane data missing from the storage is fine until first message is sent + let latest_generated_nonce = self + .outbound_lane_data(id) + .await? + .map(|data| data.latest_generated_nonce) + .unwrap_or(0); Ok((id, latest_generated_nonce)) } async fn latest_confirmed_received_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { + // lane data missing from the storage is fine until first message is sent + let latest_received_nonce = self + .outbound_lane_data(id) + .await? + .map(|data| data.latest_received_nonce) + .unwrap_or(0); Ok((id, latest_received_nonce)) } async fn generated_message_details( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, ) -> Result< - MessageDetailsMap<::SourceChainBalance>, + MessageDetailsMap< as MessageLane>::SourceChainBalance>, SubstrateError, > { let encoded_response = self - .client + .source_client .state_call( - P::OUTBOUND_LANE_MESSAGE_DETAILS_METHOD.into(), + P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) @@ -195,14 +205,14 @@ where async fn prove_messages( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, proof_parameters: MessageProofParameters, ) -> Result< ( - SourceHeaderIdOf, + SourceHeaderIdOf>, RangeInclusive, - ::MessagesProof, + as MessageLane>::MessagesProof, ), SubstrateError, > { @@ -210,8 +220,8 @@ where Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { - let message_key = pallet_bridge_messages::storage_keys::message_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + let message_key = bp_messages::storage_keys::message_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, message_nonce, ); @@ -219,13 +229,18 @@ where message_nonce += 1; } if proof_parameters.outbound_state_proof_required { - storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + storage_keys.push(bp_messages::storage_keys::outbound_lane_data_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, )); } - let proof = self.client.prove_storage(storage_keys, id.1).await?.iter_nodes().collect(); + let proof = self + .source_client + .prove_storage(storage_keys, id.1) + .await? + .iter_nodes() + .collect(); let proof = FromBridgedChainMessagesProof { bridged_header_hash: id.1, storage_proof: proof, @@ -238,19 +253,26 @@ where async fn submit_messages_receiving_proof( &self, - generated_at_block: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, + _generated_at_block: TargetHeaderIdOf>, + proof: as MessageLane>::MessagesReceivingProof, ) -> Result<(), SubstrateError> { - let lane = self.lane.clone(); - self.client + let genesis_hash = *self.source_client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let (spec_version, transaction_version) = + self.source_client.simple_runtime_version().await?; + self.source_client .submit_signed_extrinsic( - self.lane.source_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_receiving_proof_transaction( + make_messages_delivery_proof_transaction::

( + spec_version, + transaction_version, + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_block, proof, + true, ) }, ) @@ -258,7 +280,7 @@ where Ok(()) } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { target_to_source_headers_relay.require_finalized_header(id).await; } @@ -266,26 +288,89 @@ where async fn estimate_confirmation_transaction( &self, - ) -> ::SourceChainBalance { - self.client - .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( + ) -> as MessageLane>::SourceChainBalance { + let runtime_version = match self.source_client.runtime_version().await { + Ok(v) => v, + Err(_) => return BalanceOf::::max_value(), + }; + async { + let dummy_tx = make_messages_delivery_proof_transaction::

( + runtime_version.spec_version, + runtime_version.transaction_version, + self.source_client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), prepare_dummy_messages_delivery_proof::(), - )) - .await - .map(|fee| fee.inclusion_fee()) - .unwrap_or_else(|_| BalanceOf::::max_value()) + false, + )?; + self.source_client + .estimate_extrinsic_fee(dummy_tx) + .await + .map(|fee| fee.inclusion_fee()) + } + .await + .unwrap_or_else(|_| BalanceOf::::max_value()) + } +} + +/// Ensure that the messages pallet at source chain is active. +pub(crate) async fn ensure_messages_pallet_active( + client: &Client, +) -> Result<(), SubstrateError> +where + AtChain: ChainWithMessages, + WithChain: ChainWithMessages, +{ + let operating_mode = client + .storage_value(operating_mode_key(WithChain::WITH_CHAIN_MESSAGES_PALLET_NAME), None) + .await?; + let is_halted = operating_mode == Some(OperatingMode::Halted); + if is_halted { + Err(SubstrateError::BridgePalletIsHalted) + } else { + Ok(()) } } +/// Make messages delivery proof transaction from given proof. +#[allow(clippy::too_many_arguments)] +fn make_messages_delivery_proof_transaction( + spec_version: u32, + transaction_version: u32, + source_genesis_hash: &HashOf, + source_transaction_params: &TransactionParams>, + source_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, +) -> Result +where + P::SourceTransactionSignScheme: TransactionSignScheme, +{ + let call = + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, trace_call, + ); + Ok(Bytes( + P::SourceTransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *source_genesis_hash, + signer: source_transaction_params.signer.clone(), + era: TransactionEra::new(source_best_block_id, source_transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? + .encode(), + )) +} + /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't /// affect the call weight - we only care about its size. fn prepare_dummy_messages_delivery_proof( -) -> SubstrateMessagesReceivingProof { +) -> SubstrateMessagesDeliveryProof { let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, @@ -312,19 +397,19 @@ fn prepare_dummy_messages_delivery_proof( /// This function assumes that the chain that is followed by the `self_client` has /// bridge GRANDPA pallet deployed and it provides `best_finalized_header_id_method_name` /// runtime API to read the best finalized Bridged chain header. -pub async fn read_client_state( +/// +/// If `peer_client` is `None`, the value of `actual_best_finalized_peer_at_best_self` will +/// always match the `best_finalized_peer_at_best_self`. +pub async fn read_client_state( self_client: &Client, + peer_client: Option<&Client>, best_finalized_header_id_method_name: &str, -) -> Result< - ClientState, HeaderId>, - SubstrateError, -> +) -> Result, HeaderIdOf>, SubstrateError> where SelfChain: Chain, SelfChain::Header: DeserializeOwned, SelfChain::Index: DeserializeOwned, - BridgedHeaderHash: Decode, - BridgedHeaderNumber: Decode, + PeerChain: Chain, { // let's read our state first: we need best finalized header hash on **this** chain let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; @@ -346,16 +431,27 @@ where Some(self_best_hash), ) .await?; - let decoded_best_finalized_peer_on_self: (BridgedHeaderNumber, BridgedHeaderHash) = + let decoded_best_finalized_peer_on_self: (BlockNumberOf, HashOf) = Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) .map_err(SubstrateError::ResponseParseFailed)?; let peer_on_self_best_finalized_id = HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); + // read actual header, matching the `peer_on_self_best_finalized_id` from the peer chain + let actual_peer_on_self_best_finalized_id = match peer_client { + Some(peer_client) => { + let actual_peer_on_self_best_finalized = + peer_client.header_by_number(peer_on_self_best_finalized_id.0).await?; + HeaderId(peer_on_self_best_finalized_id.0, actual_peer_on_self_best_finalized.hash()) + }, + None => peer_on_self_best_finalized_id, + }; + Ok(ClientState { best_self: self_best_id, best_finalized_self: self_best_finalized_id, best_finalized_peer_at_best_self: peer_on_self_best_finalized_id, + actual_best_finalized_peer_at_best_self: actual_peer_on_self_best_finalized_id, }) } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index eafc6bd3fc5f..869a1d280282 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -19,18 +19,22 @@ //! chain. use crate::{ - messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}, - messages_source::{read_client_state, SubstrateMessagesProof}, + messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, + messages_metrics::StandaloneMessagesMetrics, + messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; - +use bp_messages::{ + storage_keys::inbound_lane_data_key, total_unrewarded_messages, InboundLaneData, LaneId, + MessageNonce, UnrewardedRelayersState, +}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; -use codec::{Decode, Encode}; +use codec::Encode; use frame_support::weights::{Weight, WeightToFeePolynomial}; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, @@ -38,23 +42,26 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, - WeightToFeeOf, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, }; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU128}; -use std::{convert::TryFrom, ops::RangeInclusive}; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; +use std::{collections::VecDeque, convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = +pub type SubstrateMessagesDeliveryProof = (UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof>); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { - client: Client, - lane: P, + target_client: Client, + source_client: Client, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, } @@ -62,28 +69,55 @@ pub struct SubstrateMessagesTarget { impl SubstrateMessagesTarget

{ /// Create new Substrate headers target. pub fn new( - client: Client, - lane: P, + target_client: Client, + source_client: Client, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { - client, - lane, + target_client, + source_client, lane_id, + relayer_id_at_source, + transaction_params, metric_values, source_to_target_headers_relay, } } + + /// Read inbound lane state from the on-chain storage at given block. + async fn inbound_lane_data( + &self, + id: TargetHeaderIdOf>, + ) -> Result>>, SubstrateError> { + self.target_client + .storage_value( + inbound_lane_data_key( + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), + Some(id.1), + ) + .await + } + + /// Ensure that the messages pallet at target chain is active. + async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { + ensure_messages_pallet_active::(&self.target_client).await + } } impl Clone for SubstrateMessagesTarget

{ fn clone(&self) -> Self { Self { - client: self.client.clone(), - lane: self.lane.clone(), + target_client: self.target_client.clone(), + source_client: self.source_client.clone(), lane_id: self.lane_id, + relayer_id_at_source: self.relayer_id_at_source.clone(), + transaction_params: self.transaction_params.clone(), metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), } @@ -95,115 +129,98 @@ impl RelayClient for SubstrateMessagesTarget

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await + self.target_client.reconnect().await?; + self.source_client.reconnect().await } } #[async_trait] -impl

TargetClient for SubstrateMessagesTarget

+impl TargetClient> for SubstrateMessagesTarget

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: TryFrom> + Bounded, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: Copy, - HeaderOf: DeserializeOwned, - BlockNumberOf: BlockNumberBase, - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::SourceHeaderNumber: Decode, - ::SourceHeaderHash: Decode, + AccountIdOf: + From< as Pair>::Public>, + P::TargetTransactionSignScheme: TransactionSignScheme, + BalanceOf: TryFrom>, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver - self.client.ensure_synced().await?; - - read_client_state::< - _, - ::SourceHeaderHash, - ::SourceHeaderNumber, - >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) + self.target_client.ensure_synced().await?; + // we can't relay messages if messages pallet at target chain is halted + self.ensure_pallet_active().await?; + + read_client_state( + &self.target_client, + Some(&self.source_client), + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await } async fn latest_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { + // lane data missing from the storage is fine until first message is received + let latest_received_nonce = self + .inbound_lane_data(id) + .await? + .map(|data| data.last_delivered_nonce()) + .unwrap_or(0); Ok((id, latest_received_nonce)) } async fn latest_confirmed_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - Ok((id, latest_received_nonce)) + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { + // lane data missing from the storage is fine until first message is received + let last_confirmed_nonce = self + .inbound_lane_data(id) + .await? + .map(|data| data.last_confirmed_nonce) + .unwrap_or(0); + Ok((id, last_confirmed_nonce)) } async fn unrewarded_relayers_state( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::INBOUND_LANE_UNREWARDED_RELAYERS_STATE.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let unrewarded_relayers_state: UnrewardedRelayersState = - Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> + { + let relayers = self + .inbound_lane_data(id) + .await? + .map(|data| data.relayers) + .unwrap_or_else(|| VecDeque::new()); + let unrewarded_relayers_state = 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), + }; Ok((id, unrewarded_relayers_state)) } async fn prove_messages_receiving( &self, - id: TargetHeaderIdOf, + id: TargetHeaderIdOf>, ) -> Result< - (TargetHeaderIdOf, ::MessagesReceivingProof), + ( + TargetHeaderIdOf>, + as MessageLane>::MessagesReceivingProof, + ), SubstrateError, > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; - let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key( - P::MESSAGE_PALLET_NAME_AT_TARGET, + let inbound_data_key = bp_messages::storage_keys::inbound_lane_data_key( + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, ); let proof = self - .client + .target_client .prove_storage(vec![inbound_data_key], id.1) .await? .iter_nodes() @@ -218,22 +235,31 @@ where async fn submit_messages_proof( &self, - generated_at_header: SourceHeaderIdOf, + _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, - proof: ::MessagesProof, + proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let lane = self.lane.clone(); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); - self.client + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; + self.target_client .submit_signed_extrinsic( - self.lane.target_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_delivery_transaction( + make_messages_delivery_transaction::

( + spec_version, + transaction_version, + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_header, + relayer_id_at_source, nonces_clone, proof, + true, ) }, ) @@ -241,7 +267,7 @@ where Ok(nonces) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { source_to_target_headers_relay.require_finalized_header(id).await; } @@ -253,7 +279,7 @@ where total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, - ) -> Result<::SourceChainBalance, SubstrateError> { + ) -> Result< as MessageLane>::SourceChainBalance, SubstrateError> { let conversion_rate = self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { SubstrateError::Custom(format!( @@ -263,19 +289,26 @@ where )) })?; + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = self.lane.make_messages_delivery_transaction( + let delivery_tx = make_messages_delivery_transaction::

( + spec_version, + transaction_version, + self.target_client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), + self.relayer_id_at_source.clone(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), total_dispatch_weight, total_size, ), - ); - let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; + false, + )?; + let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch @@ -297,23 +330,29 @@ where let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { const WEIGHT_DIFFERENCE: Weight = 100; + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let larger_delivery_tx_fee = self - .client - .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( - HeaderId(Default::default(), Default::default()), - Zero::zero(), - HeaderId(Default::default(), Default::default()), + let dummy_tx = make_messages_delivery_transaction::

( + spec_version, + transaction_version, + self.target_client.genesis_hash(), + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + self.relayer_id_at_source.clone(), + nonces.clone(), + prepare_dummy_messages_proof::( nonces.clone(), - prepare_dummy_messages_proof::( - nonces.clone(), - larger_dispatch_weight, - total_size, - ), - )) - .await?; + larger_dispatch_weight, + total_size, + ), + false, + )?; + let larger_delivery_tx_fee = + self.target_client.estimate_extrinsic_fee(dummy_tx).await?; - compute_prepaid_messages_refund::

( + compute_prepaid_messages_refund::( total_prepaid_nonces, compute_fee_multiplier::( delivery_tx_fee.adjusted_weight_fee, @@ -359,6 +398,45 @@ where } } +/// Make messages delivery transaction from given proof. +#[allow(clippy::too_many_arguments)] +fn make_messages_delivery_transaction( + spec_version: u32, + transaction_version: u32, + target_genesis_hash: &HashOf, + target_transaction_params: &TransactionParams>, + target_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + relayer_id_at_source: AccountIdOf, + nonces: RangeInclusive, + proof: SubstrateMessagesProof, + trace_call: bool, +) -> Result +where + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let messages_count = nonces.end() - nonces.start() + 1; + let dispatch_weight = proof.0; + let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( + relayer_id_at_source, + proof, + messages_count as _, + dispatch_weight, + trace_call, + ); + Ok(Bytes( + P::TargetTransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *target_genesis_hash, + signer: target_transaction_params.signer.clone(), + era: TransactionEra::new(target_best_block_id, target_transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? + .encode(), + )) +} + /// Prepare 'dummy' messages proof that will compose the delivery transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't @@ -425,80 +503,20 @@ fn compute_fee_multiplier( /// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` /// messages has been paid at the source chain. -fn compute_prepaid_messages_refund( +fn compute_prepaid_messages_refund( total_prepaid_nonces: MessageNonce, fee_multiplier: FixedU128, -) -> BalanceOf { - fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( - &P::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN.saturating_mul(total_prepaid_nonces), +) -> BalanceOf { + fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( + &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces), )) } #[cfg(test)] mod tests { use super::*; - use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; - use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; - - #[derive(Clone)] - struct TestSubstrateMessageLane; - - impl SubstrateMessageLane for TestSubstrateMessageLane { - type MessageLane = crate::messages_lane::SubstrateMessageLaneToSubstrate< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - >; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = ""; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = ""; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = ""; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = ""; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = ""; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = 100_000; - - type SourceChain = Rococo; - type TargetChain = Wococo; - - fn source_transactions_author(&self) -> bp_rococo::AccountId { - unreachable!() - } - - fn make_messages_receiving_proof_transaction( - &self, - _best_block_id: SourceHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_block: TargetHeaderIdOf, - _proof: ::MessagesReceivingProof, - ) -> Bytes { - unreachable!() - } - - fn target_transactions_author(&self) -> bp_wococo::AccountId { - unreachable!() - } - - fn make_messages_delivery_transaction( - &self, - _best_block_id: TargetHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_header: SourceHeaderIdOf, - _nonces: RangeInclusive, - _proof: ::MessagesProof, - ) -> Bytes { - unreachable!() - } - } + use relay_rococo_client::Rococo; + use relay_wococo_client::Wococo; #[test] fn prepare_dummy_messages_proof_works() { @@ -556,11 +574,10 @@ mod tests { #[test] fn compute_prepaid_messages_refund_returns_sane_results() { assert!( - compute_prepaid_messages_refund::( + compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN) - .into() + ) > (10 * Wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() ); } } diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index ee141866eb97..c1401a28a6dd 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -16,31 +16,24 @@ //! On-demand Substrate -> Substrate headers relay. -use std::fmt::Debug; - use async_std::sync::{Arc, Mutex}; use futures::{select, FutureExt}; -use num_traits::{CheckedSub, One, Zero}; +use num_traits::{One, Zero}; -use finality_relay::{ - FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader, - TargetClient as FinalityTargetClient, -}; +use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient}; use relay_substrate_client::{ - finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, - Chain, Client, HeaderIdOf, SyncHeader, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderIdOf, HeaderOf, SyncHeader, + TransactionSignScheme, }; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, - MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, }; use crate::{ - finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, - }, + finality_pipeline::{SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT}, + finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, finality_target::SubstrateFinalityTarget, - STALL_TIMEOUT, + TransactionParams, STALL_TIMEOUT, }; /// On-demand Substrate <-> Substrate headers relay. @@ -58,41 +51,27 @@ pub struct OnDemandHeadersRelay { impl OnDemandHeadersRelay { /// Create new on-demand headers relay. - pub fn new( - source_client: Client, - target_client: Client, - target_transactions_mortality: Option, - pipeline: P, - maximal_headers_difference: SourceChain::BlockNumber, + pub fn new>( + source_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, only_mandatory_headers: bool, ) -> Self where - SourceChain: Chain + Debug, - SourceChain::BlockNumber: BlockNumberBase, - TargetChain: Chain + Debug, - TargetChain::BlockNumber: BlockNumberBase, - TargetSign: Clone + Send + Sync + 'static, - P: SubstrateFinalitySyncPipeline< - FinalitySyncPipeline = SubstrateFinalityToSubstrate< - SourceChain, - TargetChain, - TargetSign, - >, - TargetChain = TargetChain, - >, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { let required_header_number = Arc::new(Mutex::new(Zero::zero())); let this = OnDemandHeadersRelay { - relay_task_name: on_demand_headers_relay_name::(), + relay_task_name: on_demand_headers_relay_name::(), required_header_number: required_header_number.clone(), }; async_std::task::spawn(async move { - background_task( + background_task::

( source_client, target_client, - target_transactions_mortality, - pipeline, - maximal_headers_difference, + target_transaction_params, only_mandatory_headers, required_header_number, ) @@ -120,35 +99,25 @@ impl OnDemandHeadersRelay { } /// Background task that is responsible for starting headers relay. -async fn background_task( - source_client: Client, - target_client: Client, - target_transactions_mortality: Option, - pipeline: P, - maximal_headers_difference: SourceChain::BlockNumber, +async fn background_task( + source_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, only_mandatory_headers: bool, - required_header_number: RequiredHeaderNumberRef, + required_header_number: RequiredHeaderNumberRef, ) where - SourceChain: Chain + Debug, - SourceChain::BlockNumber: BlockNumberBase, - TargetChain: Chain + Debug, - TargetChain::BlockNumber: BlockNumberBase, - TargetSign: Clone + Send + Sync + 'static, - P: SubstrateFinalitySyncPipeline< - FinalitySyncPipeline = SubstrateFinalityToSubstrate, - TargetChain = TargetChain, - >, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { - let relay_task_name = on_demand_headers_relay_name::(); - let mut finality_source = SubstrateFinalitySource::< - _, - SubstrateFinalityToSubstrate, - >::new(source_client.clone(), Some(required_header_number.clone())); - let mut finality_target = SubstrateFinalityTarget::new( - target_client.clone(), - pipeline.clone(), - target_transactions_mortality, + let relay_task_name = on_demand_headers_relay_name::(); + let target_transactions_mortality = target_transaction_params.mortality; + let mut finality_source = SubstrateFinalitySource::

::new( + source_client.clone(), + Some(required_header_number.clone()), ); + let mut finality_target = + SubstrateFinalityTarget::new(target_client.clone(), target_transaction_params); let mut latest_non_mandatory_at_source = Zero::zero(); let mut restart_relay = true; @@ -157,7 +126,7 @@ async fn background_task( loop { select! { - _ = async_std::task::sleep(TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, + _ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, _ = finality_relay_task => { // this should never happen in practice given the current code restart_relay = true; @@ -179,12 +148,8 @@ async fn background_task( } // read best finalized source header number from target - let best_finalized_source_header_at_target = best_finalized_source_header_at_target::< - SourceChain, - _, - _, - >(&finality_target, &relay_task_name) - .await; + let best_finalized_source_header_at_target = + best_finalized_source_header_at_target::

(&finality_target, &relay_task_name).await; if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Target, @@ -197,15 +162,28 @@ async fn background_task( } // submit mandatory header if some headers are missing + let best_finalized_source_header_at_source_fmt = + format!("{:?}", best_finalized_source_header_at_source); let best_finalized_source_header_at_target_fmt = format!("{:?}", best_finalized_source_header_at_target); - let mandatory_scan_range = mandatory_headers_scan_range::( + let required_header_number_value = *required_header_number.lock().await; + let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), - maximal_headers_difference, - &required_header_number, + required_header_number_value, ) .await; + + log::trace!( + target: "bridge", + "Mandatory headers scan range in {}: ({:?}, {:?}, {:?}) -> {:?}", + relay_task_name, + required_header_number_value, + best_finalized_source_header_at_source_fmt, + best_finalized_source_header_at_target_fmt, + mandatory_scan_range, + ); + if let Some(mandatory_scan_range) = mandatory_scan_range { let relay_mandatory_header_result = relay_mandatory_header_from_range( &finality_source, @@ -224,8 +202,25 @@ async fn background_task( // there are no (or we don't need to relay them) mandatory headers in the range // => to avoid scanning the same headers over and over again, remember that latest_non_mandatory_at_source = mandatory_scan_range.1; + + log::trace!( + target: "bridge", + "No mandatory {} headers in the range {:?} of {} relay", + P::SourceChain::NAME, + mandatory_scan_range, + relay_task_name, + ); }, - Err(e) => + Err(e) => { + log::warn!( + target: "bridge", + "Failed to scan mandatory {} headers range in {} relay (range: {:?}): {:?}", + P::SourceChain::NAME, + relay_task_name, + mandatory_scan_range, + e, + ); + if e.is_connection_error() { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Source, @@ -235,23 +230,43 @@ async fn background_task( ) .await; continue - }, + } + }, } } // start/restart relay if restart_relay { + let stall_timeout = relay_substrate_client::transaction_stall_timeout( + target_transactions_mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + + log::info!( + target: "bridge", + "Starting {} relay\n\t\ + Only mandatory headers: {}\n\t\ + Tx mortality: {:?} (~{}m)\n\t\ + Stall timeout: {:?}", + relay_task_name, + only_mandatory_headers, + target_transactions_mortality, + stall_timeout.as_secs_f64() / 60.0f64, + stall_timeout, + ); + finality_relay_task.set( finality_relay::run( finality_source.clone(), finality_target.clone(), FinalitySyncParams { tick: std::cmp::max( - SourceChain::AVERAGE_BLOCK_INTERVAL, - TargetChain::AVERAGE_BLOCK_INTERVAL, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: STALL_TIMEOUT, + stall_timeout, only_mandatory_headers, }, MetricsParams::disabled(), @@ -270,11 +285,8 @@ async fn background_task( async fn mandatory_headers_scan_range( best_finalized_source_header_at_source: Option, best_finalized_source_header_at_target: Option, - maximal_headers_difference: C::BlockNumber, - required_header_number: &RequiredHeaderNumberRef, + required_header_number: BlockNumberOf, ) -> Option<(C::BlockNumber, C::BlockNumber)> { - let required_header_number = *required_header_number.lock().await; - // if we have been unable to read header number from the target, then let's assume // that it is the same as required header number. Otherwise we risk submitting // unneeded transactions @@ -286,23 +298,8 @@ async fn mandatory_headers_scan_range( let best_finalized_source_header_at_source = best_finalized_source_header_at_source.unwrap_or(best_finalized_source_header_at_target); - // if there are too many source headers missing from the target node, sync mandatory - // headers to target - // - // why do we need that? When complex headers+messages relay is used, it'll normally only relay - // headers when there are undelivered messages/confirmations. But security model of the - // `pallet-bridge-grandpa` module relies on the fact that headers are synced in real-time and - // that it'll see authorities-change header before unbonding period will end for previous - // authorities set. - let current_headers_difference = best_finalized_source_header_at_source - .checked_sub(&best_finalized_source_header_at_target) - .unwrap_or_else(Zero::zero); - if current_headers_difference <= maximal_headers_difference { - return None - } - - // if relay is already asked to sync headers, don't do anything yet - if required_header_number > best_finalized_source_header_at_target { + // if relay is already asked to sync more headers than we have at source, don't do anything yet + if required_header_number >= best_finalized_source_header_at_source { return None } @@ -316,17 +313,13 @@ async fn mandatory_headers_scan_range( /// it. /// /// Returns `true` if header was found and (asked to be) relayed and `false` otherwise. -async fn relay_mandatory_header_from_range( - finality_source: &SubstrateFinalitySource, - required_header_number: &RequiredHeaderNumberRef, +async fn relay_mandatory_header_from_range( + finality_source: &SubstrateFinalitySource

, + required_header_number: &RequiredHeaderNumberRef, best_finalized_source_header_at_target: String, - range: (SourceChain::BlockNumber, SourceChain::BlockNumber), + range: (BlockNumberOf, BlockNumberOf), relay_task_name: &str, -) -> Result -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +) -> Result { // search for mandatory header first let mandatory_source_header_number = find_mandatory_header_in_range(finality_source, range).await?; @@ -347,7 +340,7 @@ where log::trace!( target: "bridge", "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}", - SourceChain::NAME, + P::SourceChain::NAME, relay_task_name, best_finalized_source_header_at_target, range.1, @@ -361,14 +354,10 @@ where /// Read best finalized source block number from source client. /// /// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_source( - finality_source: &SubstrateFinalitySource, +async fn best_finalized_source_header_at_source( + finality_source: &SubstrateFinalitySource

, relay_task_name: &str, -) -> Result -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +) -> Result, relay_substrate_client::Error> { finality_source.on_chain_best_finalized_block_number().await.map_err(|error| { log::error!( target: "bridge", @@ -384,41 +373,41 @@ where /// Read best finalized source block number from target client. /// /// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_target( - finality_target: &SubstrateFinalityTarget, +async fn best_finalized_source_header_at_target( + finality_target: &SubstrateFinalityTarget

, relay_task_name: &str, -) -> Result as RelayClient>::Error> +) -> Result, as RelayClient>::Error> where - SubstrateFinalityTarget: FinalityTargetClient, - P: SubstrateFinalitySyncPipeline, - P::FinalitySyncPipeline: FinalitySyncPipeline, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { - finality_target.best_finalized_source_block_number().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from target in {} relay: {:?}", - relay_task_name, - error, - ); + finality_target + .best_finalized_source_block_id() + .await + .map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from target in {} relay: {:?}", + relay_task_name, + error, + ); - error - }) + error + }) + .map(|id| id.0) } /// Read first mandatory header in given inclusive range. /// /// Returns `Ok(None)` if there were no mandatory headers in the range. -async fn find_mandatory_header_in_range( - finality_source: &SubstrateFinalitySource, - range: (SourceChain::BlockNumber, SourceChain::BlockNumber), -) -> Result, relay_substrate_client::Error> -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +async fn find_mandatory_header_in_range( + finality_source: &SubstrateFinalitySource

, + range: (BlockNumberOf, BlockNumberOf), +) -> Result>, relay_substrate_client::Error> { let mut current = range.0; while current <= range.1 { - let header: SyncHeader = + let header: SyncHeader> = finality_source.client().header_by_number(current).await?.into(); if header.is_mandatory() { return Ok(Some(current)) @@ -445,29 +434,18 @@ mod tests { const AT_TARGET: Option = Some(1); #[async_std::test] - async fn mandatory_headers_scan_range_selects_range_if_too_many_headers_are_missing() { + async fn mandatory_headers_scan_range_selects_range_if_some_headers_are_missing() { assert_eq!( - mandatory_headers_scan_range::( - AT_SOURCE, - AT_TARGET, - 5, - &Arc::new(Mutex::new(0)) - ) - .await, + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 0,).await, Some((AT_TARGET.unwrap() + 1, AT_SOURCE.unwrap())), ); } #[async_std::test] - async fn mandatory_headers_scan_range_selects_nothing_if_enough_headers_are_relayed() { + async fn mandatory_headers_scan_range_selects_nothing_if_already_queued() { assert_eq!( - mandatory_headers_scan_range::( - AT_SOURCE, - AT_TARGET, - 10, - &Arc::new(Mutex::new(0)) - ) - .await, + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, AT_SOURCE.unwrap(),) + .await, None, ); } diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index b11f00b957a4..b3357994b125 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -2,7 +2,7 @@ name = "messages-relay" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -18,6 +18,7 @@ parking_lot = "0.11.0" 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 = "master" } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 6cdb2b1aa5ae..c1778d5d11e8 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -233,6 +233,9 @@ pub struct ClientState { /// 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. @@ -843,12 +846,14 @@ pub(crate) mod tests { 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() @@ -888,12 +893,14 @@ pub(crate) mod tests { 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() diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index eac2f703692a..4decb7e092e7 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -22,6 +22,7 @@ use crate::{ }; use bp_messages::MessageNonce; +use finality_relay::SyncLoopMetrics; use relay_utils::metrics::{ metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, }; @@ -31,8 +32,10 @@ use relay_utils::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". - best_block_numbers: GaugeVec, + 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, @@ -42,12 +45,15 @@ impl MessageLaneLoopMetrics { /// Create and register messages loop metrics. pub fn new(prefix: Option<&str>) -> Result { Ok(MessageLaneLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best finalized block numbers", - ), - &["type"], + 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"), @@ -58,22 +64,28 @@ impl MessageLaneLoopMetrics { /// Update source client state metrics. pub fn update_source_state(&self, source_client_state: SourceClientState

) { - self.best_block_numbers - .with_label_values(&["source"]) - .set(source_client_state.best_self.0.into()); - self.best_block_numbers - .with_label_values(&["target_at_source"]) - .set(source_client_state.best_finalized_peer_at_best_self.0.into()); + 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.best_block_numbers - .with_label_values(&["target"]) - .set(target_client_state.best_self.0.into()); - self.best_block_numbers - .with_label_values(&["source_at_target"]) - .set(target_client_state.best_finalized_peer_at_best_self.0.into()); + 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. @@ -119,7 +131,8 @@ impl MessageLaneLoopMetrics { impl Metric for MessageLaneLoopMetrics { fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.best_block_numbers.clone(), registry)?; + 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/utils/Cargo.toml b/relays/utils/Cargo.toml index a08c3b3d688d..bb69849da26b 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-utils" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -19,7 +19,8 @@ log = "0.4.11" num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" -time = "0.2" +time = { version = "0.3", features = ["formatting", "local-offset", "std"] } +tokio = { version = "1.8", features = ["rt"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index 8c13a4d61cb3..ad69a766e623 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -29,15 +29,21 @@ pub fn initialize_relay() { /// 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::try_now_local() - .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) - .format("%Y-%m-%d %H:%M:%S %z"); + 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()); diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 805fe70bfe85..084f72e7950c 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -18,7 +18,7 @@ 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, U64, + register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, I64, U64, }; use async_std::sync::{Arc, RwLock}; @@ -30,6 +30,8 @@ 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)] diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index a992aaaf57ee..521a6345d3e3 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -187,12 +187,32 @@ impl LoopMetrics { let registry = self.registry; async_std::task::spawn(async move { - let result = init_prometheus(socket_addr, registry).await; - log::trace!( - target: "bridge-metrics", - "Prometheus endpoint has exited with result: {:?}", - result, - ); + 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, + ); + }); }); } diff --git a/scripts/dump-logs.sh b/scripts/dump-logs.sh old mode 100644 new mode 100755 index 02aa4af2f756..e5a3a403adac --- a/scripts/dump-logs.sh +++ b/scripts/dump-logs.sh @@ -28,7 +28,7 @@ SERVICES=(\ for SVC in ${SERVICES[*]} do SHORT_NAME="${SVC//deployments_/}" - docker logs $SVC &> $SHORT_NAME.log + docker logs $SVC &> $SHORT_NAME.log | true done cd - diff --git a/scripts/update-weights.sh b/scripts/update-weights.sh index 5ee7bb9e8d8e..b772386e7593 100755 --- a/scripts/update-weights.sh +++ b/scripts/update-weights.sh @@ -6,7 +6,7 @@ set -eux -time cargo run --release -p rialto-bridge-node --features=runtime-benchmarks -- benchmark \ +time cargo run --release -p millau-bridge-node --features=runtime-benchmarks -- benchmark \ --chain=dev \ --steps=50 \ --repeat=20 \ @@ -16,9 +16,9 @@ time cargo run --release -p rialto-bridge-node --features=runtime-benchmarks -- --wasm-execution=Compiled \ --heap-pages=4096 \ --output=./modules/messages/src/weights.rs \ - --template=./.maintain/rialto-weight-template.hbs + --template=./.maintain/millau-weight-template.hbs -time cargo run --release -p rialto-bridge-node --features=runtime-benchmarks -- benchmark \ +time cargo run --release -p millau-bridge-node --features=runtime-benchmarks -- benchmark \ --chain=dev \ --steps=50 \ --repeat=20 \ @@ -28,7 +28,7 @@ time cargo run --release -p rialto-bridge-node --features=runtime-benchmarks -- --wasm-execution=Compiled \ --heap-pages=4096 \ --output=./modules/grandpa/src/weights.rs \ - --template=./.maintain/rialto-weight-template.hbs + --template=./.maintain/millau-weight-template.hbs time cargo run --release -p millau-bridge-node --features=runtime-benchmarks -- benchmark \ --chain=dev \