Polkadot <> Kusama relayers (#1122)

* relay headers between Kusama and Polkadot

* relay messages between Kusama and Polkadot

* complex Kusama <> Polkadot relayer

* expose relayer_fund_account_id from messages pallet

* create relayers fund accounts on Kusama/Polkadot + some more fixes

* fmt

* fix compilation

* compilation + clippy

* compilation

* MAXIMAL_BALANCE_DECREASE_PER_DAY for K<>P header relays

* fmt

* deduplicate tests

* Update modules/messages/src/lib.rs

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* extract storage_parameter_key function

* other grumbles

* fix

* fmt

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
Svyatoslav Nikolsky
2021-09-21 16:53:37 +03:00
committed by Bastian Köcher
parent 417903f9e7
commit 2db84b74cc
31 changed files with 1936 additions and 68 deletions
@@ -24,6 +24,8 @@ pub enum FullBridge {
RialtoToMillau,
RococoToWococo,
WococoToRococo,
KusamaToPolkadot,
PolkadotToKusama,
}
impl FullBridge {
@@ -34,6 +36,8 @@ impl FullBridge {
Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX,
Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX,
Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX,
Self::KusamaToPolkadot => KUSAMA_TO_POLKADOT_INDEX,
Self::PolkadotToKusama => POLKADOT_TO_KUSAMA_INDEX,
}
}
}
@@ -42,6 +46,8 @@ pub const RIALTO_TO_MILLAU_INDEX: u8 = 0;
pub const MILLAU_TO_RIALTO_INDEX: u8 = 0;
pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0;
pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0;
pub const KUSAMA_TO_POLKADOT_INDEX: u8 = 0;
pub const POLKADOT_TO_KUSAMA_INDEX: u8 = 0;
/// The macro allows executing bridge-specific code without going fully generic.
///
@@ -138,6 +144,50 @@ macro_rules! select_full_bridge {
#[allow(unused_imports)]
use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest;
$generic
}
FullBridge::KusamaToPolkadot => {
type Source = relay_kusama_client::Kusama;
#[allow(dead_code)]
type Target = relay_polkadot_client::Polkadot;
// Derive-account
#[allow(unused_imports)]
use bp_polkadot::derive_account_from_kusama_id as derive_account;
// Relay-messages
#[allow(unused_imports)]
use crate::chains::kusama_messages_to_polkadot::run as relay_messages;
// Send-message / Estimate-fee
#[allow(unused_imports)]
use bp_polkadot::TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
// Send-message
#[allow(unused_imports)]
use relay_kusama_client::runtime::kusama_to_polkadot_account_ownership_digest as account_ownership_digest;
$generic
}
FullBridge::PolkadotToKusama => {
type Source = relay_polkadot_client::Polkadot;
#[allow(dead_code)]
type Target = relay_kusama_client::Kusama;
// Derive-account
#[allow(unused_imports)]
use bp_kusama::derive_account_from_polkadot_id as derive_account;
// Relay-messages
#[allow(unused_imports)]
use crate::chains::polkadot_messages_to_kusama::run as relay_messages;
// Send-message / Estimate-fee
#[allow(unused_imports)]
use bp_kusama::TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD;
// Send-message
#[allow(unused_imports)]
use relay_polkadot_client::runtime::polkadot_to_kusama_account_ownership_digest as account_ownership_digest;
$generic
}
}
@@ -46,6 +46,8 @@ pub enum InitBridgeName {
WestendToMillau,
RococoToWococo,
WococoToRococo,
KusamaToPolkadot,
PolkadotToKusama,
}
macro_rules! select_bridge {
@@ -127,6 +129,34 @@ macro_rules! select_bridge {
)
}
$generic
}
InitBridgeName::KusamaToPolkadot => {
type Source = relay_kusama_client::Kusama;
type Target = relay_polkadot_client::Polkadot;
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa(
relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize(init_data),
)
}
$generic
}
InitBridgeName::PolkadotToKusama => {
type Source = relay_polkadot_client::Polkadot;
type Target = relay_kusama_client::Kusama;
fn encode_init_bridge(
init_data: InitializationData<<Source as ChainBase>::Header>,
) -> <Target as Chain>::Call {
relay_kusama_client::runtime::Call::BridgePolkadotGrandpa(
relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize(init_data),
)
}
$generic
}
}
@@ -49,6 +49,8 @@ pub enum RelayHeadersBridge {
WestendToMillau,
RococoToWococo,
WococoToRococo,
KusamaToPolkadot,
PolkadotToKusama,
}
macro_rules! select_bridge {
@@ -87,6 +89,20 @@ macro_rules! select_bridge {
type Target = relay_rococo_client::Rococo;
type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo;
$generic
}
RelayHeadersBridge::KusamaToPolkadot => {
type Source = relay_kusama_client::Kusama;
type Target = relay_polkadot_client::Polkadot;
type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot;
$generic
}
RelayHeadersBridge::PolkadotToKusama => {
type Source = relay_polkadot_client::Polkadot;
type Target = relay_kusama_client::Kusama;
type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama;
$generic
}
}
@@ -26,8 +26,10 @@ use futures::{FutureExt, TryFutureExt};
use structopt::StructOpt;
use strum::VariantNames;
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use codec::Encode;
use relay_substrate_client::{AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction};
use relay_utils::metrics::MetricsParams;
use sp_core::{Bytes, Pair};
use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane};
use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay;
@@ -47,6 +49,7 @@ const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05;
pub enum RelayHeadersAndMessages {
MillauRialto(MillauRialtoHeadersAndMessages),
RococoWococo(RococoWococoHeadersAndMessages),
KusamaPolkadot(KusamaPolkadotHeadersAndMessages),
}
/// Parameters that have the same names across all bridges.
@@ -57,6 +60,9 @@ pub struct HeadersAndMessagesSharedParams {
lane: Vec<HexLaneId>,
#[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")]
relayer_mode: RelayerMode,
/// Create relayers fund accounts on both chains, if it does not exists yet.
#[structopt(long)]
create_relayers_fund_accounts: bool,
/// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed.
#[structopt(long)]
only_mandatory_headers: bool,
@@ -89,7 +95,6 @@ macro_rules! declare_bridge_options {
right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>],
}
#[allow(unreachable_patterns)]
impl From<RelayHeadersAndMessages> for [<$chain1 $chain2 HeadersAndMessages>] {
fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] {
match relay_params {
@@ -117,6 +122,9 @@ macro_rules! select_bridge {
type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto;
type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau;
type LeftAccountIdConverter = bp_millau::AccountIdConverter;
type RightAccountIdConverter = bp_rialto::AccountIdConverter;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH;
@@ -129,6 +137,22 @@ macro_rules! select_bridge {
update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate,
};
async fn left_create_account(
_left_client: Client<Left>,
_left_sign: <Left as TransactionSignScheme>::AccountKeyPair,
_account_id: AccountIdOf<Left>,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Account creation is not supported by this bridge"))
}
async fn right_create_account(
_right_client: Client<Right>,
_right_sign: <Right as TransactionSignScheme>::AccountKeyPair,
_account_id: AccountIdOf<Right>,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Account creation is not supported by this bridge"))
}
$generic
}
RelayHeadersAndMessages::RococoWococo(_) => {
@@ -143,6 +167,9 @@ macro_rules! select_bridge {
type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo;
type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo;
type LeftAccountIdConverter = bp_rococo::AccountIdConverter;
type RightAccountIdConverter = bp_wococo::AccountIdConverter;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH;
@@ -169,6 +196,113 @@ macro_rules! select_bridge {
Err(anyhow::format_err!("Conversion rate is not supported by this bridge"))
}
async fn left_create_account(
_left_client: Client<Left>,
_left_sign: <Left as TransactionSignScheme>::AccountKeyPair,
_account_id: AccountIdOf<Left>,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Account creation is not supported by this bridge"))
}
async fn right_create_account(
_right_client: Client<Right>,
_right_sign: <Right as TransactionSignScheme>::AccountKeyPair,
_account_id: AccountIdOf<Right>,
) -> anyhow::Result<()> {
Err(anyhow::format_err!("Account creation is not supported by this bridge"))
}
$generic
}
RelayHeadersAndMessages::KusamaPolkadot(_) => {
type Params = KusamaPolkadotHeadersAndMessages;
type Left = relay_kusama_client::Kusama;
type Right = relay_polkadot_client::Polkadot;
type LeftToRightFinality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot;
type RightToLeftFinality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama;
type LeftToRightMessages = crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot;
type RightToLeftMessages = crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama;
type LeftAccountIdConverter = bp_kusama::AccountIdConverter;
type RightAccountIdConverter = bp_polkadot::AccountIdConverter;
const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = bp_kusama::SESSION_LENGTH;
const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = bp_polkadot::SESSION_LENGTH;
use crate::chains::kusama_messages_to_polkadot::{
add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages,
update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate,
};
use crate::chains::polkadot_messages_to_kusama::{
add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages,
update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate,
};
async fn left_create_account(
left_client: Client<Left>,
left_sign: <Left as TransactionSignScheme>::AccountKeyPair,
account_id: AccountIdOf<Left>,
) -> anyhow::Result<()> {
let left_genesis_hash = *left_client.genesis_hash();
left_client
.submit_signed_extrinsic(left_sign.public().into(), move |_, transaction_nonce| {
Bytes(
Left::sign_transaction(
left_genesis_hash,
&left_sign,
relay_substrate_client::TransactionEra::immortal(),
UnsignedTransaction::new(
relay_kusama_client::runtime::Call::Balances(
relay_kusama_client::runtime::BalancesCall::transfer(
bp_kusama::AccountAddress::Id(account_id),
bp_kusama::EXISTENTIAL_DEPOSIT.into(),
),
),
transaction_nonce,
),
)
.encode(),
)
})
.await
.map(drop)
.map_err(|e| anyhow::format_err!("{}", e))
}
async fn right_create_account(
right_client: Client<Right>,
right_sign: <Right as TransactionSignScheme>::AccountKeyPair,
account_id: AccountIdOf<Right>,
) -> anyhow::Result<()> {
let right_genesis_hash = *right_client.genesis_hash();
right_client
.submit_signed_extrinsic(right_sign.public().into(), move |_, transaction_nonce| {
Bytes(
Right::sign_transaction(
right_genesis_hash,
&right_sign,
relay_substrate_client::TransactionEra::immortal(),
UnsignedTransaction::new(
relay_polkadot_client::runtime::Call::Balances(
relay_polkadot_client::runtime::BalancesCall::transfer(
bp_polkadot::AccountAddress::Id(account_id),
bp_polkadot::EXISTENTIAL_DEPOSIT.into(),
),
),
transaction_nonce,
),
)
.encode(),
)
})
.await
.map(drop)
.map_err(|e| anyhow::format_err!("{}", e))
}
$generic
}
}
@@ -180,9 +314,12 @@ declare_chain_options!(Millau, millau);
declare_chain_options!(Rialto, rialto);
declare_chain_options!(Rococo, rococo);
declare_chain_options!(Wococo, wococo);
declare_chain_options!(Kusama, kusama);
declare_chain_options!(Polkadot, polkadot);
// All supported bridges.
declare_bridge_options!(Millau, Rialto);
declare_bridge_options!(Rococo, Wococo);
declare_bridge_options!(Kusama, Polkadot);
impl RelayHeadersAndMessages {
/// Run the command.
@@ -275,6 +412,26 @@ impl RelayHeadersAndMessages {
);
}
if params.shared.create_relayers_fund_accounts {
let relayer_fund_acount_id =
pallet_bridge_messages::relayer_fund_account_id::<AccountIdOf<Left>, LeftAccountIdConverter>();
let relayers_fund_account_balance =
left_client.free_native_balance(relayer_fund_acount_id.clone()).await;
if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance {
log::info!(target: "bridge", "Going to create relayers fund account at {}.", Left::NAME);
left_create_account(left_client.clone(), left_sign.clone(), relayer_fund_acount_id).await?;
}
let relayer_fund_acount_id =
pallet_bridge_messages::relayer_fund_account_id::<AccountIdOf<Right>, RightAccountIdConverter>();
let relayers_fund_account_balance =
right_client.free_native_balance(relayer_fund_acount_id.clone()).await;
if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance {
log::info!(target: "bridge", "Going to create relayers fund account at {}.", Right::NAME);
right_create_account(right_client.clone(), right_sign.clone(), relayer_fund_acount_id).await?;
}
}
let left_to_right_on_demand_headers = OnDemandHeadersRelay::new(
left_client.clone(),
right_client.clone(),