Fix multiple parachain headers submission for single message delivery (#1916)

* switch off parachains relay when we don't need to relay parachains (temp solution)

* parachains relay now only works with single parachain

* fix usages of parachains relay

* revert hacky fix

* fixes

* fixed Westmint parachain ID

* fixed metrics

* fixed compilation

* fmt

* clippy

* call -> typed_state_call
This commit is contained in:
Svyatoslav Nikolsky
2023-03-01 13:26:13 +03:00
committed by Bastian Köcher
parent ba155f990f
commit e7f5560951
17 changed files with 418 additions and 801 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains
pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128;
/// Identifier of Westmint parachain at the Westend relay chain. /// Identifier of Westmint parachain at the Westend relay chain.
pub const WESTMINT_PARACHAIN_ID: u32 = 2000; pub const WESTMINT_PARACHAIN_ID: u32 = 1000;
decl_bridge_finality_runtime_apis!(westend); decl_bridge_finality_runtime_apis!(westend);
@@ -17,7 +17,6 @@
//! Rialto-to-Millau parachains sync entrypoint. //! Rialto-to-Millau parachains sync entrypoint.
use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge};
use parachains_relay::ParachainsPipeline;
use relay_millau_client::Millau; use relay_millau_client::Millau;
use relay_rialto_client::Rialto; use relay_rialto_client::Rialto;
use relay_rialto_parachain_client::RialtoParachain; use relay_rialto_parachain_client::RialtoParachain;
@@ -29,11 +28,6 @@ use substrate_relay_helper::parachains::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RialtoParachainsToMillau; pub struct RialtoParachainsToMillau;
impl ParachainsPipeline for RialtoParachainsToMillau {
type SourceChain = Rialto;
type TargetChain = Millau;
}
impl SubstrateParachainsPipeline for RialtoParachainsToMillau { impl SubstrateParachainsPipeline for RialtoParachainsToMillau {
type SourceParachain = RialtoParachain; type SourceParachain = RialtoParachain;
type SourceRelayChain = Rialto; type SourceRelayChain = Rialto;
@@ -18,7 +18,6 @@
use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge};
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use parachains_relay::ParachainsPipeline;
use relay_substrate_client::{CallOf, HeaderIdOf}; use relay_substrate_client::{CallOf, HeaderIdOf};
use substrate_relay_helper::parachains::{ use substrate_relay_helper::parachains::{
SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline,
@@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BridgeHubRococoToBridgeHubWococo; pub struct BridgeHubRococoToBridgeHubWococo;
impl ParachainsPipeline for BridgeHubRococoToBridgeHubWococo {
type SourceChain = relay_rococo_client::Rococo;
type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo;
}
impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo { impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo {
type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo;
type SourceRelayChain = relay_rococo_client::Rococo; type SourceRelayChain = relay_rococo_client::Rococo;
@@ -17,7 +17,6 @@
//! Westend-to-Millau parachains sync entrypoint. //! Westend-to-Millau parachains sync entrypoint.
use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge};
use parachains_relay::ParachainsPipeline;
use relay_millau_client::Millau; use relay_millau_client::Millau;
use relay_westend_client::{Westend, Westmint}; use relay_westend_client::{Westend, Westmint};
use substrate_relay_helper::parachains::{ use substrate_relay_helper::parachains::{
@@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct WestendParachainsToMillau; pub struct WestendParachainsToMillau;
impl ParachainsPipeline for WestendParachainsToMillau {
type SourceChain = Westend;
type TargetChain = Millau;
}
impl SubstrateParachainsPipeline for WestendParachainsToMillau { impl SubstrateParachainsPipeline for WestendParachainsToMillau {
type SourceParachain = Westmint; type SourceParachain = Westmint;
type SourceRelayChain = Westend; type SourceRelayChain = Westend;
@@ -18,7 +18,6 @@
use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge};
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use parachains_relay::ParachainsPipeline;
use relay_substrate_client::{CallOf, HeaderIdOf}; use relay_substrate_client::{CallOf, HeaderIdOf};
use substrate_relay_helper::parachains::{ use substrate_relay_helper::parachains::{
SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline,
@@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BridgeHubWococoToBridgeHubRococo; pub struct BridgeHubWococoToBridgeHubRococo;
impl ParachainsPipeline for BridgeHubWococoToBridgeHubRococo {
type SourceChain = relay_wococo_client::Wococo;
type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo;
}
impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo { impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo {
type SourceParachain = relay_bridge_hub_wococo_client::BridgeHubWococo; type SourceParachain = relay_bridge_hub_wococo_client::BridgeHubWococo;
type SourceRelayChain = relay_wococo_client::Wococo; type SourceRelayChain = relay_wococo_client::Wococo;
@@ -16,7 +16,6 @@
use crate::cli::CliChain; use crate::cli::CliChain;
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
use parachains_relay::ParachainsPipeline;
use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain};
use strum::{EnumString, EnumVariantNames}; use strum::{EnumString, EnumVariantNames};
use substrate_relay_helper::{ use substrate_relay_helper::{
@@ -90,7 +89,7 @@ where
SourceRelayChain = Self::SourceRelay, SourceRelayChain = Self::SourceRelay,
SourceParachain = Self::Source, SourceParachain = Self::Source,
TargetChain = Self::Target, TargetChain = Self::Target,
> + ParachainsPipeline<SourceChain = Self::SourceRelay, TargetChain = Self::Target>; >;
/// Finality proofs synchronization pipeline (source relay chain -> target). /// Finality proofs synchronization pipeline (source relay chain -> target).
type RelayFinality: SubstrateFinalitySyncPipeline< type RelayFinality: SubstrateFinalitySyncPipeline<
SourceChain = Self::SourceRelay, SourceChain = Self::SourceRelay,
@@ -22,20 +22,14 @@ use crate::chains::{
}; };
use async_std::sync::Mutex; use async_std::sync::Mutex;
use async_trait::async_trait; use async_trait::async_trait;
use bp_polkadot_core::parachains::ParaId; use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient};
use parachains_relay::parachains_loop::{ use relay_substrate_client::Parachain;
AvailableHeader, ParachainSyncParams, SourceClient, TargetClient,
};
use relay_substrate_client::{Parachain, ParachainBase};
use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric};
use std::sync::Arc; use std::sync::Arc;
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
use substrate_relay_helper::{ use substrate_relay_helper::{
parachains::{ parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter},
source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter,
SubstrateParachainsPipeline,
},
TransactionParams, TransactionParams,
}; };
@@ -105,13 +99,6 @@ where
parachains_relay::parachains_loop::run( parachains_relay::parachains_loop::run(
source_client, source_client,
target_client, target_client,
ParachainSyncParams {
parachains: vec![
ParaId(<Self::ParachainFinality as SubstrateParachainsPipeline>::SourceParachain::PARACHAIN_ID)
],
stall_timeout: std::time::Duration::from_secs(60),
strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any,
},
metrics_params, metrics_params,
futures::future::pending(), futures::future::pending(),
) )
+1 -1
View File
@@ -72,7 +72,7 @@ pub trait RelayChain: Chain {
/// Name of the bridge parachains pallet (used in `construct_runtime` macro call) that is /// Name of the bridge parachains pallet (used in `construct_runtime` macro call) that is
/// deployed at the **bridged** chain. /// deployed at the **bridged** chain.
/// ///
/// We assume that all chains that are bridging with this `ChainWithGrandpa` are using /// We assume that all chains that are bridging with this `RelayChain` are using
/// the same name. /// the same name.
const PARACHAINS_FINALITY_PALLET_NAME: &'static str; const PARACHAINS_FINALITY_PALLET_NAME: &'static str;
} }
@@ -68,3 +68,51 @@ impl ChainWithBalances for TestChain {
unreachable!() unreachable!()
} }
} }
/// Primitives-level parachain that may be used in tests.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TestParachainBase;
impl bp_runtime::Chain for TestParachainBase {
type BlockNumber = u32;
type Hash = sp_core::H256;
type Hasher = sp_runtime::traits::BlakeTwo256;
type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
type AccountId = u32;
type Balance = u32;
type Index = u32;
type Signature = sp_runtime::testing::TestSignature;
fn max_extrinsic_size() -> u32 {
unreachable!()
}
fn max_extrinsic_weight() -> Weight {
unreachable!()
}
}
impl bp_runtime::Parachain for TestParachainBase {
const PARACHAIN_ID: u32 = 1000;
}
/// Parachain that may be used in tests.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TestParachain;
impl bp_runtime::UnderlyingChainProvider for TestParachain {
type Chain = TestParachainBase;
}
impl Chain for TestParachain {
const NAME: &'static str = "TestParachain";
const TOKEN_ID: Option<&'static str> = None;
const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod";
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0);
type SignedBlock = sp_runtime::generic::SignedBlock<
sp_runtime::generic::Block<Self::Header, sp_runtime::OpaqueExtrinsic>,
>;
type Call = ();
}
@@ -36,9 +36,7 @@ use bp_runtime::HeaderIdProvider;
use futures::{select, FutureExt}; use futures::{select, FutureExt};
use num_traits::Zero; use num_traits::Zero;
use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber};
use parachains_relay::parachains_loop::{ use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient};
AvailableHeader, ParachainSyncParams, SourceClient, TargetClient,
};
use relay_substrate_client::{ use relay_substrate_client::{
is_ancient_block, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, is_ancient_block, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client,
Error as SubstrateError, HashOf, HeaderIdOf, ParachainBase, Error as SubstrateError, HashOf, HeaderIdOf, ParachainBase,
@@ -183,7 +181,7 @@ where
let mut proved_parachain_block = selected_parachain_block; let mut proved_parachain_block = selected_parachain_block;
if proved_relay_block != selected_relay_block { if proved_relay_block != selected_relay_block {
proved_parachain_block = parachains_source proved_parachain_block = parachains_source
.on_chain_para_head_id(proved_relay_block, para_id) .on_chain_para_head_id(proved_relay_block)
.await? .await?
// this could happen e.g. if parachain has been offboarded? // this could happen e.g. if parachain has been offboarded?
.ok_or_else(|| { .ok_or_else(|| {
@@ -209,11 +207,11 @@ where
} }
// and finally - prove parachain head // and finally - prove parachain head
let (para_proof, para_hashes) = let (para_proof, para_hash) =
parachains_source.prove_parachain_heads(proved_relay_block, &[para_id]).await?; parachains_source.prove_parachain_head(proved_relay_block).await?;
calls.push(P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( calls.push(P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call(
proved_relay_block, proved_relay_block,
para_hashes.into_iter().map(|h| (para_id, h)).collect(), vec![(para_id, para_hash)],
para_proof, para_proof,
)); ));
@@ -241,16 +239,14 @@ async fn background_task<P: SubstrateParachainsPipeline>(
let mut relay_state = RelayState::Idle; let mut relay_state = RelayState::Idle;
let mut required_parachain_header_number = Zero::zero(); let mut required_parachain_header_number = Zero::zero();
let required_para_header_number_ref = Arc::new(Mutex::new(AvailableHeader::Unavailable)); let required_para_header_ref = Arc::new(Mutex::new(AvailableHeader::Unavailable));
let mut restart_relay = true; let mut restart_relay = true;
let parachains_relay_task = futures::future::Fuse::terminated(); let parachains_relay_task = futures::future::Fuse::terminated();
futures::pin_mut!(parachains_relay_task); futures::pin_mut!(parachains_relay_task);
let mut parachains_source = ParachainsSource::<P>::new( let mut parachains_source =
source_relay_client.clone(), ParachainsSource::<P>::new(source_relay_client.clone(), required_para_header_ref.clone());
required_para_header_number_ref.clone(),
);
let mut parachains_target = let mut parachains_target =
ParachainsTarget::<P>::new(target_client.clone(), target_transaction_params.clone()); ParachainsTarget::<P>::new(target_client.clone(), target_transaction_params.clone());
@@ -271,13 +267,20 @@ async fn background_task<P: SubstrateParachainsPipeline>(
}, },
}; };
// keep in mind that we are not updating `required_para_header_number_ref` here, because // keep in mind that we are not updating `required_para_header_ref` here, because
// then we'll be submitting all previous headers as well (while required relay headers are // then we'll be submitting all previous headers as well (while required relay headers are
// delivered) and we want to avoid that (to reduce cost) // delivered) and we want to avoid that (to reduce cost)
required_parachain_header_number = std::cmp::max( if new_required_parachain_header_number > required_parachain_header_number {
required_parachain_header_number, log::trace!(
target: "bridge",
"[{}] More {} headers required. Going to sync up to the {}",
relay_task_name,
P::SourceParachain::NAME,
new_required_parachain_header_number, new_required_parachain_header_number,
); );
required_parachain_header_number = new_required_parachain_header_number;
}
}, },
_ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, _ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {},
_ = parachains_relay_task => { _ = parachains_relay_task => {
@@ -351,7 +354,7 @@ async fn background_task<P: SubstrateParachainsPipeline>(
.await; .await;
}, },
RelayState::RelayingParaHeader(required_para_header) => { RelayState::RelayingParaHeader(required_para_header) => {
*required_para_header_number_ref.lock().await = *required_para_header_ref.lock().await =
AvailableHeader::Available(required_para_header); AvailableHeader::Available(required_para_header);
}, },
} }
@@ -379,11 +382,6 @@ async fn background_task<P: SubstrateParachainsPipeline>(
parachains_relay::parachains_loop::run( parachains_relay::parachains_loop::run(
parachains_source.clone(), parachains_source.clone(),
parachains_target.clone(), parachains_target.clone(),
ParachainSyncParams {
parachains: vec![P::SourceParachain::PARACHAIN_ID.into()],
stall_timeout: std::time::Duration::from_secs(60),
strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any,
},
MetricsParams::disabled(), MetricsParams::disabled(),
futures::future::pending(), futures::future::pending(),
) )
@@ -489,10 +487,7 @@ where
source.client().best_finalized_header().await.map_err(map_source_err)?; source.client().best_finalized_header().await.map_err(map_source_err)?;
let best_finalized_relay_block_id = best_finalized_relay_header.id(); let best_finalized_relay_block_id = best_finalized_relay_header.id();
let para_header_at_source = source let para_header_at_source = source
.on_chain_para_head_id( .on_chain_para_head_id(best_finalized_relay_block_id)
best_finalized_relay_block_id,
P::SourceParachain::PARACHAIN_ID.into(),
)
.await .await
.map_err(map_source_err)?; .map_err(map_source_err)?;
@@ -515,10 +510,7 @@ where
let para_header_at_relay_header_at_target = let para_header_at_relay_header_at_target =
if let Some(available_relay_header_at_target) = available_relay_header_at_target { if let Some(available_relay_header_at_target) = available_relay_header_at_target {
source source
.on_chain_para_head_id( .on_chain_para_head_id(available_relay_header_at_target)
available_relay_header_at_target,
P::SourceParachain::PARACHAIN_ID.into(),
)
.await .await
.map_err(map_source_err)? .map_err(map_source_err)?
} else { } else {
@@ -669,7 +661,7 @@ impl<'a, P: SubstrateParachainsPipeline>
&self, &self,
at_relay_block: HeaderIdOf<P::SourceRelayChain>, at_relay_block: HeaderIdOf<P::SourceRelayChain>,
) -> Result<Option<HeaderIdOf<P::SourceParachain>>, SubstrateError> { ) -> Result<Option<HeaderIdOf<P::SourceParachain>>, SubstrateError> {
self.1.on_chain_para_head_id(at_relay_block, self.parachain_id()).await self.1.on_chain_para_head_id(at_relay_block).await
} }
} }
@@ -56,7 +56,8 @@ pub struct ParachainsPipelineAdapter<P: SubstrateParachainsPipeline> {
} }
impl<P: SubstrateParachainsPipeline> ParachainsPipeline for ParachainsPipelineAdapter<P> { impl<P: SubstrateParachainsPipeline> ParachainsPipeline for ParachainsPipelineAdapter<P> {
type SourceChain = P::SourceRelayChain; type SourceParachain = P::SourceParachain;
type SourceRelayChain = P::SourceRelayChain;
type TargetChain = P::TargetChain; type TargetChain = P::TargetChain;
} }
@@ -24,10 +24,7 @@ use bp_parachains::parachain_head_storage_key_at_source;
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::HeaderIdProvider; use bp_runtime::HeaderIdProvider;
use codec::Decode; use codec::Decode;
use parachains_relay::{ use parachains_relay::parachains_loop::{AvailableHeader, SourceClient};
parachains_loop::{AvailableHeader, SourceClient},
parachains_loop_metrics::ParachainsLoopMetrics,
};
use relay_substrate_client::{ use relay_substrate_client::{
is_ancient_block, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, is_ancient_block, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase,
RelayChain, RelayChain,
@@ -63,8 +60,8 @@ impl<P: SubstrateParachainsPipeline> ParachainsSource<P> {
pub async fn on_chain_para_head_id( pub async fn on_chain_para_head_id(
&self, &self,
at_block: HeaderIdOf<P::SourceRelayChain>, at_block: HeaderIdOf<P::SourceRelayChain>,
para_id: ParaId,
) -> Result<Option<HeaderIdOf<P::SourceParachain>>, SubstrateError> { ) -> Result<Option<HeaderIdOf<P::SourceParachain>>, SubstrateError> {
let para_id = ParaId(P::SourceParachain::PARACHAIN_ID);
let storage_key = let storage_key =
parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, para_id); parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, para_id);
let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?;
@@ -104,18 +101,7 @@ where
async fn parachain_head( async fn parachain_head(
&self, &self,
at_block: HeaderIdOf<P::SourceRelayChain>, at_block: HeaderIdOf<P::SourceRelayChain>,
metrics: Option<&ParachainsLoopMetrics>, ) -> Result<AvailableHeader<HeaderIdOf<P::SourceParachain>>, Self::Error> {
para_id: ParaId,
) -> Result<AvailableHeader<ParaHash>, Self::Error> {
// we don't need to support many parachains now
if para_id.0 != P::SourceParachain::PARACHAIN_ID {
return Err(SubstrateError::Custom(format!(
"Parachain id {} is not matching expected {}",
para_id.0,
P::SourceParachain::PARACHAIN_ID,
)))
}
// if requested relay header is ancient, then we don't even want to try to read the // if requested relay header is ancient, then we don't even want to try to read the
// parachain head - we simply return `Unavailable` // parachain head - we simply return `Unavailable`
let best_block_number = self.client.best_finalized_header_number().await?; let best_block_number = self.client.best_finalized_header_number().await?;
@@ -125,7 +111,7 @@ where
// else - try to read head from the source client // else - try to read head from the source client
let mut para_head_id = AvailableHeader::Missing; let mut para_head_id = AvailableHeader::Missing;
if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block, para_id).await? { if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block).await? {
// Never return head that is larger than requested. This way we'll never sync // Never return head that is larger than requested. This way we'll never sync
// headers past `max_header_id`. // headers past `max_header_id`.
para_head_id = match *self.max_head_id.lock().await { para_head_id = match *self.max_head_id.lock().await {
@@ -141,26 +127,14 @@ where
} }
} }
if let (Some(metrics), AvailableHeader::Available(para_head_id)) = (metrics, para_head_id) { Ok(para_head_id)
metrics.update_best_parachain_block_at_source(para_id, para_head_id.0);
} }
Ok(para_head_id.map(|para_head_id| para_head_id.1)) async fn prove_parachain_head(
}
async fn prove_parachain_heads(
&self, &self,
at_block: HeaderIdOf<P::SourceRelayChain>, at_block: HeaderIdOf<P::SourceRelayChain>,
parachains: &[ParaId], ) -> Result<(ParaHeadsProof, ParaHash), Self::Error> {
) -> Result<(ParaHeadsProof, Vec<ParaHash>), Self::Error> {
let parachain = ParaId(P::SourceParachain::PARACHAIN_ID); let parachain = ParaId(P::SourceParachain::PARACHAIN_ID);
if parachains != [parachain] {
return Err(SubstrateError::Custom(format!(
"Trying to prove unexpected parachains {parachains:?}. Expected {parachain:?}",
)))
}
let parachain = parachains[0];
let storage_key = let storage_key =
parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, parachain); parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, parachain);
let parachain_heads_proof = self let parachain_heads_proof = self
@@ -190,6 +164,6 @@ where
})?; })?;
let parachain_head_hash = parachain_head.hash(); let parachain_head_hash = parachain_head.hash();
Ok((ParaHeadsProof(parachain_heads_proof), vec![parachain_head_hash])) Ok((ParaHeadsProof(parachain_heads_proof), parachain_head_hash))
} }
} }
@@ -24,18 +24,15 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use bp_runtime::HeaderIdProvider; use bp_runtime::HeaderIdProvider;
use codec::Decode; use codec::Decode;
use parachains_relay::{ use parachains_relay::parachains_loop::TargetClient;
parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics,
};
use relay_substrate_client::{ use relay_substrate_client::{
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, AccountIdOf, AccountKeyPairOf, Chain, Client, Error as SubstrateError, HeaderIdOf,
HeaderIdOf, ParachainBase, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, ParachainBase, TransactionEra, TransactionTracker, UnsignedTransaction,
}; };
use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use relay_utils::relay_loop::Client as RelayClient;
use sp_core::{Bytes, Pair}; use sp_core::{Bytes, Pair};
/// Substrate client as parachain heads source. /// Substrate client as parachain heads source.
@@ -92,93 +89,50 @@ where
Ok(best_id) Ok(best_id)
} }
async fn best_finalized_source_block( async fn best_finalized_source_relay_chain_block(
&self, &self,
at_block: &HeaderIdOf<P::TargetChain>, at_block: &HeaderIdOf<P::TargetChain>,
) -> Result<HeaderIdOf<P::SourceRelayChain>, Self::Error> { ) -> Result<HeaderIdOf<P::SourceRelayChain>, Self::Error> {
let encoded_best_finalized_source_block = self self.client
.client .typed_state_call::<_, Option<HeaderIdOf<P::SourceRelayChain>>>(
.state_call(
P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD.into(),
Bytes(Vec::new()), (),
Some(at_block.1), Some(at_block.1),
) )
.await?; .await?
Option::<HeaderId<HashOf<P::SourceRelayChain>, BlockNumberOf<P::SourceRelayChain>>>::decode(
&mut &encoded_best_finalized_source_block.0[..],
)
.map_err(SubstrateError::ResponseParseFailed)?
.map(Ok) .map(Ok)
.unwrap_or(Err(SubstrateError::NoParachainHeadAtTarget( .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))
P::SourceParachain::PARACHAIN_ID,
P::TargetChain::NAME.into(),
)))
} }
async fn parachain_head( async fn parachain_head(
&self, &self,
at_block: HeaderIdOf<P::TargetChain>, at_block: HeaderIdOf<P::TargetChain>,
metrics: Option<&ParachainsLoopMetrics>, ) -> Result<Option<HeaderIdOf<P::SourceParachain>>, Self::Error> {
para_id: ParaId, let encoded_best_finalized_source_para_block = self
) -> Result<Option<BestParaHeadHash>, Self::Error> {
let best_para_head_hash: Option<BestParaHeadHash> = self
.client .client
.storage_map_value::<ParasInfoKeyProvider>( .state_call(
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD.into(),
&para_id, Bytes(Vec::new()),
Some(at_block.1), Some(at_block.1),
) )
.await? .await?;
.map(|para_info| para_info.best_head_hash);
if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) { Ok(Option::<HeaderIdOf<P::SourceParachain>>::decode(
let imported_para_head_number = self &mut &encoded_best_finalized_source_para_block.0[..],
.client
.storage_double_map_value::<ImportedParaHeadsKeyProvider>(
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
&para_id,
&best_para_head_hash.head_hash,
Some(at_block.1),
) )
.await .map_err(SubstrateError::ResponseParseFailed)?)
.and_then(|maybe_encoded_head| match maybe_encoded_head {
Some(encoded_head) => encoded_head
.decode_parachain_head_data::<P::SourceParachain>()
.map(|head| head.number)
.map(Some)
.map_err(Self::Error::ResponseParseFailed),
None => Ok(None),
})
.map_err(|e| {
log::error!(
target: "bridge-metrics",
"Failed to read or decode {} parachain header at {}: {:?}. Metric will have obsolete value",
P::SourceParachain::NAME,
P::TargetChain::NAME,
e,
);
e
})
.unwrap_or(None);
if let Some(imported_para_head_number) = imported_para_head_number {
metrics.update_best_parachain_block_at_target(para_id, imported_para_head_number);
}
} }
Ok(best_para_head_hash) async fn submit_parachain_head_proof(
}
async fn submit_parachain_heads_proof(
&self, &self,
at_relay_block: HeaderIdOf<P::SourceRelayChain>, at_relay_block: HeaderIdOf<P::SourceRelayChain>,
updated_parachains: Vec<(ParaId, ParaHash)>, updated_head_hash: ParaHash,
proof: ParaHeadsProof, proof: ParaHeadsProof,
) -> Result<Self::TransactionTracker, Self::Error> { ) -> Result<Self::TransactionTracker, Self::Error> {
let transaction_params = self.transaction_params.clone(); let transaction_params = self.transaction_params.clone();
let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call(
at_relay_block, at_relay_block,
updated_parachains, vec![(ParaId(P::SourceParachain::PARACHAIN_ID), updated_head_hash)],
proof, proof,
); );
self.client self.client
-1
View File
@@ -14,7 +14,6 @@ relay-utils = { path = "../utils" }
# Bridge dependencies # Bridge dependencies
bp-parachains = { path = "../../primitives/parachains" }
bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-polkadot-core = { path = "../../primitives/polkadot-core" }
relay-substrate-client = { path = "../client-substrate" } relay-substrate-client = { path = "../client-substrate" }
+4 -2
View File
@@ -16,7 +16,7 @@
use std::fmt::Debug; use std::fmt::Debug;
use relay_substrate_client::Chain; use relay_substrate_client::{Chain, Parachain};
pub mod parachains_loop; pub mod parachains_loop;
pub mod parachains_loop_metrics; pub mod parachains_loop_metrics;
@@ -24,7 +24,9 @@ pub mod parachains_loop_metrics;
/// Finality proofs synchronization pipeline. /// Finality proofs synchronization pipeline.
pub trait ParachainsPipeline: 'static + Clone + Debug + Send + Sync { pub trait ParachainsPipeline: 'static + Clone + Debug + Send + Sync {
/// Relay chain which is storing parachain heads in its `paras` module. /// Relay chain which is storing parachain heads in its `paras` module.
type SourceChain: Chain; type SourceRelayChain: Chain;
/// Parachain which headers we are syncing here.
type SourceParachain: Parachain;
/// Target chain (either relay or para) which wants to know about new parachain heads. /// Target chain (either relay or para) which wants to know about new parachain heads.
type TargetChain: Chain; type TargetChain: Chain;
} }
File diff suppressed because it is too large Load Diff
@@ -16,7 +16,7 @@
use bp_polkadot_core::parachains::ParaId; use bp_polkadot_core::parachains::ParaId;
use relay_utils::{ use relay_utils::{
metrics::{metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64}, metrics::{metric_name, register, Gauge, Metric, PrometheusError, Registry, U64},
UniqueSaturatedInto, UniqueSaturatedInto,
}; };
@@ -24,28 +24,22 @@ use relay_utils::{
#[derive(Clone)] #[derive(Clone)]
pub struct ParachainsLoopMetrics { pub struct ParachainsLoopMetrics {
/// Best parachains header numbers at the source. /// Best parachains header numbers at the source.
best_source_block_numbers: GaugeVec<U64>, best_source_block_numbers: Gauge<U64>,
/// Best parachains header numbers at the target. /// Best parachains header numbers at the target.
best_target_block_numbers: GaugeVec<U64>, best_target_block_numbers: Gauge<U64>,
} }
impl ParachainsLoopMetrics { impl ParachainsLoopMetrics {
/// Create and register parachains loop metrics. /// Create and register parachains loop metrics.
pub fn new(prefix: Option<&str>) -> Result<Self, PrometheusError> { pub fn new(prefix: Option<&str>) -> Result<Self, PrometheusError> {
Ok(ParachainsLoopMetrics { Ok(ParachainsLoopMetrics {
best_source_block_numbers: GaugeVec::new( best_source_block_numbers: Gauge::new(
Opts::new(
metric_name(prefix, "best_parachain_block_number_at_source"), metric_name(prefix, "best_parachain_block_number_at_source"),
"Best parachain block numbers at the source relay chain".to_string(), "Best parachain block numbers at the source relay chain".to_string(),
),
&["parachain"],
)?, )?,
best_target_block_numbers: GaugeVec::new( best_target_block_numbers: Gauge::new(
Opts::new(
metric_name(prefix, "best_parachain_block_number_at_target"), metric_name(prefix, "best_parachain_block_number_at_target"),
"Best parachain block numbers at the target chain".to_string(), "Best parachain block numbers at the target chain".to_string(),
),
&["parachain"],
)?, )?,
}) })
} }
@@ -57,14 +51,13 @@ impl ParachainsLoopMetrics {
block_number: Number, block_number: Number,
) { ) {
let block_number = block_number.unique_saturated_into(); let block_number = block_number.unique_saturated_into();
let label = parachain_label(&parachain);
log::trace!( log::trace!(
target: "bridge-metrics", target: "bridge-metrics",
"Updated value of metric 'best_parachain_block_number_at_source[{}]': {:?}", "Updated value of metric 'best_parachain_block_number_at_source[{:?}]': {:?}",
label, parachain,
block_number, block_number,
); );
self.best_source_block_numbers.with_label_values(&[&label]).set(block_number); self.best_source_block_numbers.set(block_number);
} }
/// Update best block number at target. /// Update best block number at target.
@@ -74,14 +67,13 @@ impl ParachainsLoopMetrics {
block_number: Number, block_number: Number,
) { ) {
let block_number = block_number.unique_saturated_into(); let block_number = block_number.unique_saturated_into();
let label = parachain_label(&parachain);
log::trace!( log::trace!(
target: "bridge-metrics", target: "bridge-metrics",
"Updated value of metric 'best_parachain_block_number_at_target[{}]': {:?}", "Updated value of metric 'best_parachain_block_number_at_target[{:?}]': {:?}",
label, parachain,
block_number, block_number,
); );
self.best_target_block_numbers.with_label_values(&[&label]).set(block_number); self.best_target_block_numbers.set(block_number);
} }
} }
@@ -92,8 +84,3 @@ impl Metric for ParachainsLoopMetrics {
Ok(()) Ok(())
} }
} }
/// Return metric label for the parachain.
fn parachain_label(parachain: &ParaId) -> String {
format!("para_{}", parachain.0)
}