diff --git a/bridges/modules/dispatch/src/lib.rs b/bridges/modules/dispatch/src/lib.rs index 76706d4d1e..416d080b0c 100644 --- a/bridges/modules/dispatch/src/lib.rs +++ b/bridges/modules/dispatch/src/lib.rs @@ -45,6 +45,7 @@ use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; /// Spec version type. pub type SpecVersion = u32; +// TODO [#895] move to primitives /// Origin of a Call when it is dispatched on the target chain. /// /// The source chain can (and should) verify that the message can be dispatched on the target chain @@ -89,6 +90,7 @@ pub enum CallOrigin { diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index 98f47dd6f1..9fb7372b02 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -39,16 +39,13 @@ use crate::weights::WeightInfo; use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::InitializationData; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::ensure; use frame_system::{ensure_signed, RawOrigin}; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; -use sp_runtime::RuntimeDebug; #[cfg(test)] mod mock; @@ -511,22 +508,6 @@ impl, I: 'static> Pallet { } } -/// Data required for initializing the bridge pallet. -/// -/// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct InitializationData { - /// The header from which we should start syncing. - pub header: H, - /// The initial authorities of the pallet. - pub authority_list: sp_finality_grandpa::AuthorityList, - /// The ID of the initial authority set. - pub set_id: sp_finality_grandpa::SetId, - /// Should the pallet block transaction immediately after initialization. - pub is_halted: bool, -} - pub(crate) fn find_scheduled_change(header: &H) -> Option> { use sp_runtime::generic::OpaqueDigestItemId; diff --git a/bridges/primitives/chain-rococo/Cargo.toml b/bridges/primitives/chain-rococo/Cargo.toml index acdbfc6c51..b97e8d9d1a 100644 --- a/bridges/primitives/chain-rococo/Cargo.toml +++ b/bridges/primitives/chain-rococo/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # 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 } @@ -23,6 +24,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index 38dd92561b..cc3eb47b1b 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -41,9 +42,33 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 6, }; +/// Rococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - MockPallet, + /// Westend bridge pallet. + #[codec(index = 40)] + BridgeGrandpaWestend(BridgeGrandpaWestendCall), +} + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaWestendCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), } impl sp_runtime::traits::Dispatchable for Call { diff --git a/bridges/primitives/chain-westend/Cargo.toml b/bridges/primitives/chain-westend/Cargo.toml index c96e8703d8..d5fda1ccef 100644 --- a/bridges/primitives/chain-westend/Cargo.toml +++ b/bridges/primitives/chain-westend/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # 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 } @@ -23,6 +24,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/primitives/chain-westend/src/lib.rs index 3b52534afa..dbbfabd5dc 100644 --- a/bridges/primitives/chain-westend/src/lib.rs +++ b/bridges/primitives/chain-westend/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -42,9 +43,33 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 5, }; +/// Westend Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Westend chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Westend +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/westend/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - MockModule, + /// Rococo bridge pallet. + #[codec(index = 40)] + BridgeGrandpaRococo(BridgeGrandpaRococoCall), +} + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaRococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), } impl sp_runtime::traits::Dispatchable for Call { diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index d33a6d36eb..adac6eb268 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -55,6 +55,22 @@ impl AuthoritySet { } } +/// Data required for initializing the bridge pallet. +/// +/// The bridge needs to know where to start its sync from, and this provides that initial context. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct InitializationData { + /// The header from which we should start syncing. + pub header: H, + /// The initial authorities of the pallet. + pub authority_list: AuthorityList, + /// The ID of the initial authority set. + pub set_id: SetId, + /// Should the pallet block transaction immediately after initialization. + pub is_halted: bool, +} + /// base trait for verifying transaction inclusion proofs. pub trait InclusionProofVerifier { /// Transaction type. diff --git a/bridges/relays/bin-substrate/Cargo.toml b/bridges/relays/bin-substrate/Cargo.toml index 1a281a6d58..d203201e60 100644 --- a/bridges/relays/bin-substrate/Cargo.toml +++ b/bridges/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } +bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } @@ -35,12 +36,12 @@ headers-relay = { path = "../headers" } 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" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } relay-rialto-client = { path = "../client-rialto" } +relay-rococo-client = { path = "../client-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/bridges/relays/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs index a9923e71e9..cdd8ec3691 100644 --- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs @@ -15,9 +15,9 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use bp_header_chain::InitializationData; use bp_runtime::Chain as ChainBase; use codec::Encode; -use pallet_bridge_grandpa::InitializationData; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use structopt::{clap::arg_enum, StructOpt}; @@ -44,6 +44,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + WestendToRococo, + RococoToWestend, } } @@ -98,6 +100,30 @@ macro_rules! select_bridge { .into() } + $generic + } + InitBridgeName::WestendToRococo => { + type Source = relay_westend_client::Westend; + type Target = relay_rococo_client::Rococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::initialize(init_data)) + } + + $generic + } + InitBridgeName::RococoToWestend => { + type Source = relay_rococo_client::Rococo; + type Target = relay_westend_client::Westend; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::initialize(init_data)) + } + $generic } } diff --git a/bridges/relays/bin-substrate/src/cli/mod.rs b/bridges/relays/bin-substrate/src/cli/mod.rs index 8af3301231..505ef11ee2 100644 --- a/bridges/relays/bin-substrate/src/cli/mod.rs +++ b/bridges/relays/bin-substrate/src/cli/mod.rs @@ -373,6 +373,7 @@ macro_rules! declare_chain_options { /// Parse signing params into chain-specific KeyPair. pub fn to_keypair(&self) -> anyhow::Result { use sp_core::crypto::Pair; + Chain::KeyPair::from_string( &self.[<$chain_prefix _signer>], self.[<$chain_prefix _signer_password>].as_deref() diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers.rs b/bridges/relays/bin-substrate/src/cli/relay_headers.rs index a60bbe344d..8137f8a240 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers.rs @@ -42,6 +42,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + WestendToRococo, + RococoToWestend, } } @@ -67,6 +69,20 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau; + $generic + } + RelayHeadersBridge::WestendToRococo => { + type Source = relay_westend_client::Westend; + type Target = relay_rococo_client::Rococo; + type Finality = crate::rialto_millau::westend_headers_to_rococo::WestendFinalityToRococo; + + $generic + } + RelayHeadersBridge::RococoToWestend => { + type Source = relay_rococo_client::Rococo; + type Target = relay_westend_client::Westend; + type Finality = crate::rialto_millau::rococo_headers_to_westend::RococoFinalityToWestend; + $generic } } diff --git a/bridges/relays/bin-substrate/src/headers_initialize.rs b/bridges/relays/bin-substrate/src/headers_initialize.rs index 83db39bf7b..c2eab1bd35 100644 --- a/bridges/relays/bin-substrate/src/headers_initialize.rs +++ b/bridges/relays/bin-substrate/src/headers_initialize.rs @@ -21,6 +21,7 @@ //! and authorities set from source to target chain. The headers sync starts //! with this header. +use bp_header_chain::InitializationData; use bp_header_chain::{ find_grandpa_authorities_scheduled_change, justification::{verify_justification, GrandpaJustification}, @@ -28,7 +29,6 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use pallet_bridge_grandpa::InitializationData; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; diff --git a/bridges/relays/bin-substrate/src/rialto_millau/mod.rs b/bridges/relays/bin-substrate/src/rialto_millau/mod.rs index af17f62a05..cf86f781c0 100644 --- a/bridges/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/bridges/relays/bin-substrate/src/rialto_millau/mod.rs @@ -20,7 +20,9 @@ pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod rococo_headers_to_westend; pub mod westend_headers_to_millau; +pub mod westend_headers_to_rococo; use crate::cli::{ bridge, @@ -32,9 +34,44 @@ use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use relay_rialto_client::Rialto; +use relay_rococo_client::Rococo; +use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; use relay_westend_client::Westend; use sp_version::RuntimeVersion; +pub(crate) fn add_polkadot_kusama_price_metrics( + params: MetricsParams, +) -> anyhow::Result { + Ok( + relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama + // relays, but we want to test metrics/dashboards in advance + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), + "$.polkadot.usd".into(), + "polkadot_price".into(), + "Polkadot price in USD".into(), + ) + }) + .map_err(|e| anyhow::format_err!("{}", e))? + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), + "$.kusama.usd".into(), + "kusama_price".into(), + "Kusama price in USD".into(), + ) + }) + .map_err(|e| anyhow::format_err!("{}", e))? + .into_params(), + ) +} + impl CliEncodeCall for Millau { fn max_extrinsic_size() -> u32 { bp_millau::max_extrinsic_size() @@ -197,6 +234,25 @@ impl CliChain for Westend { } } +impl CliChain for Rococo { + const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + 0 + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Rococo is not yet supported.".into()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -373,3 +429,89 @@ mod tests { ); } } + +#[cfg(test)] +mod rococo_tests { + use bp_header_chain::justification::GrandpaJustification; + use codec::Encode; + + #[test] + fn scale_compatibility_of_bridges_call() { + // given + let header = sp_runtime::generic::Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: sp_runtime::generic::Digest { logs: vec![] }, + }; + let justification = GrandpaJustification { + round: 0, + commit: finality_grandpa::Commit { + target_hash: Default::default(), + target_number: Default::default(), + precommits: vec![], + }, + votes_ancestries: vec![], + }; + let actual = bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof(header.clone(), justification.clone()); + let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( + header, + justification, + ); + + // when + let actual_encoded = actual.encode(); + let expected_encoded = expected.encode(); + + // then + assert_eq!( + actual_encoded, expected_encoded, + "Encoding difference. Raw: {:?} vs {:?}", + actual, expected + ); + } +} + +#[cfg(test)] +mod westend_tests { + use bp_header_chain::justification::GrandpaJustification; + use codec::Encode; + + #[test] + fn scale_compatibility_of_bridges_call() { + // given + let header = sp_runtime::generic::Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: sp_runtime::generic::Digest { logs: vec![] }, + }; + let justification = GrandpaJustification { + round: 0, + commit: finality_grandpa::Commit { + target_hash: Default::default(), + target_number: Default::default(), + precommits: vec![], + }, + votes_ancestries: vec![], + }; + let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof(header.clone(), justification.clone()); + let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( + header, + justification, + ); + + // when + let actual_encoded = actual.encode(); + let expected_encoded = expected.encode(); + + // then + assert_eq!( + actual_encoded, expected_encoded, + "Encoding difference. Raw: {:?} vs {:?}", + actual, expected + ); + } +} diff --git a/bridges/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs b/bridges/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs new file mode 100644 index 0000000000..82905b4d89 --- /dev/null +++ b/bridges/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Rococo-to-Westend headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_westend_client::{SigningParams as WestendSigningParams, Westend}; +use sp_core::{Bytes, Pair}; + +/// Rococo-to-Westend finality sync pipeline. +pub(crate) type RococoFinalityToWestend = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for RococoFinalityToWestend { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type TargetChain = Westend; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_westend::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: RococoSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Westend::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index f8f023da19..798cc7c611 100644 --- a/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -22,7 +22,7 @@ use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_substrate_client::{Chain, TransactionSignScheme}; -use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; +use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use sp_core::{Bytes, Pair}; @@ -35,34 +35,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - Ok( - relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama - // relays, but we want to test metrics/dashboards in advance - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), - "$.polkadot.usd".into(), - "polkadot_price".into(), - "Polkadot price in USD".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), - "$.kusama.usd".into(), - "kusama_price".into(), - "Kusama price in USD".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .into_params(), - ) + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_millau::AccountId { diff --git a/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs b/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs new file mode 100644 index 0000000000..b57cc75781 --- /dev/null +++ b/bridges/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Westend-to-Rococo headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; +use sp_core::{Bytes, Pair}; + +/// Westend-to-Rococo finality sync pipeline. +pub(crate) type WestendFinalityToRococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; + + type TargetChain = Rococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: WestendSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/bridges/relays/client-rococo/src/lib.rs b/bridges/relays/client-rococo/src/lib.rs index ccf7a89163..1e2dd6569b 100644 --- a/bridges/relays/client-rococo/src/lib.rs +++ b/bridges/relays/client-rococo/src/lib.rs @@ -89,31 +89,4 @@ impl TransactionSignScheme for Rococo { } /// Rococo signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} +pub type SigningParams = sp_core::sr25519::Pair; diff --git a/bridges/relays/client-westend/src/lib.rs b/bridges/relays/client-westend/src/lib.rs index 0a6569512a..5ca4552bc2 100644 --- a/bridges/relays/client-westend/src/lib.rs +++ b/bridges/relays/client-westend/src/lib.rs @@ -89,31 +89,4 @@ impl TransactionSignScheme for Westend { } /// Westend signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} +pub type SigningParams = sp_core::sr25519::Pair;