Make relay CLI generic (#849)

* Start generalizing rialto-millau commands.

* cargo fmt --all

* Introduce generic balance.

* Unify message payloads.

* cargo fmt --all

* init - generic

* Attempt to unify send message.

* Start moving things around.

* cargo fmt --all

* Move init-bridge.

* cargo fmt --all

* Improve UX of bridge argument.

* Fix clippy.

* Fix docs and scripts.

* Add docs.

* Apply suggestions from code review

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* Fix copyright.

* Add issue numbers.

* More todos.

* Update comments.

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
This commit is contained in:
Tomasz Drwięga
2021-04-01 12:49:49 +02:00
committed by Bastian Köcher
parent b6d034afaf
commit 904b9f4da5
22 changed files with 896 additions and 879 deletions
+12 -12
View File
@@ -158,20 +158,20 @@ Then we need to initialize and run the relayer:
```bash ```bash
docker run --network=host -it \ docker run --network=host -it \
paritytech/substrate-relay initialize-rialto-headers-bridge-in-millau \ paritytech/substrate-relay init-bridge RialtoToMillau \
--millau-host localhost \ --target-host localhost \
--millau-port 9945 \ --target-port 9945 \
--rialto-host localhost \ --source-host localhost \
--rialto-port 9944 \ --source-port 9944 \
--millau-signer //Alice --target-signer //Alice
docker run --network=host -it \ docker run --network=host -it \
paritytech/substrate-relay rialto-headers-to-millau \ paritytech/substrate-relay relay-headers RialtoToMillau \
--millau-host localhost \ --target-host localhost \
--millau-port 9945 \ --target-port 9945 \
--rialto-host localhost \ --source-host localhost \
--rialto-port 9944 \ --source-port 9944 \
--millau-signer //Bob \ --target-signer //Bob \
``` ```
You should now see the relayer submitting headers from the Millau chain to the Rialto chain. You should now see the relayer submitting headers from the Millau chain to the Rialto chain.
@@ -16,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false }
# Substrate Based Dependencies # Substrate Based Dependencies
sp-api = { 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-std = { 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] [features]
default = ["std"] default = ["std"]
@@ -25,4 +26,5 @@ std = [
"bp-runtime/std", "bp-runtime/std",
"sp-api/std", "sp-api/std",
"sp-std/std", "sp-std/std",
"sp-version/std",
] ]
@@ -22,12 +22,24 @@
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight};
use sp_std::prelude::*; use sp_std::prelude::*;
use sp_version::RuntimeVersion;
pub use bp_polkadot_core::*; pub use bp_polkadot_core::*;
/// Westend Chain /// Westend Chain
pub type Westend = PolkadotLike; pub type Westend = PolkadotLike;
/// Runtime version.
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: 50,
impl_version: 0,
apis: sp_version::create_apis_vec![[]],
transaction_version: 5,
};
// We use this to get the account on Westend (target) which is derived from Rococo's (source) // We use this to get the account on Westend (target) which is derived from Rococo's (source)
// account. // account.
pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId { pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -> AccountId {
@@ -56,7 +56,6 @@ pub enum ExchangeRelayMode {
} }
/// PoA exchange transaction relay params. /// PoA exchange transaction relay params.
#[derive(Debug)]
pub struct EthereumExchangeParams { pub struct EthereumExchangeParams {
/// Ethereum connection params. /// Ethereum connection params.
pub eth_params: EthereumConnectionParams, pub eth_params: EthereumConnectionParams,
@@ -72,6 +71,19 @@ pub struct EthereumExchangeParams {
pub instance: Arc<dyn BridgeInstance>, pub instance: Arc<dyn BridgeInstance>,
} }
impl std::fmt::Debug for EthereumExchangeParams {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("EthereumExchangeParams")
.field("eth_params", &self.eth_params)
.field("sub_params", &self.sub_params)
.field("sub_sign", &sp_core::Pair::public(&self.sub_sign))
.field("mode", &self.mode)
.field("metrics_params", &self.metrics_params)
.field("instance", &self.instance)
.finish()
}
}
/// Ethereum to Substrate exchange pipeline. /// Ethereum to Substrate exchange pipeline.
struct EthereumToSubstrateExchange; struct EthereumToSubstrateExchange;
@@ -62,7 +62,6 @@ pub mod consts {
} }
/// Ethereum synchronization parameters. /// Ethereum synchronization parameters.
#[derive(Debug)]
pub struct EthereumSyncParams { pub struct EthereumSyncParams {
/// Ethereum connection params. /// Ethereum connection params.
pub eth_params: EthereumConnectionParams, pub eth_params: EthereumConnectionParams,
@@ -78,6 +77,19 @@ pub struct EthereumSyncParams {
pub instance: Arc<dyn BridgeInstance>, pub instance: Arc<dyn BridgeInstance>,
} }
impl Debug for EthereumSyncParams {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("EthereumSyncParams")
.field("eth_params", &self.eth_params)
.field("sub_params", &self.sub_params)
.field("sub_sign", &sp_core::Pair::public(&self.sub_sign))
.field("sync_params", &self.sync_params)
.field("metrics_params", &self.metrics_params)
.field("instance", &self.instance)
.finish()
}
}
/// Ethereum synchronization pipeline. /// Ethereum synchronization pipeline.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
+3 -2
View File
@@ -167,10 +167,11 @@ fn substrate_connection_params(matches: &clap::ArgMatches) -> Result<SubstrateCo
} }
fn rialto_signing_params(matches: &clap::ArgMatches) -> Result<RialtoSigningParams, String> { fn rialto_signing_params(matches: &clap::ArgMatches) -> Result<RialtoSigningParams, String> {
let mut params = RialtoSigningParams::default(); let mut params = sp_keyring::AccountKeyring::Alice.pair();
if let Some(sub_signer) = matches.value_of("sub-signer") { if let Some(sub_signer) = matches.value_of("sub-signer") {
let sub_signer_password = matches.value_of("sub-signer-password"); let sub_signer_password = matches.value_of("sub-signer-password");
params.signer = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) params = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password)
.map_err(|e| format!("Failed to parse sub-signer: {:?}", e))?; .map_err(|e| format!("Failed to parse sub-signer: {:?}", e))?;
} }
Ok(params) Ok(params)
@@ -156,20 +156,17 @@ impl SubmitEthereumHeaders for SubstrateClient<Rialto> {
) -> SubmittedHeaders<EthereumHeaderId, RpcError> { ) -> SubmittedHeaders<EthereumHeaderId, RpcError> {
let ids = headers.iter().map(|header| header.id()).collect(); let ids = headers.iter().map(|header| header.id()).collect();
let submission_result = async { let submission_result = async {
self.submit_signed_extrinsic( self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| {
params.signer.public().as_array_ref().clone().into(),
|transaction_nonce| {
Bytes( Bytes(
Rialto::sign_transaction( Rialto::sign_transaction(
*self.genesis_hash(), *self.genesis_hash(),
&params.signer, &params,
transaction_nonce, transaction_nonce,
instance.build_signed_header_call(headers), instance.build_signed_header_call(headers),
) )
.encode(), .encode(),
) )
}, })
)
.await?; .await?;
Ok(()) Ok(())
} }
@@ -260,20 +257,17 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient<Rialto> {
instance: Arc<dyn BridgeInstance>, instance: Arc<dyn BridgeInstance>,
proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, proof: rialto_runtime::exchange::EthereumTransactionInclusionProof,
) -> RpcResult<()> { ) -> RpcResult<()> {
self.submit_signed_extrinsic( self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| {
params.signer.public().as_array_ref().clone().into(),
|transaction_nonce| {
Bytes( Bytes(
Rialto::sign_transaction( Rialto::sign_transaction(
*self.genesis_hash(), *self.genesis_hash(),
&params.signer, &params,
transaction_nonce, transaction_nonce,
instance.build_currency_exchange_call(proof), instance.build_currency_exchange_call(proof),
) )
.encode(), .encode(),
) )
}, })
)
.await?; .await?;
Ok(()) Ok(())
} }
+1
View File
@@ -52,6 +52,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-finality-grandpa = { 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" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies] [dev-dependencies]
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -0,0 +1,137 @@
// 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 <http://www.gnu.org/licenses/>.
use crate::cli::{CliChain, SourceConnectionParams, TargetConnectionParams, TargetSigningParams};
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};
/// Initialize bridge pallet.
#[derive(StructOpt)]
pub struct InitBridge {
/// A bridge instance to initalize.
#[structopt(possible_values = &InitBridgeName::variants(), case_insensitive = true)]
bridge: InitBridgeName,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
target: TargetConnectionParams,
#[structopt(flatten)]
target_sign: TargetSigningParams,
}
// TODO [#851] Use kebab-case.
arg_enum! {
#[derive(Debug)]
/// Bridge to initialize.
pub enum InitBridgeName {
MillauToRialto,
RialtoToMillau,
WestendToMillau,
}
}
macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
match $bridge {
InitBridgeName::MillauToRialto => {
type Source = relay_millau_client::Millau;
type Target = relay_rialto_client::Rialto;
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
rialto_runtime::SudoCall::sudo(Box::new(
rialto_runtime::BridgeGrandpaMillauCall::initialize(init_data).into(),
))
.into()
}
$generic
}
InitBridgeName::RialtoToMillau => {
type Source = relay_rialto_client::Rialto;
type Target = relay_millau_client::Millau;
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::<
millau_runtime::Runtime,
millau_runtime::RialtoGrandpaInstance,
>::initialize(init_data);
millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into()
}
$generic
}
InitBridgeName::WestendToMillau => {
type Source = relay_westend_client::Westend;
type Target = relay_millau_client::Millau;
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
// at Westend -> Millau initialization we're not using sudo, because otherwise our deployments
// may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge.
// => since there's single possible sudo account, one of transaction may fail with duplicate nonce error
millau_runtime::BridgeGrandpaWestendCall::<
millau_runtime::Runtime,
millau_runtime::WestendGrandpaInstance,
>::initialize(init_data)
.into()
}
$generic
}
}
};
}
impl InitBridge {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
select_bridge!(self.bridge, {
let source_client = crate::rialto_millau::source_chain_client::<Source>(self.source).await?;
let target_client = crate::rialto_millau::target_chain_client::<Target>(self.target).await?;
let target_sign =
Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?;
crate::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,
transaction_nonce,
encode_init_bridge(initialization_data),
)
.encode(),
)
},
)
.await;
Ok(())
})
}
}
@@ -1,4 +1,4 @@
// Copyright 2019-2020 Parity Technologies (UK) Ltd. // Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common. // This file is part of Parity Bridges Common.
// Parity Bridges Common is free software: you can redistribute it and/or modify // Parity Bridges Common is free software: you can redistribute it and/or modify
@@ -18,12 +18,15 @@
use std::convert::TryInto; use std::convert::TryInto;
use crate::rialto_millau::cli as rialto_millau;
use bp_messages::LaneId; use bp_messages::LaneId;
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::weights::Weight;
use sp_runtime::app_crypto::Ss58Codec; use sp_runtime::app_crypto::Ss58Codec;
use structopt::{clap::arg_enum, StructOpt}; use structopt::{clap::arg_enum, StructOpt};
use crate::rialto_millau::cli as rialto_millau; mod init_bridge;
mod relay_headers;
/// Parse relay CLI args. /// Parse relay CLI args.
pub fn parse_args() -> Command { pub fn parse_args() -> Command {
@@ -38,7 +41,7 @@ pub enum Command {
/// ///
/// The on-chain bridge component should have been already initialized with /// The on-chain bridge component should have been already initialized with
/// `init-bridge` sub-command. /// `init-bridge` sub-command.
RelayHeaders(RelayHeaders), RelayHeaders(relay_headers::RelayHeaders),
/// Start messages relay between two chains. /// Start messages relay between two chains.
/// ///
/// Ties up to `Messages` pallets on both chains and starts relaying messages. /// Ties up to `Messages` pallets on both chains and starts relaying messages.
@@ -47,7 +50,7 @@ pub enum Command {
/// Initialize on-chain bridge pallet with current header data. /// Initialize on-chain bridge pallet with current header data.
/// ///
/// Sends initialization transaction to bootstrap the bridge with current finalized block data. /// Sends initialization transaction to bootstrap the bridge with current finalized block data.
InitBridge(InitBridge), InitBridge(init_bridge::InitBridge),
/// Send custom message over the bridge. /// Send custom message over the bridge.
/// ///
/// Allows interacting with the bridge by sending messages over `Messages` component. /// Allows interacting with the bridge by sending messages over `Messages` component.
@@ -74,9 +77,9 @@ impl Command {
/// Run the command. /// Run the command.
pub async fn run(self) -> anyhow::Result<()> { pub async fn run(self) -> anyhow::Result<()> {
match self { match self {
Self::InitBridge(arg) => arg.run().await?,
Self::RelayHeaders(arg) => arg.run().await?, Self::RelayHeaders(arg) => arg.run().await?,
Self::RelayMessages(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?,
Self::InitBridge(arg) => arg.run().await?,
Self::SendMessage(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?,
Self::EncodeCall(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?,
Self::EncodeMessagePayload(arg) => arg.run().await?, Self::EncodeMessagePayload(arg) => arg.run().await?,
@@ -87,23 +90,6 @@ impl Command {
} }
} }
/// Start headers relayer process.
#[derive(StructOpt)]
pub enum RelayHeaders {
#[structopt(flatten)]
RialtoMillau(rialto_millau::RelayHeaders),
}
impl RelayHeaders {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
match self {
Self::RialtoMillau(arg) => arg.run().await?,
}
Ok(())
}
}
/// Start message relayer process. /// Start message relayer process.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum RelayMessages { pub enum RelayMessages {
@@ -121,23 +107,6 @@ impl RelayMessages {
} }
} }
/// Initialize bridge pallet.
#[derive(StructOpt)]
pub enum InitBridge {
#[structopt(flatten)]
RialtoMillau(rialto_millau::InitBridge),
}
impl InitBridge {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
match self {
Self::RialtoMillau(arg) => arg.run().await?,
}
Ok(())
}
}
/// Send bridge message. /// Send bridge message.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum SendMessage { pub enum SendMessage {
@@ -240,6 +209,25 @@ arg_enum! {
} }
} }
/// Generic balance type.
#[derive(Debug)]
pub struct Balance(pub u128);
impl std::str::FromStr for Balance {
type Err = <u128 as std::str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.parse()?))
}
}
impl Balance {
/// Cast balance to `u64` type, panicking if it's too large.
pub fn cast(&self) -> u64 {
self.0.try_into().expect("Balance is too high for this chain.")
}
}
/// Generic account id with custom parser. /// Generic account id with custom parser.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AccountId { pub struct AccountId {
@@ -267,19 +255,19 @@ const SS58_FORMAT_PROOF: &str = "u16 -> Ss58Format is infallible; qed";
impl AccountId { impl AccountId {
/// Create new SS58-formatted address from raw account id. /// Create new SS58-formatted address from raw account id.
pub fn from_raw<T: AccountChain>(account: sp_runtime::AccountId32) -> Self { pub fn from_raw<T: CliChain>(account: sp_runtime::AccountId32) -> Self {
Self { Self {
account, account,
ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF), ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF),
} }
} }
/// Enforces formatting account to be for given `AccountChain` type. /// Enforces formatting account to be for given [`CliChain`] type.
/// ///
/// This will change the `ss58format` of the account to match the requested one. /// This will change the `ss58format` of the account to match the requested one.
/// Note that a warning will be produced in case the current format does not match /// Note that a warning will be produced in case the current format does not match
/// the requested one, but the conversion always succeeds. /// the requested one, but the conversion always succeeds.
pub fn enforce_chain<T: AccountChain>(&mut self) { pub fn enforce_chain<T: CliChain>(&mut self) {
let original = self.clone(); let original = self.clone();
self.ss58_format = T::ss58_format().try_into().expect(SS58_FORMAT_PROOF); self.ss58_format = T::ss58_format().try_into().expect(SS58_FORMAT_PROOF);
log::debug!("{} SS58 format: {} (RAW: {})", self, self.ss58_format, self.account); log::debug!("{} SS58 format: {} (RAW: {})", self, self.ss58_format, self.account);
@@ -302,15 +290,48 @@ impl AccountId {
} }
} }
/// A trait representing an account address bound to a specific chain. /// Bridge-supported network definition.
/// ///
/// Can be used to convert [`AccountId`] formatting to be chain-specific. /// Used to abstract away CLI commands.
pub trait AccountChain { pub trait CliChain: relay_substrate_client::Chain {
/// Network name associated with the SS58 format. /// Chain's current version of the runtime.
const NAME: &'static str; const RUNTIME_VERSION: sp_version::RuntimeVersion;
/// Crypto keypair type used to send messages.
///
/// In case of chains supporting multiple cryptos, pick one used by the CLI.
type KeyPair: sp_core::crypto::Pair;
/// Bridge Message Payload type.
///
/// TODO [#854] This should be removed in favour of target-specifc types.
type MessagePayload;
/// Numeric value of SS58 format. /// Numeric value of SS58 format.
fn ss58_format() -> u16; fn ss58_format() -> u16;
/// Parse CLI call and encode it to be dispatched on this specific chain.
fn encode_call(call: crate::rialto_millau::cli::Call) -> Result<Self::Call, String>;
/// Construct message payload to be sent over the bridge.
fn encode_message(message: crate::rialto_millau::cli::MessagePayload) -> Result<Self::MessagePayload, String>;
/// Maximal extrinsic weight (from the runtime).
fn max_extrinsic_weight() -> Weight;
/// Convert CLI signing parameters of `Source` chain into a `KeyPair` instance.
fn source_signing_params(params: SourceSigningParams) -> Result<Self::KeyPair, String> {
use sp_core::crypto::Pair;
Self::KeyPair::from_string(&params.source_signer, params.source_signer_password.as_deref())
.map_err(|e| format!("Failed to parse source-signer: {:?}", e))
}
/// Convert CLI signing parameters of `Target` chain into a `KeyPair` instance.
fn target_signing_params(params: TargetSigningParams) -> Result<Self::KeyPair, String> {
use sp_core::crypto::Pair;
Self::KeyPair::from_string(&params.target_signer, params.target_signer_password.as_deref())
.map_err(|e| format!("Failed to parse target-signer: {:?}", e))
}
} }
/// Lane id. /// Lane id.
@@ -445,6 +466,11 @@ macro_rules! declare_chain_options {
}; };
} }
// TODO [#852] Use structop renames instead of different fields.
// TODO [#852] Add Into<ConnectionParams>?
declare_chain_options!(Source, source);
declare_chain_options!(Target, target);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::FromStr; use std::str::FromStr;
@@ -0,0 +1,91 @@
// 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 <http://www.gnu.org/licenses/>.
use crate::cli::{CliChain, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams};
use structopt::{clap::arg_enum, StructOpt};
/// Start headers relayer process.
#[derive(StructOpt)]
pub struct RelayHeaders {
/// A bridge instance to relay headers for.
#[structopt(possible_values = &RelayHeadersBridge::variants(), case_insensitive = true)]
bridge: RelayHeadersBridge,
#[structopt(flatten)]
source: SourceConnectionParams,
#[structopt(flatten)]
target: TargetConnectionParams,
#[structopt(flatten)]
target_sign: TargetSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
}
// TODO [#851] Use kebab-case.
arg_enum! {
#[derive(Debug)]
/// Headers relay bridge.
pub enum RelayHeadersBridge {
MillauToRialto,
RialtoToMillau,
WestendToMillau,
}
}
macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
match $bridge {
RelayHeadersBridge::MillauToRialto => {
type Source = relay_millau_client::Millau;
type Target = relay_rialto_client::Rialto;
type Finality = crate::rialto_millau::millau_headers_to_rialto::MillauFinalityToRialto;
$generic
}
RelayHeadersBridge::RialtoToMillau => {
type Source = relay_rialto_client::Rialto;
type Target = relay_millau_client::Millau;
type Finality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau;
$generic
}
RelayHeadersBridge::WestendToMillau => {
type Source = relay_westend_client::Westend;
type Target = relay_millau_client::Millau;
type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau;
$generic
}
}
};
}
impl RelayHeaders {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
select_bridge!(self.bridge, {
let source_client = crate::rialto_millau::source_chain_client::<Source>(self.source).await?;
let target_client = crate::rialto_millau::target_chain_client::<Target>(self.target).await?;
let target_sign =
Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?;
crate::finality_pipeline::run(
Finality::new(target_client.clone(), target_sign),
source_client,
target_client,
self.prometheus_params.into(),
)
.await
})
}
}
@@ -56,7 +56,7 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline {
} }
/// Substrate-to-Substrate finality proof pipeline. /// Substrate-to-Substrate finality proof pipeline.
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct SubstrateFinalityToSubstrate<SourceChain, TargetChain: Chain, TargetSign> { pub struct SubstrateFinalityToSubstrate<SourceChain, TargetChain: Chain, TargetSign> {
/// Client for the target chain. /// Client for the target chain.
pub(crate) target_client: Client<TargetChain>, pub(crate) target_client: Client<TargetChain>,
@@ -66,6 +66,16 @@ pub struct SubstrateFinalityToSubstrate<SourceChain, TargetChain: Chain, TargetS
_marker: PhantomData<SourceChain>, _marker: PhantomData<SourceChain>,
} }
impl<SourceChain, TargetChain: Chain, TargetSign> Debug
for SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("SubstrateFinalityToSubstrate")
.field("target_client", &self.target_client)
.finish()
}
}
impl<SourceChain, TargetChain: Chain, TargetSign> SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign> { impl<SourceChain, TargetChain: Chain, TargetSign> SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign> {
/// Create new Substrate-to-Substrate headers pipeline. /// Create new Substrate-to-Substrate headers pipeline.
pub fn new(target_client: Client<TargetChain>, target_sign: TargetSign) -> Self { pub fn new(target_client: Client<TargetChain>, target_sign: TargetSign) -> Self {
@@ -83,7 +93,7 @@ where
SourceChain: Clone + Chain + Debug, SourceChain: Clone + Chain + Debug,
BlockNumberOf<SourceChain>: BlockNumberBase, BlockNumberOf<SourceChain>: BlockNumberBase,
TargetChain: Clone + Chain + Debug, TargetChain: Clone + Chain + Debug,
TargetSign: Clone + Send + Sync + Debug, TargetSign: Clone + Send + Sync,
{ {
const SOURCE_NAME: &'static str = SourceChain::NAME; const SOURCE_NAME: &'static str = SourceChain::NAME;
const TARGET_NAME: &'static str = TargetChain::NAME; const TARGET_NAME: &'static str = TargetChain::NAME;
@@ -100,7 +110,7 @@ pub async fn run<SourceChain, TargetChain, P>(
source_client: Client<SourceChain>, source_client: Client<SourceChain>,
target_client: Client<TargetChain>, target_client: Client<TargetChain>,
metrics_params: Option<relay_utils::metrics::MetricsParams>, metrics_params: Option<relay_utils::metrics::MetricsParams>,
) -> Result<(), String> ) -> anyhow::Result<()>
where where
P: SubstrateFinalitySyncPipeline< P: SubstrateFinalitySyncPipeline<
Hash = HashOf<SourceChain>, Hash = HashOf<SourceChain>,
@@ -132,4 +142,5 @@ where
futures::future::pending(), futures::future::pending(),
) )
.await .await
.map_err(|e| anyhow::format_err!("{}", e))
} }
@@ -19,68 +19,26 @@
use frame_support::weights::Weight; use frame_support::weights::Weight;
use structopt::StructOpt; use structopt::StructOpt;
use crate::cli::{AccountId, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams}; use crate::cli::{
use crate::declare_chain_options; AccountId, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams, SourceConnectionParams,
SourceSigningParams, TargetConnectionParams, TargetSigningParams,
/// Start headers relayer process. };
#[derive(StructOpt)]
pub enum RelayHeaders {
/// Relay Millau headers to Rialto.
MillauToRialto {
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
rialto: RialtoConnectionParams,
#[structopt(flatten)]
rialto_sign: RialtoSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
},
/// Relay Rialto headers to Millau.
RialtoToMillau {
#[structopt(flatten)]
rialto: RialtoConnectionParams,
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
millau_sign: MillauSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
},
/// Relay Westend headers to Millau.
WestendToMillau {
#[structopt(flatten)]
westend: WestendConnectionParams,
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
millau_sign: MillauSigningParams,
#[structopt(flatten)]
prometheus_params: PrometheusParams,
},
}
impl RelayHeaders {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
super::run_relay_headers(self).await.map_err(format_err)?;
Ok(())
}
}
/// Start message relayer process. /// Start message relayer process.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum RelayMessages { pub enum RelayMessages {
/// Serve given lane of Millau -> Rialto messages. /// Serve given lane of Millau -> Rialto messages.
MillauToRialto { MillauToRialto {
#[structopt(flatten)] #[structopt(flatten)]
millau: MillauConnectionParams, source: SourceConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
millau_sign: MillauSigningParams, source_sign: SourceSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
rialto: RialtoConnectionParams, target: TargetConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
rialto_sign: RialtoSigningParams, target_sign: TargetSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
prometheus_params: PrometheusParams, prometheus_params: PrometheusParams,
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
@@ -90,13 +48,13 @@ pub enum RelayMessages {
/// Serve given lane of Rialto -> Millau messages. /// Serve given lane of Rialto -> Millau messages.
RialtoToMillau { RialtoToMillau {
#[structopt(flatten)] #[structopt(flatten)]
rialto: RialtoConnectionParams, source: SourceConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
rialto_sign: RialtoSigningParams, source_sign: SourceSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
millau: MillauConnectionParams, target: TargetConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
millau_sign: MillauSigningParams, target_sign: TargetSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
prometheus_params: PrometheusParams, prometheus_params: PrometheusParams,
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
@@ -113,57 +71,19 @@ impl RelayMessages {
} }
} }
/// Initialize bridge pallet.
#[derive(StructOpt)]
pub enum InitBridge {
/// Initialize Millau headers bridge in Rialto.
MillauToRialto {
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
rialto: RialtoConnectionParams,
#[structopt(flatten)]
rialto_sign: RialtoSigningParams,
},
/// Initialize Rialto headers bridge in Millau.
RialtoToMillau {
#[structopt(flatten)]
rialto: RialtoConnectionParams,
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
millau_sign: MillauSigningParams,
},
/// Initialize Westend headers bridge in Millau.
WestendToMillau {
#[structopt(flatten)]
westend: WestendConnectionParams,
#[structopt(flatten)]
millau: MillauConnectionParams,
#[structopt(flatten)]
millau_sign: MillauSigningParams,
},
}
impl InitBridge {
/// Run the command.
pub async fn run(self) -> anyhow::Result<()> {
super::run_init_bridge(self).await.map_err(format_err)?;
Ok(())
}
}
/// Send bridge message. /// Send bridge message.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum SendMessage { pub enum SendMessage {
/// Submit message to given Millau -> Rialto lane. /// Submit message to given Millau -> Rialto lane.
MillauToRialto { MillauToRialto {
#[structopt(flatten)] #[structopt(flatten)]
millau: MillauConnectionParams, source: SourceConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
millau_sign: MillauSigningParams, source_sign: SourceSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
rialto_sign: RialtoSigningParams, target_sign: TargetSigningParams,
/// Hex-encoded lane id. Defaults to `00000000`. /// Hex-encoded lane id. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")] #[structopt(long, default_value = "00000000")]
lane: HexLaneId, lane: HexLaneId,
@@ -172,10 +92,10 @@ pub enum SendMessage {
dispatch_weight: Option<ExplicitOrMaximal<Weight>>, dispatch_weight: Option<ExplicitOrMaximal<Weight>>,
/// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically.
#[structopt(long)] #[structopt(long)]
fee: Option<bp_millau::Balance>, fee: Option<Balance>,
/// Message type. /// Message type.
#[structopt(subcommand)] #[structopt(subcommand)]
message: ToRialtoMessage, message: Call,
/// The origin to use when dispatching the message on the target chain. Defaults to /// The origin to use when dispatching the message on the target chain. Defaults to
/// `SourceAccount`. /// `SourceAccount`.
#[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")]
@@ -184,11 +104,11 @@ pub enum SendMessage {
/// Submit message to given Rialto -> Millau lane. /// Submit message to given Rialto -> Millau lane.
RialtoToMillau { RialtoToMillau {
#[structopt(flatten)] #[structopt(flatten)]
rialto: RialtoConnectionParams, source: SourceConnectionParams,
#[structopt(flatten)] #[structopt(flatten)]
rialto_sign: RialtoSigningParams, source_sign: SourceSigningParams,
#[structopt(flatten)] #[structopt(flatten)]
millau_sign: MillauSigningParams, target_sign: TargetSigningParams,
/// Hex-encoded lane id. Defaults to `00000000`. /// Hex-encoded lane id. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")] #[structopt(long, default_value = "00000000")]
lane: HexLaneId, lane: HexLaneId,
@@ -197,10 +117,10 @@ pub enum SendMessage {
dispatch_weight: Option<ExplicitOrMaximal<Weight>>, dispatch_weight: Option<ExplicitOrMaximal<Weight>>,
/// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically.
#[structopt(long)] #[structopt(long)]
fee: Option<bp_rialto::Balance>, fee: Option<Balance>,
/// Message type. /// Message type.
#[structopt(subcommand)] #[structopt(subcommand)]
message: ToMillauMessage, message: Call,
/// The origin to use when dispatching the message on the target chain. Defaults to /// The origin to use when dispatching the message on the target chain. Defaults to
/// `SourceAccount`. /// `SourceAccount`.
#[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")]
@@ -217,17 +137,19 @@ impl SendMessage {
} }
/// A call to encode. /// A call to encode.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum EncodeCall { pub enum EncodeCall {
/// Encode Rialto's Call. /// Encode Rialto's Call.
Rialto { Rialto {
#[structopt(flatten)] #[structopt(flatten)]
call: ToRialtoMessage, call: Call,
}, },
/// Encode Millau's Call. /// Encode Millau's Call.
Millau { Millau {
#[structopt(flatten)] #[structopt(flatten)]
call: ToMillauMessage, call: Call,
}, },
} }
@@ -240,17 +162,19 @@ impl EncodeCall {
} }
/// A `MessagePayload` to encode. /// A `MessagePayload` to encode.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum EncodeMessagePayload { pub enum EncodeMessagePayload {
/// Message Payload of Rialto to Millau call. /// Message Payload of Rialto to Millau call.
RialtoToMillau { RialtoToMillau {
#[structopt(flatten)] #[structopt(flatten)]
payload: RialtoToMillauMessagePayload, payload: MessagePayload,
}, },
/// Message Payload of Millau to Rialto call. /// Message Payload of Millau to Rialto call.
MillauToRialto { MillauToRialto {
#[structopt(flatten)] #[structopt(flatten)]
payload: MillauToRialtoMessagePayload, payload: MessagePayload,
}, },
} }
@@ -263,29 +187,31 @@ impl EncodeMessagePayload {
} }
/// Estimate Delivery & Dispatch Fee command. /// Estimate Delivery & Dispatch Fee command.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum EstimateFee { pub enum EstimateFee {
/// Estimate fee of Rialto to Millau message. /// Estimate fee of Rialto to Millau message.
RialtoToMillau { RialtoToMillau {
#[structopt(flatten)] #[structopt(flatten)]
rialto: RialtoConnectionParams, source: SourceConnectionParams,
/// Hex-encoded id of lane that will be delivering the message. /// Hex-encoded id of lane that will be delivering the message.
#[structopt(long)] #[structopt(long)]
lane: HexLaneId, lane: HexLaneId,
/// Payload to send over the bridge. /// Payload to send over the bridge.
#[structopt(flatten)] #[structopt(flatten)]
payload: RialtoToMillauMessagePayload, payload: MessagePayload,
}, },
/// Estimate fee of Rialto to Millau message. /// Estimate fee of Rialto to Millau message.
MillauToRialto { MillauToRialto {
#[structopt(flatten)] #[structopt(flatten)]
millau: MillauConnectionParams, source: SourceConnectionParams,
/// Hex-encoded id of lane that will be delivering the message. /// Hex-encoded id of lane that will be delivering the message.
#[structopt(long)] #[structopt(long)]
lane: HexLaneId, lane: HexLaneId,
/// Payload to send over the bridge. /// Payload to send over the bridge.
#[structopt(flatten)] #[structopt(flatten)]
payload: MillauToRialtoMessagePayload, payload: MessagePayload,
}, },
} }
@@ -303,6 +229,8 @@ impl EstimateFee {
/// that has been sent over the bridge. /// that has been sent over the bridge.
/// This account can also be used to receive target-chain funds (or other form of ownership), /// This account can also be used to receive target-chain funds (or other form of ownership),
/// since messages sent over the bridge will be able to spend these. /// since messages sent over the bridge will be able to spend these.
///
/// TODO [#855] Move to separate module.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum DeriveAccount { pub enum DeriveAccount {
/// Given Rialto AccountId, display corresponding Millau AccountId. /// Given Rialto AccountId, display corresponding Millau AccountId.
@@ -323,47 +251,31 @@ fn format_err(err: String) -> anyhow::Error {
anyhow::anyhow!(err) anyhow::anyhow!(err)
} }
/// MessagePayload that can be delivered to messages pallet on Millau. /// Generic message payload.
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
pub enum MillauToRialtoMessagePayload { pub enum MessagePayload {
/// Raw, SCALE-encoded `MessagePayload`. /// Raw, SCALE-encoded `MessagePayload`.
Raw { Raw {
/// Hex-encoded SCALE data. /// Hex-encoded SCALE data.
data: HexBytes, data: HexBytes,
}, },
/// Construct message to send over the bridge. /// Construct message to send over the bridge.
Message { Call {
/// Message details. /// Message details.
#[structopt(flatten)] #[structopt(flatten)]
message: ToRialtoMessage, call: Call,
/// SS58 encoded account that will send the payload (must have SS58Prefix = 42) /// SS58 encoded account that will send the payload (must have SS58Prefix = 42)
#[structopt(long)] #[structopt(long)]
sender: AccountId, sender: AccountId,
}, },
} }
/// MessagePayload that can be delivered to messages pallet on Rialto. /// All possible messages that may be delivered to generic Substrate chain.
///
/// Note this enum may be used in the context of both Source (as part of `encode-call`)
/// and Target chain (as part of `encode-message/send-message`).
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
pub enum RialtoToMillauMessagePayload { pub enum Call {
/// Raw, SCALE-encoded `MessagePayload`.
Raw {
/// Hex-encoded SCALE data.
data: HexBytes,
},
/// Construct message to send over the bridge.
Message {
/// Message details.
#[structopt(flatten)]
message: ToMillauMessage,
/// SS58 encoded account that will send the payload (must have SS58Prefix = 42)
#[structopt(long)]
sender: AccountId,
},
}
/// All possible messages that may be delivered to the Rialto chain.
#[derive(StructOpt, Debug)]
pub enum ToRialtoMessage {
/// Raw bytes for the message /// Raw bytes for the message
Raw { Raw {
/// Raw, SCALE-encoded message /// Raw, SCALE-encoded message
@@ -382,10 +294,11 @@ pub enum ToRialtoMessage {
recipient: AccountId, recipient: AccountId,
/// Amount of target tokens to send in target chain base currency units. /// Amount of target tokens to send in target chain base currency units.
#[structopt(long)] #[structopt(long)]
amount: bp_rialto::Balance, amount: Balance,
}, },
/// A call to the Millau Bridge Messages pallet to send a message over the bridge. // TODO [#853] Support multiple bridges.
MillauSendMessage { /// A call to the specific Bridge Messages pallet to queue message to be sent over a bridge.
BridgeSendMessage {
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")] #[structopt(long, default_value = "00000000")]
lane: HexLaneId, lane: HexLaneId,
@@ -394,47 +307,6 @@ pub enum ToRialtoMessage {
payload: HexBytes, payload: HexBytes,
/// Declared delivery and dispatch fee in base source-chain currency units. /// Declared delivery and dispatch fee in base source-chain currency units.
#[structopt(long)] #[structopt(long)]
fee: bp_rialto::Balance, fee: Balance,
}, },
} }
/// All possible messages that may be delivered to the Millau chain.
#[derive(StructOpt, Debug)]
pub enum ToMillauMessage {
/// Raw bytes for the message
Raw {
/// Raw, SCALE-encoded message
data: HexBytes,
},
/// Make an on-chain remark (comment).
Remark {
/// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark.
#[structopt(long)]
remark_size: Option<ExplicitOrMaximal<usize>>,
},
/// Transfer the specified `amount` of native tokens to a particular `recipient`.
Transfer {
/// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42)
#[structopt(long)]
recipient: AccountId,
/// Amount of target tokens to send in target chain base currency units.
#[structopt(long)]
amount: bp_millau::Balance,
},
/// A call to the Rialto Bridge Messages pallet to send a message over the bridge.
RialtoSendMessage {
/// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`.
#[structopt(long, default_value = "00000000")]
lane: HexLaneId,
/// Raw SCALE-encoded Message Payload to submit to the messages pallet.
#[structopt(long)]
payload: HexBytes,
/// Declared delivery and dispatch fee in base source-chain currency units.
#[structopt(long)]
fee: bp_millau::Balance,
},
}
declare_chain_options!(Rialto, rialto);
declare_chain_options!(Millau, millau);
declare_chain_options!(Westend, westend);
@@ -16,7 +16,6 @@
//! Millau-to-Rialto headers sync entrypoint. //! Millau-to-Rialto headers sync entrypoint.
use super::{MillauClient, RialtoClient};
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use codec::Encode; use codec::Encode;
@@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
type TargetChain = Rialto; type TargetChain = Rialto;
fn transactions_author(&self) -> bp_rialto::AccountId { fn transactions_author(&self) -> bp_rialto::AccountId {
self.target_sign.signer.public().as_array_ref().clone().into() self.target_sign.public().as_array_ref().clone().into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -48,24 +47,8 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
.into(); .into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
} }
/// Run Millau-to-Rialto finality sync.
pub async fn run(
millau_client: MillauClient,
rialto_client: RialtoClient,
rialto_sign: RialtoSigningParams,
metrics_params: Option<relay_utils::metrics::MetricsParams>,
) -> Result<(), String> {
crate::finality_pipeline::run(
MillauFinalityToRialto::new(rialto_client.clone(), rialto_sign),
millau_client,
rialto_client,
metrics_params,
)
.await
}
@@ -56,7 +56,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
type TargetChain = Rialto; type TargetChain = Rialto;
fn source_transactions_author(&self) -> bp_rialto::AccountId { fn source_transactions_author(&self) -> bp_rialto::AccountId {
self.source_sign.signer.public().as_array_ref().clone().into() self.source_sign.public().as_array_ref().clone().into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
@@ -70,7 +70,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into();
let call_weight = call.get_dispatch_info().weight; let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.source_client.genesis_hash(); let genesis_hash = *self.source_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}",
@@ -83,7 +83,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
} }
fn target_transactions_author(&self) -> bp_rialto::AccountId { fn target_transactions_author(&self) -> bp_rialto::AccountId {
self.target_sign.signer.public().as_array_ref().clone().into() self.target_sign.public().as_array_ref().clone().into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -109,7 +109,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
.into(); .into();
let call_weight = call.get_dispatch_info().weight; let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}",
@@ -138,7 +138,7 @@ pub async fn run(
metrics_params: Option<MetricsParams>, metrics_params: Option<MetricsParams>,
) -> Result<(), String> { ) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60); let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_millau = millau_sign.signer.public().as_array_ref().clone().into(); let relayer_id_at_millau = millau_sign.public().as_array_ref().clone().into();
let lane = MillauMessagesToRialto { let lane = MillauMessagesToRialto {
source_client: millau_client.clone(), source_client: millau_client.clone(),
File diff suppressed because it is too large Load Diff
@@ -16,7 +16,6 @@
//! Rialto-to-Millau headers sync entrypoint. //! Rialto-to-Millau headers sync entrypoint.
use super::{MillauClient, RialtoClient};
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use codec::Encode; use codec::Encode;
@@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
type TargetChain = Millau; type TargetChain = Millau;
fn transactions_author(&self) -> bp_millau::AccountId { fn transactions_author(&self) -> bp_millau::AccountId {
self.target_sign.signer.public().as_array_ref().clone().into() self.target_sign.public().as_array_ref().clone().into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -50,24 +49,8 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
.into(); .into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
} }
/// Run Rialto-to-Millau finality sync.
pub async fn run(
rialto_client: RialtoClient,
millau_client: MillauClient,
millau_sign: MillauSigningParams,
metrics_params: Option<relay_utils::metrics::MetricsParams>,
) -> Result<(), String> {
crate::finality_pipeline::run(
RialtoFinalityToMillau::new(millau_client.clone(), millau_sign),
rialto_client,
millau_client,
metrics_params,
)
.await
}
@@ -56,7 +56,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
type TargetChain = Millau; type TargetChain = Millau;
fn source_transactions_author(&self) -> bp_rialto::AccountId { fn source_transactions_author(&self) -> bp_rialto::AccountId {
self.source_sign.signer.public().as_array_ref().clone().into() self.source_sign.public().as_array_ref().clone().into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
@@ -70,7 +70,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into();
let call_weight = call.get_dispatch_info().weight; let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.source_client.genesis_hash(); let genesis_hash = *self.source_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}",
@@ -83,7 +83,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
} }
fn target_transactions_author(&self) -> bp_rialto::AccountId { fn target_transactions_author(&self) -> bp_rialto::AccountId {
self.target_sign.signer.public().as_array_ref().clone().into() self.target_sign.public().as_array_ref().clone().into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -109,7 +109,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
.into(); .into();
let call_weight = call.get_dispatch_info().weight; let call_weight = call.get_dispatch_info().weight;
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}",
@@ -138,7 +138,7 @@ pub async fn run(
metrics_params: Option<MetricsParams>, metrics_params: Option<MetricsParams>,
) -> Result<(), String> { ) -> Result<(), String> {
let stall_timeout = Duration::from_secs(5 * 60); let stall_timeout = Duration::from_secs(5 * 60);
let relayer_id_at_rialto = rialto_sign.signer.public().as_array_ref().clone().into(); let relayer_id_at_rialto = rialto_sign.public().as_array_ref().clone().into();
let lane = RialtoMessagesToMillau { let lane = RialtoMessagesToMillau {
source_client: rialto_client.clone(), source_client: rialto_client.clone(),
@@ -16,7 +16,6 @@
//! Westend-to-Millau headers sync entrypoint. //! Westend-to-Millau headers sync entrypoint.
use super::{MillauClient, WestendClient};
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use codec::Encode; use codec::Encode;
@@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau {
type TargetChain = Millau; type TargetChain = Millau;
fn transactions_author(&self) -> bp_millau::AccountId { fn transactions_author(&self) -> bp_millau::AccountId {
self.target_sign.signer.public().as_array_ref().clone().into() self.target_sign.public().as_array_ref().clone().into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -50,24 +49,8 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau {
.into(); .into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
} }
/// Run Westend-to-Millau finality sync.
pub async fn run(
westend_client: WestendClient,
millau_client: MillauClient,
millau_sign: MillauSigningParams,
metrics_params: Option<relay_utils::metrics::MetricsParams>,
) -> Result<(), String> {
crate::finality_pipeline::run(
WestendFinalityToMillau::new(millau_client.clone(), millau_sign),
westend_client,
millau_client,
metrics_params,
)
.await
}
+1 -20
View File
@@ -100,26 +100,7 @@ impl TransactionSignScheme for Millau {
} }
/// Millau signing params. /// Millau signing params.
#[derive(Clone)] pub type SigningParams = sp_core::sr25519::Pair;
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<Self, sp_core::crypto::SecretStringError> {
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())
}
}
/// Millau header type used in headers sync. /// Millau header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<millau_runtime::Header>; pub type SyncHeader = relay_substrate_client::SyncHeader<millau_runtime::Header>;
+1 -28
View File
@@ -100,34 +100,7 @@ impl TransactionSignScheme for Rialto {
} }
/// Rialto signing params. /// Rialto signing params.
#[derive(Clone)] pub type SigningParams = sp_core::sr25519::Pair;
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<Self, sp_core::crypto::SecretStringError> {
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(),
}
}
}
/// Rialto header type used in headers sync. /// Rialto header type used in headers sync.
pub type SyncHeader = relay_substrate_client::SyncHeader<rialto_runtime::Header>; pub type SyncHeader = relay_substrate_client::SyncHeader<rialto_runtime::Header>;
+25 -10
View File
@@ -42,6 +42,19 @@ pub enum Error {
Custom(String), Custom(String),
} }
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::RpcError(ref e) => Some(e),
Self::ResponseParseFailed(ref e) => Some(e),
Self::UninitializedBridgePallet => None,
Self::AccountDoesNotExist => None,
Self::ClientNotSynced(_) => None,
Self::Custom(_) => None,
}
}
}
impl From<RpcError> for Error { impl From<RpcError> for Error {
fn from(error: RpcError) -> Self { fn from(error: RpcError) -> Self {
Error::RpcError(error) Error::RpcError(error)
@@ -61,21 +74,23 @@ impl MaybeConnectionError for Error {
} }
} }
impl From<Error> for String { impl std::fmt::Display for Error {
fn from(error: Error) -> String { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
error.to_string() let s = match self {
}
}
impl ToString for Error {
fn to_string(&self) -> String {
match self {
Self::RpcError(e) => e.to_string(), Self::RpcError(e) => e.to_string(),
Self::ResponseParseFailed(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(),
Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(),
Self::AccountDoesNotExist => "Account does not exist on the chain".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(),
Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health),
Self::Custom(e) => e.clone(), Self::Custom(e) => e.clone(),
} };
write!(f, "{}", s)
}
}
impl From<Error> for String {
fn from(error: Error) -> String {
error.to_string()
} }
} }