mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 17:31:03 +00:00
Fix on-different-forks metrics during initialization (#1468)
* fix on-different-forks metrics during initialization * "initialize" parachain finality pallet in on-demand parachains relay * decrease converstion rate requests count * more error logging * fix compilation * clippy
This commit is contained in:
committed by
Bastian Köcher
parent
418942826d
commit
31a2be845c
+1
-1
@@ -216,7 +216,7 @@ To run a Rialto node for example, you can use the following command:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
|
docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \
|
||||||
-it paritytech/rialto-bridge-node --dev --tmp \
|
-it local/rialto-bridge-node --dev --tmp \
|
||||||
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
|
--rpc-cors=all --unsafe-rpc-external --unsafe-ws-external
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -795,33 +795,28 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl bp_rialto::RialtoFinalityApi<Block> for Runtime {
|
impl bp_rialto::RialtoFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) {
|
fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> {
|
||||||
let header = BridgeRialtoGrandpa::best_finalized();
|
BridgeRialtoGrandpa::best_finalized().map(|header| (header.number, header.hash()))
|
||||||
(header.number, header.hash())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_westend::WestendFinalityApi<Block> for Runtime {
|
impl bp_westend::WestendFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> (bp_westend::BlockNumber, bp_westend::Hash) {
|
fn best_finalized() -> Option<(bp_westend::BlockNumber, bp_westend::Hash)> {
|
||||||
let header = BridgeWestendGrandpa::best_finalized();
|
BridgeWestendGrandpa::best_finalized().map(|header| (header.number, header.hash()))
|
||||||
(header.number, header.hash())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_rialto_parachain::RialtoParachainFinalityApi<Block> for Runtime {
|
impl bp_rialto_parachain::RialtoParachainFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) {
|
fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> {
|
||||||
// the parachains finality pallet is never decoding parachain heads, so it is
|
// the parachains finality pallet is never decoding parachain heads, so it is
|
||||||
// only done in the integration code
|
// only done in the integration code
|
||||||
use bp_rialto_parachain::RIALTO_PARACHAIN_ID;
|
use bp_rialto_parachain::RIALTO_PARACHAIN_ID;
|
||||||
let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::<
|
let encoded_head = pallet_bridge_parachains::Pallet::<
|
||||||
Runtime,
|
Runtime,
|
||||||
WithRialtoParachainsInstance,
|
WithRialtoParachainsInstance,
|
||||||
>::best_parachain_head(RIALTO_PARACHAIN_ID.into())
|
>::best_parachain_head(RIALTO_PARACHAIN_ID.into())?;
|
||||||
.and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok());
|
let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?;
|
||||||
match best_rialto_parachain_head {
|
Some((*head.number(), head.hash()))
|
||||||
Some(head) => (*head.number(), head.hash()),
|
|
||||||
None => (Default::default(), Default::default()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -683,9 +683,8 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) {
|
fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> {
|
||||||
let header = BridgeMillauGrandpa::best_finalized();
|
BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash()))
|
||||||
(header.number, header.hash())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -640,9 +640,8 @@ impl_runtime_apis! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) {
|
fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> {
|
||||||
let header = BridgeMillauGrandpa::best_finalized();
|
BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash()))
|
||||||
(header.number, header.hash())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -537,17 +537,9 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
|||||||
///
|
///
|
||||||
/// Returns a dummy header if there is no best header. This can only happen
|
/// Returns a dummy header if there is no best header. This can only happen
|
||||||
/// if the pallet has not been initialized yet.
|
/// if the pallet has not been initialized yet.
|
||||||
pub fn best_finalized() -> BridgedHeader<T, I> {
|
pub fn best_finalized() -> Option<BridgedHeader<T, I>> {
|
||||||
let hash = <BestFinalized<T, I>>::get();
|
let hash = <BestFinalized<T, I>>::get();
|
||||||
<ImportedHeaders<T, I>>::get(hash).unwrap_or_else(|| {
|
<ImportedHeaders<T, I>>::get(hash)
|
||||||
<BridgedHeader<T, I>>::new(
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a particular header is known to the bridge pallet.
|
/// Check if a particular header is known to the bridge pallet.
|
||||||
@@ -718,7 +710,7 @@ mod tests {
|
|||||||
BestFinalized::<TestRuntime>::get(),
|
BestFinalized::<TestRuntime>::get(),
|
||||||
BridgedBlockHash::<TestRuntime, ()>::default()
|
BridgedBlockHash::<TestRuntime, ()>::default()
|
||||||
);
|
);
|
||||||
assert_eq!(Pallet::<TestRuntime>::best_finalized(), test_header(0));
|
assert_eq!(Pallet::<TestRuntime>::best_finalized(), None);
|
||||||
|
|
||||||
let init_data = init_with_origin(Origin::root()).unwrap();
|
let init_data = init_with_origin(Origin::root()).unwrap();
|
||||||
|
|
||||||
@@ -1131,7 +1123,7 @@ mod tests {
|
|||||||
run_test(|| {
|
run_test(|| {
|
||||||
initialize_substrate_bridge();
|
initialize_substrate_bridge();
|
||||||
assert_ok!(submit_finality_proof(1));
|
assert_ok!(submit_finality_proof(1));
|
||||||
let first_header = Pallet::<TestRuntime>::best_finalized();
|
let first_header = Pallet::<TestRuntime>::best_finalized().unwrap();
|
||||||
next_block();
|
next_block();
|
||||||
|
|
||||||
assert_ok!(submit_finality_proof(2));
|
assert_ok!(submit_finality_proof(2));
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Kusama runtime itself.
|
/// Kusama runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Kusama chain.
|
/// Outbound message lane API for messages that are sent to Kusama chain.
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Millau runtime itself.
|
/// Millau runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Millau chain.
|
/// Outbound message lane API for messages that are sent to Millau chain.
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Polkadot runtime itself.
|
/// Polkadot runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Polkadot chain.
|
/// Outbound message lane API for messages that are sent to Polkadot chain.
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// RialtoParachain runtime itself.
|
/// RialtoParachain runtime itself.
|
||||||
pub trait RialtoParachainFinalityApi {
|
pub trait RialtoParachainFinalityApi {
|
||||||
/// 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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to RialtoParachain chain.
|
/// Outbound message lane API for messages that are sent to RialtoParachain chain.
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Rialto runtime itself.
|
/// Rialto runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Rialto chain.
|
/// Outbound message lane API for messages that are sent to Rialto chain.
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Rococo runtime itself.
|
/// Rococo runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Rococo chain.
|
/// Outbound message lane API for messages that are sent to Rococo chain.
|
||||||
|
|||||||
@@ -106,6 +106,6 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Westend runtime itself.
|
/// Westend runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ sp_api::decl_runtime_apis! {
|
|||||||
/// Wococo runtime itself.
|
/// Wococo runtime itself.
|
||||||
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() -> Option<(BlockNumber, Hash)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Outbound message lane API for messages that are sent to Wococo chain.
|
/// Outbound message lane API for messages that are sent to Wococo chain.
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ pub trait InclusionProofVerifier {
|
|||||||
/// A trait for pallets which want to keep track of finalized headers from a bridged chain.
|
/// A trait for pallets which want to keep track of finalized headers from a bridged chain.
|
||||||
pub trait HeaderChain<H, E> {
|
pub trait HeaderChain<H, E> {
|
||||||
/// Get the best finalized header known to the header chain.
|
/// Get the best finalized header known to the header chain.
|
||||||
fn best_finalized() -> H;
|
fn best_finalized() -> Option<H>;
|
||||||
|
|
||||||
/// Get the best authority set known to the header chain.
|
/// Get the best authority set known to the header chain.
|
||||||
fn authority_set() -> AuthoritySet;
|
fn authority_set() -> AuthoritySet;
|
||||||
@@ -98,8 +98,8 @@ pub trait HeaderChain<H, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<H: Default, E> HeaderChain<H, E> for () {
|
impl<H: Default, E> HeaderChain<H, E> for () {
|
||||||
fn best_finalized() -> H {
|
fn best_finalized() -> Option<H> {
|
||||||
H::default()
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn authority_set() -> AuthoritySet {
|
fn authority_set() -> AuthoritySet {
|
||||||
|
|||||||
@@ -456,8 +456,12 @@ impl<C: Chain> Client<C> {
|
|||||||
IndexOf<C>,
|
IndexOf<C>,
|
||||||
C::SignedBlock,
|
C::SignedBlock,
|
||||||
>::author_submit_extrinsic(&*client, transaction)
|
>::author_submit_extrinsic(&*client, transaction)
|
||||||
.await?;
|
.await
|
||||||
log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash);
|
.map_err(|e| {
|
||||||
|
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
||||||
Ok(tx_hash)
|
Ok(tx_hash)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@@ -499,7 +503,11 @@ impl<C: Chain> Client<C> {
|
|||||||
IndexOf<C>,
|
IndexOf<C>,
|
||||||
C::SignedBlock,
|
C::SignedBlock,
|
||||||
>::author_submit_extrinsic(&*client, extrinsic)
|
>::author_submit_extrinsic(&*client, extrinsic)
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
||||||
Ok(tx_hash)
|
Ok(tx_hash)
|
||||||
})
|
})
|
||||||
@@ -528,7 +536,11 @@ impl<C: Chain> Client<C> {
|
|||||||
.map_err(|e| Error::RpcError(e.into()))?])),
|
.map_err(|e| Error::RpcError(e.into()))?])),
|
||||||
"author_unwatchExtrinsic",
|
"author_unwatchExtrinsic",
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
|
||||||
Ok(subscription)
|
Ok(subscription)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ pub enum Error<Hash: Debug + MaybeDisplay, HeaderNumber: Debug + MaybeDisplay> {
|
|||||||
/// Failed to retrieve best finalized source header hash from the target chain.
|
/// Failed to retrieve best finalized source header hash from the target chain.
|
||||||
#[error("Failed to retrieve best finalized {0} header from the target chain: {1}")]
|
#[error("Failed to retrieve best finalized {0} header from the target chain: {1}")]
|
||||||
RetrieveBestFinalizedHeaderHash(&'static str, client::Error),
|
RetrieveBestFinalizedHeaderHash(&'static str, client::Error),
|
||||||
|
/// Failed to submit signed extrinsic from to the target chain.
|
||||||
|
#[error(
|
||||||
|
"Failed to retrieve `is_initialized` flag of the with-{0} finality pallet at {1}: {2:?}"
|
||||||
|
)]
|
||||||
|
IsInitializedRetrieve(&'static str, &'static str, client::Error),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ use std::marker::PhantomData;
|
|||||||
|
|
||||||
/// Finality enfine, used by the Substrate chain.
|
/// Finality enfine, used by the Substrate chain.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Engine<C: Chain> {
|
pub trait Engine<C: Chain>: Send {
|
||||||
/// Unique consensus engine identifier.
|
/// Unique consensus engine identifier.
|
||||||
const ID: ConsensusEngineId;
|
const ID: ConsensusEngineId;
|
||||||
/// Type of finality proofs, used by consensus engine.
|
/// Type of finality proofs, used by consensus engine.
|
||||||
@@ -59,6 +59,23 @@ pub trait Engine<C: Chain> {
|
|||||||
async fn prepare_initialization_data(
|
async fn prepare_initialization_data(
|
||||||
client: Client<C>,
|
client: Client<C>,
|
||||||
) -> Result<Self::InitializationData, Error<HashOf<C>, BlockNumberOf<C>>>;
|
) -> Result<Self::InitializationData, Error<HashOf<C>, BlockNumberOf<C>>>;
|
||||||
|
|
||||||
|
/// Returns `Ok(true)` if finality pallet at the bridged chain has already been initialized.
|
||||||
|
async fn is_initialized<TargetChain: Chain>(
|
||||||
|
target_client: &Client<TargetChain>,
|
||||||
|
) -> Result<bool, SubstrateError> {
|
||||||
|
Ok(target_client
|
||||||
|
.raw_storage_value(Self::is_initialized_key(), None)
|
||||||
|
.await?
|
||||||
|
.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Ok(true)` if finality pallet at the bridged chain is halted.
|
||||||
|
async fn is_halted<TargetChain: Chain>(
|
||||||
|
target_client: &Client<TargetChain>,
|
||||||
|
) -> Result<bool, SubstrateError> {
|
||||||
|
Ok(target_client.storage_value(Self::is_halted_key(), None).await?.unwrap_or(false))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GRANDPA finality engine.
|
/// GRANDPA finality engine.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
use crate::{error::Error, finality::engine::Engine};
|
use crate::{error::Error, finality::engine::Engine};
|
||||||
|
|
||||||
use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf};
|
use relay_substrate_client::{Chain, Client, Error as SubstrateError};
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
use sp_runtime::traits::Header as HeaderT;
|
||||||
|
|
||||||
@@ -80,7 +80,9 @@ where
|
|||||||
+ Send
|
+ Send
|
||||||
+ 'static,
|
+ 'static,
|
||||||
{
|
{
|
||||||
let is_initialized = is_initialized::<E, SourceChain, TargetChain>(&target_client).await?;
|
let is_initialized = E::is_initialized(&target_client)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Error::IsInitializedRetrieve(SourceChain::NAME, TargetChain::NAME, e))?;
|
||||||
if is_initialized {
|
if is_initialized {
|
||||||
log::info!(
|
log::info!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
@@ -108,18 +110,3 @@ where
|
|||||||
.map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?;
|
.map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?;
|
||||||
Ok(Some(initialization_tx_hash))
|
Ok(Some(initialization_tx_hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Ok(true)` if bridge has already been initialized.
|
|
||||||
pub(crate) async fn is_initialized<
|
|
||||||
E: Engine<SourceChain>,
|
|
||||||
SourceChain: Chain,
|
|
||||||
TargetChain: Chain,
|
|
||||||
>(
|
|
||||||
target_client: &Client<TargetChain>,
|
|
||||||
) -> Result<bool, Error<HashOf<SourceChain>, BlockNumberOf<SourceChain>>> {
|
|
||||||
Ok(target_client
|
|
||||||
.raw_storage_value(E::is_initialized_key(), None)
|
|
||||||
.await
|
|
||||||
.map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))?
|
|
||||||
.is_some())
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -51,15 +51,12 @@ impl<P: SubstrateFinalitySyncPipeline> SubstrateFinalityTarget<P> {
|
|||||||
|
|
||||||
/// Ensure that the bridge pallet at target chain is active.
|
/// Ensure that the bridge pallet at target chain is active.
|
||||||
pub async fn ensure_pallet_active(&self) -> Result<(), Error> {
|
pub async fn ensure_pallet_active(&self) -> Result<(), Error> {
|
||||||
let is_halted = self.client.storage_value(P::FinalityEngine::is_halted_key(), None).await?;
|
let is_halted = P::FinalityEngine::is_halted(&self.client).await?;
|
||||||
if is_halted.unwrap_or(false) {
|
if is_halted {
|
||||||
return Err(Error::BridgePalletIsHalted)
|
return Err(Error::BridgePalletIsHalted)
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_initialized =
|
let is_initialized = P::FinalityEngine::is_initialized(&self.client)
|
||||||
super::initialize::is_initialized::<P::FinalityEngine, P::SourceChain, P::TargetChain>(
|
|
||||||
&self.client,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::Custom(e.to_string()))?;
|
.map_err(|e| Error::Custom(e.to_string()))?;
|
||||||
if !is_initialized {
|
if !is_initialized {
|
||||||
|
|||||||
@@ -146,7 +146,11 @@ where
|
|||||||
async fn state(&self) -> Result<SourceClientState<MessageLaneAdapter<P>>, SubstrateError> {
|
async fn state(&self) -> Result<SourceClientState<MessageLaneAdapter<P>>, SubstrateError> {
|
||||||
// we can't continue to deliver confirmations if source node is out of sync, because
|
// we can't continue to deliver confirmations if source node is out of sync, because
|
||||||
// it may have already received confirmations that we're going to deliver
|
// it may have already received confirmations that we're going to deliver
|
||||||
|
//
|
||||||
|
// we can't continue to deliver messages if target node is out of sync, because
|
||||||
|
// it may have already received (some of) messages that we're going to deliver
|
||||||
self.source_client.ensure_synced().await?;
|
self.source_client.ensure_synced().await?;
|
||||||
|
self.target_client.ensure_synced().await?;
|
||||||
// we can't relay confirmations if messages pallet at source chain is halted
|
// we can't relay confirmations if messages pallet at source chain is halted
|
||||||
self.ensure_pallet_active().await?;
|
self.ensure_pallet_active().await?;
|
||||||
|
|
||||||
@@ -562,9 +566,13 @@ where
|
|||||||
Some(at_self_hash),
|
Some(at_self_hash),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let decoded_best_finalized_peer_on_self: (BlockNumberOf<PeerChain>, HashOf<PeerChain>) =
|
let decoded_best_finalized_peer_on_self =
|
||||||
Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..])
|
Option::<(BlockNumberOf<PeerChain>, HashOf<PeerChain>)>::decode(
|
||||||
.map_err(SubstrateError::ResponseParseFailed)?;
|
&mut &encoded_best_finalized_peer_on_self.0[..],
|
||||||
|
)
|
||||||
|
.map_err(SubstrateError::ResponseParseFailed)?
|
||||||
|
.map(Ok)
|
||||||
|
.unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?;
|
||||||
let peer_on_self_best_finalized_id =
|
let peer_on_self_best_finalized_id =
|
||||||
HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1);
|
HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1);
|
||||||
|
|
||||||
|
|||||||
@@ -146,8 +146,12 @@ where
|
|||||||
BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
|
BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
|
||||||
{
|
{
|
||||||
async fn state(&self) -> Result<TargetClientState<MessageLaneAdapter<P>>, SubstrateError> {
|
async fn state(&self) -> Result<TargetClientState<MessageLaneAdapter<P>>, SubstrateError> {
|
||||||
|
// we can't continue to deliver confirmations if source node is out of sync, because
|
||||||
|
// it may have already received confirmations that we're going to deliver
|
||||||
|
//
|
||||||
// we can't continue to deliver messages if target node is out of sync, because
|
// we can't continue to deliver messages if target node is out of sync, because
|
||||||
// it may have already received (some of) messages that we're going to deliver
|
// it may have already received (some of) messages that we're going to deliver
|
||||||
|
self.source_client.ensure_synced().await?;
|
||||||
self.target_client.ensure_synced().await?;
|
self.target_client.ensure_synced().await?;
|
||||||
// we can't relay messages if messages pallet at target chain is halted
|
// we can't relay messages if messages pallet at target chain is halted
|
||||||
self.ensure_pallet_active().await?;
|
self.ensure_pallet_active().await?;
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ async fn background_task<P: SubstrateFinalitySyncPipeline>(
|
|||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
"[{}] Starting on-demand relay task\n\t\
|
"[{}] Starting on-demand headers relay task\n\t\
|
||||||
Only mandatory headers: {}\n\t\
|
Only mandatory headers: {}\n\t\
|
||||||
Tx mortality: {:?} (~{}m)\n\t\
|
Tx mortality: {:?} (~{}m)\n\t\
|
||||||
Stall timeout: {:?}",
|
Stall timeout: {:?}",
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ async fn background_task<P: SubstrateParachainsPipeline>(
|
|||||||
new_required_parachain_header_number,
|
new_required_parachain_header_number,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
_ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {},
|
||||||
_ = parachains_relay_task => {
|
_ = parachains_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;
|
||||||
@@ -266,7 +267,7 @@ async fn background_task<P: SubstrateParachainsPipeline>(
|
|||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
target: "bridge",
|
target: "bridge",
|
||||||
"[{}] Starting on-demand-relay task\n\t\
|
"[{}] Starting on-demand-parachains relay task\n\t\
|
||||||
Tx mortality: {:?} (~{}m)\n\t\
|
Tx mortality: {:?} (~{}m)\n\t\
|
||||||
Stall timeout: {:?}",
|
Stall timeout: {:?}",
|
||||||
relay_task_name,
|
relay_task_name,
|
||||||
@@ -317,7 +318,7 @@ struct RelayData<ParaHash, ParaNumber, RelayNumber> {
|
|||||||
/// Parachain header number that is required at the target chain.
|
/// Parachain header number that is required at the target chain.
|
||||||
pub required_para_header: ParaNumber,
|
pub required_para_header: ParaNumber,
|
||||||
/// Parachain header number, known to the target chain.
|
/// Parachain header number, known to the target chain.
|
||||||
pub para_header_at_target: ParaNumber,
|
pub para_header_at_target: Option<ParaNumber>,
|
||||||
/// Parachain header id, known to the source (relay) chain.
|
/// Parachain header id, known to the source (relay) chain.
|
||||||
pub para_header_at_source: Option<HeaderId<ParaHash, ParaNumber>>,
|
pub para_header_at_source: Option<HeaderId<ParaHash, ParaNumber>>,
|
||||||
/// Parachain header, that is available at the source relay chain at `relay_header_at_target`
|
/// Parachain header, that is available at the source relay chain at `relay_header_at_target`
|
||||||
@@ -374,9 +375,15 @@ where
|
|||||||
best_target_block_hash,
|
best_target_block_hash,
|
||||||
P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD,
|
P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD,
|
||||||
)
|
)
|
||||||
.await
|
.await;
|
||||||
.map_err(map_target_err)?
|
// if there are no parachain heads at the target (`BridgePalletIsNotInitialized`), we'll need
|
||||||
.0;
|
// to submit at least one. Otherwise the pallet will be treated as uninitialized and messages
|
||||||
|
// sync will stall.
|
||||||
|
let para_header_at_target = match para_header_at_target {
|
||||||
|
Ok(para_header_at_target) => Some(para_header_at_target.0),
|
||||||
|
Err(SubstrateError::BridgePalletIsNotInitialized) => None,
|
||||||
|
Err(e) => return Err(map_target_err(e)),
|
||||||
|
};
|
||||||
|
|
||||||
let best_finalized_relay_header =
|
let best_finalized_relay_header =
|
||||||
source.client().best_finalized_header().await.map_err(map_source_err)?;
|
source.client().best_finalized_header().await.map_err(map_source_err)?;
|
||||||
@@ -424,7 +431,7 @@ fn select_headers_to_relay<ParaHash, ParaNumber, RelayNumber>(
|
|||||||
) -> RelayState<ParaHash, ParaNumber, RelayNumber>
|
) -> RelayState<ParaHash, ParaNumber, RelayNumber>
|
||||||
where
|
where
|
||||||
ParaHash: Clone,
|
ParaHash: Clone,
|
||||||
ParaNumber: Copy + PartialOrd,
|
ParaNumber: Copy + PartialOrd + Zero,
|
||||||
RelayNumber: Copy + Debug + Ord,
|
RelayNumber: Copy + Debug + Ord,
|
||||||
{
|
{
|
||||||
// this switch is responsible for processing `RelayingRelayHeader` state
|
// this switch is responsible for processing `RelayingRelayHeader` state
|
||||||
@@ -450,30 +457,38 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this switch is responsible for processing `RelayingParaHeader` state
|
// this switch is responsible for processing `RelayingParaHeader` state
|
||||||
|
let para_header_at_target_or_zero = data.para_header_at_target.unwrap_or_else(Zero::zero);
|
||||||
match state {
|
match state {
|
||||||
RelayState::Idle => (),
|
RelayState::Idle => (),
|
||||||
RelayState::RelayingRelayHeader(_) => unreachable!("processed by previous match; qed"),
|
RelayState::RelayingRelayHeader(_) => unreachable!("processed by previous match; qed"),
|
||||||
RelayState::RelayingParaHeader(para_header_id) => {
|
RelayState::RelayingParaHeader(para_header_id) => {
|
||||||
if data.para_header_at_target < para_header_id.0 {
|
if para_header_at_target_or_zero < para_header_id.0 {
|
||||||
// parachain header hasn't yet been relayed
|
// parachain header hasn't yet been relayed
|
||||||
return RelayState::RelayingParaHeader(para_header_id)
|
return RelayState::RelayingParaHeader(para_header_id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have already satisfied our "customer", do nothing
|
|
||||||
if data.required_para_header <= data.para_header_at_target {
|
|
||||||
return RelayState::Idle
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we haven't read para head from the source, we can't yet do anyhting
|
// if we haven't read para head from the source, we can't yet do anyhting
|
||||||
let para_header_at_source = match data.para_header_at_source {
|
let para_header_at_source = match data.para_header_at_source {
|
||||||
Some(ref para_header_at_source) => para_header_at_source.clone(),
|
Some(ref para_header_at_source) => para_header_at_source.clone(),
|
||||||
None => return RelayState::Idle,
|
None => return RelayState::Idle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if we have parachain head at the source, but no parachain heads at the target, we'll need
|
||||||
|
// to deliver at least one parachain head
|
||||||
|
let (required_para_header, para_header_at_target) = match data.para_header_at_target {
|
||||||
|
Some(para_header_at_target) => (data.required_para_header, para_header_at_target),
|
||||||
|
None => (para_header_at_source.0, Zero::zero()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// if we have already satisfied our "customer", do nothing
|
||||||
|
if required_para_header <= para_header_at_target {
|
||||||
|
return RelayState::Idle
|
||||||
|
}
|
||||||
|
|
||||||
// if required header is not available even at the source chain, let's wait
|
// if required header is not available even at the source chain, let's wait
|
||||||
if data.required_para_header > para_header_at_source.0 {
|
if required_para_header > para_header_at_source.0 {
|
||||||
return RelayState::Idle
|
return RelayState::Idle
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,7 +514,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 90,
|
required_para_header: 90,
|
||||||
para_header_at_target: 50,
|
para_header_at_target: Some(50),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 700,
|
relay_header_at_target: 700,
|
||||||
@@ -517,7 +532,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 90,
|
required_para_header: 90,
|
||||||
para_header_at_target: 50,
|
para_header_at_target: Some(50),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 750,
|
relay_header_at_target: 750,
|
||||||
@@ -535,7 +550,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 90,
|
required_para_header: 90,
|
||||||
para_header_at_target: 50,
|
para_header_at_target: Some(50),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -552,7 +567,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 90,
|
required_para_header: 90,
|
||||||
para_header_at_target: 50,
|
para_header_at_target: Some(50),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -570,7 +585,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 90,
|
required_para_header: 90,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -588,7 +603,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 120,
|
required_para_header: 120,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: None,
|
para_header_at_source: None,
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -606,7 +621,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 120,
|
required_para_header: 120,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: Some(HeaderId(110, 110)),
|
para_header_at_source: Some(HeaderId(110, 110)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -624,7 +639,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 120,
|
required_para_header: 120,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: Some(HeaderId(125, 125)),
|
para_header_at_source: Some(HeaderId(125, 125)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 780,
|
relay_header_at_target: 780,
|
||||||
@@ -642,7 +657,7 @@ mod tests {
|
|||||||
select_headers_to_relay(
|
select_headers_to_relay(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 120,
|
required_para_header: 120,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: Some(HeaderId(125, 125)),
|
para_header_at_source: Some(HeaderId(125, 125)),
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 800,
|
relay_header_at_target: 800,
|
||||||
@@ -660,7 +675,7 @@ mod tests {
|
|||||||
select_headers_to_relay::<i32, _, _>(
|
select_headers_to_relay::<i32, _, _>(
|
||||||
&RelayData {
|
&RelayData {
|
||||||
required_para_header: 120,
|
required_para_header: 120,
|
||||||
para_header_at_target: 105,
|
para_header_at_target: Some(105),
|
||||||
para_header_at_source: None,
|
para_header_at_source: None,
|
||||||
relay_header_at_source: 800,
|
relay_header_at_source: 800,
|
||||||
relay_header_at_target: 800,
|
relay_header_at_target: 800,
|
||||||
@@ -671,4 +686,40 @@ mod tests {
|
|||||||
RelayState::Idle,
|
RelayState::Idle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn relay_starts_relaying_first_parachain_header() {
|
||||||
|
assert_eq!(
|
||||||
|
select_headers_to_relay::<i32, _, _>(
|
||||||
|
&RelayData {
|
||||||
|
required_para_header: 0,
|
||||||
|
para_header_at_target: None,
|
||||||
|
para_header_at_source: Some(HeaderId(125, 125)),
|
||||||
|
relay_header_at_source: 800,
|
||||||
|
relay_header_at_target: 800,
|
||||||
|
para_header_at_relay_header_at_target: Some(HeaderId(125, 125)),
|
||||||
|
},
|
||||||
|
RelayState::Idle,
|
||||||
|
),
|
||||||
|
RelayState::RelayingParaHeader(HeaderId(125, 125)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn relay_starts_relaying_relay_header_to_relay_first_parachain_header() {
|
||||||
|
assert_eq!(
|
||||||
|
select_headers_to_relay::<i32, _, _>(
|
||||||
|
&RelayData {
|
||||||
|
required_para_header: 0,
|
||||||
|
para_header_at_target: None,
|
||||||
|
para_header_at_source: Some(HeaderId(125, 125)),
|
||||||
|
relay_header_at_source: 800,
|
||||||
|
relay_header_at_target: 700,
|
||||||
|
para_header_at_relay_header_at_target: Some(HeaderId(125, 125)),
|
||||||
|
},
|
||||||
|
RelayState::Idle,
|
||||||
|
),
|
||||||
|
RelayState::RelayingRelayHeader(800),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,11 +102,13 @@ where
|
|||||||
Some(at_block.1),
|
Some(at_block.1),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let decoded_best_finalized_source_block: (
|
let decoded_best_finalized_source_block =
|
||||||
BlockNumberOf<P::SourceRelayChain>,
|
Option::<(BlockNumberOf<P::SourceRelayChain>, HashOf<P::SourceRelayChain>)>::decode(
|
||||||
HashOf<P::SourceRelayChain>,
|
&mut &encoded_best_finalized_source_block.0[..],
|
||||||
) = Decode::decode(&mut &encoded_best_finalized_source_block.0[..])
|
)
|
||||||
.map_err(SubstrateError::ResponseParseFailed)?;
|
.map_err(SubstrateError::ResponseParseFailed)?
|
||||||
|
.map(Ok)
|
||||||
|
.unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?;
|
||||||
Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1))
|
Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use async_trait::async_trait;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
/// Value update interval.
|
/// Value update interval.
|
||||||
const UPDATE_INTERVAL: Duration = Duration::from_secs(60);
|
const UPDATE_INTERVAL: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
/// Metric that represents float value received from HTTP service as float gauge.
|
/// Metric that represents float value received from HTTP service as float gauge.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user