Common crate for substrate-relay (#1082)

* lib-substrate-relay

* pass to build

* remove unused file

* clippy && tests

* Changed follow suggestions

* License

* Make changes follow suggested

* docs

* fix fmt
This commit is contained in:
fewensa
2021-08-27 17:23:25 +08:00
committed by Bastian Köcher
parent 1527f515de
commit 8cb2633437
26 changed files with 628 additions and 328 deletions
+3 -3
View File
@@ -14,7 +14,6 @@ futures = "0.3.12"
hex = "0.4" hex = "0.4"
log = "0.4.14" log = "0.4.14"
num-format = "0.4" num-format = "0.4"
num-traits = "0.2"
paste = "1.0" paste = "1.0"
structopt = "0.3" structopt = "0.3"
strum = { version = "0.21.0", features = ["derive"] } strum = { version = "0.21.0", features = ["derive"] }
@@ -33,9 +32,7 @@ bp-wococo = { path = "../../primitives/chain-wococo" }
bp-runtime = { path = "../../primitives/runtime" } bp-runtime = { path = "../../primitives/runtime" }
bp-westend = { path = "../../primitives/chain-westend" } bp-westend = { path = "../../primitives/chain-westend" }
bridge-runtime-common = { path = "../../bin/runtime-common" } bridge-runtime-common = { path = "../../bin/runtime-common" }
finality-grandpa = { version = "0.14.0" }
finality-relay = { path = "../finality" } finality-relay = { path = "../finality" }
headers-relay = { path = "../headers" }
messages-relay = { path = "../messages" } messages-relay = { path = "../messages" }
millau-runtime = { path = "../../bin/millau/runtime" } millau-runtime = { path = "../../bin/millau/runtime" }
pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-messages = { path = "../../modules/messages" }
@@ -49,6 +46,7 @@ relay-substrate-client = { path = "../client-substrate" }
relay-utils = { path = "../utils" } relay-utils = { path = "../utils" }
relay-westend-client = { path = "../client-westend" } relay-westend-client = { path = "../client-westend" }
rialto-runtime = { path = "../../bin/rialto/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" }
substrate-relay-helper = { path = "../lib-substrate-relay" }
# Substrate Dependencies # Substrate Dependencies
@@ -64,3 +62,5 @@ hex-literal = "0.3"
pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-grandpa = { path = "../../modules/grandpa" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
tempdir = "0.3" tempdir = "0.3"
finality-grandpa = { version = "0.14.0" }
@@ -16,25 +16,40 @@
//! Millau-to-Rialto headers sync entrypoint. //! Millau-to-Rialto headers sync entrypoint.
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode; use codec::Encode;
use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader};
use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{Chain, TransactionSignScheme};
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_header_chain::justification::GrandpaJustification;
use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader};
use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
/// Millau-to-Rialto finality sync pipeline. /// Millau-to-Rialto finality sync pipeline.
pub(crate) type MillauFinalityToRialto = SubstrateFinalityToSubstrate<Millau, Rialto, RialtoSigningParams>; pub(crate) type FinalityPipelineMillauToRialto = SubstrateFinalityToSubstrate<Millau, Rialto, RialtoSigningParams>;
#[derive(Clone, Debug)]
pub(crate) struct MillauFinalityToRialto {
finality_pipeline: FinalityPipelineMillauToRialto,
}
impl MillauFinalityToRialto {
pub fn new(target_client: Client<Rialto>, target_sign: RialtoSigningParams) -> Self {
Self {
finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign),
}
}
}
impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
type FinalitySyncPipeline = FinalityPipelineMillauToRialto;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
type TargetChain = Rialto; type TargetChain = Rialto;
fn transactions_author(&self) -> bp_rialto::AccountId { fn transactions_author(&self) -> bp_rialto::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.finality_pipeline.target_sign.public().as_array_ref()).into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -45,8 +60,13 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto {
) -> Bytes { ) -> Bytes {
let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into(); let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction = Rialto::sign_transaction(
genesis_hash,
&self.finality_pipeline.target_sign,
transaction_nonce,
call,
);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
@@ -16,31 +16,39 @@
//! Millau-to-Rialto messages sync entrypoint. //! Millau-to-Rialto messages sync entrypoint.
use crate::messages_lane::{ use std::{ops::RangeInclusive, time::Duration};
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate, use codec::Encode;
}; use frame_support::dispatch::GetDispatchInfo;
use crate::messages_source::SubstrateMessagesSource; use sp_core::{Bytes, Pair};
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce; use bp_messages::MessageNonce;
use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use messages_relay::message_lane::MessageLane; use messages_relay::message_lane::MessageLane;
use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams; use relay_utils::metrics::MetricsParams;
use sp_core::{Bytes, Pair}; use substrate_relay_helper::messages_lane::{
use std::{ops::RangeInclusive, time::Duration}; select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate,
};
use substrate_relay_helper::messages_source::SubstrateMessagesSource;
use substrate_relay_helper::messages_target::SubstrateMessagesTarget;
/// Millau-to-Rialto message lane. /// Millau-to-Rialto message lane.
pub type MillauMessagesToRialto = pub type MessageLaneMillauMessagesToRialto =
SubstrateMessageLaneToSubstrate<Millau, MillauSigningParams, Rialto, RialtoSigningParams>; SubstrateMessageLaneToSubstrate<Millau, MillauSigningParams, Rialto, RialtoSigningParams>;
#[derive(Clone)]
pub struct MillauMessagesToRialto {
message_lane: MessageLaneMillauMessagesToRialto,
}
impl SubstrateMessageLane for MillauMessagesToRialto { impl SubstrateMessageLane for MillauMessagesToRialto {
type MessageLane = MessageLaneMillauMessagesToRialto;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD;
@@ -58,21 +66,22 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
type TargetChain = Rialto; type TargetChain = Rialto;
fn source_transactions_author(&self) -> bp_millau::AccountId { fn source_transactions_author(&self) -> bp_millau::AccountId {
(*self.source_sign.public().as_array_ref()).into() (*self.message_lane.source_sign.public().as_array_ref()).into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
&self, &self,
transaction_nonce: <Millau as Chain>::Index, transaction_nonce: <Millau as Chain>::Index,
_generated_at_block: RialtoHeaderId, _generated_at_block: RialtoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof, proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes { ) -> Bytes {
let (relayers_state, proof) = proof; let (relayers_state, proof) = proof;
let call: millau_runtime::Call = let call: millau_runtime::Call =
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.message_lane.source_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); let transaction =
Millau::sign_transaction(genesis_hash, &self.message_lane.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: {}/{}",
@@ -85,7 +94,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
} }
fn target_transactions_author(&self) -> bp_rialto::AccountId { fn target_transactions_author(&self) -> bp_rialto::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.message_lane.target_sign.public().as_array_ref()).into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -93,7 +102,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
transaction_nonce: <Rialto as Chain>::Index, transaction_nonce: <Rialto as Chain>::Index,
_generated_at_header: MillauHeaderId, _generated_at_header: MillauHeaderId,
_nonces: RangeInclusive<MessageNonce>, _nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof, proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes { ) -> Bytes {
let (dispatch_weight, proof) = proof; let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof { let FromBridgedChainMessagesProof {
@@ -103,15 +112,16 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
} = proof; } = proof;
let messages_count = nonces_end - nonces_start + 1; let messages_count = nonces_end - nonces_start + 1;
let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof(
self.relayer_id_at_source.clone(), self.message_lane.relayer_id_at_source.clone(),
proof, proof,
messages_count as _, messages_count as _,
dispatch_weight, dispatch_weight,
) )
.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.message_lane.target_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction =
Rialto::sign_transaction(genesis_hash, &self.message_lane.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: {}/{}",
@@ -142,11 +152,13 @@ pub async fn run(
let lane_id = params.lane_id; let lane_id = params.lane_id;
let source_client = params.source_client; let source_client = params.source_client;
let lane = MillauMessagesToRialto { let lane = MillauMessagesToRialto {
source_client: source_client.clone(), message_lane: SubstrateMessageLaneToSubstrate {
source_sign: params.source_sign, source_client: source_client.clone(),
target_client: params.target_client.clone(), source_sign: params.source_sign,
target_sign: params.target_sign, target_client: params.target_client.clone(),
relayer_id_at_source: relayer_id_at_millau, target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_millau,
},
}; };
// 2/3 is reserved for proofs and tx overhead // 2/3 is reserved for proofs and tx overhead
@@ -166,7 +178,7 @@ pub async fn run(
Max messages size in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\
Relayer mode: {:?}", Relayer mode: {:?}",
lane.relayer_id_at_source, lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch, max_messages_in_single_batch,
max_messages_size_in_single_batch, max_messages_size_in_single_batch,
max_messages_weight_in_single_batch, max_messages_weight_in_single_batch,
@@ -175,7 +187,7 @@ pub async fn run(
let (metrics_params, metrics_values) = add_standalone_metrics( let (metrics_params, metrics_values) = add_standalone_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::< Some(messages_relay::message_lane_loop::metrics_prefix::<
MillauMessagesToRialto, <MillauMessagesToRialto as SubstrateMessageLane>::MessageLane,
>(&lane_id)), >(&lane_id)),
params.metrics_params, params.metrics_params,
source_client.clone(), source_client.clone(),
@@ -223,7 +235,7 @@ pub(crate) fn add_standalone_metrics(
metrics_params: MetricsParams, metrics_params: MetricsParams,
source_client: Client<Millau>, source_client: Client<Millau>,
) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> {
crate::messages_lane::add_standalone_metrics::<MillauMessagesToRialto>( substrate_relay_helper::messages_lane::add_standalone_metrics::<MillauMessagesToRialto>(
metrics_prefix, metrics_prefix,
metrics_params, metrics_params,
source_client, source_client,
+7 -25
View File
@@ -41,7 +41,7 @@ pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "bitcoin";
/// The identifier of token, which value is associated with Millau token value by relayer. /// The identifier of token, which value is associated with Millau token value by relayer.
pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "wrapped-bitcoin"; pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "wrapped-bitcoin";
use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; use relay_utils::metrics::MetricsParams;
pub(crate) fn add_polkadot_kusama_price_metrics<T: finality_relay::FinalitySyncPipeline>( pub(crate) fn add_polkadot_kusama_price_metrics<T: finality_relay::FinalitySyncPipeline>(
prefix: Option<String>, prefix: Option<String>,
@@ -50,33 +50,15 @@ pub(crate) fn add_polkadot_kusama_price_metrics<T: finality_relay::FinalitySyncP
// Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama
// relays, but we want to test metrics/dashboards in advance // relays, but we want to test metrics/dashboards in advance
Ok(relay_utils::relay_metrics(prefix, params) Ok(relay_utils::relay_metrics(prefix, params)
.standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "polkadot"))? .standalone_metric(|registry, prefix| {
.standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "kusama"))? substrate_relay_helper::helpers::token_price_metric(registry, prefix, "polkadot")
})?
.standalone_metric(|registry, prefix| {
substrate_relay_helper::helpers::token_price_metric(registry, prefix, "kusama")
})?
.into_params()) .into_params())
} }
/// Creates standalone token price metric.
pub(crate) fn token_price_metric(
registry: &Registry,
prefix: Option<&str>,
token_id: &str,
) -> Result<FloatJsonValueMetric, PrometheusError> {
FloatJsonValueMetric::new(
registry,
prefix,
format!(
"https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc",
token_id
),
format!("$.{}.btc", token_id),
format!("{}_to_base_conversion_rate", token_id.replace("-", "_")),
format!(
"Rate used to convert from {} to some BASE tokens",
token_id.to_uppercase()
),
)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::cli::{encode_call, send_message}; use crate::cli::{encode_call, send_message};
@@ -16,25 +16,41 @@
//! Rialto-to-Millau headers sync entrypoint. //! Rialto-to-Millau headers sync entrypoint.
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode; use codec::Encode;
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader};
use relay_substrate_client::{Chain, TransactionSignScheme};
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_header_chain::justification::GrandpaJustification;
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
/// Rialto-to-Millau finality sync pipeline. /// Rialto-to-Millau finality sync pipeline.
pub(crate) type RialtoFinalityToMillau = SubstrateFinalityToSubstrate<Rialto, Millau, MillauSigningParams>; pub(crate) type FinalityPipelineRialtoFinalityToMillau =
SubstrateFinalityToSubstrate<Rialto, Millau, MillauSigningParams>;
#[derive(Clone, Debug)]
pub struct RialtoFinalityToMillau {
finality_pipeline: FinalityPipelineRialtoFinalityToMillau,
}
impl RialtoFinalityToMillau {
pub fn new(target_client: Client<Millau>, target_sign: MillauSigningParams) -> Self {
Self {
finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new(target_client, target_sign),
}
}
}
impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
type FinalitySyncPipeline = FinalityPipelineRialtoFinalityToMillau;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
type TargetChain = Millau; type TargetChain = Millau;
fn transactions_author(&self) -> bp_millau::AccountId { fn transactions_author(&self) -> bp_millau::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.finality_pipeline.target_sign.public().as_array_ref()).into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -49,8 +65,13 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau {
>::submit_finality_proof(header.into_inner(), proof) >::submit_finality_proof(header.into_inner(), proof)
.into(); .into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction = Millau::sign_transaction(
genesis_hash,
&self.finality_pipeline.target_sign,
transaction_nonce,
call,
);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
@@ -16,31 +16,39 @@
//! Rialto-to-Millau messages sync entrypoint. //! Rialto-to-Millau messages sync entrypoint.
use crate::messages_lane::{ use std::{ops::RangeInclusive, time::Duration};
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate, use codec::Encode;
}; use frame_support::dispatch::GetDispatchInfo;
use crate::messages_source::SubstrateMessagesSource; use sp_core::{Bytes, Pair};
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce; use bp_messages::MessageNonce;
use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use frame_support::dispatch::GetDispatchInfo;
use messages_relay::message_lane::MessageLane; use messages_relay::message_lane::MessageLane;
use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams};
use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams; use relay_utils::metrics::MetricsParams;
use sp_core::{Bytes, Pair}; use substrate_relay_helper::messages_lane::{
use std::{ops::RangeInclusive, time::Duration}; select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate,
};
use substrate_relay_helper::messages_source::SubstrateMessagesSource;
use substrate_relay_helper::messages_target::SubstrateMessagesTarget;
/// Rialto-to-Millau message lane. /// Rialto-to-Millau message lane.
pub type RialtoMessagesToMillau = pub type MessageLaneRialtoMessagesToMillau =
SubstrateMessageLaneToSubstrate<Rialto, RialtoSigningParams, Millau, MillauSigningParams>; SubstrateMessageLaneToSubstrate<Rialto, RialtoSigningParams, Millau, MillauSigningParams>;
#[derive(Clone)]
pub struct RialtoMessagesToMillau {
message_lane: MessageLaneRialtoMessagesToMillau,
}
impl SubstrateMessageLane for RialtoMessagesToMillau { impl SubstrateMessageLane for RialtoMessagesToMillau {
type MessageLane = MessageLaneRialtoMessagesToMillau;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD;
@@ -58,21 +66,22 @@ 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.public().as_array_ref()).into() (*self.message_lane.source_sign.public().as_array_ref()).into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
&self, &self,
transaction_nonce: <Rialto as Chain>::Index, transaction_nonce: <Rialto as Chain>::Index,
_generated_at_block: MillauHeaderId, _generated_at_block: MillauHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof, proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes { ) -> Bytes {
let (relayers_state, proof) = proof; let (relayers_state, proof) = proof;
let call: rialto_runtime::Call = let call: rialto_runtime::Call =
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.message_lane.source_client.genesis_hash();
let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); let transaction =
Rialto::sign_transaction(genesis_hash, &self.message_lane.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: {}/{}",
@@ -85,7 +94,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
} }
fn target_transactions_author(&self) -> bp_millau::AccountId { fn target_transactions_author(&self) -> bp_millau::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.message_lane.target_sign.public().as_array_ref()).into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -93,7 +102,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
transaction_nonce: <Millau as Chain>::Index, transaction_nonce: <Millau as Chain>::Index,
_generated_at_header: RialtoHeaderId, _generated_at_header: RialtoHeaderId,
_nonces: RangeInclusive<MessageNonce>, _nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof, proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes { ) -> Bytes {
let (dispatch_weight, proof) = proof; let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof { let FromBridgedChainMessagesProof {
@@ -103,15 +112,16 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
} = proof; } = proof;
let messages_count = nonces_end - nonces_start + 1; let messages_count = nonces_end - nonces_start + 1;
let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof(
self.relayer_id_at_source.clone(), self.message_lane.relayer_id_at_source.clone(),
proof, proof,
messages_count as _, messages_count as _,
dispatch_weight, dispatch_weight,
) )
.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.message_lane.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction =
Millau::sign_transaction(genesis_hash, &self.message_lane.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: {}/{}",
@@ -142,11 +152,13 @@ pub async fn run(
let lane_id = params.lane_id; let lane_id = params.lane_id;
let source_client = params.source_client; let source_client = params.source_client;
let lane = RialtoMessagesToMillau { let lane = RialtoMessagesToMillau {
source_client: source_client.clone(), message_lane: SubstrateMessageLaneToSubstrate {
source_sign: params.source_sign, source_client: source_client.clone(),
target_client: params.target_client.clone(), source_sign: params.source_sign,
target_sign: params.target_sign, target_client: params.target_client.clone(),
relayer_id_at_source: relayer_id_at_rialto, target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_rialto,
},
}; };
// 2/3 is reserved for proofs and tx overhead // 2/3 is reserved for proofs and tx overhead
@@ -165,7 +177,7 @@ pub async fn run(
Max messages size in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\
Relayer mode: {:?}", Relayer mode: {:?}",
lane.relayer_id_at_source, lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch, max_messages_in_single_batch,
max_messages_size_in_single_batch, max_messages_size_in_single_batch,
max_messages_weight_in_single_batch, max_messages_weight_in_single_batch,
@@ -174,7 +186,7 @@ pub async fn run(
let (metrics_params, metrics_values) = add_standalone_metrics( let (metrics_params, metrics_values) = add_standalone_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::< Some(messages_relay::message_lane_loop::metrics_prefix::<
RialtoMessagesToMillau, <RialtoMessagesToMillau as SubstrateMessageLane>::MessageLane,
>(&lane_id)), >(&lane_id)),
params.metrics_params, params.metrics_params,
source_client.clone(), source_client.clone(),
@@ -222,7 +234,7 @@ pub(crate) fn add_standalone_metrics(
metrics_params: MetricsParams, metrics_params: MetricsParams,
source_client: Client<Rialto>, source_client: Client<Rialto>,
) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> {
crate::messages_lane::add_standalone_metrics::<RialtoMessagesToMillau>( substrate_relay_helper::messages_lane::add_standalone_metrics::<RialtoMessagesToMillau>(
metrics_prefix, metrics_prefix,
metrics_params, metrics_params,
source_client, source_client,
@@ -16,43 +16,63 @@
//! Rococo-to-Wococo headers sync entrypoint. //! Rococo-to-Wococo headers sync entrypoint.
use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY;
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode; 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}; use sp_core::{Bytes, Pair};
use bp_header_chain::justification::GrandpaJustification;
use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo};
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY;
/// Rococo-to-Wococo finality sync pipeline. /// Rococo-to-Wococo finality sync pipeline.
pub(crate) type RococoFinalityToWococo = SubstrateFinalityToSubstrate<Rococo, Wococo, WococoSigningParams>; pub(crate) type FinalityPipelineRococoFinalityToWococo =
SubstrateFinalityToSubstrate<Rococo, Wococo, WococoSigningParams>;
#[derive(Clone, Debug)]
pub(crate) struct RococoFinalityToWococo {
finality_pipeline: FinalityPipelineRococoFinalityToWococo,
}
impl RococoFinalityToWococo {
pub fn new(target_client: Client<Wococo>, target_sign: WococoSigningParams) -> Self {
Self {
finality_pipeline: FinalityPipelineRococoFinalityToWococo::new(target_client, target_sign),
}
}
}
impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
type TargetChain = Wococo; type TargetChain = Wococo;
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> { fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(Some(finality_relay::metrics_prefix::<Self>()), params) crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(
Some(finality_relay::metrics_prefix::<Self::FinalitySyncPipeline>()),
params,
)
} }
fn start_relay_guards(&self) { fn start_relay_guards(&self) {
relay_substrate_client::guard::abort_on_spec_version_change( relay_substrate_client::guard::abort_on_spec_version_change(
self.target_client.clone(), self.finality_pipeline.target_client.clone(),
bp_wococo::VERSION.spec_version, bp_wococo::VERSION.spec_version,
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
self.target_client.clone(), self.finality_pipeline.target_client.clone(),
self.transactions_author(), self.transactions_author(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
fn transactions_author(&self) -> bp_wococo::AccountId { fn transactions_author(&self) -> bp_wococo::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.finality_pipeline.target_sign.public().as_array_ref()).into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -64,8 +84,13 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo(
relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof), relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof),
); );
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction = Wococo::sign_transaction(
genesis_hash,
&self.finality_pipeline.target_sign,
transaction_nonce,
call,
);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
@@ -16,30 +16,38 @@
//! Rococo-to-Wococo messages sync entrypoint. //! Rococo-to-Wococo messages sync entrypoint.
use crate::messages_lane::{ use std::{ops::RangeInclusive, time::Duration};
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate, use codec::Encode;
}; use sp_core::{Bytes, Pair};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce; use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane; use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams; use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair}; use substrate_relay_helper::messages_lane::{
use std::{ops::RangeInclusive, time::Duration}; select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate,
};
use substrate_relay_helper::messages_source::SubstrateMessagesSource;
use substrate_relay_helper::messages_target::SubstrateMessagesTarget;
/// Rococo-to-Wococo message lane. /// Rococo-to-Wococo message lane.
pub type RococoMessagesToWococo = pub type MessageLaneRococoMessagesToWococo =
SubstrateMessageLaneToSubstrate<Rococo, RococoSigningParams, Wococo, WococoSigningParams>; SubstrateMessageLaneToSubstrate<Rococo, RococoSigningParams, Wococo, WococoSigningParams>;
#[derive(Clone)]
pub struct RococoMessagesToWococo {
message_lane: MessageLaneRococoMessagesToWococo,
}
impl SubstrateMessageLane for RococoMessagesToWococo { impl SubstrateMessageLane for RococoMessagesToWococo {
type MessageLane = MessageLaneRococoMessagesToWococo;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD;
@@ -57,14 +65,14 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
type TargetChain = Wococo; type TargetChain = Wococo;
fn source_transactions_author(&self) -> bp_rococo::AccountId { fn source_transactions_author(&self) -> bp_rococo::AccountId {
(*self.source_sign.public().as_array_ref()).into() (*self.message_lane.source_sign.public().as_array_ref()).into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
&self, &self,
transaction_nonce: <Rococo as Chain>::Index, transaction_nonce: <Rococo as Chain>::Index,
_generated_at_block: WococoHeaderId, _generated_at_block: WococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof, proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes { ) -> Bytes {
let (relayers_state, proof) = proof; let (relayers_state, proof) = proof;
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
@@ -73,8 +81,9 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
relayers_state, relayers_state,
), ),
); );
let genesis_hash = *self.source_client.genesis_hash(); let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); let transaction =
Rococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Wococo -> Rococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}", "Prepared Wococo -> Rococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
@@ -86,7 +95,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
} }
fn target_transactions_author(&self) -> bp_wococo::AccountId { fn target_transactions_author(&self) -> bp_wococo::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.message_lane.target_sign.public().as_array_ref()).into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -94,7 +103,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
transaction_nonce: <Wococo as Chain>::Index, transaction_nonce: <Wococo as Chain>::Index,
_generated_at_header: RococoHeaderId, _generated_at_header: RococoHeaderId,
_nonces: RangeInclusive<MessageNonce>, _nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof, proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes { ) -> Bytes {
let (dispatch_weight, proof) = proof; let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof { let FromBridgedChainMessagesProof {
@@ -106,14 +115,15 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(), self.message_lane.relayer_id_at_source.clone(),
proof, proof,
messages_count as _, messages_count as _,
dispatch_weight, dispatch_weight,
), ),
); );
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction =
Wococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Rococo -> Wococo delivery transaction. Weight: <unknown>/{}, size: {}/{}", "Prepared Rococo -> Wococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
@@ -151,11 +161,13 @@ pub async fn run(
let lane_id = params.lane_id; let lane_id = params.lane_id;
let source_client = params.source_client; let source_client = params.source_client;
let lane = RococoMessagesToWococo { let lane = RococoMessagesToWococo {
source_client: source_client.clone(), message_lane: SubstrateMessageLaneToSubstrate {
source_sign: params.source_sign, source_client: source_client.clone(),
target_client: params.target_client.clone(), source_sign: params.source_sign,
target_sign: params.target_sign, target_client: params.target_client.clone(),
relayer_id_at_source: relayer_id_at_rococo, target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_rococo,
},
}; };
// 2/3 is reserved for proofs and tx overhead // 2/3 is reserved for proofs and tx overhead
@@ -180,7 +192,7 @@ pub async fn run(
Max messages size in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\
Relayer mode: {:?}", Relayer mode: {:?}",
lane.relayer_id_at_source, lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch, max_messages_in_single_batch,
max_messages_size_in_single_batch, max_messages_size_in_single_batch,
max_messages_weight_in_single_batch, max_messages_weight_in_single_batch,
@@ -189,7 +201,7 @@ pub async fn run(
let (metrics_params, metrics_values) = add_standalone_metrics( let (metrics_params, metrics_values) = add_standalone_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::< Some(messages_relay::message_lane_loop::metrics_prefix::<
RococoMessagesToWococo, <RococoMessagesToWococo as SubstrateMessageLane>::MessageLane,
>(&lane_id)), >(&lane_id)),
params.metrics_params, params.metrics_params,
source_client.clone(), source_client.clone(),
@@ -237,7 +249,7 @@ pub(crate) fn add_standalone_metrics(
metrics_params: MetricsParams, metrics_params: MetricsParams,
source_client: Client<Rococo>, source_client: Client<Rococo>,
) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> {
crate::messages_lane::add_standalone_metrics::<RococoMessagesToWococo>( substrate_relay_helper::messages_lane::add_standalone_metrics::<RococoMessagesToWococo>(
metrics_prefix, metrics_prefix,
metrics_params, metrics_params,
source_client, source_client,
@@ -16,30 +16,49 @@
//! Westend-to-Millau headers sync entrypoint. //! Westend-to-Millau headers sync entrypoint.
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
use bp_header_chain::justification::GrandpaJustification;
use codec::Encode; use codec::Encode;
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
use relay_substrate_client::{Chain, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend};
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
use bp_header_chain::justification::GrandpaJustification;
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams;
use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend};
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
/// Westend-to-Millau finality sync pipeline. /// Westend-to-Millau finality sync pipeline.
pub(crate) type WestendFinalityToMillau = SubstrateFinalityToSubstrate<Westend, Millau, MillauSigningParams>; pub(crate) type FinalityPipelineWestendFinalityToMillau =
SubstrateFinalityToSubstrate<Westend, Millau, MillauSigningParams>;
#[derive(Clone, Debug)]
pub(crate) struct WestendFinalityToMillau {
finality_pipeline: FinalityPipelineWestendFinalityToMillau,
}
impl WestendFinalityToMillau {
pub fn new(target_client: Client<Millau>, target_sign: MillauSigningParams) -> Self {
Self {
finality_pipeline: FinalityPipelineWestendFinalityToMillau::new(target_client, target_sign),
}
}
}
impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau {
type FinalitySyncPipeline = FinalityPipelineWestendFinalityToMillau;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD;
type TargetChain = Millau; type TargetChain = Millau;
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> { fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(Some(finality_relay::metrics_prefix::<Self>()), params) crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(
Some(finality_relay::metrics_prefix::<Self::FinalitySyncPipeline>()),
params,
)
} }
fn transactions_author(&self) -> bp_millau::AccountId { fn transactions_author(&self) -> bp_millau::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.finality_pipeline.target_sign.public().as_array_ref()).into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -54,8 +73,13 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau {
>::submit_finality_proof(header.into_inner(), proof) >::submit_finality_proof(header.into_inner(), proof)
.into(); .into();
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction = Millau::sign_transaction(
genesis_hash,
&self.finality_pipeline.target_sign,
transaction_nonce,
call,
);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
@@ -16,15 +16,15 @@
//! Wococo-to-Rococo headers sync entrypoint. //! Wococo-to-Rococo headers sync entrypoint.
use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use codec::Encode;
use sp_core::{Bytes, Pair};
use bp_header_chain::justification::GrandpaJustification; use bp_header_chain::justification::GrandpaJustification;
use codec::Encode;
use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams; use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo};
use sp_core::{Bytes, Pair}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate};
/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat
/// relay as gone wild. /// relay as gone wild.
@@ -34,31 +34,50 @@ use sp_core::{Bytes, Pair};
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000;
/// Wococo-to-Rococo finality sync pipeline. /// Wococo-to-Rococo finality sync pipeline.
pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate<Wococo, Rococo, RococoSigningParams>; pub(crate) type FinalityPipelineWococoFinalityToRococo =
SubstrateFinalityToSubstrate<Wococo, Rococo, RococoSigningParams>;
#[derive(Clone, Debug)]
pub(crate) struct WococoFinalityToRococo {
finality_pipeline: FinalityPipelineWococoFinalityToRococo,
}
impl WococoFinalityToRococo {
pub fn new(target_client: Client<Rococo>, target_sign: RococoSigningParams) -> Self {
Self {
finality_pipeline: FinalityPipelineWococoFinalityToRococo::new(target_client, target_sign),
}
}
}
impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo;
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
type TargetChain = Rococo; type TargetChain = Rococo;
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> { fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
crate::chains::add_polkadot_kusama_price_metrics::<Self>(Some(finality_relay::metrics_prefix::<Self>()), params) crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(
Some(finality_relay::metrics_prefix::<Self::FinalitySyncPipeline>()),
params,
)
} }
fn start_relay_guards(&self) { fn start_relay_guards(&self) {
relay_substrate_client::guard::abort_on_spec_version_change( relay_substrate_client::guard::abort_on_spec_version_change(
self.target_client.clone(), self.finality_pipeline.target_client.clone(),
bp_rococo::VERSION.spec_version, bp_rococo::VERSION.spec_version,
); );
relay_substrate_client::guard::abort_when_account_balance_decreased( relay_substrate_client::guard::abort_when_account_balance_decreased(
self.target_client.clone(), self.finality_pipeline.target_client.clone(),
self.transactions_author(), self.transactions_author(),
MAXIMAL_BALANCE_DECREASE_PER_DAY, MAXIMAL_BALANCE_DECREASE_PER_DAY,
); );
} }
fn transactions_author(&self) -> bp_rococo::AccountId { fn transactions_author(&self) -> bp_rococo::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.finality_pipeline.target_sign.public().as_array_ref()).into()
} }
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
@@ -70,8 +89,13 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo(
relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof), relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof),
); );
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction = Rococo::sign_transaction(
genesis_hash,
&self.finality_pipeline.target_sign,
transaction_nonce,
call,
);
Bytes(transaction.encode()) Bytes(transaction.encode())
} }
@@ -79,10 +103,12 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use frame_support::weights::WeightToFeePolynomial; use frame_support::weights::WeightToFeePolynomial;
use pallet_bridge_grandpa::weights::WeightInfo; use pallet_bridge_grandpa::weights::WeightInfo;
use super::*;
#[test] #[test]
fn maximal_balance_decrease_per_day_is_sane() { fn maximal_balance_decrease_per_day_is_sane() {
// Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified. // Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified.
@@ -16,30 +16,37 @@
//! Wococo-to-Rococo messages sync entrypoint. //! Wococo-to-Rococo messages sync entrypoint.
use crate::messages_lane::{ use std::{ops::RangeInclusive, time::Duration};
select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate, use codec::Encode;
}; use sp_core::{Bytes, Pair};
use crate::messages_source::SubstrateMessagesSource;
use crate::messages_target::SubstrateMessagesTarget;
use bp_messages::MessageNonce; use bp_messages::MessageNonce;
use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID};
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
use codec::Encode;
use messages_relay::message_lane::MessageLane; use messages_relay::message_lane::MessageLane;
use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams};
use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_substrate_client::{Chain, Client, TransactionSignScheme};
use relay_utils::metrics::MetricsParams; use relay_utils::metrics::MetricsParams;
use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo};
use sp_core::{Bytes, Pair}; use substrate_relay_helper::messages_lane::{
use std::{ops::RangeInclusive, time::Duration}; select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane,
SubstrateMessageLaneToSubstrate,
};
use substrate_relay_helper::messages_source::SubstrateMessagesSource;
use substrate_relay_helper::messages_target::SubstrateMessagesTarget;
/// Wococo-to-Rococo message lane. /// Wococo-to-Rococo message lane.
pub type WococoMessagesToRococo = pub type MessageLaneWococoMessagesToRococo =
SubstrateMessageLaneToSubstrate<Wococo, WococoSigningParams, Rococo, RococoSigningParams>; SubstrateMessageLaneToSubstrate<Wococo, WococoSigningParams, Rococo, RococoSigningParams>;
#[derive(Clone)]
pub struct WococoMessagesToRococo {
message_lane: MessageLaneWococoMessagesToRococo,
}
impl SubstrateMessageLane for WococoMessagesToRococo { impl SubstrateMessageLane for WococoMessagesToRococo {
type MessageLane = MessageLaneWococoMessagesToRococo;
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD;
const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str =
bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD;
@@ -57,14 +64,14 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
type TargetChain = Rococo; type TargetChain = Rococo;
fn source_transactions_author(&self) -> bp_wococo::AccountId { fn source_transactions_author(&self) -> bp_wococo::AccountId {
(*self.source_sign.public().as_array_ref()).into() (*self.message_lane.source_sign.public().as_array_ref()).into()
} }
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
&self, &self,
transaction_nonce: <Wococo as Chain>::Index, transaction_nonce: <Wococo as Chain>::Index,
_generated_at_block: RococoHeaderId, _generated_at_block: RococoHeaderId,
proof: <Self as MessageLane>::MessagesReceivingProof, proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes { ) -> Bytes {
let (relayers_state, proof) = proof; let (relayers_state, proof) = proof;
let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo(
@@ -73,8 +80,9 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
relayers_state, relayers_state,
), ),
); );
let genesis_hash = *self.source_client.genesis_hash(); let genesis_hash = *self.message_lane.source_client.genesis_hash();
let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); let transaction =
Wococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Rococo -> Wococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}", "Prepared Rococo -> Wococo confirmation transaction. Weight: <unknown>/{}, size: {}/{}",
@@ -86,7 +94,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
} }
fn target_transactions_author(&self) -> bp_rococo::AccountId { fn target_transactions_author(&self) -> bp_rococo::AccountId {
(*self.target_sign.public().as_array_ref()).into() (*self.message_lane.target_sign.public().as_array_ref()).into()
} }
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
@@ -94,7 +102,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
transaction_nonce: <Rococo as Chain>::Index, transaction_nonce: <Rococo as Chain>::Index,
_generated_at_header: WococoHeaderId, _generated_at_header: WococoHeaderId,
_nonces: RangeInclusive<MessageNonce>, _nonces: RangeInclusive<MessageNonce>,
proof: <Self as MessageLane>::MessagesProof, proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes { ) -> Bytes {
let (dispatch_weight, proof) = proof; let (dispatch_weight, proof) = proof;
let FromBridgedChainMessagesProof { let FromBridgedChainMessagesProof {
@@ -106,14 +114,15 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo(
relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof(
self.relayer_id_at_source.clone(), self.message_lane.relayer_id_at_source.clone(),
proof, proof,
messages_count as _, messages_count as _,
dispatch_weight, dispatch_weight,
), ),
); );
let genesis_hash = *self.target_client.genesis_hash(); let genesis_hash = *self.message_lane.target_client.genesis_hash();
let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); let transaction =
Rococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call);
log::trace!( log::trace!(
target: "bridge", target: "bridge",
"Prepared Wococo -> Rococo delivery transaction. Weight: <unknown>/{}, size: {}/{}", "Prepared Wococo -> Rococo delivery transaction. Weight: <unknown>/{}, size: {}/{}",
@@ -151,11 +160,13 @@ pub async fn run(
let lane_id = params.lane_id; let lane_id = params.lane_id;
let source_client = params.source_client; let source_client = params.source_client;
let lane = WococoMessagesToRococo { let lane = WococoMessagesToRococo {
source_client: source_client.clone(), message_lane: SubstrateMessageLaneToSubstrate {
source_sign: params.source_sign, source_client: source_client.clone(),
target_client: params.target_client.clone(), source_sign: params.source_sign,
target_sign: params.target_sign, target_client: params.target_client.clone(),
relayer_id_at_source: relayer_id_at_wococo, target_sign: params.target_sign,
relayer_id_at_source: relayer_id_at_wococo,
},
}; };
// 2/3 is reserved for proofs and tx overhead // 2/3 is reserved for proofs and tx overhead
@@ -180,7 +191,7 @@ pub async fn run(
Max messages size in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\
Max messages weight in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\
Relayer mode: {:?}", Relayer mode: {:?}",
lane.relayer_id_at_source, lane.message_lane.relayer_id_at_source,
max_messages_in_single_batch, max_messages_in_single_batch,
max_messages_size_in_single_batch, max_messages_size_in_single_batch,
max_messages_weight_in_single_batch, max_messages_weight_in_single_batch,
@@ -189,7 +200,7 @@ pub async fn run(
let (metrics_params, metrics_values) = add_standalone_metrics( let (metrics_params, metrics_values) = add_standalone_metrics(
Some(messages_relay::message_lane_loop::metrics_prefix::< Some(messages_relay::message_lane_loop::metrics_prefix::<
WococoMessagesToRococo, <WococoMessagesToRococo as SubstrateMessageLane>::MessageLane,
>(&lane_id)), >(&lane_id)),
params.metrics_params, params.metrics_params,
source_client.clone(), source_client.clone(),
@@ -237,7 +248,7 @@ pub(crate) fn add_standalone_metrics(
metrics_params: MetricsParams, metrics_params: MetricsParams,
source_client: Client<Wococo>, source_client: Client<Wococo>,
) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> {
crate::messages_lane::add_standalone_metrics::<WococoMessagesToRococo>( substrate_relay_helper::messages_lane::add_standalone_metrics::<WococoMessagesToRococo>(
metrics_prefix, metrics_prefix,
metrics_params, metrics_params,
source_client, source_client,
@@ -141,7 +141,7 @@ impl InitBridge {
let target_client = self.target.to_client::<Target>().await?; let target_client = self.target.to_client::<Target>().await?;
let target_sign = self.target_sign.to_keypair::<Target>()?; let target_sign = self.target_sign.to_keypair::<Target>()?;
crate::headers_initialize::initialize( substrate_relay_helper::headers_initialize::initialize(
source_client, source_client,
target_client.clone(), target_client.clone(),
target_sign.public().into(), target_sign.public().into(),
@@ -14,11 +14,13 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams};
use crate::finality_pipeline::SubstrateFinalitySyncPipeline;
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
use substrate_relay_helper::finality_pipeline::SubstrateFinalitySyncPipeline;
use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams};
/// Start headers relayer process. /// Start headers relayer process.
#[derive(StructOpt)] #[derive(StructOpt)]
pub struct RelayHeaders { pub struct RelayHeaders {
@@ -102,7 +104,7 @@ impl RelayHeaders {
let finality = Finality::new(target_client.clone(), target_sign); let finality = Finality::new(target_client.clone(), target_sign);
finality.start_relay_guards(); finality.start_relay_guards();
crate::finality_pipeline::run( substrate_relay_helper::finality_pipeline::run(
finality, finality,
source_client, source_client,
target_client, target_client,
@@ -22,16 +22,17 @@
//! 2) add `declare_bridge_options!(...)` for the bridge; //! 2) add `declare_bridge_options!(...)` for the bridge;
//! 3) add bridge support to the `select_bridge! { ... }` macro. //! 3) add bridge support to the `select_bridge! { ... }` macro.
use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams};
use crate::declare_chain_options;
use crate::messages_lane::MessagesRelayParams;
use crate::on_demand_headers::OnDemandHeadersRelay;
use futures::{FutureExt, TryFutureExt}; use futures::{FutureExt, TryFutureExt};
use relay_utils::metrics::MetricsParams;
use structopt::StructOpt; use structopt::StructOpt;
use strum::VariantNames; use strum::VariantNames;
use relay_utils::metrics::MetricsParams;
use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane};
use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay;
use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams};
use crate::declare_chain_options;
/// Start headers+messages relayer process. /// Start headers+messages relayer process.
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum RelayHeadersAndMessages { pub enum RelayHeadersAndMessages {
@@ -195,7 +196,9 @@ impl RelayHeadersAndMessages {
lane_id: lane, lane_id: lane,
relayer_mode, relayer_mode,
metrics_params: metrics_params.clone().disable().metrics_prefix( metrics_params: metrics_params.clone().disable().metrics_prefix(
messages_relay::message_lane_loop::metrics_prefix::<LeftToRightMessages>(&lane), messages_relay::message_lane_loop::metrics_prefix::<
<LeftToRightMessages as SubstrateMessageLane>::MessageLane,
>(&lane),
), ),
}) })
.map_err(|e| anyhow::format_err!("{}", e)) .map_err(|e| anyhow::format_err!("{}", e))
@@ -210,7 +213,9 @@ impl RelayHeadersAndMessages {
lane_id: lane, lane_id: lane,
relayer_mode, relayer_mode,
metrics_params: metrics_params.clone().disable().metrics_prefix( metrics_params: metrics_params.clone().disable().metrics_prefix(
messages_relay::message_lane_loop::metrics_prefix::<RightToLeftMessages>(&lane), messages_relay::message_lane_loop::metrics_prefix::<
<RightToLeftMessages as SubstrateMessageLane>::MessageLane,
>(&lane),
), ),
}) })
.map_err(|e| anyhow::format_err!("{}", e)) .map_err(|e| anyhow::format_err!("{}", e))
@@ -14,15 +14,17 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames};
use substrate_relay_helper::messages_lane::MessagesRelayParams;
use crate::cli::bridge::FullBridge; use crate::cli::bridge::FullBridge;
use crate::cli::{ use crate::cli::{
HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams,
TargetSigningParams, TargetSigningParams,
}; };
use crate::messages_lane::MessagesRelayParams;
use crate::select_full_bridge; use crate::select_full_bridge;
use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames};
/// Relayer operating mode. /// Relayer operating mode.
#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)] #[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)]
-7
View File
@@ -20,13 +20,6 @@
mod chains; mod chains;
mod cli; mod cli;
mod finality_pipeline;
mod finality_target;
mod headers_initialize;
mod messages_lane;
mod messages_source;
mod messages_target;
mod on_demand_headers;
fn main() { fn main() {
let command = cli::parse_args(); let command = cli::parse_args();
@@ -0,0 +1,51 @@
[package]
name = "substrate-relay-helper"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
anyhow = "1.0"
async-std = "1.9.0"
async-trait = "0.1.42"
codec = { package = "parity-scale-codec", version = "2.2.0" }
futures = "0.3.12"
num-format = "0.4"
num-traits = "0.2"
log = "0.4.14"
# Bridge dependencies
bp-header-chain = { path = "../../primitives/header-chain" }
bridge-runtime-common = { path = "../../bin/runtime-common" }
finality-grandpa = { version = "0.14.0" }
finality-relay = { path = "../finality" }
relay-utils = { path = "../utils" }
headers-relay = { path = "../headers" }
messages-relay = { path = "../messages" }
relay-substrate-client = { path = "../client-substrate" }
pallet-bridge-messages = { path = "../../modules/messages" }
bp-runtime = { path = "../../primitives/runtime" }
bp-messages = { path = "../../primitives/messages" }
# Substrate Dependencies
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { 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-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies]
relay-millau-client = { path = "../client-millau" }
relay-rialto-client = { path = "../client-rialto" }
bp-rialto = { path = "../../primitives/chain-rialto" }
bp-millau = { path = "../../primitives/chain-millau" }
rialto-runtime = { path = "../../bin/rialto/runtime" }
@@ -34,7 +34,9 @@ pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(120);
pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096;
/// Headers sync pipeline for Substrate <-> Substrate relays. /// Headers sync pipeline for Substrate <-> Substrate relays.
pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
type FinalitySyncPipeline: FinalitySyncPipeline;
/// Name of the runtime method that returns id of best finalized source header at target chain. /// Name of the runtime method that returns id of best finalized source header at target chain.
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str;
@@ -60,8 +62,8 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline {
fn make_submit_finality_proof_transaction( fn make_submit_finality_proof_transaction(
&self, &self,
transaction_nonce: <Self::TargetChain as Chain>::Index, transaction_nonce: <Self::TargetChain as Chain>::Index,
header: Self::Header, header: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::Header,
proof: Self::FinalityProof, proof: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::FinalityProof,
) -> Bytes; ) -> Bytes;
} }
@@ -69,9 +71,9 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline {
#[derive(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 target_client: Client<TargetChain>,
/// Data required to sign target chain transactions. /// Data required to sign target chain transactions.
pub(crate) target_sign: TargetSign, pub target_sign: TargetSign,
/// Unused generic arguments dump. /// Unused generic arguments dump.
_marker: PhantomData<SourceChain>, _marker: PhantomData<SourceChain>,
} }
@@ -123,12 +125,12 @@ pub async fn run<SourceChain, TargetChain, P>(
metrics_params: MetricsParams, metrics_params: MetricsParams,
) -> anyhow::Result<()> ) -> anyhow::Result<()>
where where
P: SubstrateFinalitySyncPipeline< P: SubstrateFinalitySyncPipeline<TargetChain = TargetChain>,
P::FinalitySyncPipeline: FinalitySyncPipeline<
Hash = HashOf<SourceChain>, Hash = HashOf<SourceChain>,
Number = BlockNumberOf<SourceChain>, Number = BlockNumberOf<SourceChain>,
Header = SyncHeader<SourceChain::Header>, Header = SyncHeader<SourceChain::Header>,
FinalityProof = GrandpaJustification<SourceChain::Header>, FinalityProof = GrandpaJustification<SourceChain::Header>,
TargetChain = TargetChain,
>, >,
SourceChain: Clone + Chain, SourceChain: Clone + Chain,
BlockNumberOf<SourceChain>: BlockNumberBase, BlockNumberOf<SourceChain>: BlockNumberBase,
@@ -22,7 +22,7 @@ use crate::finality_pipeline::SubstrateFinalitySyncPipeline;
use async_trait::async_trait; use async_trait::async_trait;
use codec::Decode; use codec::Decode;
use finality_relay::TargetClient; use finality_relay::{FinalitySyncPipeline, TargetClient};
use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_substrate_client::{Chain, Client, Error as SubstrateError};
use relay_utils::relay_loop::Client as RelayClient; use relay_utils::relay_loop::Client as RelayClient;
@@ -58,28 +58,35 @@ impl<C: Chain, P: SubstrateFinalitySyncPipeline> RelayClient for SubstrateFinali
} }
#[async_trait] #[async_trait]
impl<C, P> TargetClient<P> for SubstrateFinalityTarget<C, P> impl<C, P> TargetClient<P::FinalitySyncPipeline> for SubstrateFinalityTarget<C, P>
where where
C: Chain, C: Chain,
P::Number: Decode,
P::Hash: Decode,
P: SubstrateFinalitySyncPipeline<TargetChain = C>, P: SubstrateFinalitySyncPipeline<TargetChain = C>,
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Number: Decode,
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Hash: Decode,
{ {
async fn best_finalized_source_block_number(&self) -> Result<P::Number, SubstrateError> { async fn best_finalized_source_block_number(
&self,
) -> Result<<P::FinalitySyncPipeline as FinalitySyncPipeline>::Number, SubstrateError> {
// we can't continue to relay finality if target node is out of sync, because // we can't continue to relay finality if target node is out of sync, because
// it may have already received (some of) headers that we're going to relay // it may have already received (some of) headers that we're going to relay
self.client.ensure_synced().await?; self.client.ensure_synced().await?;
Ok(crate::messages_source::read_client_state::<C, P::Hash, P::Number>( Ok(crate::messages_source::read_client_state::<
&self.client, C,
P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, <P::FinalitySyncPipeline as FinalitySyncPipeline>::Hash,
) <P::FinalitySyncPipeline as FinalitySyncPipeline>::Number,
>(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET)
.await? .await?
.best_finalized_peer_at_best_self .best_finalized_peer_at_best_self
.0) .0)
} }
async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), SubstrateError> { async fn submit_finality_proof(
&self,
header: <P::FinalitySyncPipeline as FinalitySyncPipeline>::Header,
proof: <P::FinalitySyncPipeline as FinalitySyncPipeline>::FinalityProof,
) -> Result<(), SubstrateError> {
let transactions_author = self.pipeline.transactions_author(); let transactions_author = self.pipeline.transactions_author();
let pipeline = self.pipeline.clone(); let pipeline = self.pipeline.clone();
self.client self.client
@@ -0,0 +1,41 @@
// 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/>.
//! Substrate relay helpers
use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, Registry};
/// Creates standalone token price metric.
pub fn token_price_metric(
registry: &Registry,
prefix: Option<&str>,
token_id: &str,
) -> Result<FloatJsonValueMetric, PrometheusError> {
FloatJsonValueMetric::new(
registry,
prefix,
format!(
"https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc",
token_id
),
format!("$.{}.btc", token_id),
format!("{}_to_base_conversion_rate", token_id.replace("-", "_")),
format!(
"Rate used to convert from {} to some BASE tokens",
token_id.to_uppercase()
),
)
}
@@ -0,0 +1,28 @@
// 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/>.
//! The library of substrate relay. contains some public codes to provide to substrate relay.
#![warn(missing_docs)]
pub mod finality_pipeline;
pub mod finality_target;
pub mod headers_initialize;
pub mod helpers;
pub mod messages_lane;
pub mod messages_source;
pub mod messages_target;
pub mod on_demand_headers;
@@ -56,7 +56,9 @@ pub struct MessagesRelayParams<SC: Chain, SS, TC: Chain, TS> {
} }
/// Message sync pipeline for Substrate <-> Substrate relays. /// Message sync pipeline for Substrate <-> Substrate relays.
pub trait SubstrateMessageLane: MessageLane { pub trait SubstrateMessageLane: 'static + Clone + Send + Sync {
type MessageLane: MessageLane;
/// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain.
const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str;
/// Name of the runtime method that returns latest generated nonce at the source chain. /// Name of the runtime method that returns latest generated nonce at the source chain.
@@ -88,9 +90,9 @@ pub trait SubstrateMessageLane: MessageLane {
fn make_messages_delivery_transaction( fn make_messages_delivery_transaction(
&self, &self,
transaction_nonce: <Self::TargetChain as Chain>::Index, transaction_nonce: <Self::TargetChain as Chain>::Index,
generated_at_header: SourceHeaderIdOf<Self>, generated_at_header: SourceHeaderIdOf<Self::MessageLane>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof: Self::MessagesProof, proof: <Self::MessageLane as MessageLane>::MessagesProof,
) -> Bytes; ) -> Bytes;
/// Returns id of account that we're using to sign transactions at source chain (delivery proof). /// Returns id of account that we're using to sign transactions at source chain (delivery proof).
@@ -100,8 +102,8 @@ pub trait SubstrateMessageLane: MessageLane {
fn make_messages_receiving_proof_transaction( fn make_messages_receiving_proof_transaction(
&self, &self,
transaction_nonce: <Self::SourceChain as Chain>::Index, transaction_nonce: <Self::SourceChain as Chain>::Index,
generated_at_header: TargetHeaderIdOf<Self>, generated_at_header: TargetHeaderIdOf<Self::MessageLane>,
proof: Self::MessagesReceivingProof, proof: <Self::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Bytes; ) -> Bytes;
} }
@@ -109,15 +111,15 @@ pub trait SubstrateMessageLane: MessageLane {
#[derive(Debug)] #[derive(Debug)]
pub struct SubstrateMessageLaneToSubstrate<Source: Chain, SourceSignParams, Target: Chain, TargetSignParams> { pub struct SubstrateMessageLaneToSubstrate<Source: Chain, SourceSignParams, Target: Chain, TargetSignParams> {
/// Client for the source Substrate chain. /// Client for the source Substrate chain.
pub(crate) source_client: Client<Source>, pub source_client: Client<Source>,
/// Parameters required to sign transactions for source chain. /// Parameters required to sign transactions for source chain.
pub(crate) source_sign: SourceSignParams, pub source_sign: SourceSignParams,
/// Client for the target Substrate chain. /// Client for the target Substrate chain.
pub(crate) target_client: Client<Target>, pub target_client: Client<Target>,
/// Parameters required to sign transactions for target chain. /// Parameters required to sign transactions for target chain.
pub(crate) target_sign: TargetSignParams, pub target_sign: TargetSignParams,
/// Account id of relayer at the source chain. /// Account id of relayer at the source chain.
pub(crate) relayer_id_at_source: Source::AccountId, pub relayer_id_at_source: Source::AccountId,
} }
impl<Source: Chain, SourceSignParams: Clone, Target: Chain, TargetSignParams: Clone> Clone impl<Source: Chain, SourceSignParams: Clone, Target: Chain, TargetSignParams: Clone> Clone
@@ -261,14 +263,14 @@ pub fn add_standalone_metrics<P: SubstrateMessageLane>(
} }
if let Some(source_chain_token_id) = source_chain_token_id { if let Some(source_chain_token_id) = source_chain_token_id {
metrics_params = metrics_params.standalone_metric(|registry, prefix| { metrics_params = metrics_params.standalone_metric(|registry, prefix| {
let metric = crate::chains::token_price_metric(registry, prefix, source_chain_token_id)?; let metric = crate::helpers::token_price_metric(registry, prefix, source_chain_token_id)?;
source_to_base_conversion_rate = Some(metric.shared_value_ref()); source_to_base_conversion_rate = Some(metric.shared_value_ref());
Ok(metric) Ok(metric)
})?; })?;
} }
if let Some(target_chain_token_id) = target_chain_token_id { if let Some(target_chain_token_id) = target_chain_token_id {
metrics_params = metrics_params.standalone_metric(|registry, prefix| { metrics_params = metrics_params.standalone_metric(|registry, prefix| {
let metric = crate::chains::token_price_metric(registry, prefix, target_chain_token_id)?; let metric = crate::helpers::token_price_metric(registry, prefix, target_chain_token_id)?;
target_to_base_conversion_rate = Some(metric.shared_value_ref()); target_to_base_conversion_rate = Some(metric.shared_value_ref());
Ok(metric) Ok(metric)
})?; })?;
@@ -276,8 +278,8 @@ pub fn add_standalone_metrics<P: SubstrateMessageLane>(
Ok(( Ok((
metrics_params.into_params(), metrics_params.into_params(),
StandaloneMessagesMetrics { StandaloneMessagesMetrics {
source_to_base_conversion_rate,
target_to_base_conversion_rate, target_to_base_conversion_rate,
source_to_base_conversion_rate,
}, },
)) ))
} }
@@ -30,6 +30,7 @@ use bridge_runtime_common::messages::{
}; };
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{traits::Instance, weights::Weight}; use frame_support::{traits::Instance, weights::Weight};
use messages_relay::message_lane::MessageLane;
use messages_relay::{ use messages_relay::{
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
message_lane_loop::{ message_lane_loop::{
@@ -107,42 +108,49 @@ where
} }
#[async_trait] #[async_trait]
impl<SC, TC, P, I> SourceClient<P> for SubstrateMessagesSource<SC, TC, P, I> impl<SC, TC, P, I> SourceClient<P::MessageLane> for SubstrateMessagesSource<SC, TC, P, I>
where where
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>, SC: Chain<
Hash = <P::MessageLane as MessageLane>::SourceHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::SourceHeaderNumber,
Balance = <P::MessageLane as MessageLane>::SourceChainBalance,
>,
SC::Hash: Copy, SC::Hash: Copy,
SC::BlockNumber: Copy, SC::BlockNumber: Copy,
SC::Balance: Decode + Bounded, SC::Balance: Decode + Bounded,
SC::Header: DeserializeOwned, SC::Header: DeserializeOwned,
SC::Index: DeserializeOwned, SC::Index: DeserializeOwned,
SC::BlockNumber: BlockNumberBase, SC::BlockNumber: BlockNumberBase,
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>, TC: Chain<
P: SubstrateMessageLane< Hash = <P::MessageLane as MessageLane>::TargetHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::TargetHeaderNumber,
>,
P: SubstrateMessageLane<SourceChain = SC, TargetChain = TC>,
P::MessageLane: MessageLane<
MessagesProof = SubstrateMessagesProof<SC>, MessagesProof = SubstrateMessagesProof<SC>,
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>, MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
SourceChain = SC,
TargetChain = TC,
>, >,
P::TargetHeaderNumber: Decode, <P::MessageLane as MessageLane>::TargetHeaderNumber: Decode,
P::TargetHeaderHash: Decode, <P::MessageLane as MessageLane>::TargetHeaderHash: Decode,
I: Send + Sync + Instance, I: Send + Sync + Instance,
{ {
async fn state(&self) -> Result<SourceClientState<P>, SubstrateError> { async fn state(&self) -> Result<SourceClientState<P::MessageLane>, SubstrateError> {
// we can't continue to deliver confirmations if source node is out of sync, because // we can't continue to deliver confirmations if source node is out of sync, because
// it may have already received confirmations that we're going to deliver // it may have already received confirmations that we're going to deliver
self.client.ensure_synced().await?; self.client.ensure_synced().await?;
read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( read_client_state::<
&self.client, _,
P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, <P::MessageLane as MessageLane>::TargetHeaderHash,
) <P::MessageLane as MessageLane>::TargetHeaderNumber,
>(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE)
.await .await
} }
async fn latest_generated_nonce( async fn latest_generated_nonce(
&self, &self,
id: SourceHeaderIdOf<P>, id: SourceHeaderIdOf<P::MessageLane>,
) -> Result<(SourceHeaderIdOf<P>, MessageNonce), SubstrateError> { ) -> Result<(SourceHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -158,8 +166,8 @@ where
async fn latest_confirmed_received_nonce( async fn latest_confirmed_received_nonce(
&self, &self,
id: SourceHeaderIdOf<P>, id: SourceHeaderIdOf<P::MessageLane>,
) -> Result<(SourceHeaderIdOf<P>, MessageNonce), SubstrateError> { ) -> Result<(SourceHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -175,9 +183,9 @@ where
async fn generated_message_details( async fn generated_message_details(
&self, &self,
id: SourceHeaderIdOf<P>, id: SourceHeaderIdOf<P::MessageLane>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
) -> Result<MessageDetailsMap<P::SourceChainBalance>, SubstrateError> { ) -> Result<MessageDetailsMap<<P::MessageLane as MessageLane>::SourceChainBalance>, SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -195,10 +203,17 @@ where
async fn prove_messages( async fn prove_messages(
&self, &self,
id: SourceHeaderIdOf<P>, id: SourceHeaderIdOf<P::MessageLane>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof_parameters: MessageProofParameters, proof_parameters: MessageProofParameters,
) -> Result<(SourceHeaderIdOf<P>, RangeInclusive<MessageNonce>, P::MessagesProof), SubstrateError> { ) -> Result<
(
SourceHeaderIdOf<P::MessageLane>,
RangeInclusive<MessageNonce>,
<P::MessageLane as MessageLane>::MessagesProof,
),
SubstrateError,
> {
let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1);
let mut message_nonce = *nonces.start(); let mut message_nonce = *nonces.start();
while message_nonce <= *nonces.end() { while message_nonce <= *nonces.end() {
@@ -230,8 +245,8 @@ where
async fn submit_messages_receiving_proof( async fn submit_messages_receiving_proof(
&self, &self,
generated_at_block: TargetHeaderIdOf<P>, generated_at_block: TargetHeaderIdOf<P::MessageLane>,
proof: P::MessagesReceivingProof, proof: <P::MessageLane as MessageLane>::MessagesReceivingProof,
) -> Result<(), SubstrateError> { ) -> Result<(), SubstrateError> {
let lane = self.lane.clone(); let lane = self.lane.clone();
self.client self.client
@@ -242,13 +257,13 @@ where
Ok(()) Ok(())
} }
async fn require_target_header_on_source(&self, id: TargetHeaderIdOf<P>) { async fn require_target_header_on_source(&self, id: TargetHeaderIdOf<P::MessageLane>) {
if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay {
target_to_source_headers_relay.require_finalized_header(id).await; target_to_source_headers_relay.require_finalized_header(id).await;
} }
} }
async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance { async fn estimate_confirmation_transaction(&self) -> <P::MessageLane as MessageLane>::SourceChainBalance {
self.client self.client
.estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction(
Zero::zero(), Zero::zero(),
@@ -30,6 +30,7 @@ use bridge_runtime_common::messages::{
}; };
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{traits::Instance, weights::Weight}; use frame_support::{traits::Instance, weights::Weight};
use messages_relay::message_lane::MessageLane;
use messages_relay::{ use messages_relay::{
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
message_lane_loop::{TargetClient, TargetClientState}, message_lane_loop::{TargetClient, TargetClientState},
@@ -110,42 +111,49 @@ where
} }
#[async_trait] #[async_trait]
impl<SC, TC, P, I> TargetClient<P> for SubstrateMessagesTarget<SC, TC, P, I> impl<SC, TC, P, I> TargetClient<P::MessageLane> for SubstrateMessagesTarget<SC, TC, P, I>
where where
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>, SC: Chain<
Hash = <P::MessageLane as MessageLane>::SourceHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::SourceHeaderNumber,
Balance = <P::MessageLane as MessageLane>::SourceChainBalance,
>,
SC::Balance: TryFrom<TC::Balance> + Bounded, SC::Balance: TryFrom<TC::Balance> + Bounded,
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>, TC: Chain<
Hash = <P::MessageLane as MessageLane>::TargetHeaderHash,
BlockNumber = <P::MessageLane as MessageLane>::TargetHeaderNumber,
>,
TC::Hash: Copy, TC::Hash: Copy,
TC::BlockNumber: Copy, TC::BlockNumber: Copy,
TC::Header: DeserializeOwned, TC::Header: DeserializeOwned,
TC::Index: DeserializeOwned, TC::Index: DeserializeOwned,
<TC::Header as HeaderT>::Number: BlockNumberBase, <TC::Header as HeaderT>::Number: BlockNumberBase,
P: SubstrateMessageLane< P: SubstrateMessageLane<SourceChain = SC, TargetChain = TC>,
P::MessageLane: MessageLane<
MessagesProof = SubstrateMessagesProof<SC>, MessagesProof = SubstrateMessagesProof<SC>,
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>, MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
SourceChain = SC,
TargetChain = TC,
>, >,
P::SourceHeaderNumber: Decode, <P::MessageLane as MessageLane>::SourceHeaderNumber: Decode,
P::SourceHeaderHash: Decode, <P::MessageLane as MessageLane>::SourceHeaderHash: Decode,
I: Send + Sync + Instance, I: Send + Sync + Instance,
{ {
async fn state(&self) -> Result<TargetClientState<P>, SubstrateError> { async fn state(&self) -> Result<TargetClientState<P::MessageLane>, SubstrateError> {
// we can't continue to deliver messages if target node is out of sync, because // we can't continue to deliver messages if target node is out of sync, because
// it may have already received (some of) messages that we're going to deliver // it may have already received (some of) messages that we're going to deliver
self.client.ensure_synced().await?; self.client.ensure_synced().await?;
read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( read_client_state::<
&self.client, _,
P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, <P::MessageLane as MessageLane>::SourceHeaderHash,
) <P::MessageLane as MessageLane>::SourceHeaderNumber,
>(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET)
.await .await
} }
async fn latest_received_nonce( async fn latest_received_nonce(
&self, &self,
id: TargetHeaderIdOf<P>, id: TargetHeaderIdOf<P::MessageLane>,
) -> Result<(TargetHeaderIdOf<P>, MessageNonce), SubstrateError> { ) -> Result<(TargetHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -161,8 +169,8 @@ where
async fn latest_confirmed_received_nonce( async fn latest_confirmed_received_nonce(
&self, &self,
id: TargetHeaderIdOf<P>, id: TargetHeaderIdOf<P::MessageLane>,
) -> Result<(TargetHeaderIdOf<P>, MessageNonce), SubstrateError> { ) -> Result<(TargetHeaderIdOf<P::MessageLane>, MessageNonce), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -178,8 +186,8 @@ where
async fn unrewarded_relayers_state( async fn unrewarded_relayers_state(
&self, &self,
id: TargetHeaderIdOf<P>, id: TargetHeaderIdOf<P::MessageLane>,
) -> Result<(TargetHeaderIdOf<P>, UnrewardedRelayersState), SubstrateError> { ) -> Result<(TargetHeaderIdOf<P::MessageLane>, UnrewardedRelayersState), SubstrateError> {
let encoded_response = self let encoded_response = self
.client .client
.state_call( .state_call(
@@ -195,8 +203,14 @@ where
async fn prove_messages_receiving( async fn prove_messages_receiving(
&self, &self,
id: TargetHeaderIdOf<P>, id: TargetHeaderIdOf<P::MessageLane>,
) -> Result<(TargetHeaderIdOf<P>, P::MessagesReceivingProof), SubstrateError> { ) -> Result<
(
TargetHeaderIdOf<P::MessageLane>,
<P::MessageLane as MessageLane>::MessagesReceivingProof,
),
SubstrateError,
> {
let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let (id, relayers_state) = self.unrewarded_relayers_state(id).await?;
let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::<I>(&self.lane_id); let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::<I>(&self.lane_id);
let proof = self let proof = self
@@ -215,9 +229,9 @@ where
async fn submit_messages_proof( async fn submit_messages_proof(
&self, &self,
generated_at_header: SourceHeaderIdOf<P>, generated_at_header: SourceHeaderIdOf<P::MessageLane>,
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof: P::MessagesProof, proof: <P::MessageLane as MessageLane>::MessagesProof,
) -> Result<RangeInclusive<MessageNonce>, SubstrateError> { ) -> Result<RangeInclusive<MessageNonce>, SubstrateError> {
let lane = self.lane.clone(); let lane = self.lane.clone();
let nonces_clone = nonces.clone(); let nonces_clone = nonces.clone();
@@ -229,7 +243,7 @@ where
Ok(nonces) Ok(nonces)
} }
async fn require_source_header_on_target(&self, id: SourceHeaderIdOf<P>) { async fn require_source_header_on_target(&self, id: SourceHeaderIdOf<P::MessageLane>) {
if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay {
source_to_target_headers_relay.require_finalized_header(id).await; source_to_target_headers_relay.require_finalized_header(id).await;
} }
@@ -240,7 +254,7 @@ where
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
total_dispatch_weight: Weight, total_dispatch_weight: Weight,
total_size: u32, total_size: u32,
) -> Result<P::SourceChainBalance, SubstrateError> { ) -> Result<<P::MessageLane as MessageLane>::SourceChainBalance, SubstrateError> {
let conversion_rate = self let conversion_rate = self
.metric_values .metric_values
.target_to_source_conversion_rate() .target_to_source_conversion_rate()
@@ -16,27 +16,28 @@
//! On-demand Substrate -> Substrate headers relay. //! On-demand Substrate -> Substrate headers relay.
use crate::finality_pipeline::{ use std::fmt::Debug;
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT,
};
use crate::finality_target::SubstrateFinalityTarget;
use async_std::sync::{Arc, Mutex}; use async_std::sync::{Arc, Mutex};
use bp_header_chain::justification::GrandpaJustification; use futures::{select, FutureExt};
use num_traits::{CheckedSub, One, Zero};
use finality_relay::{ use finality_relay::{
FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader, FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader,
TargetClient as FinalityTargetClient, TargetClient as FinalityTargetClient,
}; };
use futures::{select, FutureExt};
use num_traits::{CheckedSub, One, Zero};
use relay_substrate_client::{ use relay_substrate_client::{
finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef},
BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader, Chain, Client, HeaderIdOf, SyncHeader,
}; };
use relay_utils::{ use relay_utils::{
metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, MaybeConnectionError, metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, MaybeConnectionError,
}; };
use std::fmt::Debug;
use crate::finality_pipeline::{
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT,
};
use crate::finality_target::SubstrateFinalityTarget;
/// On-demand Substrate <-> Substrate headers relay. /// On-demand Substrate <-> Substrate headers relay.
/// ///
@@ -52,10 +53,10 @@ pub struct OnDemandHeadersRelay<SourceChain: Chain> {
impl<SourceChain: Chain> OnDemandHeadersRelay<SourceChain> { impl<SourceChain: Chain> OnDemandHeadersRelay<SourceChain> {
/// Create new on-demand headers relay. /// Create new on-demand headers relay.
pub fn new<TargetChain: Chain, TargetSign>( pub fn new<TargetChain: Chain, TargetSign, P>(
source_client: Client<SourceChain>, source_client: Client<SourceChain>,
target_client: Client<TargetChain>, target_client: Client<TargetChain>,
pipeline: SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>, pipeline: P,
maximal_headers_difference: SourceChain::BlockNumber, maximal_headers_difference: SourceChain::BlockNumber,
) -> Self ) -> Self
where where
@@ -64,15 +65,10 @@ impl<SourceChain: Chain> OnDemandHeadersRelay<SourceChain> {
TargetChain: Chain + Debug, TargetChain: Chain + Debug,
TargetChain::BlockNumber: BlockNumberBase, TargetChain::BlockNumber: BlockNumberBase,
TargetSign: Clone + Send + Sync + 'static, TargetSign: Clone + Send + Sync + 'static,
SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>: SubstrateFinalitySyncPipeline< P: SubstrateFinalitySyncPipeline<
Hash = HashOf<SourceChain>, FinalitySyncPipeline = SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>,
Number = BlockNumberOf<SourceChain>,
Header = SyncHeader<SourceChain::Header>,
FinalityProof = GrandpaJustification<SourceChain::Header>,
TargetChain = TargetChain, TargetChain = TargetChain,
>, >,
SubstrateFinalityTarget<TargetChain, SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>>:
FinalityTargetClient<SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>>,
{ {
let required_header_number = Arc::new(Mutex::new(Zero::zero())); let required_header_number = Arc::new(Mutex::new(Zero::zero()));
let this = OnDemandHeadersRelay { let this = OnDemandHeadersRelay {
@@ -111,10 +107,11 @@ impl<SourceChain: Chain> OnDemandHeadersRelay<SourceChain> {
} }
/// Background task that is responsible for starting headers relay. /// Background task that is responsible for starting headers relay.
async fn background_task<SourceChain, TargetChain, TargetSign>( async fn background_task<SourceChain, TargetChain, TargetSign, P>(
source_client: Client<SourceChain>, source_client: Client<SourceChain>,
target_client: Client<TargetChain>, target_client: Client<TargetChain>,
pipeline: SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>, // pipeline: SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>,
pipeline: P,
maximal_headers_difference: SourceChain::BlockNumber, maximal_headers_difference: SourceChain::BlockNumber,
required_header_number: RequiredHeaderNumberRef<SourceChain>, required_header_number: RequiredHeaderNumberRef<SourceChain>,
) where ) where
@@ -123,15 +120,10 @@ async fn background_task<SourceChain, TargetChain, TargetSign>(
TargetChain: Chain + Debug, TargetChain: Chain + Debug,
TargetChain::BlockNumber: BlockNumberBase, TargetChain::BlockNumber: BlockNumberBase,
TargetSign: Clone + Send + Sync + 'static, TargetSign: Clone + Send + Sync + 'static,
SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>: SubstrateFinalitySyncPipeline< P: SubstrateFinalitySyncPipeline<
Hash = HashOf<SourceChain>, FinalitySyncPipeline = SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>,
Number = BlockNumberOf<SourceChain>,
Header = SyncHeader<SourceChain::Header>,
FinalityProof = GrandpaJustification<SourceChain::Header>,
TargetChain = TargetChain, TargetChain = TargetChain,
>, >,
SubstrateFinalityTarget<TargetChain, SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>>:
FinalityTargetClient<SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>>,
{ {
let relay_task_name = on_demand_headers_relay_name::<SourceChain, TargetChain>(); let relay_task_name = on_demand_headers_relay_name::<SourceChain, TargetChain>();
let mut finality_source = SubstrateFinalitySource::< let mut finality_source = SubstrateFinalitySource::<
@@ -373,8 +365,9 @@ async fn best_finalized_source_header_at_target<SourceChain: Chain, TargetChain:
relay_task_name: &str, relay_task_name: &str,
) -> Result<SourceChain::BlockNumber, <SubstrateFinalityTarget<TargetChain, P> as RelayClient>::Error> ) -> Result<SourceChain::BlockNumber, <SubstrateFinalityTarget<TargetChain, P> as RelayClient>::Error>
where where
SubstrateFinalityTarget<TargetChain, P>: FinalityTargetClient<P>, SubstrateFinalityTarget<TargetChain, P>: FinalityTargetClient<P::FinalitySyncPipeline>,
P: FinalitySyncPipeline<Number = SourceChain::BlockNumber>, P: SubstrateFinalitySyncPipeline,
P::FinalitySyncPipeline: FinalitySyncPipeline<Number = SourceChain::BlockNumber>,
{ {
finality_target finality_target
.best_finalized_source_block_number() .best_finalized_source_block_number()