mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
Relay subcommands to initialize substrate bridge pallet (#483)
* initialize substrate bridge from relay * is_halted: false * initialize using su instead of owner * Fix wording in comments Co-authored-by: Hernando Castano <castano.ha@gmail.com>
This commit is contained in:
committed by
Bastian Köcher
parent
3f7655a056
commit
0c38193af7
@@ -58,6 +58,7 @@ pub use frame_support::{
|
|||||||
pub use pallet_balances::Call as BalancesCall;
|
pub use pallet_balances::Call as BalancesCall;
|
||||||
pub use pallet_message_lane::Call as MessageLaneCall;
|
pub use pallet_message_lane::Call as MessageLaneCall;
|
||||||
pub use pallet_substrate_bridge::Call as BridgeRialtoCall;
|
pub use pallet_substrate_bridge::Call as BridgeRialtoCall;
|
||||||
|
pub use pallet_sudo::Call as SudoCall;
|
||||||
pub use pallet_timestamp::Call as TimestampCall;
|
pub use pallet_timestamp::Call as TimestampCall;
|
||||||
|
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall;
|
|||||||
pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall;
|
pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall;
|
||||||
pub use pallet_message_lane::Call as MessageLaneCall;
|
pub use pallet_message_lane::Call as MessageLaneCall;
|
||||||
pub use pallet_substrate_bridge::Call as BridgeMillauCall;
|
pub use pallet_substrate_bridge::Call as BridgeMillauCall;
|
||||||
|
pub use pallet_sudo::Call as SudoCall;
|
||||||
pub use pallet_timestamp::Call as TimestampCall;
|
pub use pallet_timestamp::Call as TimestampCall;
|
||||||
|
|
||||||
#[cfg(any(feature = "std", test))]
|
#[cfg(any(feature = "std", test))]
|
||||||
|
|||||||
@@ -37,5 +37,6 @@ rialto-runtime = { path = "../../bin/rialto/runtime" }
|
|||||||
|
|
||||||
frame-support = "2.0"
|
frame-support = "2.0"
|
||||||
sp-core = "2.0"
|
sp-core = "2.0"
|
||||||
|
sp-finality-grandpa = "2.0"
|
||||||
sp-runtime = "2.0"
|
sp-runtime = "2.0"
|
||||||
sp-trie = "2.0"
|
sp-trie = "2.0"
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
//! Deal with CLI args of substrate-to-substrate relay.
|
//! Deal with CLI args of substrate-to-substrate relay.
|
||||||
|
|
||||||
use bp_message_lane::LaneId;
|
use bp_message_lane::LaneId;
|
||||||
|
use sp_core::Bytes;
|
||||||
|
use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId;
|
||||||
use structopt::{clap::arg_enum, StructOpt};
|
use structopt::{clap::arg_enum, StructOpt};
|
||||||
|
|
||||||
/// Parse relay CLI args.
|
/// Parse relay CLI args.
|
||||||
@@ -28,6 +30,17 @@ pub fn parse_args() -> Command {
|
|||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
#[structopt(about = "Substrate-to-Substrate relay")]
|
#[structopt(about = "Substrate-to-Substrate relay")]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
|
/// Initialize Millau headers bridge in Rialto.
|
||||||
|
InitializeMillauHeadersBridgeInRialto {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
millau: MillauConnectionParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
rialto: RialtoConnectionParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
rialto_sign: RialtoSigningParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
millau_bridge_params: MillauBridgeInitializationParams,
|
||||||
|
},
|
||||||
/// Relay Millau headers to Rialto.
|
/// Relay Millau headers to Rialto.
|
||||||
MillauHeadersToRialto {
|
MillauHeadersToRialto {
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
@@ -39,6 +52,17 @@ pub enum Command {
|
|||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
prometheus_params: PrometheusParams,
|
prometheus_params: PrometheusParams,
|
||||||
},
|
},
|
||||||
|
/// Initialize Rialto headers bridge in Millau.
|
||||||
|
InitializeRialtoHeadersBridgeInMillau {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
rialto: RialtoConnectionParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
millau: MillauConnectionParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
millau_sign: MillauSigningParams,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
rialto_bridge_params: RialtoBridgeInitializationParams,
|
||||||
|
},
|
||||||
/// Relay Rialto headers to Millau.
|
/// Relay Rialto headers to Millau.
|
||||||
RialtoHeadersToMillau {
|
RialtoHeadersToMillau {
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
@@ -165,6 +189,20 @@ macro_rules! declare_chain_options {
|
|||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub [<$chain_prefix _signer_password>]: Option<String>,
|
pub [<$chain_prefix _signer_password>]: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = $chain " headers bridge initialization params."]
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
pub struct [<$chain BridgeInitializationParams>] {
|
||||||
|
#[doc = "Hex-encoded " $chain " header to initialize bridge with. If not specified, genesis header is used."]
|
||||||
|
#[structopt(long)]
|
||||||
|
pub [<$chain_prefix _initial_header>]: Option<Bytes>,
|
||||||
|
#[doc = "Hex-encoded " $chain " GRANDPA authorities set to initialize bridge with. If not specified, set from genesis block is used."]
|
||||||
|
#[structopt(long)]
|
||||||
|
pub [<$chain_prefix _initial_authorities>]: Option<Bytes>,
|
||||||
|
#[doc = "Id of the " $chain " GRANDPA authorities set to initialize bridge with. If not specified, zero is used."]
|
||||||
|
#[structopt(long)]
|
||||||
|
pub [<$chain_prefix _initial_authorities_set_id>]: Option<GrandpaAuthoritiesSetId>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity Bridges Common.
|
||||||
|
|
||||||
|
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Initialize Substrate -> Substrate headers bridge.
|
||||||
|
//!
|
||||||
|
//! Initialization is a transaction that calls `initialize()` function of the
|
||||||
|
//! `pallet-substrate-bridge` pallet. This transaction brings initial header
|
||||||
|
//! and authorities set from source to target chain. The headers sync starts
|
||||||
|
//! with this header.
|
||||||
|
|
||||||
|
use codec::Decode;
|
||||||
|
use pallet_substrate_bridge::InitializationData;
|
||||||
|
use relay_substrate_client::{Chain, Client};
|
||||||
|
use sp_core::Bytes;
|
||||||
|
use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, SetId as GrandpaAuthoritiesSetId};
|
||||||
|
|
||||||
|
/// Submit headers-bridge initialization transaction.
|
||||||
|
pub async fn initialize<SourceChain: Chain, TargetChain: Chain>(
|
||||||
|
source_client: Client<SourceChain>,
|
||||||
|
target_client: Client<TargetChain>,
|
||||||
|
raw_initial_header: Option<Bytes>,
|
||||||
|
raw_initial_authorities_set: Option<Bytes>,
|
||||||
|
initial_authorities_set_id: Option<GrandpaAuthoritiesSetId>,
|
||||||
|
prepare_initialize_transaction: impl FnOnce(InitializationData<SourceChain::Header>) -> Result<Bytes, String>,
|
||||||
|
) {
|
||||||
|
let result = do_initialize(
|
||||||
|
source_client,
|
||||||
|
target_client,
|
||||||
|
raw_initial_header,
|
||||||
|
raw_initial_authorities_set,
|
||||||
|
initial_authorities_set_id,
|
||||||
|
prepare_initialize_transaction,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(tx_hash) => log::info!(
|
||||||
|
target: "bridge",
|
||||||
|
"Successfully submitted {}-headers bridge initialization transaction to {}: {:?}",
|
||||||
|
SourceChain::NAME,
|
||||||
|
TargetChain::NAME,
|
||||||
|
tx_hash,
|
||||||
|
),
|
||||||
|
Err(err) => log::error!(
|
||||||
|
target: "bridge",
|
||||||
|
"Failed to submit {}-headers bridge initialization transaction to {}: {:?}",
|
||||||
|
SourceChain::NAME,
|
||||||
|
TargetChain::NAME,
|
||||||
|
err,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Craft and submit initialization transaction, returning any error that may occur.
|
||||||
|
async fn do_initialize<SourceChain: Chain, TargetChain: Chain>(
|
||||||
|
source_client: Client<SourceChain>,
|
||||||
|
target_client: Client<TargetChain>,
|
||||||
|
raw_initial_header: Option<Bytes>,
|
||||||
|
raw_initial_authorities_set: Option<Bytes>,
|
||||||
|
initial_authorities_set_id: Option<GrandpaAuthoritiesSetId>,
|
||||||
|
prepare_initialize_transaction: impl FnOnce(InitializationData<SourceChain::Header>) -> Result<Bytes, String>,
|
||||||
|
) -> Result<TargetChain::Hash, String> {
|
||||||
|
let initialization_data = prepare_initialization_data(
|
||||||
|
source_client,
|
||||||
|
raw_initial_header,
|
||||||
|
raw_initial_authorities_set,
|
||||||
|
initial_authorities_set_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let initialization_tx = prepare_initialize_transaction(initialization_data)?;
|
||||||
|
let initialization_tx_hash = target_client
|
||||||
|
.submit_extrinsic(initialization_tx)
|
||||||
|
.await
|
||||||
|
.map_err(|err| format!("Failed to submit {} transaction: {:?}", TargetChain::NAME, err))?;
|
||||||
|
Ok(initialization_tx_hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepare initialization data for the headers-bridge pallet.
|
||||||
|
async fn prepare_initialization_data<SourceChain: Chain>(
|
||||||
|
source_client: Client<SourceChain>,
|
||||||
|
raw_initial_header: Option<Bytes>,
|
||||||
|
raw_initial_authorities_set: Option<Bytes>,
|
||||||
|
initial_authorities_set_id: Option<GrandpaAuthoritiesSetId>,
|
||||||
|
) -> Result<InitializationData<SourceChain::Header>, String> {
|
||||||
|
let source_genesis_hash = *source_client.genesis_hash();
|
||||||
|
|
||||||
|
let initial_header = match raw_initial_header {
|
||||||
|
Some(raw_initial_header) => SourceChain::Header::decode(&mut &raw_initial_header.0[..])
|
||||||
|
.map_err(|err| format!("Failed to decode {} initial header: {:?}", SourceChain::NAME, err))?,
|
||||||
|
None => source_client
|
||||||
|
.header_by_hash(source_genesis_hash)
|
||||||
|
.await
|
||||||
|
.map_err(|err| format!("Failed to retrive {} genesis header: {:?}", SourceChain::NAME, err))?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let raw_initial_authorities_set = match raw_initial_authorities_set {
|
||||||
|
Some(raw_initial_authorities_set) => raw_initial_authorities_set.0,
|
||||||
|
None => source_client
|
||||||
|
.grandpa_authorities_set(source_genesis_hash)
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
format!(
|
||||||
|
"Failed to retrive {} authorities set at genesis header: {:?}",
|
||||||
|
SourceChain::NAME,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
})?,
|
||||||
|
};
|
||||||
|
let initial_authorities_set =
|
||||||
|
GrandpaAuthoritiesSet::decode(&mut &raw_initial_authorities_set[..]).map_err(|err| {
|
||||||
|
format!(
|
||||||
|
"Failed to decode {} initial authorities set: {:?}",
|
||||||
|
SourceChain::NAME,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(InitializationData {
|
||||||
|
header: initial_header,
|
||||||
|
authority_list: initial_authorities_set,
|
||||||
|
set_id: initial_authorities_set_id.unwrap_or(0),
|
||||||
|
// There may be multiple scheduled changes, so on real chains we should select proper
|
||||||
|
// moment, when there's nothing scheduled. On ephemeral (temporary) chains, it is ok to
|
||||||
|
// start with genesis.
|
||||||
|
scheduled_change: None,
|
||||||
|
is_halted: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ pub type MillauClient = relay_substrate_client::Client<Millau>;
|
|||||||
pub type RialtoClient = relay_substrate_client::Client<Rialto>;
|
pub type RialtoClient = relay_substrate_client::Client<Rialto>;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
mod headers_initialize;
|
||||||
mod headers_maintain;
|
mod headers_maintain;
|
||||||
mod headers_pipeline;
|
mod headers_pipeline;
|
||||||
mod headers_target;
|
mod headers_target;
|
||||||
@@ -53,6 +54,54 @@ fn main() {
|
|||||||
|
|
||||||
async fn run_command(command: cli::Command) -> Result<(), String> {
|
async fn run_command(command: cli::Command) -> Result<(), String> {
|
||||||
match command {
|
match command {
|
||||||
|
cli::Command::InitializeMillauHeadersBridgeInRialto {
|
||||||
|
millau,
|
||||||
|
rialto,
|
||||||
|
rialto_sign,
|
||||||
|
millau_bridge_params,
|
||||||
|
} => {
|
||||||
|
let millau_client = MillauClient::new(ConnectionParams {
|
||||||
|
host: millau.millau_host,
|
||||||
|
port: millau.millau_port,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let rialto_client = RialtoClient::new(ConnectionParams {
|
||||||
|
host: rialto.rialto_host,
|
||||||
|
port: rialto.rialto_port,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let rialto_sign = RialtoSigningParams::from_suri(
|
||||||
|
&rialto_sign.rialto_signer,
|
||||||
|
rialto_sign.rialto_signer_password.as_deref(),
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?;
|
||||||
|
let rialto_signer_next_index = rialto_client
|
||||||
|
.next_account_index(rialto_sign.signer.public().into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
headers_initialize::initialize(
|
||||||
|
millau_client,
|
||||||
|
rialto_client.clone(),
|
||||||
|
millau_bridge_params.millau_initial_header,
|
||||||
|
millau_bridge_params.millau_initial_authorities,
|
||||||
|
millau_bridge_params.millau_initial_authorities_set_id,
|
||||||
|
move |initialization_data| {
|
||||||
|
Ok(Bytes(
|
||||||
|
Rialto::sign_transaction(
|
||||||
|
&rialto_client,
|
||||||
|
&rialto_sign.signer,
|
||||||
|
rialto_signer_next_index,
|
||||||
|
millau_runtime::SudoCall::sudo(Box::new(
|
||||||
|
rialto_runtime::BridgeMillauCall::initialize(initialization_data).into(),
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
.encode(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
cli::Command::MillauHeadersToRialto {
|
cli::Command::MillauHeadersToRialto {
|
||||||
millau,
|
millau,
|
||||||
rialto,
|
rialto,
|
||||||
@@ -76,6 +125,54 @@ async fn run_command(command: cli::Command) -> Result<(), String> {
|
|||||||
.map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?;
|
.map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?;
|
||||||
millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await;
|
millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await;
|
||||||
}
|
}
|
||||||
|
cli::Command::InitializeRialtoHeadersBridgeInMillau {
|
||||||
|
rialto,
|
||||||
|
millau,
|
||||||
|
millau_sign,
|
||||||
|
rialto_bridge_params,
|
||||||
|
} => {
|
||||||
|
let rialto_client = RialtoClient::new(ConnectionParams {
|
||||||
|
host: rialto.rialto_host,
|
||||||
|
port: rialto.rialto_port,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let millau_client = MillauClient::new(ConnectionParams {
|
||||||
|
host: millau.millau_host,
|
||||||
|
port: millau.millau_port,
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
let millau_sign = MillauSigningParams::from_suri(
|
||||||
|
&millau_sign.millau_signer,
|
||||||
|
millau_sign.millau_signer_password.as_deref(),
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?;
|
||||||
|
let millau_signer_next_index = millau_client
|
||||||
|
.next_account_index(millau_sign.signer.public().into())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
headers_initialize::initialize(
|
||||||
|
rialto_client,
|
||||||
|
millau_client.clone(),
|
||||||
|
rialto_bridge_params.rialto_initial_header,
|
||||||
|
rialto_bridge_params.rialto_initial_authorities,
|
||||||
|
rialto_bridge_params.rialto_initial_authorities_set_id,
|
||||||
|
move |initialization_data| {
|
||||||
|
Ok(Bytes(
|
||||||
|
Millau::sign_transaction(
|
||||||
|
&millau_client,
|
||||||
|
&millau_sign.signer,
|
||||||
|
millau_signer_next_index,
|
||||||
|
millau_runtime::SudoCall::sudo(Box::new(
|
||||||
|
millau_runtime::BridgeRialtoCall::initialize(initialization_data).into(),
|
||||||
|
))
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
.encode(),
|
||||||
|
))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
cli::Command::RialtoHeadersToMillau {
|
cli::Command::RialtoHeadersToMillau {
|
||||||
rialto,
|
rialto,
|
||||||
millau,
|
millau,
|
||||||
|
|||||||
Reference in New Issue
Block a user