diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index 268ee3cae150..66cbb475bda2 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 231, + spec_version: 232, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, @@ -55,14 +55,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// 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 { - /// Generic bridge pallet. - #[codec(index = 40)] - BridgeCall(BridgeGrandpaCall), + /// Wococo bridge pallet. + #[codec(index = 41)] + BridgeGrandpaWococo(BridgeGrandpaWococoCall), } #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] #[allow(non_camel_case_types)] -pub enum BridgeGrandpaCall { +pub enum BridgeGrandpaWococoCall { #[codec(index = 0)] submit_finality_proof( ::Header, diff --git a/bridges/primitives/chain-wococo/Cargo.toml b/bridges/primitives/chain-wococo/Cargo.toml new file mode 100644 index 000000000000..ecf783a51eeb --- /dev/null +++ b/bridges/primitives/chain-wococo/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "bp-wococo" +description = "Primitives of Wococo runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +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 } + +# Substrate Based Dependencies +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 } + +[features] +default = ["std"] +std = [ + "bp-header-chain/std", + "bp-messages/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "parity-scale-codec/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] diff --git a/bridges/primitives/chain-wococo/src/lib.rs b/bridges/primitives/chain-wococo/src/lib.rs new file mode 100644 index 000000000000..f7a472ddf31d --- /dev/null +++ b/bridges/primitives/chain-wococo/src/lib.rs @@ -0,0 +1,172 @@ +// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; +use sp_std::prelude::*; +use sp_version::RuntimeVersion; + +pub use bp_polkadot_core::*; + +/// Wococo Chain +pub type Wococo = PolkadotLike; + +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +// 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.5"), + authoring_version: 0, + spec_version: 232, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 0, +}; + +/// Wococo 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 { + /// 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 { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + +// We use this to get the account on Wococo (target) which is derived from Rococo's (source) +// account. +pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// 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. +pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToWococoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_WOCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWococoOutboundLaneApi_messages_dispatch_weight"; +/// 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. + /// + /// This API is implemented by runtimes that are bridging with the Wococo chain, not the + /// Wococo runtime itself. + pub trait WococoFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// 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. + /// + /// This API is implemented by runtimes that are sending messages to Wococo chain, not the + /// Wococo runtime itself. + pub trait ToWococoOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Wococo from this chain. + /// + /// Please keep in mind that this method returns 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 total dispatch weight and encoded payload size 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 messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// 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 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/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs index e7f990d28309..aa457f1d0b0b 100644 --- a/bridges/primitives/runtime/src/lib.rs +++ b/bridges/primitives/runtime/src/lib.rs @@ -50,8 +50,8 @@ pub const KUSAMA_BRIDGE_INSTANCE: InstanceId = *b"ksma"; /// Bridge-with-Rococo instance id. pub const ROCOCO_BRIDGE_INSTANCE: InstanceId = *b"roco"; -/// Bridge-with-Westend instance id. -pub const WESTEND_BRIDGE_INSTANCE: InstanceId = *b"wend"; +/// Bridge-with-Wococo instance id. +pub const WOCOCO_BRIDGE_INSTANCE: InstanceId = *b"woco"; /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; diff --git a/bridges/relays/bin-substrate/Cargo.toml b/bridges/relays/bin-substrate/Cargo.toml index d203201e60a4..f5711e0766d1 100644 --- a/bridges/relays/bin-substrate/Cargo.toml +++ b/bridges/relays/bin-substrate/Cargo.toml @@ -27,6 +27,7 @@ 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-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } @@ -42,6 +43,7 @@ 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-wococo-client = { path = "../client-wococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs index 2000c4c223da..20ddf4a92af1 100644 --- a/bridges/relays/bin-substrate/src/chains/mod.rs +++ b/bridges/relays/bin-substrate/src/chains/mod.rs @@ -20,12 +20,15 @@ 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_wococo; pub mod westend_headers_to_millau; +pub mod wococo_headers_to_rococo; mod millau; mod rialto; mod rococo; mod westend; +mod wococo; use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; @@ -268,7 +271,7 @@ mod rococo_tests { votes_ancestries: vec![], }; - let actual = bp_rococo::BridgeGrandpaCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, justification, diff --git a/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs new file mode 100644 index 000000000000..5247c6068b5e --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/rococo_headers_to_wococo.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-Wococo 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_wococo_client::{SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; + +/// Rococo-to-Wococo finality sync pipeline. +pub(crate) type RococoFinalityToWococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type TargetChain = Wococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_wococo::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_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/bridges/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs b/bridges/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs new file mode 100644 index 000000000000..f1b390215748 --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/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::chains::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::BridgeGrandpaCall::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/bin-substrate/src/chains/wococo.rs b/bridges/relays/bin-substrate/src/chains/wococo.rs new file mode 100644 index 000000000000..549aa8a882c7 --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/wococo.rs @@ -0,0 +1,39 @@ +// 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::cli::{encode_message, CliChain}; +use frame_support::weights::Weight; +use relay_wococo_client::Wococo; +use sp_version::RuntimeVersion; + +impl CliChain for Wococo { + const RUNTIME_VERSION: RuntimeVersion = bp_wococo::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 Wococo is not yet supported.".into()) + } +} diff --git a/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/bridges/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs new file mode 100644 index 000000000000..9dfae5294e29 --- /dev/null +++ b/bridges/relays/bin-substrate/src/chains/wococo_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 . + +//! Wococo-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_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; +use sp_core::{Bytes, Pair}; + +/// Wococo-to-Rococo finality sync pipeline. +pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + + type TargetChain = Rococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::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: WococoSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::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/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs index 73af141a36c5..b5590b9e5a44 100644 --- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs @@ -44,6 +44,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + RococoToWococo, + WococoToRococo, } } @@ -98,6 +100,30 @@ macro_rules! select_bridge { .into() } + $generic + } + InitBridgeName::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + type Target = relay_wococo_client::Wococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::initialize(init_data)) + } + + $generic + } + InitBridgeName::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + type Target = relay_rococo_client::Rococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::initialize(init_data)) + } + $generic } } diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers.rs b/bridges/relays/bin-substrate/src/cli/relay_headers.rs index 1385527d976e..e8459b58bf60 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, + RococoToWococo, + WococoToRococo, } } @@ -67,6 +69,20 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; + $generic + } + RelayHeadersBridge::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + type Target = relay_wococo_client::Wococo; + type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + + $generic + } + RelayHeadersBridge::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + type Target = relay_rococo_client::Rococo; + type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + $generic } } diff --git a/bridges/relays/client-wococo/Cargo.toml b/bridges/relays/client-wococo/Cargo.toml new file mode 100644 index 000000000000..22d710ca3d7b --- /dev/null +++ b/bridges/relays/client-wococo/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "relay-wococo-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + +# Bridge dependencies +bp-wococo = { path = "../../primitives/chain-wococo" } + +# Substrate Dependencies +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/client-wococo/src/lib.rs b/bridges/relays/client-wococo/src/lib.rs new file mode 100644 index 000000000000..be2f872b7d77 --- /dev/null +++ b/bridges/relays/client-wococo/src/lib.rs @@ -0,0 +1,97 @@ +// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see . + +//! Types used to connect to the Wococo-Substrate chain. + +use codec::Encode; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Wococo header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Wococo header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + +/// Wococo chain definition +#[derive(Debug, Clone, Copy)] +pub struct Wococo; + +impl ChainBase for Wococo { + type BlockNumber = bp_wococo::BlockNumber; + type Hash = bp_wococo::Hash; + type Hasher = bp_wococo::Hashing; + type Header = bp_wococo::Header; +} + +impl Chain for Wococo { + const NAME: &'static str = "Wococo"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_wococo::AccountId; + type Index = bp_wococo::Index; + type SignedBlock = bp_wococo::SignedBlock; + type Call = bp_wococo::Call; +} + +impl ChainWithBalances for Wococo { + type NativeBalance = bp_wococo::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_wococo::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Wococo { + type Chain = Wococo; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = bp_wococo::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + call, + bp_wococo::SignedExtensions::new( + bp_wococo::VERSION, + sp_runtime::generic::Era::Immortal, + genesis_hash, + signer_nonce, + 0, + ), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_wococo::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) + } +} + +/// Wococo signing params. +pub type SigningParams = sp_core::sr25519::Pair;