mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 11:41:02 +00:00
Refactor finality relay helpers (#1220)
* refactor finality relay helper definitions * add missing doc * removed commented code * fmt * disable rustfmt for macro * move best_finalized method const to relay chain def
This commit is contained in:
committed by
Bastian Köcher
parent
f84590817b
commit
e675b13042
@@ -731,10 +731,6 @@ impl_runtime_apis! {
|
|||||||
let header = BridgeRialtoGrandpa::best_finalized();
|
let header = BridgeRialtoGrandpa::best_finalized();
|
||||||
(header.number, header.hash())
|
(header.number, header.hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_known_header(hash: bp_rialto::Hash) -> bool {
|
|
||||||
BridgeRialtoGrandpa::is_known_header(hash)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_westend::WestendFinalityApi<Block> for Runtime {
|
impl bp_westend::WestendFinalityApi<Block> for Runtime {
|
||||||
@@ -742,10 +738,6 @@ impl_runtime_apis! {
|
|||||||
let header = BridgeWestendGrandpa::best_finalized();
|
let header = BridgeWestendGrandpa::best_finalized();
|
||||||
(header.number, header.hash())
|
(header.number, header.hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_known_header(hash: bp_westend::Hash) -> bool {
|
|
||||||
BridgeWestendGrandpa::is_known_header(hash)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_rialto::ToRialtoOutboundLaneApi<Block, Balance, ToRialtoMessagePayload> for Runtime {
|
impl bp_rialto::ToRialtoOutboundLaneApi<Block, Balance, ToRialtoMessagePayload> for Runtime {
|
||||||
|
|||||||
@@ -662,10 +662,6 @@ impl_runtime_apis! {
|
|||||||
let header = BridgeMillauGrandpa::best_finalized();
|
let header = BridgeMillauGrandpa::best_finalized();
|
||||||
(header.number, header.hash())
|
(header.number, header.hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_known_header(hash: bp_millau::Hash) -> bool {
|
|
||||||
BridgeMillauGrandpa::is_known_header(hash)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str =
|
|||||||
|
|
||||||
/// Name of the `KusamaFinalityApi::best_finalized` runtime method.
|
/// Name of the `KusamaFinalityApi::best_finalized` runtime method.
|
||||||
pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized";
|
pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized";
|
||||||
/// Name of the `KusamaFinalityApi::is_known_header` runtime method.
|
|
||||||
pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_header";
|
|
||||||
|
|
||||||
/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
||||||
/// method.
|
/// method.
|
||||||
@@ -124,8 +122,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait KusamaFinalityApi {
|
pub trait KusamaFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Kusama chain.
|
/// Outbound message lane API for messages that are sent to Kusama chain.
|
||||||
|
|||||||
@@ -298,8 +298,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait MillauFinalityApi {
|
pub trait MillauFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Millau chain.
|
/// Outbound message lane API for messages that are sent to Millau chain.
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str =
|
|||||||
|
|
||||||
/// Name of the `PolkadotFinalityApi::best_finalized` runtime method.
|
/// Name of the `PolkadotFinalityApi::best_finalized` runtime method.
|
||||||
pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized";
|
pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized";
|
||||||
/// Name of the `PolkadotFinalityApi::is_known_header` runtime method.
|
|
||||||
pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_header";
|
|
||||||
|
|
||||||
/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
||||||
/// method.
|
/// method.
|
||||||
@@ -124,8 +122,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait PolkadotFinalityApi {
|
pub trait PolkadotFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Polkadot chain.
|
/// Outbound message lane API for messages that are sent to Polkadot chain.
|
||||||
|
|||||||
@@ -271,8 +271,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait RialtoFinalityApi {
|
pub trait RialtoFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Rialto chain.
|
/// Outbound message lane API for messages that are sent to Rialto chain.
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages";
|
|||||||
|
|
||||||
/// Name of the `RococoFinalityApi::best_finalized` runtime method.
|
/// Name of the `RococoFinalityApi::best_finalized` runtime method.
|
||||||
pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized";
|
pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized";
|
||||||
/// Name of the `RococoFinalityApi::is_known_header` runtime method.
|
|
||||||
pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_header";
|
|
||||||
|
|
||||||
/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
||||||
/// method.
|
/// method.
|
||||||
@@ -125,8 +123,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait RococoFinalityApi {
|
pub trait RococoFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Rococo chain.
|
/// Outbound message lane API for messages that are sent to Rococo chain.
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount<AccountId>) -
|
|||||||
|
|
||||||
/// Name of the `WestendFinalityApi::best_finalized` runtime method.
|
/// Name of the `WestendFinalityApi::best_finalized` runtime method.
|
||||||
pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized";
|
pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized";
|
||||||
/// Name of the `WestendFinalityApi::is_known_header` runtime method.
|
|
||||||
pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_header";
|
|
||||||
|
|
||||||
/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
||||||
/// method.
|
/// method.
|
||||||
@@ -131,8 +129,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait WestendFinalityApi {
|
pub trait WestendFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Westend chain.
|
/// Outbound message lane API for messages that are sent to Westend chain.
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages";
|
|||||||
|
|
||||||
/// Name of the `WococoFinalityApi::best_finalized` runtime method.
|
/// Name of the `WococoFinalityApi::best_finalized` runtime method.
|
||||||
pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized";
|
pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized";
|
||||||
/// Name of the `WococoFinalityApi::is_known_header` runtime method.
|
|
||||||
pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header";
|
|
||||||
|
|
||||||
/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime
|
||||||
/// method.
|
/// method.
|
||||||
@@ -78,8 +76,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
pub trait WococoFinalityApi {
|
pub trait WococoFinalityApi {
|
||||||
/// Returns number and hash of the best finalized header known to the bridge module.
|
/// Returns number and hash of the best finalized header known to the bridge module.
|
||||||
fn best_finalized() -> (BlockNumber, Hash);
|
fn best_finalized() -> (BlockNumber, Hash);
|
||||||
/// Returns true if the header is known to the runtime.
|
|
||||||
fn is_known_header(hash: Hash) -> bool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Wococo chain.
|
/// Outbound message lane API for messages that are sent to Wococo chain.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
// 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 frame_support::Parameter;
|
use frame_support::Parameter;
|
||||||
use num_traits::{AsPrimitive, Bounded, CheckedSub, SaturatingAdd, Zero};
|
use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
traits::{
|
traits::{
|
||||||
AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
|
AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay,
|
||||||
@@ -46,6 +46,7 @@ pub trait Chain: Send + Sync + 'static {
|
|||||||
+ MaybeMallocSizeOf
|
+ MaybeMallocSizeOf
|
||||||
+ AsPrimitive<usize>
|
+ AsPrimitive<usize>
|
||||||
+ Default
|
+ Default
|
||||||
|
+ Saturating
|
||||||
// original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but
|
// original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but
|
||||||
// `sp_runtime::generic::Era` requires block number -> `u64` conversion.
|
// `sp_runtime::generic::Era` requires block number -> `u64` conversion.
|
||||||
+ Into<u64>;
|
+ Into<u64>;
|
||||||
|
|||||||
@@ -16,17 +16,8 @@
|
|||||||
|
|
||||||
//! Kusama-to-Polkadot headers sync entrypoint.
|
//! Kusama-to-Polkadot headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
use sp_core::Pair;
|
||||||
use sp_core::{Bytes, Pair};
|
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams};
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
|
||||||
use relay_kusama_client::{Kusama, SyncHeader as KusamaSyncHeader};
|
|
||||||
use relay_polkadot_client::{Polkadot, SigningParams as PolkadotSigningParams};
|
|
||||||
use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use relay_utils::metrics::MetricsParams;
|
|
||||||
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.
|
||||||
@@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{
|
|||||||
/// DOT, but let's round up to 30 DOT here.
|
/// DOT, but let's round up to 30 DOT here.
|
||||||
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000;
|
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000;
|
||||||
|
|
||||||
/// Kusama-to-Polkadot finality sync pipeline.
|
/// Description of Kusama -> Polkadot finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelineKusamaFinalityToPolkadot =
|
|
||||||
SubstrateFinalityToSubstrate<Kusama, Polkadot, PolkadotSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct KusamaFinalityToPolkadot {
|
pub struct KusamaFinalityToPolkadot;
|
||||||
finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot,
|
substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!(
|
||||||
}
|
KusamaFinalityToPolkadot,
|
||||||
|
KusamaFinalityToPolkadotCallBuilder,
|
||||||
impl KusamaFinalityToPolkadot {
|
relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa,
|
||||||
pub fn new(target_client: Client<Polkadot>, target_sign: PolkadotSigningParams) -> Self {
|
relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof
|
||||||
Self {
|
);
|
||||||
finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new(
|
|
||||||
target_client,
|
|
||||||
target_sign,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot {
|
impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot {
|
||||||
type FinalitySyncPipeline = FinalityPipelineKusamaFinalityToPolkadot;
|
type SourceChain = relay_kusama_client::Kusama;
|
||||||
|
type TargetChain = relay_polkadot_client::Polkadot;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder;
|
||||||
bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
|
type TransactionSignScheme = relay_polkadot_client::Polkadot;
|
||||||
|
|
||||||
type TargetChain = Polkadot;
|
fn start_relay_guards(
|
||||||
|
target_client: &relay_substrate_client::Client<relay_polkadot_client::Polkadot>,
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
transaction_params: &TransactionParams<sp_core::sr25519::Pair>,
|
||||||
crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(params)
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
fn start_relay_guards(&self) {
|
|
||||||
relay_substrate_client::guard::abort_on_spec_version_change(
|
relay_substrate_client::guard::abort_on_spec_version_change(
|
||||||
self.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
bp_polkadot::VERSION.spec_version,
|
bp_polkadot::VERSION.spec_version,
|
||||||
);
|
);
|
||||||
relay_substrate_client::guard::abort_when_account_balance_decreased(
|
relay_substrate_client::guard::abort_when_account_balance_decreased(
|
||||||
self.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
self.transactions_author(),
|
transaction_params.transactions_signer.public().into(),
|
||||||
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_polkadot::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Polkadot>,
|
|
||||||
transaction_nonce: bp_runtime::IndexOf<Polkadot>,
|
|
||||||
header: KusamaSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_kusama::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa(
|
|
||||||
relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof(
|
|
||||||
Box::new(header.into_inner()),
|
|
||||||
proof,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Polkadot::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -16,65 +16,22 @@
|
|||||||
|
|
||||||
//! Millau-to-Rialto headers sync entrypoint.
|
//! Millau-to-Rialto headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
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::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use substrate_relay_helper::finality_pipeline::{
|
use substrate_relay_helper::finality_pipeline::{
|
||||||
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate,
|
DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Millau-to-Rialto finality sync pipeline.
|
/// Description of Millau -> Rialto finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelineMillauToRialto =
|
|
||||||
SubstrateFinalityToSubstrate<Millau, Rialto, RialtoSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct MillauFinalityToRialto {
|
pub 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;
|
type SourceChain = relay_millau_client::Millau;
|
||||||
|
type TargetChain = relay_rialto_client::Rialto;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder<
|
||||||
bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
|
Self,
|
||||||
|
rialto_runtime::Runtime,
|
||||||
type TargetChain = Rialto;
|
rialto_runtime::MillauGrandpaInstance,
|
||||||
|
>;
|
||||||
fn transactions_author(&self) -> bp_rialto::AccountId {
|
type TransactionSignScheme = relay_rialto_client::Rialto;
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Rialto>,
|
|
||||||
transaction_nonce: IndexOf<Rialto>,
|
|
||||||
header: MillauSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_millau::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof {
|
|
||||||
finality_target: Box::new(header.into_inner()),
|
|
||||||
justification: proof,
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Rialto::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,18 +39,6 @@ mod rococo;
|
|||||||
mod westend;
|
mod westend;
|
||||||
mod wococo;
|
mod wococo;
|
||||||
|
|
||||||
use relay_utils::metrics::{MetricsParams, StandaloneMetric};
|
|
||||||
|
|
||||||
pub(crate) fn add_polkadot_kusama_price_metrics<T: finality_relay::FinalitySyncPipeline>(
|
|
||||||
params: MetricsParams,
|
|
||||||
) -> anyhow::Result<MetricsParams> {
|
|
||||||
substrate_relay_helper::helpers::token_price_metric(polkadot::TOKEN_ID)?
|
|
||||||
.register_and_spawn(¶ms.registry)?;
|
|
||||||
substrate_relay_helper::helpers::token_price_metric(kusama::TOKEN_ID)?
|
|
||||||
.register_and_spawn(¶ms.registry)?;
|
|
||||||
Ok(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::cli::{encode_call, send_message};
|
use crate::cli::{encode_call, send_message};
|
||||||
|
|||||||
@@ -16,17 +16,8 @@
|
|||||||
|
|
||||||
//! Polkadot-to-Kusama headers sync entrypoint.
|
//! Polkadot-to-Kusama headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
use sp_core::Pair;
|
||||||
use sp_core::{Bytes, Pair};
|
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams};
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
|
||||||
use relay_kusama_client::{Kusama, SigningParams as KusamaSigningParams};
|
|
||||||
use relay_polkadot_client::{Polkadot, SyncHeader as PolkadotSyncHeader};
|
|
||||||
use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use relay_utils::metrics::MetricsParams;
|
|
||||||
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.
|
||||||
@@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{
|
|||||||
/// KSM, but let's round up to 0.1 KSM here.
|
/// KSM, but let's round up to 0.1 KSM here.
|
||||||
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000;
|
pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000;
|
||||||
|
|
||||||
/// Polkadot-to-Kusama finality sync pipeline.
|
/// Description of Polkadot -> Kusama finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelinePolkadotFinalityToKusama =
|
|
||||||
SubstrateFinalityToSubstrate<Polkadot, Kusama, KusamaSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct PolkadotFinalityToKusama {
|
pub struct PolkadotFinalityToKusama;
|
||||||
finality_pipeline: FinalityPipelinePolkadotFinalityToKusama,
|
substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!(
|
||||||
}
|
PolkadotFinalityToKusama,
|
||||||
|
PolkadotFinalityToKusamaCallBuilder,
|
||||||
impl PolkadotFinalityToKusama {
|
relay_kusama_client::runtime::Call::BridgePolkadotGrandpa,
|
||||||
pub fn new(target_client: Client<Kusama>, target_sign: KusamaSigningParams) -> Self {
|
relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof
|
||||||
Self {
|
);
|
||||||
finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new(
|
|
||||||
target_client,
|
|
||||||
target_sign,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama {
|
impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama {
|
||||||
type FinalitySyncPipeline = FinalityPipelinePolkadotFinalityToKusama;
|
type SourceChain = relay_polkadot_client::Polkadot;
|
||||||
|
type TargetChain = relay_kusama_client::Kusama;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder;
|
||||||
bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
|
type TransactionSignScheme = relay_kusama_client::Kusama;
|
||||||
|
|
||||||
type TargetChain = Kusama;
|
fn start_relay_guards(
|
||||||
|
target_client: &relay_substrate_client::Client<relay_kusama_client::Kusama>,
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
transaction_params: &TransactionParams<sp_core::sr25519::Pair>,
|
||||||
crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(params)
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
fn start_relay_guards(&self) {
|
|
||||||
relay_substrate_client::guard::abort_on_spec_version_change(
|
relay_substrate_client::guard::abort_on_spec_version_change(
|
||||||
self.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
bp_kusama::VERSION.spec_version,
|
bp_kusama::VERSION.spec_version,
|
||||||
);
|
);
|
||||||
relay_substrate_client::guard::abort_when_account_balance_decreased(
|
relay_substrate_client::guard::abort_when_account_balance_decreased(
|
||||||
self.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
self.transactions_author(),
|
transaction_params.transactions_signer.public().into(),
|
||||||
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_kusama::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Kusama>,
|
|
||||||
transaction_nonce: bp_runtime::IndexOf<Kusama>,
|
|
||||||
header: PolkadotSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_polkadot::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = relay_kusama_client::runtime::Call::BridgePolkadotGrandpa(
|
|
||||||
relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof(
|
|
||||||
Box::new(header.into_inner()),
|
|
||||||
proof,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Kusama::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -16,73 +16,22 @@
|
|||||||
|
|
||||||
//! Rialto-to-Millau headers sync entrypoint.
|
//! Rialto-to-Millau headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
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::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use substrate_relay_helper::finality_pipeline::{
|
use substrate_relay_helper::finality_pipeline::{
|
||||||
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate,
|
DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Rialto-to-Millau finality sync pipeline.
|
/// Description of Millau -> Rialto finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelineRialtoFinalityToMillau =
|
|
||||||
SubstrateFinalityToSubstrate<Rialto, Millau, MillauSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RialtoFinalityToMillau {
|
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;
|
type SourceChain = relay_rialto_client::Rialto;
|
||||||
|
type TargetChain = relay_millau_client::Millau;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder<
|
||||||
bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
|
Self,
|
||||||
|
|
||||||
type TargetChain = Millau;
|
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_millau::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Millau>,
|
|
||||||
transaction_nonce: IndexOf<Millau>,
|
|
||||||
header: RialtoSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_rialto::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = millau_runtime::BridgeGrandpaCall::<
|
|
||||||
millau_runtime::Runtime,
|
millau_runtime::Runtime,
|
||||||
millau_runtime::RialtoGrandpaInstance,
|
millau_runtime::RialtoGrandpaInstance,
|
||||||
>::submit_finality_proof {
|
>;
|
||||||
finality_target: Box::new(header.into_inner()),
|
type TransactionSignScheme = relay_millau_client::Millau;
|
||||||
justification: proof,
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Millau::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,89 +16,40 @@
|
|||||||
|
|
||||||
//! Rococo-to-Wococo headers sync entrypoint.
|
//! Rococo-to-Wococo headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
use sp_core::{Bytes, Pair};
|
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
|
||||||
use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader};
|
|
||||||
use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
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;
|
use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY;
|
||||||
|
|
||||||
/// Rococo-to-Wococo finality sync pipeline.
|
use sp_core::Pair;
|
||||||
pub(crate) type FinalityPipelineRococoFinalityToWococo =
|
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams};
|
||||||
SubstrateFinalityToSubstrate<Rococo, Wococo, WococoSigningParams>;
|
|
||||||
|
|
||||||
|
/// Description of Rococo -> Wococo finalized headers bridge.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct RococoFinalityToWococo {
|
pub struct RococoFinalityToWococo;
|
||||||
finality_pipeline: FinalityPipelineRococoFinalityToWococo,
|
substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!(
|
||||||
}
|
RococoFinalityToWococo,
|
||||||
|
RococoFinalityToWococoCallBuilder,
|
||||||
impl RococoFinalityToWococo {
|
relay_wococo_client::runtime::Call::BridgeGrandpaRococo,
|
||||||
pub fn new(target_client: Client<Wococo>, target_sign: WococoSigningParams) -> Self {
|
relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof
|
||||||
Self {
|
);
|
||||||
finality_pipeline: FinalityPipelineRococoFinalityToWococo::new(
|
|
||||||
target_client,
|
|
||||||
target_sign,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
|
impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo {
|
||||||
type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo;
|
type SourceChain = relay_rococo_client::Rococo;
|
||||||
|
type TargetChain = relay_wococo_client::Wococo;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder;
|
||||||
bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
|
type TransactionSignScheme = relay_wococo_client::Wococo;
|
||||||
|
|
||||||
type TargetChain = Wococo;
|
fn start_relay_guards(
|
||||||
|
target_client: &relay_substrate_client::Client<relay_wococo_client::Wococo>,
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
transaction_params: &TransactionParams<sp_core::sr25519::Pair>,
|
||||||
crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(params)
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
fn start_relay_guards(&self) {
|
|
||||||
relay_substrate_client::guard::abort_on_spec_version_change(
|
relay_substrate_client::guard::abort_on_spec_version_change(
|
||||||
self.finality_pipeline.target_client.clone(),
|
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.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
self.transactions_author(),
|
transaction_params.transactions_signer.public().into(),
|
||||||
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_wococo::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Wococo>,
|
|
||||||
transaction_nonce: IndexOf<Wococo>,
|
|
||||||
header: RococoSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_rococo::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo(
|
|
||||||
relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(
|
|
||||||
Box::new(header.into_inner()),
|
|
||||||
proof,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Wococo::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,78 +16,22 @@
|
|||||||
|
|
||||||
//! Westend-to-Millau headers sync entrypoint.
|
//! Westend-to-Millau headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
use sp_core::{Bytes, Pair};
|
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
|
||||||
use relay_millau_client::{Millau, SigningParams as MillauSigningParams};
|
|
||||||
use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use relay_utils::metrics::MetricsParams;
|
|
||||||
use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend};
|
|
||||||
use substrate_relay_helper::finality_pipeline::{
|
use substrate_relay_helper::finality_pipeline::{
|
||||||
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate,
|
DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Westend-to-Millau finality sync pipeline.
|
/// Description of Westend -> Millau finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelineWestendFinalityToMillau =
|
|
||||||
SubstrateFinalityToSubstrate<Westend, Millau, MillauSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct WestendFinalityToMillau {
|
pub 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;
|
type SourceChain = relay_westend_client::Westend;
|
||||||
|
type TargetChain = relay_millau_client::Millau;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder<
|
||||||
bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD;
|
Self,
|
||||||
|
|
||||||
type TargetChain = Millau;
|
|
||||||
|
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
|
||||||
crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_millau::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Millau>,
|
|
||||||
transaction_nonce: IndexOf<Millau>,
|
|
||||||
header: WestendSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_westend::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = millau_runtime::BridgeGrandpaCall::<
|
|
||||||
millau_runtime::Runtime,
|
millau_runtime::Runtime,
|
||||||
millau_runtime::WestendGrandpaInstance,
|
millau_runtime::WestendGrandpaInstance,
|
||||||
>::submit_finality_proof {
|
>;
|
||||||
finality_target: Box::new(header.into_inner()),
|
type TransactionSignScheme = relay_millau_client::Millau;
|
||||||
justification: proof,
|
|
||||||
}
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Millau::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,8 @@
|
|||||||
|
|
||||||
//! Wococo-to-Rococo headers sync entrypoint.
|
//! Wococo-to-Rococo headers sync entrypoint.
|
||||||
|
|
||||||
use codec::Encode;
|
use sp_core::Pair;
|
||||||
use sp_core::{Bytes, Pair};
|
use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams};
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
|
||||||
use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams};
|
|
||||||
use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction};
|
|
||||||
use relay_utils::metrics::MetricsParams;
|
|
||||||
use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo};
|
|
||||||
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.
|
||||||
@@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{
|
|||||||
/// Note that this is in plancks, so this corresponds to `1500 UNITS`.
|
/// Note that this is in plancks, so this corresponds to `1500 UNITS`.
|
||||||
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.
|
/// Description of Wococo -> Rococo finalized headers bridge.
|
||||||
pub(crate) type FinalityPipelineWococoFinalityToRococo =
|
|
||||||
SubstrateFinalityToSubstrate<Wococo, Rococo, RococoSigningParams>;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct WococoFinalityToRococo {
|
pub struct WococoFinalityToRococo;
|
||||||
finality_pipeline: FinalityPipelineWococoFinalityToRococo,
|
substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!(
|
||||||
}
|
WococoFinalityToRococo,
|
||||||
|
WococoFinalityToRococoCallBuilder,
|
||||||
impl WococoFinalityToRococo {
|
relay_rococo_client::runtime::Call::BridgeGrandpaWococo,
|
||||||
pub fn new(target_client: Client<Rococo>, target_sign: RococoSigningParams) -> Self {
|
relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof
|
||||||
Self {
|
);
|
||||||
finality_pipeline: FinalityPipelineWococoFinalityToRococo::new(
|
|
||||||
target_client,
|
|
||||||
target_sign,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
|
impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo {
|
||||||
type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo;
|
type SourceChain = relay_wococo_client::Wococo;
|
||||||
|
type TargetChain = relay_rococo_client::Rococo;
|
||||||
|
|
||||||
const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str =
|
type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder;
|
||||||
bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
|
type TransactionSignScheme = relay_rococo_client::Rococo;
|
||||||
|
|
||||||
type TargetChain = Rococo;
|
fn start_relay_guards(
|
||||||
|
target_client: &relay_substrate_client::Client<relay_rococo_client::Rococo>,
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
transaction_params: &TransactionParams<sp_core::sr25519::Pair>,
|
||||||
crate::chains::add_polkadot_kusama_price_metrics::<Self::FinalitySyncPipeline>(params)
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
fn start_relay_guards(&self) {
|
|
||||||
relay_substrate_client::guard::abort_on_spec_version_change(
|
relay_substrate_client::guard::abort_on_spec_version_change(
|
||||||
self.finality_pipeline.target_client.clone(),
|
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.finality_pipeline.target_client.clone(),
|
target_client.clone(),
|
||||||
self.transactions_author(),
|
transaction_params.transactions_signer.public().into(),
|
||||||
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
MAXIMAL_BALANCE_DECREASE_PER_DAY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transactions_author(&self) -> bp_rococo::AccountId {
|
|
||||||
(*self.finality_pipeline.target_sign.public().as_array_ref()).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Rococo>,
|
|
||||||
transaction_nonce: IndexOf<Rococo>,
|
|
||||||
header: WococoSyncHeader,
|
|
||||||
proof: GrandpaJustification<bp_wococo::Header>,
|
|
||||||
) -> Bytes {
|
|
||||||
let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo(
|
|
||||||
relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(
|
|
||||||
Box::new(header.into_inner()),
|
|
||||||
proof,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let genesis_hash = *self.finality_pipeline.target_client.genesis_hash();
|
|
||||||
let transaction = Rococo::sign_transaction(
|
|
||||||
genesis_hash,
|
|
||||||
&self.finality_pipeline.target_sign,
|
|
||||||
era,
|
|
||||||
UnsignedTransaction::new(call, transaction_nonce),
|
|
||||||
);
|
|
||||||
|
|
||||||
Bytes(transaction.encode())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -121,18 +121,22 @@ impl RelayHeaders {
|
|||||||
let target_client = self.target.to_client::<Target>().await?;
|
let target_client = self.target.to_client::<Target>().await?;
|
||||||
let target_transactions_mortality = self.target_sign.target_transactions_mortality;
|
let target_transactions_mortality = self.target_sign.target_transactions_mortality;
|
||||||
let target_sign = self.target_sign.to_keypair::<Target>()?;
|
let target_sign = self.target_sign.to_keypair::<Target>()?;
|
||||||
let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?;
|
|
||||||
|
let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into();
|
||||||
GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;
|
GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?;
|
||||||
|
|
||||||
let finality = Finality::new(target_client.clone(), target_sign);
|
let target_transactions_params =
|
||||||
finality.start_relay_guards();
|
substrate_relay_helper::finality_pipeline::TransactionParams {
|
||||||
|
transactions_signer: target_sign,
|
||||||
|
transactions_mortality: target_transactions_mortality,
|
||||||
|
};
|
||||||
|
Finality::start_relay_guards(&target_client, &target_transactions_params);
|
||||||
|
|
||||||
substrate_relay_helper::finality_pipeline::run(
|
substrate_relay_helper::finality_pipeline::run::<Finality>(
|
||||||
finality,
|
|
||||||
source_client,
|
source_client,
|
||||||
target_client,
|
target_client,
|
||||||
self.only_mandatory_headers,
|
self.only_mandatory_headers,
|
||||||
target_transactions_mortality,
|
target_transactions_params,
|
||||||
metrics_params,
|
metrics_params,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -489,25 +489,35 @@ impl RelayHeadersAndMessages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start on-demand header relays
|
// start on-demand header relays
|
||||||
let left_to_right_finality =
|
let left_to_right_transaction_params =
|
||||||
LeftToRightFinality::new(right_client.clone(), right_sign.clone());
|
substrate_relay_helper::finality_pipeline::TransactionParams {
|
||||||
let right_to_left_finality =
|
transactions_mortality: right_transactions_mortality,
|
||||||
RightToLeftFinality::new(left_client.clone(), left_sign.clone());
|
transactions_signer: right_sign.clone(),
|
||||||
left_to_right_finality.start_relay_guards();
|
};
|
||||||
right_to_left_finality.start_relay_guards();
|
let right_to_left_transaction_params =
|
||||||
let left_to_right_on_demand_headers = OnDemandHeadersRelay::new(
|
substrate_relay_helper::finality_pipeline::TransactionParams {
|
||||||
|
transactions_mortality: left_transactions_mortality,
|
||||||
|
transactions_signer: left_sign.clone(),
|
||||||
|
};
|
||||||
|
LeftToRightFinality::start_relay_guards(
|
||||||
|
&right_client,
|
||||||
|
&left_to_right_transaction_params,
|
||||||
|
);
|
||||||
|
RightToLeftFinality::start_relay_guards(
|
||||||
|
&left_client,
|
||||||
|
&right_to_left_transaction_params,
|
||||||
|
);
|
||||||
|
let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::<LeftToRightFinality>(
|
||||||
left_client.clone(),
|
left_client.clone(),
|
||||||
right_client.clone(),
|
right_client.clone(),
|
||||||
right_transactions_mortality,
|
left_to_right_transaction_params,
|
||||||
left_to_right_finality,
|
|
||||||
MAX_MISSING_LEFT_HEADERS_AT_RIGHT,
|
MAX_MISSING_LEFT_HEADERS_AT_RIGHT,
|
||||||
params.shared.only_mandatory_headers,
|
params.shared.only_mandatory_headers,
|
||||||
);
|
);
|
||||||
let right_to_left_on_demand_headers = OnDemandHeadersRelay::new(
|
let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::<RightToLeftFinality>(
|
||||||
right_client.clone(),
|
right_client.clone(),
|
||||||
left_client.clone(),
|
left_client.clone(),
|
||||||
left_transactions_mortality,
|
right_to_left_transaction_params,
|
||||||
right_to_left_finality,
|
|
||||||
MAX_MISSING_RIGHT_HEADERS_AT_LEFT,
|
MAX_MISSING_RIGHT_HEADERS_AT_LEFT,
|
||||||
params.shared.only_mandatory_headers,
|
params.shared.only_mandatory_headers,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ impl ChainBase for Kusama {
|
|||||||
|
|
||||||
impl Chain for Kusama {
|
impl Chain for Kusama {
|
||||||
const NAME: &'static str = "Kusama";
|
const NAME: &'static str = "Kusama";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ impl ChainBase for Millau {
|
|||||||
|
|
||||||
impl Chain for Millau {
|
impl Chain for Millau {
|
||||||
const NAME: &'static str = "Millau";
|
const NAME: &'static str = "Millau";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ impl ChainBase for Polkadot {
|
|||||||
|
|
||||||
impl Chain for Polkadot {
|
impl Chain for Polkadot {
|
||||||
const NAME: &'static str = "Polkadot";
|
const NAME: &'static str = "Polkadot";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ impl ChainBase for RialtoParachain {
|
|||||||
|
|
||||||
impl Chain for RialtoParachain {
|
impl Chain for RialtoParachain {
|
||||||
const NAME: &'static str = "RialtoParachain";
|
const NAME: &'static str = "RialtoParachain";
|
||||||
|
// should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "<UNIMPLEMENTED>";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ impl ChainBase for Rialto {
|
|||||||
|
|
||||||
impl Chain for Rialto {
|
impl Chain for Rialto {
|
||||||
const NAME: &'static str = "Rialto";
|
const NAME: &'static str = "Rialto";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ impl ChainBase for Rococo {
|
|||||||
|
|
||||||
impl Chain for Rococo {
|
impl Chain for Rococo {
|
||||||
const NAME: &'static str = "Rococo";
|
const NAME: &'static str = "Rococo";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ use std::{fmt::Debug, time::Duration};
|
|||||||
pub trait Chain: ChainBase + Clone {
|
pub trait Chain: ChainBase + Clone {
|
||||||
/// Chain name.
|
/// Chain name.
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
/// Name of the runtime API method that is returning best known finalized header number
|
||||||
|
/// and hash (as tuple).
|
||||||
|
///
|
||||||
|
/// Keep in mind that this method is normally provided by the other chain, which is
|
||||||
|
/// bridged with this chain.
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str;
|
||||||
|
|
||||||
/// Average block interval.
|
/// Average block interval.
|
||||||
///
|
///
|
||||||
/// How often blocks are produced on that chain. It's suggested to set this value
|
/// How often blocks are produced on that chain. It's suggested to set this value
|
||||||
@@ -45,7 +52,7 @@ pub trait Chain: ChainBase + Clone {
|
|||||||
/// Block type.
|
/// Block type.
|
||||||
type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>;
|
type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification<Self::Header>;
|
||||||
/// The aggregated `Call` type.
|
/// The aggregated `Call` type.
|
||||||
type Call: Clone + Dispatchable + Debug;
|
type Call: Clone + Dispatchable + Debug + Send;
|
||||||
|
|
||||||
/// Type that is used by the chain, to convert from weight to fee.
|
/// Type that is used by the chain, to convert from weight to fee.
|
||||||
type WeightToFee: WeightToFeePolynomial<Balance = Self::Balance>;
|
type WeightToFee: WeightToFeePolynomial<Balance = Self::Balance>;
|
||||||
@@ -102,6 +109,9 @@ impl<C: Chain> UnsignedTransaction<C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Account key pair used by transactions signing scheme.
|
||||||
|
pub type AccountKeyPairOf<S> = <S as TransactionSignScheme>::AccountKeyPair;
|
||||||
|
|
||||||
/// Substrate-based chain transactions signing scheme.
|
/// Substrate-based chain transactions signing scheme.
|
||||||
pub trait TransactionSignScheme {
|
pub trait TransactionSignScheme {
|
||||||
/// Chain that this scheme is to be used.
|
/// Chain that this scheme is to be used.
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ mod tests {
|
|||||||
|
|
||||||
impl Chain for TestChain {
|
impl Chain for TestChain {
|
||||||
const NAME: &'static str = "Test";
|
const NAME: &'static str = "Test";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = 0;
|
const STORAGE_PROOF_OVERHEAD: u32 = 0;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ mod error;
|
|||||||
mod rpc;
|
mod rpc;
|
||||||
mod sync_header;
|
mod sync_header;
|
||||||
|
|
||||||
pub mod finality_source;
|
|
||||||
pub mod guard;
|
pub mod guard;
|
||||||
pub mod metrics;
|
pub mod metrics;
|
||||||
|
|
||||||
@@ -32,8 +31,8 @@ use std::time::Duration;
|
|||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
chain::{
|
chain::{
|
||||||
BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme,
|
AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances,
|
||||||
TransactionStatusOf, UnsignedTransaction, WeightToFeeOf,
|
TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf,
|
||||||
},
|
},
|
||||||
client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription},
|
client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription},
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ impl ChainBase for Westend {
|
|||||||
|
|
||||||
impl Chain for Westend {
|
impl Chain for Westend {
|
||||||
const NAME: &'static str = "Westend";
|
const NAME: &'static str = "Westend";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ impl ChainBase for Wococo {
|
|||||||
|
|
||||||
impl Chain for Wococo {
|
impl Chain for Wococo {
|
||||||
const NAME: &'static str = "Wococo";
|
const NAME: &'static str = "Wococo";
|
||||||
|
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str =
|
||||||
|
bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD;
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE;
|
const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE;
|
||||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ relay-utils = { path = "../utils" }
|
|||||||
messages-relay = { path = "../messages" }
|
messages-relay = { path = "../messages" }
|
||||||
relay-substrate-client = { path = "../client-substrate" }
|
relay-substrate-client = { path = "../client-substrate" }
|
||||||
|
|
||||||
|
pallet-bridge-grandpa = { path = "../../modules/grandpa" }
|
||||||
pallet-bridge-messages = { path = "../../modules/messages" }
|
pallet-bridge-messages = { path = "../../modules/messages" }
|
||||||
|
|
||||||
bp-runtime = { path = "../../primitives/runtime" }
|
bp-runtime = { path = "../../primitives/runtime" }
|
||||||
|
|||||||
@@ -14,18 +14,20 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
//! Substrate-to-Substrate headers sync entrypoint.
|
//! Types and functions intended to ease adding of new Substrate -> Substrate
|
||||||
|
//! finality proofs synchronization pipelines.
|
||||||
|
|
||||||
use crate::{finality_target::SubstrateFinalityTarget, STALL_TIMEOUT};
|
use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget};
|
||||||
|
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use bp_runtime::AccountIdOf;
|
use finality_relay::FinalitySyncPipeline;
|
||||||
use finality_relay::{FinalitySyncParams, FinalitySyncPipeline};
|
use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig};
|
||||||
use relay_substrate_client::{
|
use relay_substrate_client::{
|
||||||
finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader,
|
transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client,
|
||||||
|
HashOf, HeaderOf, SyncHeader, TransactionSignScheme,
|
||||||
};
|
};
|
||||||
use relay_utils::{metrics::MetricsParams, BlockNumberBase};
|
use relay_utils::metrics::MetricsParams;
|
||||||
use sp_core::Bytes;
|
use sp_core::Pair;
|
||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
/// Default limit of recent finality proofs.
|
/// Default limit of recent finality proofs.
|
||||||
@@ -34,130 +36,152 @@ use std::{fmt::Debug, marker::PhantomData};
|
|||||||
/// Substrate+GRANDPA based chains (good to know).
|
/// Substrate+GRANDPA based chains (good to know).
|
||||||
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.
|
/// Submit-finality-proofs transaction creation parameters.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TransactionParams<TS> {
|
||||||
|
/// Transactions author.
|
||||||
|
pub transactions_signer: TS,
|
||||||
|
/// Transactions mortality.
|
||||||
|
pub transactions_mortality: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Substrate -> Substrate finality proofs synchronization pipeline.
|
||||||
pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
|
pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync {
|
||||||
/// Pipeline for syncing finalized Source chain headers to Target chain.
|
/// Headers of this chain are submitted to the `TargetChain`.
|
||||||
type FinalitySyncPipeline: FinalitySyncPipeline;
|
type SourceChain: Chain;
|
||||||
|
/// Headers of the `SourceChain` are submitted to this 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;
|
|
||||||
|
|
||||||
/// Chain with GRANDPA bridge pallet.
|
|
||||||
type TargetChain: Chain;
|
type TargetChain: Chain;
|
||||||
|
|
||||||
/// Customize metrics exposed by headers sync loop.
|
/// How submit finality proof call is built?
|
||||||
fn customize_metrics(params: MetricsParams) -> anyhow::Result<MetricsParams> {
|
type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder<Self>;
|
||||||
Ok(params)
|
/// Scheme used to sign target chain transactions.
|
||||||
}
|
type TransactionSignScheme: TransactionSignScheme;
|
||||||
|
|
||||||
/// Start finality relay guards.
|
/// Add relay guards if required.
|
||||||
///
|
fn start_relay_guards(
|
||||||
/// Different finality bridges may have different set of guards - e.g. on ephemeral chains we
|
_target_client: &Client<Self::TargetChain>,
|
||||||
/// don't need a version guards, on test chains we don't care that much about relayer account
|
_transaction_params: &TransactionParams<AccountKeyPairOf<Self::TransactionSignScheme>>,
|
||||||
/// balance, ... So the implementation is left to the specific bridges.
|
) {
|
||||||
fn start_relay_guards(&self) {}
|
|
||||||
|
|
||||||
/// Returns id of account that we're using to sign transactions at target chain.
|
|
||||||
fn transactions_author(&self) -> AccountIdOf<Self::TargetChain>;
|
|
||||||
|
|
||||||
/// Make submit header transaction.
|
|
||||||
fn make_submit_finality_proof_transaction(
|
|
||||||
&self,
|
|
||||||
era: bp_runtime::TransactionEraOf<Self::TargetChain>,
|
|
||||||
transaction_nonce: bp_runtime::IndexOf<Self::TargetChain>,
|
|
||||||
header: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::Header,
|
|
||||||
proof: <Self::FinalitySyncPipeline as FinalitySyncPipeline>::FinalityProof,
|
|
||||||
) -> Bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Substrate-to-Substrate finality proof pipeline.
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct SubstrateFinalityToSubstrate<SourceChain, TargetChain: Chain, TargetSign> {
|
|
||||||
/// Client for the target chain.
|
|
||||||
pub target_client: Client<TargetChain>,
|
|
||||||
/// Data required to sign target chain transactions.
|
|
||||||
pub target_sign: TargetSign,
|
|
||||||
/// Unused generic arguments dump.
|
|
||||||
_marker: PhantomData<SourceChain>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<SourceChain, TargetChain: Chain, TargetSign> Debug
|
|
||||||
for SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
f.debug_struct("SubstrateFinalityToSubstrate")
|
|
||||||
.field("target_client", &self.target_client)
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SourceChain, TargetChain: Chain, TargetSign>
|
/// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`.
|
||||||
SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
#[derive(Clone, Debug)]
|
||||||
{
|
pub struct FinalitySyncPipelineAdapter<P: SubstrateFinalitySyncPipeline> {
|
||||||
/// Create new Substrate-to-Substrate headers pipeline.
|
_phantom: PhantomData<P>,
|
||||||
pub fn new(target_client: Client<TargetChain>, target_sign: TargetSign) -> Self {
|
|
||||||
SubstrateFinalityToSubstrate { target_client, target_sign, _marker: Default::default() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SourceChain, TargetChain, TargetSign> FinalitySyncPipeline
|
impl<P: SubstrateFinalitySyncPipeline> FinalitySyncPipeline for FinalitySyncPipelineAdapter<P> {
|
||||||
for SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>
|
const SOURCE_NAME: &'static str = P::SourceChain::NAME;
|
||||||
|
const TARGET_NAME: &'static str = P::TargetChain::NAME;
|
||||||
|
|
||||||
|
type Hash = HashOf<P::SourceChain>;
|
||||||
|
type Number = BlockNumberOf<P::SourceChain>;
|
||||||
|
type Header = relay_substrate_client::SyncHeader<HeaderOf<P::SourceChain>>;
|
||||||
|
type FinalityProof = GrandpaJustification<HeaderOf<P::SourceChain>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Different ways of building `submit_finality_proof` calls.
|
||||||
|
pub trait SubmitFinalityProofCallBuilder<P: SubstrateFinalitySyncPipeline> {
|
||||||
|
/// Given source chain header and its finality proofs, build call of `submit_finality_proof`
|
||||||
|
/// function of bridge GRANDPA module at the target chain.
|
||||||
|
fn build_submit_finality_proof_call(
|
||||||
|
header: SyncHeader<HeaderOf<P::SourceChain>>,
|
||||||
|
proof: GrandpaJustification<HeaderOf<P::SourceChain>>,
|
||||||
|
) -> CallOf<P::TargetChain>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Building `submit_finality_proof` call when you have direct access to the target
|
||||||
|
/// chain runtime.
|
||||||
|
pub struct DirectSubmitFinalityProofCallBuilder<P, R, I> {
|
||||||
|
_phantom: PhantomData<(P, R, I)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P, R, I> SubmitFinalityProofCallBuilder<P> for DirectSubmitFinalityProofCallBuilder<P, R, I>
|
||||||
where
|
where
|
||||||
SourceChain: Clone + Chain + Debug,
|
P: SubstrateFinalitySyncPipeline,
|
||||||
BlockNumberOf<SourceChain>: BlockNumberBase,
|
R: BridgeGrandpaConfig<I>,
|
||||||
TargetChain: Clone + Chain + Debug,
|
I: 'static,
|
||||||
TargetSign: 'static + Clone + Send + Sync,
|
R::BridgedChain: bp_runtime::Chain<Header = HeaderOf<P::SourceChain>>,
|
||||||
|
CallOf<P::TargetChain>: From<BridgeGrandpaCall<R, I>>,
|
||||||
{
|
{
|
||||||
const SOURCE_NAME: &'static str = SourceChain::NAME;
|
fn build_submit_finality_proof_call(
|
||||||
const TARGET_NAME: &'static str = TargetChain::NAME;
|
header: SyncHeader<HeaderOf<P::SourceChain>>,
|
||||||
|
proof: GrandpaJustification<HeaderOf<P::SourceChain>>,
|
||||||
type Hash = HashOf<SourceChain>;
|
) -> CallOf<P::TargetChain> {
|
||||||
type Number = BlockNumberOf<SourceChain>;
|
BridgeGrandpaCall::<R, I>::submit_finality_proof {
|
||||||
type Header = SyncHeader<SourceChain::Header>;
|
finality_target: Box::new(header.into_inner()),
|
||||||
type FinalityProof = GrandpaJustification<SourceChain::Header>;
|
justification: proof,
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run Substrate-to-Substrate finality sync.
|
/// Macro that generates `SubmitFinalityProofCallBuilder` implementation for the case when
|
||||||
pub async fn run<SourceChain, TargetChain, P>(
|
/// you only have an access to the mocked version of target chain runtime. In this case you
|
||||||
pipeline: P,
|
/// should provide "name" of the call variant for the bridge GRANDPA calls and the "name" of
|
||||||
source_client: Client<SourceChain>,
|
/// the variant for the `submit_finality_proof` call within that first option.
|
||||||
target_client: Client<TargetChain>,
|
#[rustfmt::skip]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! generate_mocked_submit_finality_proof_call_builder {
|
||||||
|
($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => {
|
||||||
|
pub struct $mocked_builder;
|
||||||
|
|
||||||
|
impl $crate::finality_pipeline::SubmitFinalityProofCallBuilder<$pipeline>
|
||||||
|
for $mocked_builder
|
||||||
|
{
|
||||||
|
fn build_submit_finality_proof_call(
|
||||||
|
header: relay_substrate_client::SyncHeader<
|
||||||
|
relay_substrate_client::HeaderOf<
|
||||||
|
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
proof: bp_header_chain::justification::GrandpaJustification<
|
||||||
|
relay_substrate_client::HeaderOf<
|
||||||
|
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
) -> relay_substrate_client::CallOf<
|
||||||
|
<$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::TargetChain
|
||||||
|
> {
|
||||||
|
$bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run Substrate-to-Substrate finality sync loop.
|
||||||
|
pub async fn run<P: SubstrateFinalitySyncPipeline>(
|
||||||
|
source_client: Client<P::SourceChain>,
|
||||||
|
target_client: Client<P::TargetChain>,
|
||||||
only_mandatory_headers: bool,
|
only_mandatory_headers: bool,
|
||||||
transactions_mortality: Option<u32>,
|
transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||||
metrics_params: MetricsParams,
|
metrics_params: MetricsParams,
|
||||||
) -> anyhow::Result<()>
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
P: SubstrateFinalitySyncPipeline<TargetChain = TargetChain>,
|
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<P::TransactionSignScheme> as Pair>::Public>,
|
||||||
P::FinalitySyncPipeline: FinalitySyncPipeline<
|
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||||
Hash = HashOf<SourceChain>,
|
|
||||||
Number = BlockNumberOf<SourceChain>,
|
|
||||||
Header = SyncHeader<SourceChain::Header>,
|
|
||||||
FinalityProof = GrandpaJustification<SourceChain::Header>,
|
|
||||||
>,
|
|
||||||
SourceChain: Clone + Chain,
|
|
||||||
BlockNumberOf<SourceChain>: BlockNumberBase,
|
|
||||||
TargetChain: Clone + Chain,
|
|
||||||
{
|
{
|
||||||
log::info!(
|
log::info!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
"Starting {} -> {} finality proof relay",
|
"Starting {} -> {} finality proof relay",
|
||||||
SourceChain::NAME,
|
P::SourceChain::NAME,
|
||||||
TargetChain::NAME,
|
P::TargetChain::NAME,
|
||||||
);
|
);
|
||||||
|
|
||||||
finality_relay::run(
|
finality_relay::run(
|
||||||
FinalitySource::new(source_client, None),
|
SubstrateFinalitySource::<P>::new(source_client, None),
|
||||||
SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality),
|
SubstrateFinalityTarget::<P>::new(target_client, transaction_params.clone()),
|
||||||
FinalitySyncParams {
|
finality_relay::FinalitySyncParams {
|
||||||
tick: std::cmp::max(
|
tick: std::cmp::max(
|
||||||
SourceChain::AVERAGE_BLOCK_INTERVAL,
|
P::SourceChain::AVERAGE_BLOCK_INTERVAL,
|
||||||
TargetChain::AVERAGE_BLOCK_INTERVAL,
|
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||||
),
|
),
|
||||||
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
|
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
|
||||||
stall_timeout: relay_substrate_client::transaction_stall_timeout(
|
stall_timeout: transaction_stall_timeout(
|
||||||
transactions_mortality,
|
transaction_params.transactions_mortality,
|
||||||
TargetChain::AVERAGE_BLOCK_INTERVAL,
|
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||||
STALL_TIMEOUT,
|
crate::STALL_TIMEOUT,
|
||||||
),
|
),
|
||||||
only_mandatory_headers,
|
only_mandatory_headers,
|
||||||
},
|
},
|
||||||
|
|||||||
+50
-40
@@ -16,49 +16,59 @@
|
|||||||
|
|
||||||
//! Default generic implementation of finality source for basic Substrate client.
|
//! Default generic implementation of finality source for basic Substrate client.
|
||||||
|
|
||||||
use crate::{
|
use crate::finality_pipeline::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline};
|
||||||
chain::{BlockWithJustification, Chain},
|
|
||||||
client::Client,
|
|
||||||
error::Error,
|
|
||||||
sync_header::SyncHeader,
|
|
||||||
};
|
|
||||||
|
|
||||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bp_header_chain::justification::GrandpaJustification;
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader};
|
use finality_relay::SourceClient;
|
||||||
use futures::stream::{unfold, Stream, StreamExt};
|
use futures::stream::{unfold, Stream, StreamExt};
|
||||||
|
use relay_substrate_client::{
|
||||||
|
BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf,
|
||||||
|
};
|
||||||
use relay_utils::relay_loop::Client as RelayClient;
|
use relay_utils::relay_loop::Client as RelayClient;
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
use sp_runtime::traits::Header as HeaderT;
|
||||||
use std::{marker::PhantomData, pin::Pin};
|
use std::pin::Pin;
|
||||||
|
|
||||||
/// Shared updatable reference to the maximal header number that we want to sync from the source.
|
/// Shared updatable reference to the maximal header number that we want to sync from the source.
|
||||||
pub type RequiredHeaderNumberRef<C> = Arc<Mutex<<C as bp_runtime::Chain>::BlockNumber>>;
|
pub type RequiredHeaderNumberRef<C> = Arc<Mutex<<C as bp_runtime::Chain>::BlockNumber>>;
|
||||||
|
|
||||||
|
/// Substrate finality proofs stream.
|
||||||
|
pub type SubstrateFinalityProofsStream<P> = Pin<
|
||||||
|
Box<
|
||||||
|
dyn Stream<
|
||||||
|
Item = GrandpaJustification<
|
||||||
|
HeaderOf<<P as SubstrateFinalitySyncPipeline>::SourceChain>,
|
||||||
|
>,
|
||||||
|
> + Send,
|
||||||
|
>,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Substrate node as finality source.
|
/// Substrate node as finality source.
|
||||||
pub struct FinalitySource<C: Chain, P> {
|
pub struct SubstrateFinalitySource<P: SubstrateFinalitySyncPipeline> {
|
||||||
client: Client<C>,
|
client: Client<P::SourceChain>,
|
||||||
maximal_header_number: Option<RequiredHeaderNumberRef<C>>,
|
maximal_header_number: Option<RequiredHeaderNumberRef<P::SourceChain>>,
|
||||||
_phantom: PhantomData<P>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Chain, P> FinalitySource<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> SubstrateFinalitySource<P> {
|
||||||
/// Create new headers source using given client.
|
/// Create new headers source using given client.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Client<C>,
|
client: Client<P::SourceChain>,
|
||||||
maximal_header_number: Option<RequiredHeaderNumberRef<C>>,
|
maximal_header_number: Option<RequiredHeaderNumberRef<P::SourceChain>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
FinalitySource { client, maximal_header_number, _phantom: Default::default() }
|
SubstrateFinalitySource { client, maximal_header_number }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns reference to the underlying RPC client.
|
/// Returns reference to the underlying RPC client.
|
||||||
pub fn client(&self) -> &Client<C> {
|
pub fn client(&self) -> &Client<P::SourceChain> {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns best finalized block number.
|
/// Returns best finalized block number.
|
||||||
pub async fn on_chain_best_finalized_block_number(&self) -> Result<C::BlockNumber, Error> {
|
pub async fn on_chain_best_finalized_block_number(
|
||||||
|
&self,
|
||||||
|
) -> Result<BlockNumberOf<P::SourceChain>, Error> {
|
||||||
// we **CAN** continue to relay finality proofs if source node is out of sync, because
|
// we **CAN** continue to relay finality proofs if source node is out of sync, because
|
||||||
// target node may be missing proofs that are already available at the source
|
// target node may be missing proofs that are already available at the source
|
||||||
let finalized_header_hash = self.client.best_finalized_header_hash().await?;
|
let finalized_header_hash = self.client.best_finalized_header_hash().await?;
|
||||||
@@ -67,18 +77,17 @@ impl<C: Chain, P> FinalitySource<C, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Chain, P> Clone for FinalitySource<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> Clone for SubstrateFinalitySource<P> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
FinalitySource {
|
SubstrateFinalitySource {
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
maximal_header_number: self.maximal_header_number.clone(),
|
maximal_header_number: self.maximal_header_number.clone(),
|
||||||
_phantom: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<C: Chain, P: FinalitySyncPipeline> RelayClient for FinalitySource<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> RelayClient for SubstrateFinalitySource<P> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
async fn reconnect(&mut self) -> Result<(), Error> {
|
async fn reconnect(&mut self) -> Result<(), Error> {
|
||||||
@@ -87,21 +96,12 @@ impl<C: Chain, P: FinalitySyncPipeline> RelayClient for FinalitySource<C, P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<C, P> SourceClient<P> for FinalitySource<C, P>
|
impl<P: SubstrateFinalitySyncPipeline> SourceClient<FinalitySyncPipelineAdapter<P>>
|
||||||
where
|
for SubstrateFinalitySource<P>
|
||||||
C: Chain,
|
|
||||||
C::BlockNumber: relay_utils::BlockNumberBase,
|
|
||||||
P: FinalitySyncPipeline<
|
|
||||||
Hash = C::Hash,
|
|
||||||
Number = C::BlockNumber,
|
|
||||||
Header = SyncHeader<C::Header>,
|
|
||||||
FinalityProof = GrandpaJustification<C::Header>,
|
|
||||||
>,
|
|
||||||
P::Header: SourceHeader<C::BlockNumber>,
|
|
||||||
{
|
{
|
||||||
type FinalityProofsStream = Pin<Box<dyn Stream<Item = GrandpaJustification<C::Header>> + Send>>;
|
type FinalityProofsStream = SubstrateFinalityProofsStream<P>;
|
||||||
|
|
||||||
async fn best_finalized_block_number(&self) -> Result<P::Number, Error> {
|
async fn best_finalized_block_number(&self) -> Result<BlockNumberOf<P::SourceChain>, Error> {
|
||||||
let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?;
|
let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?;
|
||||||
// never return block number larger than requested. This way we'll never sync headers
|
// never return block number larger than requested. This way we'll never sync headers
|
||||||
// past `maximal_header_number`
|
// past `maximal_header_number`
|
||||||
@@ -116,15 +116,23 @@ where
|
|||||||
|
|
||||||
async fn header_and_finality_proof(
|
async fn header_and_finality_proof(
|
||||||
&self,
|
&self,
|
||||||
number: P::Number,
|
number: BlockNumberOf<P::SourceChain>,
|
||||||
) -> Result<(P::Header, Option<P::FinalityProof>), Error> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
relay_substrate_client::SyncHeader<HeaderOf<P::SourceChain>>,
|
||||||
|
Option<GrandpaJustification<HeaderOf<P::SourceChain>>>,
|
||||||
|
),
|
||||||
|
Error,
|
||||||
|
> {
|
||||||
let header_hash = self.client.block_hash_by_number(number).await?;
|
let header_hash = self.client.block_hash_by_number(number).await?;
|
||||||
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
let signed_block = self.client.get_block(Some(header_hash)).await?;
|
||||||
|
|
||||||
let justification = signed_block
|
let justification = signed_block
|
||||||
.justification()
|
.justification()
|
||||||
.map(|raw_justification| {
|
.map(|raw_justification| {
|
||||||
GrandpaJustification::<C::Header>::decode(&mut raw_justification.as_slice())
|
GrandpaJustification::<HeaderOf<P::SourceChain>>::decode(
|
||||||
|
&mut raw_justification.as_slice(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.transpose()
|
.transpose()
|
||||||
.map_err(Error::ResponseParseFailed)?;
|
.map_err(Error::ResponseParseFailed)?;
|
||||||
@@ -141,7 +149,7 @@ where
|
|||||||
log::error!(
|
log::error!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
"Failed to read justification target from the {} justifications stream: {:?}",
|
"Failed to read justification target from the {} justifications stream: {:?}",
|
||||||
P::SOURCE_NAME,
|
P::SourceChain::NAME,
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -153,7 +161,9 @@ where
|
|||||||
.ok()??;
|
.ok()??;
|
||||||
|
|
||||||
let decoded_justification =
|
let decoded_justification =
|
||||||
GrandpaJustification::<C::Header>::decode(&mut &next_justification[..]);
|
GrandpaJustification::<HeaderOf<P::SourceChain>>::decode(
|
||||||
|
&mut &next_justification[..],
|
||||||
|
);
|
||||||
|
|
||||||
let justification = match decoded_justification {
|
let justification = match decoded_justification {
|
||||||
Ok(j) => j,
|
Ok(j) => j,
|
||||||
@@ -15,70 +15,78 @@
|
|||||||
// 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/>.
|
||||||
|
|
||||||
//! Substrate client as Substrate finality proof target. The chain we connect to should have
|
//! Substrate client as Substrate finality proof target. The chain we connect to should have
|
||||||
//! runtime that implements `<BridgedChainName>FinalityApi` to allow bridging with
|
//! bridge GRANDPA pallet deployed and provide `<BridgedChainName>FinalityApi` to allow bridging
|
||||||
//! <BridgedName> chain.
|
//! with <BridgedName> chain.
|
||||||
|
|
||||||
use crate::finality_pipeline::SubstrateFinalitySyncPipeline;
|
use crate::finality_pipeline::{
|
||||||
|
FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline,
|
||||||
|
TransactionParams,
|
||||||
|
};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use codec::Decode;
|
use bp_header_chain::justification::GrandpaJustification;
|
||||||
use finality_relay::{FinalitySyncPipeline, TargetClient};
|
use codec::Encode;
|
||||||
use relay_substrate_client::{Chain, Client, Error as SubstrateError};
|
use finality_relay::TargetClient;
|
||||||
|
use relay_substrate_client::{
|
||||||
|
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error, HashOf, HeaderOf,
|
||||||
|
SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction,
|
||||||
|
};
|
||||||
use relay_utils::relay_loop::Client as RelayClient;
|
use relay_utils::relay_loop::Client as RelayClient;
|
||||||
|
use sp_core::{Bytes, Pair};
|
||||||
|
|
||||||
/// Substrate client as Substrate finality target.
|
/// Substrate client as Substrate finality target.
|
||||||
pub struct SubstrateFinalityTarget<C: Chain, P> {
|
pub struct SubstrateFinalityTarget<P: SubstrateFinalitySyncPipeline> {
|
||||||
client: Client<C>,
|
client: Client<P::TargetChain>,
|
||||||
pipeline: P,
|
transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||||
transactions_mortality: Option<u32>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Chain, P> SubstrateFinalityTarget<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> SubstrateFinalityTarget<P> {
|
||||||
/// Create new Substrate headers target.
|
/// Create new Substrate headers target.
|
||||||
pub fn new(client: Client<C>, pipeline: P, transactions_mortality: Option<u32>) -> Self {
|
pub fn new(
|
||||||
SubstrateFinalityTarget { client, pipeline, transactions_mortality }
|
client: Client<P::TargetChain>,
|
||||||
|
transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||||
|
) -> Self {
|
||||||
|
SubstrateFinalityTarget { client, transaction_params }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Chain, P: SubstrateFinalitySyncPipeline> Clone for SubstrateFinalityTarget<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> Clone for SubstrateFinalityTarget<P> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
SubstrateFinalityTarget {
|
SubstrateFinalityTarget {
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
pipeline: self.pipeline.clone(),
|
transaction_params: self.transaction_params.clone(),
|
||||||
transactions_mortality: self.transactions_mortality,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<C: Chain, P: SubstrateFinalitySyncPipeline> RelayClient for SubstrateFinalityTarget<C, P> {
|
impl<P: SubstrateFinalitySyncPipeline> RelayClient for SubstrateFinalityTarget<P> {
|
||||||
type Error = SubstrateError;
|
type Error = Error;
|
||||||
|
|
||||||
async fn reconnect(&mut self) -> Result<(), SubstrateError> {
|
async fn reconnect(&mut self) -> Result<(), Error> {
|
||||||
self.client.reconnect().await
|
self.client.reconnect().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<C, P> TargetClient<P::FinalitySyncPipeline> for SubstrateFinalityTarget<C, P>
|
impl<P: SubstrateFinalitySyncPipeline> TargetClient<FinalitySyncPipelineAdapter<P>>
|
||||||
|
for SubstrateFinalityTarget<P>
|
||||||
where
|
where
|
||||||
C: Chain,
|
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<P::TransactionSignScheme> as Pair>::Public>,
|
||||||
P: SubstrateFinalitySyncPipeline<TargetChain = C>,
|
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||||
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Number: Decode,
|
|
||||||
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Hash: Decode,
|
|
||||||
{
|
{
|
||||||
async fn best_finalized_source_block_number(
|
async fn best_finalized_source_block_number(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<<P::FinalitySyncPipeline as FinalitySyncPipeline>::Number, SubstrateError> {
|
) -> Result<BlockNumberOf<P::SourceChain>, Error> {
|
||||||
// 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::<
|
Ok(crate::messages_source::read_client_state::<
|
||||||
C,
|
P::TargetChain,
|
||||||
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Hash,
|
HashOf<P::SourceChain>,
|
||||||
<P::FinalitySyncPipeline as FinalitySyncPipeline>::Number,
|
BlockNumberOf<P::SourceChain>,
|
||||||
>(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET)
|
>(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD)
|
||||||
.await?
|
.await?
|
||||||
.best_finalized_peer_at_best_self
|
.best_finalized_peer_at_best_self
|
||||||
.0)
|
.0)
|
||||||
@@ -86,24 +94,28 @@ where
|
|||||||
|
|
||||||
async fn submit_finality_proof(
|
async fn submit_finality_proof(
|
||||||
&self,
|
&self,
|
||||||
header: <P::FinalitySyncPipeline as FinalitySyncPipeline>::Header,
|
header: SyncHeader<HeaderOf<P::SourceChain>>,
|
||||||
proof: <P::FinalitySyncPipeline as FinalitySyncPipeline>::FinalityProof,
|
proof: GrandpaJustification<HeaderOf<P::SourceChain>>,
|
||||||
) -> Result<(), SubstrateError> {
|
) -> Result<(), Error> {
|
||||||
let transactions_author = self.pipeline.transactions_author();
|
let genesis_hash = *self.client.genesis_hash();
|
||||||
let pipeline = self.pipeline.clone();
|
let transaction_params = self.transaction_params.clone();
|
||||||
let transactions_mortality = self.transactions_mortality;
|
let call =
|
||||||
|
P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof);
|
||||||
self.client
|
self.client
|
||||||
.submit_signed_extrinsic(
|
.submit_signed_extrinsic(
|
||||||
transactions_author,
|
self.transaction_params.transactions_signer.public().into(),
|
||||||
move |best_block_id, transaction_nonce| {
|
move |best_block_id, transaction_nonce| {
|
||||||
pipeline.make_submit_finality_proof_transaction(
|
Bytes(
|
||||||
relay_substrate_client::TransactionEra::new(
|
P::TransactionSignScheme::sign_transaction(
|
||||||
|
genesis_hash,
|
||||||
|
&transaction_params.transactions_signer,
|
||||||
|
TransactionEra::new(
|
||||||
best_block_id,
|
best_block_id,
|
||||||
transactions_mortality,
|
transaction_params.transactions_mortality,
|
||||||
),
|
),
|
||||||
transaction_nonce,
|
UnsignedTransaction::new(call, transaction_nonce),
|
||||||
header,
|
)
|
||||||
proof,
|
.encode(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use std::time::Duration;
|
|||||||
pub mod conversion_rate_update;
|
pub mod conversion_rate_update;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod finality_pipeline;
|
pub mod finality_pipeline;
|
||||||
|
pub mod finality_source;
|
||||||
pub mod finality_target;
|
pub mod finality_target;
|
||||||
pub mod headers_initialize;
|
pub mod headers_initialize;
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
|
|||||||
@@ -16,29 +16,24 @@
|
|||||||
|
|
||||||
//! On-demand Substrate -> Substrate headers relay.
|
//! On-demand Substrate -> Substrate headers relay.
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use async_std::sync::{Arc, Mutex};
|
use async_std::sync::{Arc, Mutex};
|
||||||
use futures::{select, FutureExt};
|
use futures::{select, FutureExt};
|
||||||
use num_traits::{CheckedSub, One, Zero};
|
use num_traits::{CheckedSub, One, Zero};
|
||||||
|
|
||||||
use finality_relay::{
|
use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient};
|
||||||
FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader,
|
|
||||||
TargetClient as FinalityTargetClient,
|
|
||||||
};
|
|
||||||
use relay_substrate_client::{
|
use relay_substrate_client::{
|
||||||
finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef},
|
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderIdOf, HeaderOf, SyncHeader,
|
||||||
Chain, Client, HeaderIdOf, SyncHeader,
|
TransactionSignScheme,
|
||||||
};
|
};
|
||||||
use relay_utils::{
|
use relay_utils::{
|
||||||
metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient,
|
metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError,
|
||||||
MaybeConnectionError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
finality_pipeline::{
|
finality_pipeline::{
|
||||||
SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT,
|
SubstrateFinalitySyncPipeline, TransactionParams, RECENT_FINALITY_PROOFS_LIMIT,
|
||||||
},
|
},
|
||||||
|
finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource},
|
||||||
finality_target::SubstrateFinalityTarget,
|
finality_target::SubstrateFinalityTarget,
|
||||||
STALL_TIMEOUT,
|
STALL_TIMEOUT,
|
||||||
};
|
};
|
||||||
@@ -58,40 +53,28 @@ 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, P>(
|
pub fn new<P: SubstrateFinalitySyncPipeline<SourceChain = SourceChain>>(
|
||||||
source_client: Client<SourceChain>,
|
source_client: Client<P::SourceChain>,
|
||||||
target_client: Client<TargetChain>,
|
target_client: Client<P::TargetChain>,
|
||||||
target_transactions_mortality: Option<u32>,
|
target_transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||||
pipeline: P,
|
maximal_headers_difference: BlockNumberOf<P::SourceChain>,
|
||||||
maximal_headers_difference: SourceChain::BlockNumber,
|
|
||||||
only_mandatory_headers: bool,
|
only_mandatory_headers: bool,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
SourceChain: Chain + Debug,
|
AccountIdOf<P::TargetChain>:
|
||||||
SourceChain::BlockNumber: BlockNumberBase,
|
From<<AccountKeyPairOf<P::TransactionSignScheme> as sp_core::Pair>::Public>,
|
||||||
TargetChain: Chain + Debug,
|
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||||
TargetChain::BlockNumber: BlockNumberBase,
|
|
||||||
TargetSign: Clone + Send + Sync + 'static,
|
|
||||||
P: SubstrateFinalitySyncPipeline<
|
|
||||||
FinalitySyncPipeline = SubstrateFinalityToSubstrate<
|
|
||||||
SourceChain,
|
|
||||||
TargetChain,
|
|
||||||
TargetSign,
|
|
||||||
>,
|
|
||||||
TargetChain = TargetChain,
|
|
||||||
>,
|
|
||||||
{
|
{
|
||||||
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 {
|
||||||
relay_task_name: on_demand_headers_relay_name::<SourceChain, TargetChain>(),
|
relay_task_name: on_demand_headers_relay_name::<P::SourceChain, P::TargetChain>(),
|
||||||
required_header_number: required_header_number.clone(),
|
required_header_number: required_header_number.clone(),
|
||||||
};
|
};
|
||||||
async_std::task::spawn(async move {
|
async_std::task::spawn(async move {
|
||||||
background_task(
|
background_task::<P>(
|
||||||
source_client,
|
source_client,
|
||||||
target_client,
|
target_client,
|
||||||
target_transactions_mortality,
|
target_transaction_params,
|
||||||
pipeline,
|
|
||||||
maximal_headers_difference,
|
maximal_headers_difference,
|
||||||
only_mandatory_headers,
|
only_mandatory_headers,
|
||||||
required_header_number,
|
required_header_number,
|
||||||
@@ -120,35 +103,25 @@ 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, P>(
|
async fn background_task<P: SubstrateFinalitySyncPipeline>(
|
||||||
source_client: Client<SourceChain>,
|
source_client: Client<P::SourceChain>,
|
||||||
target_client: Client<TargetChain>,
|
target_client: Client<P::TargetChain>,
|
||||||
target_transactions_mortality: Option<u32>,
|
target_transaction_params: TransactionParams<AccountKeyPairOf<P::TransactionSignScheme>>,
|
||||||
pipeline: P,
|
maximal_headers_difference: BlockNumberOf<P::SourceChain>,
|
||||||
maximal_headers_difference: SourceChain::BlockNumber,
|
|
||||||
only_mandatory_headers: bool,
|
only_mandatory_headers: bool,
|
||||||
required_header_number: RequiredHeaderNumberRef<SourceChain>,
|
required_header_number: RequiredHeaderNumberRef<P::SourceChain>,
|
||||||
) where
|
) where
|
||||||
SourceChain: Chain + Debug,
|
AccountIdOf<P::TargetChain>:
|
||||||
SourceChain::BlockNumber: BlockNumberBase,
|
From<<AccountKeyPairOf<P::TransactionSignScheme> as sp_core::Pair>::Public>,
|
||||||
TargetChain: Chain + Debug,
|
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||||
TargetChain::BlockNumber: BlockNumberBase,
|
|
||||||
TargetSign: Clone + Send + Sync + 'static,
|
|
||||||
P: SubstrateFinalitySyncPipeline<
|
|
||||||
FinalitySyncPipeline = SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>,
|
|
||||||
TargetChain = TargetChain,
|
|
||||||
>,
|
|
||||||
{
|
{
|
||||||
let relay_task_name = on_demand_headers_relay_name::<SourceChain, TargetChain>();
|
let relay_task_name = on_demand_headers_relay_name::<P::SourceChain, P::TargetChain>();
|
||||||
let mut finality_source = SubstrateFinalitySource::<
|
let mut finality_source = SubstrateFinalitySource::<P>::new(
|
||||||
_,
|
source_client.clone(),
|
||||||
SubstrateFinalityToSubstrate<SourceChain, TargetChain, TargetSign>,
|
Some(required_header_number.clone()),
|
||||||
>::new(source_client.clone(), Some(required_header_number.clone()));
|
|
||||||
let mut finality_target = SubstrateFinalityTarget::new(
|
|
||||||
target_client.clone(),
|
|
||||||
pipeline.clone(),
|
|
||||||
target_transactions_mortality,
|
|
||||||
);
|
);
|
||||||
|
let mut finality_target =
|
||||||
|
SubstrateFinalityTarget::new(target_client.clone(), target_transaction_params);
|
||||||
let mut latest_non_mandatory_at_source = Zero::zero();
|
let mut latest_non_mandatory_at_source = Zero::zero();
|
||||||
|
|
||||||
let mut restart_relay = true;
|
let mut restart_relay = true;
|
||||||
@@ -157,7 +130,7 @@ async fn background_task<SourceChain, TargetChain, TargetSign, P>(
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
_ = async_std::task::sleep(TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {},
|
_ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {},
|
||||||
_ = finality_relay_task => {
|
_ = finality_relay_task => {
|
||||||
// this should never happen in practice given the current code
|
// this should never happen in practice given the current code
|
||||||
restart_relay = true;
|
restart_relay = true;
|
||||||
@@ -179,12 +152,8 @@ async fn background_task<SourceChain, TargetChain, TargetSign, P>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read best finalized source header number from target
|
// read best finalized source header number from target
|
||||||
let best_finalized_source_header_at_target = best_finalized_source_header_at_target::<
|
let best_finalized_source_header_at_target =
|
||||||
SourceChain,
|
best_finalized_source_header_at_target::<P>(&finality_target, &relay_task_name).await;
|
||||||
_,
|
|
||||||
_,
|
|
||||||
>(&finality_target, &relay_task_name)
|
|
||||||
.await;
|
|
||||||
if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) {
|
if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) {
|
||||||
relay_utils::relay_loop::reconnect_failed_client(
|
relay_utils::relay_loop::reconnect_failed_client(
|
||||||
FailedClient::Target,
|
FailedClient::Target,
|
||||||
@@ -199,7 +168,7 @@ async fn background_task<SourceChain, TargetChain, TargetSign, P>(
|
|||||||
// submit mandatory header if some headers are missing
|
// submit mandatory header if some headers are missing
|
||||||
let best_finalized_source_header_at_target_fmt =
|
let best_finalized_source_header_at_target_fmt =
|
||||||
format!("{:?}", best_finalized_source_header_at_target);
|
format!("{:?}", best_finalized_source_header_at_target);
|
||||||
let mandatory_scan_range = mandatory_headers_scan_range::<SourceChain>(
|
let mandatory_scan_range = mandatory_headers_scan_range::<P::SourceChain>(
|
||||||
best_finalized_source_header_at_source.ok(),
|
best_finalized_source_header_at_source.ok(),
|
||||||
best_finalized_source_header_at_target.ok(),
|
best_finalized_source_header_at_target.ok(),
|
||||||
maximal_headers_difference,
|
maximal_headers_difference,
|
||||||
@@ -247,8 +216,8 @@ async fn background_task<SourceChain, TargetChain, TargetSign, P>(
|
|||||||
finality_target.clone(),
|
finality_target.clone(),
|
||||||
FinalitySyncParams {
|
FinalitySyncParams {
|
||||||
tick: std::cmp::max(
|
tick: std::cmp::max(
|
||||||
SourceChain::AVERAGE_BLOCK_INTERVAL,
|
P::SourceChain::AVERAGE_BLOCK_INTERVAL,
|
||||||
TargetChain::AVERAGE_BLOCK_INTERVAL,
|
P::TargetChain::AVERAGE_BLOCK_INTERVAL,
|
||||||
),
|
),
|
||||||
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
|
recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT,
|
||||||
stall_timeout: STALL_TIMEOUT,
|
stall_timeout: STALL_TIMEOUT,
|
||||||
@@ -316,17 +285,13 @@ async fn mandatory_headers_scan_range<C: Chain>(
|
|||||||
/// it.
|
/// it.
|
||||||
///
|
///
|
||||||
/// Returns `true` if header was found and (asked to be) relayed and `false` otherwise.
|
/// Returns `true` if header was found and (asked to be) relayed and `false` otherwise.
|
||||||
async fn relay_mandatory_header_from_range<SourceChain: Chain, P>(
|
async fn relay_mandatory_header_from_range<P: SubstrateFinalitySyncPipeline>(
|
||||||
finality_source: &SubstrateFinalitySource<SourceChain, P>,
|
finality_source: &SubstrateFinalitySource<P>,
|
||||||
required_header_number: &RequiredHeaderNumberRef<SourceChain>,
|
required_header_number: &RequiredHeaderNumberRef<P::SourceChain>,
|
||||||
best_finalized_source_header_at_target: String,
|
best_finalized_source_header_at_target: String,
|
||||||
range: (SourceChain::BlockNumber, SourceChain::BlockNumber),
|
range: (BlockNumberOf<P::SourceChain>, BlockNumberOf<P::SourceChain>),
|
||||||
relay_task_name: &str,
|
relay_task_name: &str,
|
||||||
) -> Result<bool, relay_substrate_client::Error>
|
) -> Result<bool, relay_substrate_client::Error> {
|
||||||
where
|
|
||||||
SubstrateFinalitySource<SourceChain, P>: FinalitySourceClient<P>,
|
|
||||||
P: FinalitySyncPipeline<Number = SourceChain::BlockNumber>,
|
|
||||||
{
|
|
||||||
// search for mandatory header first
|
// search for mandatory header first
|
||||||
let mandatory_source_header_number =
|
let mandatory_source_header_number =
|
||||||
find_mandatory_header_in_range(finality_source, range).await?;
|
find_mandatory_header_in_range(finality_source, range).await?;
|
||||||
@@ -347,7 +312,7 @@ where
|
|||||||
log::trace!(
|
log::trace!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
"Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}",
|
"Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}",
|
||||||
SourceChain::NAME,
|
P::SourceChain::NAME,
|
||||||
relay_task_name,
|
relay_task_name,
|
||||||
best_finalized_source_header_at_target,
|
best_finalized_source_header_at_target,
|
||||||
range.1,
|
range.1,
|
||||||
@@ -361,14 +326,10 @@ where
|
|||||||
/// Read best finalized source block number from source client.
|
/// Read best finalized source block number from source client.
|
||||||
///
|
///
|
||||||
/// Returns `None` if we have failed to read the number.
|
/// Returns `None` if we have failed to read the number.
|
||||||
async fn best_finalized_source_header_at_source<SourceChain: Chain, P>(
|
async fn best_finalized_source_header_at_source<P: SubstrateFinalitySyncPipeline>(
|
||||||
finality_source: &SubstrateFinalitySource<SourceChain, P>,
|
finality_source: &SubstrateFinalitySource<P>,
|
||||||
relay_task_name: &str,
|
relay_task_name: &str,
|
||||||
) -> Result<SourceChain::BlockNumber, relay_substrate_client::Error>
|
) -> Result<BlockNumberOf<P::SourceChain>, relay_substrate_client::Error> {
|
||||||
where
|
|
||||||
SubstrateFinalitySource<SourceChain, P>: FinalitySourceClient<P>,
|
|
||||||
P: FinalitySyncPipeline<Number = SourceChain::BlockNumber>,
|
|
||||||
{
|
|
||||||
finality_source.on_chain_best_finalized_block_number().await.map_err(|error| {
|
finality_source.on_chain_best_finalized_block_number().await.map_err(|error| {
|
||||||
log::error!(
|
log::error!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
@@ -384,14 +345,14 @@ where
|
|||||||
/// Read best finalized source block number from target client.
|
/// Read best finalized source block number from target client.
|
||||||
///
|
///
|
||||||
/// Returns `None` if we have failed to read the number.
|
/// Returns `None` if we have failed to read the number.
|
||||||
async fn best_finalized_source_header_at_target<SourceChain: Chain, TargetChain: Chain, P>(
|
async fn best_finalized_source_header_at_target<P: SubstrateFinalitySyncPipeline>(
|
||||||
finality_target: &SubstrateFinalityTarget<TargetChain, P>,
|
finality_target: &SubstrateFinalityTarget<P>,
|
||||||
relay_task_name: &str,
|
relay_task_name: &str,
|
||||||
) -> Result<SourceChain::BlockNumber, <SubstrateFinalityTarget<TargetChain, P> as RelayClient>::Error>
|
) -> Result<BlockNumberOf<P::SourceChain>, <SubstrateFinalityTarget<P> as RelayClient>::Error>
|
||||||
where
|
where
|
||||||
SubstrateFinalityTarget<TargetChain, P>: FinalityTargetClient<P::FinalitySyncPipeline>,
|
AccountIdOf<P::TargetChain>:
|
||||||
P: SubstrateFinalitySyncPipeline,
|
From<<AccountKeyPairOf<P::TransactionSignScheme> as sp_core::Pair>::Public>,
|
||||||
P::FinalitySyncPipeline: FinalitySyncPipeline<Number = SourceChain::BlockNumber>,
|
P::TransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
|
||||||
{
|
{
|
||||||
finality_target.best_finalized_source_block_number().await.map_err(|error| {
|
finality_target.best_finalized_source_block_number().await.map_err(|error| {
|
||||||
log::error!(
|
log::error!(
|
||||||
@@ -408,17 +369,13 @@ where
|
|||||||
/// Read first mandatory header in given inclusive range.
|
/// Read first mandatory header in given inclusive range.
|
||||||
///
|
///
|
||||||
/// Returns `Ok(None)` if there were no mandatory headers in the range.
|
/// Returns `Ok(None)` if there were no mandatory headers in the range.
|
||||||
async fn find_mandatory_header_in_range<SourceChain: Chain, P>(
|
async fn find_mandatory_header_in_range<P: SubstrateFinalitySyncPipeline>(
|
||||||
finality_source: &SubstrateFinalitySource<SourceChain, P>,
|
finality_source: &SubstrateFinalitySource<P>,
|
||||||
range: (SourceChain::BlockNumber, SourceChain::BlockNumber),
|
range: (BlockNumberOf<P::SourceChain>, BlockNumberOf<P::SourceChain>),
|
||||||
) -> Result<Option<SourceChain::BlockNumber>, relay_substrate_client::Error>
|
) -> Result<Option<BlockNumberOf<P::SourceChain>>, relay_substrate_client::Error> {
|
||||||
where
|
|
||||||
SubstrateFinalitySource<SourceChain, P>: FinalitySourceClient<P>,
|
|
||||||
P: FinalitySyncPipeline<Number = SourceChain::BlockNumber>,
|
|
||||||
{
|
|
||||||
let mut current = range.0;
|
let mut current = range.0;
|
||||||
while current <= range.1 {
|
while current <= range.1 {
|
||||||
let header: SyncHeader<SourceChain::Header> =
|
let header: SyncHeader<HeaderOf<P::SourceChain>> =
|
||||||
finality_source.client().header_by_number(current).await?.into();
|
finality_source.client().header_by_number(current).await?.into();
|
||||||
if header.is_mandatory() {
|
if header.is_mandatory() {
|
||||||
return Ok(Some(current))
|
return Ok(Some(current))
|
||||||
|
|||||||
Reference in New Issue
Block a user