mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 18:41:03 +00:00
Only store header state root (pallet-bridge-parachains) (#1701)
* store block number ++ state root in parachains pallet * fixed parachains finality APIs * (test commit) * removed test code * deduplicated code a bit * removed commented code * spelling * Update modules/parachains/src/lib.rs Co-authored-by: Adrian Catangiu <adrian@parity.io> * Update modules/parachains/src/lib.rs Co-authored-by: Adrian Catangiu <adrian@parity.io> * Update modules/parachains/src/mock.rs Co-authored-by: Adrian Catangiu <adrian@parity.io> * added comment Co-authored-by: Adrian Catangiu <adrian@parity.io>
This commit is contained in:
committed by
Bastian Köcher
parent
2c5e2f09eb
commit
d63a75697c
@@ -16,6 +16,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive"
|
|||||||
|
|
||||||
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
bp-messages = { path = "../../../primitives/messages", default-features = false }
|
||||||
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
bp-millau = { path = "../../../primitives/chain-millau", default-features = false }
|
||||||
|
bp-parachains = { path = "../../../primitives/parachains", default-features = false }
|
||||||
bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false }
|
bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false }
|
||||||
bp-relayers = { path = "../../../primitives/relayers", default-features = false }
|
bp-relayers = { path = "../../../primitives/relayers", default-features = false }
|
||||||
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false }
|
||||||
@@ -84,6 +85,7 @@ std = [
|
|||||||
"beefy-primitives/std",
|
"beefy-primitives/std",
|
||||||
"bp-messages/std",
|
"bp-messages/std",
|
||||||
"bp-millau/std",
|
"bp-millau/std",
|
||||||
|
"bp-parachains/std",
|
||||||
"bp-polkadot-core/std",
|
"bp-polkadot-core/std",
|
||||||
"bp-relayers/std",
|
"bp-relayers/std",
|
||||||
"bp-rialto/std",
|
"bp-rialto/std",
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ pub mod rialto_parachain_messages;
|
|||||||
pub mod xcm_config;
|
pub mod xcm_config;
|
||||||
|
|
||||||
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
|
use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet};
|
||||||
use bp_runtime::{HeaderId, HeaderIdProvider};
|
use bp_parachains::SingleParaStoredHeaderDataBuilder;
|
||||||
use codec::Decode;
|
use bp_runtime::HeaderId;
|
||||||
use pallet_grandpa::{
|
use pallet_grandpa::{
|
||||||
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
||||||
};
|
};
|
||||||
@@ -522,8 +522,8 @@ parameter_types! {
|
|||||||
pub const RialtoParachainId: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID;
|
pub const RialtoParachainId: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID;
|
||||||
pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME;
|
pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME;
|
||||||
pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME;
|
pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME;
|
||||||
pub const MaxRialtoParaHeadSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_SIZE;
|
pub const MaxRialtoParaHeadDataSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;
|
||||||
pub const MaxWestendParaHeadSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_SIZE;
|
pub const MaxWestendParaHeadDataSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instance of the with-Rialto parachains pallet.
|
/// Instance of the with-Rialto parachains pallet.
|
||||||
@@ -534,9 +534,10 @@ impl pallet_bridge_parachains::Config<WithRialtoParachainsInstance> for Runtime
|
|||||||
type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight<Runtime>;
|
||||||
type BridgesGrandpaPalletInstance = RialtoGrandpaInstance;
|
type BridgesGrandpaPalletInstance = RialtoGrandpaInstance;
|
||||||
type ParasPalletName = RialtoParasPalletName;
|
type ParasPalletName = RialtoParasPalletName;
|
||||||
type TrackedParachains = frame_support::traits::Everything;
|
type ParaStoredHeaderDataBuilder =
|
||||||
|
SingleParaStoredHeaderDataBuilder<bp_rialto_parachain::RialtoParachain>;
|
||||||
type HeadsToKeep = HeadersToKeep;
|
type HeadsToKeep = HeadersToKeep;
|
||||||
type MaxParaHeadSize = MaxRialtoParaHeadSize;
|
type MaxParaHeadDataSize = MaxRialtoParaHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instance of the with-Westend parachains pallet.
|
/// Instance of the with-Westend parachains pallet.
|
||||||
@@ -547,9 +548,9 @@ impl pallet_bridge_parachains::Config<WithWestendParachainsInstance> for Runtime
|
|||||||
type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight<Runtime>;
|
||||||
type BridgesGrandpaPalletInstance = WestendGrandpaInstance;
|
type BridgesGrandpaPalletInstance = WestendGrandpaInstance;
|
||||||
type ParasPalletName = WestendParasPalletName;
|
type ParasPalletName = WestendParasPalletName;
|
||||||
type TrackedParachains = frame_support::traits::Everything;
|
type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder<bp_westend::Westmint>;
|
||||||
type HeadsToKeep = HeadersToKeep;
|
type HeadsToKeep = HeadersToKeep;
|
||||||
type MaxParaHeadSize = MaxWestendParaHeadSize;
|
type MaxParaHeadDataSize = MaxWestendParaHeadDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl pallet_utility::Config for Runtime {
|
impl pallet_utility::Config for Runtime {
|
||||||
@@ -902,28 +903,19 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
impl bp_westend::WestmintFinalityApi<Block> for Runtime {
|
impl bp_westend::WestmintFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> Option<HeaderId<bp_westend::Hash, bp_westend::BlockNumber>> {
|
fn best_finalized() -> Option<HeaderId<bp_westend::Hash, bp_westend::BlockNumber>> {
|
||||||
// the parachains finality pallet is never decoding parachain heads, so it is
|
pallet_bridge_parachains::Pallet::<
|
||||||
// only done in the integration code
|
|
||||||
use bp_westend::WESTMINT_PARACHAIN_ID;
|
|
||||||
let encoded_head = pallet_bridge_parachains::Pallet::<
|
|
||||||
Runtime,
|
Runtime,
|
||||||
WithWestendParachainsInstance,
|
WithWestendParachainsInstance,
|
||||||
>::best_parachain_head(WESTMINT_PARACHAIN_ID.into())?;
|
>::best_parachain_head_id::<bp_westend::Westmint>().unwrap_or(None)
|
||||||
let head = bp_westend::Header::decode(&mut &encoded_head.0[..]).ok()?;
|
|
||||||
Some(head.id())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_rialto_parachain::RialtoParachainFinalityApi<Block> for Runtime {
|
impl bp_rialto_parachain::RialtoParachainFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> Option<HeaderId<bp_rialto::Hash, bp_rialto::BlockNumber>> {
|
fn best_finalized() -> Option<HeaderId<bp_rialto::Hash, bp_rialto::BlockNumber>> {
|
||||||
// the parachains finality pallet is never decoding parachain heads, so it is
|
pallet_bridge_parachains::Pallet::<
|
||||||
// only done in the integration code
|
|
||||||
let encoded_head = pallet_bridge_parachains::Pallet::<
|
|
||||||
Runtime,
|
Runtime,
|
||||||
WithRialtoParachainsInstance,
|
WithRialtoParachainsInstance,
|
||||||
>::best_parachain_head(bp_rialto_parachain::RIALTO_PARACHAIN_ID.into())?;
|
>::best_parachain_head_id::<bp_rialto_parachain::RialtoParachain>().unwrap_or(None)
|
||||||
let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?;
|
|
||||||
Some(head.id())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master",
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bp-header-chain = { path = "../../primitives/header-chain" }
|
bp-header-chain = { path = "../../primitives/header-chain" }
|
||||||
bp-test-utils = { path = "../../primitives/test-utils" }
|
bp-test-utils = { path = "../../primitives/test-utils" }
|
||||||
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -27,12 +27,10 @@ pub use weights::WeightInfo;
|
|||||||
pub use weights_ext::WeightInfoExt;
|
pub use weights_ext::WeightInfoExt;
|
||||||
|
|
||||||
use bp_header_chain::HeaderChain;
|
use bp_header_chain::HeaderChain;
|
||||||
use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo};
|
use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData};
|
||||||
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
|
use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId};
|
||||||
use bp_runtime::{HashOf, HeaderOf, Parachain, StorageProofError};
|
use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofError};
|
||||||
use codec::Decode;
|
use frame_support::dispatch::PostDispatchInfo;
|
||||||
use frame_support::{dispatch::PostDispatchInfo, traits::Contains};
|
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
|
||||||
use sp_std::{marker::PhantomData, vec::Vec};
|
use sp_std::{marker::PhantomData, vec::Vec};
|
||||||
|
|
||||||
// Re-export in crate namespace for `construct_runtime!`.
|
// Re-export in crate namespace for `construct_runtime!`.
|
||||||
@@ -69,7 +67,10 @@ struct UpdateParachainHeadArtifacts {
|
|||||||
#[frame_support::pallet]
|
#[frame_support::pallet]
|
||||||
pub mod pallet {
|
pub mod pallet {
|
||||||
use super::*;
|
use super::*;
|
||||||
use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
|
use bp_parachains::{
|
||||||
|
BestParaHeadHash, ImportedParaHeadsKeyProvider, ParaStoredHeaderDataBuilder,
|
||||||
|
ParasInfoKeyProvider,
|
||||||
|
};
|
||||||
use bp_runtime::{
|
use bp_runtime::{
|
||||||
BasicOperatingMode, BoundedStorageValue, OwnedBridgeModule, StorageDoubleMapKeyProvider,
|
BasicOperatingMode, BoundedStorageValue, OwnedBridgeModule, StorageDoubleMapKeyProvider,
|
||||||
StorageMapKeyProvider,
|
StorageMapKeyProvider,
|
||||||
@@ -77,9 +78,9 @@ pub mod pallet {
|
|||||||
use frame_support::pallet_prelude::*;
|
use frame_support::pallet_prelude::*;
|
||||||
use frame_system::pallet_prelude::*;
|
use frame_system::pallet_prelude::*;
|
||||||
|
|
||||||
/// Stored parachain head of given parachains pallet.
|
/// Stored parachain head data of given parachains pallet.
|
||||||
pub type StoredParaHeadOf<T, I> =
|
pub type StoredParaHeadDataOf<T, I> =
|
||||||
BoundedStorageValue<<T as Config<I>>::MaxParaHeadSize, ParaHead>;
|
BoundedStorageValue<<T as Config<I>>::MaxParaHeadDataSize, ParaStoredHeaderData>;
|
||||||
/// Weight info of the given parachains pallet.
|
/// Weight info of the given parachains pallet.
|
||||||
pub type WeightInfoOf<T, I> = <T as Config<I>>::WeightInfo;
|
pub type WeightInfoOf<T, I> = <T as Config<I>>::WeightInfo;
|
||||||
|
|
||||||
@@ -153,12 +154,18 @@ pub mod pallet {
|
|||||||
#[pallet::constant]
|
#[pallet::constant]
|
||||||
type ParasPalletName: Get<&'static str>;
|
type ParasPalletName: Get<&'static str>;
|
||||||
|
|
||||||
/// Set of parachains that are tracked by this pallet.
|
/// Parachain head data builder.
|
||||||
///
|
///
|
||||||
/// The set may be extended easily, without requiring any runtime upgrades. Removing tracked
|
/// We never store parachain heads here, since they may be too big (e.g. because of large
|
||||||
/// parachain requires special handling - pruning existing heads and cleaning related data
|
/// digest items). Instead we're using the same approach as `pallet-bridge-grandpa`
|
||||||
/// structures.
|
/// pallet - we are only storing `bp_messages::StoredHeaderData` (number and state root),
|
||||||
type TrackedParachains: Contains<ParaId>;
|
/// which is enough for our applications. However, we work with different parachains here
|
||||||
|
/// and they can use different primitives (for block numbers and hash). So we can't store
|
||||||
|
/// it directly. Instead, we're storing `bp_messages::StoredHeaderData` in SCALE-encoded
|
||||||
|
/// form, wrapping it into `bp_parachains::ParaStoredHeaderData`.
|
||||||
|
///
|
||||||
|
/// This builder helps to convert from `HeadData` to `bp_parachains::ParaStoredHeaderData`.
|
||||||
|
type ParaStoredHeaderDataBuilder: ParaStoredHeaderDataBuilder;
|
||||||
|
|
||||||
/// Maximal number of single parachain heads to keep in the storage.
|
/// Maximal number of single parachain heads to keep in the storage.
|
||||||
///
|
///
|
||||||
@@ -170,16 +177,17 @@ pub mod pallet {
|
|||||||
#[pallet::constant]
|
#[pallet::constant]
|
||||||
type HeadsToKeep: Get<u32>;
|
type HeadsToKeep: Get<u32>;
|
||||||
|
|
||||||
/// Maximal size (in bytes) of the SCALE-encoded parachain head.
|
/// Maximal size (in bytes) of the SCALE-encoded parachain head data
|
||||||
|
/// (`bp_parachains::ParaStoredHeaderData`).
|
||||||
///
|
///
|
||||||
/// Keep in mind that the size of any tracked parachain header must not exceed this value.
|
/// Keep in mind that the size of any tracked parachain header data must not exceed this
|
||||||
/// So if you're going to track multiple parachains, one of which is storing large digests
|
/// value. So if you're going to track multiple parachains, one of which is using large
|
||||||
/// in its headers, you shall choose this maximal value.
|
/// hashes, you shall choose this maximal value.
|
||||||
///
|
///
|
||||||
/// There's no mandatory headers in this pallet, so it can't stall if there's some header
|
/// There's no mandatory headers in this pallet, so it can't stall if there's some header
|
||||||
/// that exceeds this bound.
|
/// that exceeds this bound.
|
||||||
#[pallet::constant]
|
#[pallet::constant]
|
||||||
type MaxParaHeadSize: Get<u32>;
|
type MaxParaHeadDataSize: Get<u32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optional pallet owner.
|
/// Optional pallet owner.
|
||||||
@@ -212,7 +220,7 @@ pub mod pallet {
|
|||||||
<ParasInfoKeyProvider as StorageMapKeyProvider>::Value,
|
<ParasInfoKeyProvider as StorageMapKeyProvider>::Value,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// Parachain heads which have been imported into the pallet.
|
/// State roots of parachain heads which have been imported into the pallet.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
pub type ImportedParaHeads<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
|
pub type ImportedParaHeads<T: Config<I>, I: 'static = ()> = StorageDoubleMap<
|
||||||
_,
|
_,
|
||||||
@@ -220,7 +228,7 @@ pub mod pallet {
|
|||||||
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Key1,
|
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Key1,
|
||||||
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Hasher2,
|
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Hasher2,
|
||||||
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Key2,
|
<ImportedParaHeadsKeyProvider as StorageDoubleMapKeyProvider>::Key2,
|
||||||
StoredParaHeadOf<T, I>,
|
StoredParaHeadDataOf<T, I>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// A ring buffer of imported parachain head hashes. Ordered by the insertion time.
|
/// A ring buffer of imported parachain head hashes. Ordered by the insertion time.
|
||||||
@@ -291,17 +299,6 @@ pub mod pallet {
|
|||||||
sp_trie::StorageProof::new(parachain_heads_proof.0),
|
sp_trie::StorageProof::new(parachain_heads_proof.0),
|
||||||
move |storage| {
|
move |storage| {
|
||||||
for (parachain, parachain_head_hash) in parachains {
|
for (parachain, parachain_head_hash) in parachains {
|
||||||
// if we're not tracking this parachain, we'll just ignore its head proof here
|
|
||||||
if !T::TrackedParachains::contains(¶chain) {
|
|
||||||
log::trace!(
|
|
||||||
target: LOG_TARGET,
|
|
||||||
"The head of parachain {:?} has been provided, but it is not tracked by the pallet",
|
|
||||||
parachain,
|
|
||||||
);
|
|
||||||
Self::deposit_event(Event::UntrackedParachainRejected { parachain });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let parachain_head = match Pallet::<T, I>::read_parachain_head(&storage, parachain) {
|
let parachain_head = match Pallet::<T, I>::read_parachain_head(&storage, parachain) {
|
||||||
Ok(Some(parachain_head)) => parachain_head,
|
Ok(Some(parachain_head)) => parachain_head,
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
@@ -349,12 +346,26 @@ pub mod pallet {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert from parachain head into stored parachain head data
|
||||||
|
let parachain_head_data = match T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) {
|
||||||
|
Some(parachain_head_data) => parachain_head_data,
|
||||||
|
None => {
|
||||||
|
log::trace!(
|
||||||
|
target: LOG_TARGET,
|
||||||
|
"The head of parachain {:?} has been provided, but it is not tracked by the pallet",
|
||||||
|
parachain,
|
||||||
|
);
|
||||||
|
Self::deposit_event(Event::UntrackedParachainRejected { parachain });
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let update_result: Result<_, ()> = ParasInfo::<T, I>::try_mutate(parachain, |stored_best_head| {
|
let update_result: Result<_, ()> = ParasInfo::<T, I>::try_mutate(parachain, |stored_best_head| {
|
||||||
let artifacts = Pallet::<T, I>::update_parachain_head(
|
let artifacts = Pallet::<T, I>::update_parachain_head(
|
||||||
parachain,
|
parachain,
|
||||||
stored_best_head.take(),
|
stored_best_head.take(),
|
||||||
relay_block_number,
|
relay_block_number,
|
||||||
parachain_head,
|
parachain_head_data,
|
||||||
parachain_head_hash,
|
parachain_head_hash,
|
||||||
)?;
|
)?;
|
||||||
*stored_best_head = Some(artifacts.best_head);
|
*stored_best_head = Some(artifacts.best_head);
|
||||||
@@ -406,14 +417,36 @@ pub mod pallet {
|
|||||||
ParasInfo::<T, I>::get(parachain)
|
ParasInfo::<T, I>::get(parachain)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get best finalized header of the given parachain.
|
/// Get best finalized head data of the given parachain.
|
||||||
pub fn best_parachain_head(parachain: ParaId) -> Option<ParaHead> {
|
pub fn best_parachain_head(parachain: ParaId) -> Option<ParaStoredHeaderData> {
|
||||||
let best_para_head_hash = ParasInfo::<T, I>::get(parachain)?.best_head_hash.head_hash;
|
let best_para_head_hash = ParasInfo::<T, I>::get(parachain)?.best_head_hash.head_hash;
|
||||||
ImportedParaHeads::<T, I>::get(parachain, best_para_head_hash).map(|h| h.into_inner())
|
ImportedParaHeads::<T, I>::get(parachain, best_para_head_hash).map(|h| h.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get parachain head with given hash.
|
/// Get best finalized head hash of the given parachain.
|
||||||
pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option<ParaHead> {
|
pub fn best_parachain_head_hash(parachain: ParaId) -> Option<ParaHash> {
|
||||||
|
Some(ParasInfo::<T, I>::get(parachain)?.best_head_hash.head_hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get best finalized head id of the given parachain.
|
||||||
|
pub fn best_parachain_head_id<C: Chain<Hash = ParaHash> + Parachain>(
|
||||||
|
) -> Result<Option<HeaderIdOf<C>>, codec::Error> {
|
||||||
|
let parachain = ParaId(C::PARACHAIN_ID);
|
||||||
|
let best_head_hash = match Self::best_parachain_head_hash(parachain) {
|
||||||
|
Some(best_head_hash) => best_head_hash,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
let encoded_head = match Self::parachain_head(parachain, best_head_hash) {
|
||||||
|
Some(encoded_head) => encoded_head,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
encoded_head
|
||||||
|
.decode_parachain_head_data::<C>()
|
||||||
|
.map(|data| Some(HeaderId(data.number, best_head_hash)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get parachain head data with given hash.
|
||||||
|
pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option<ParaStoredHeaderData> {
|
||||||
ImportedParaHeads::<T, I>::get(parachain, hash).map(|h| h.into_inner())
|
ImportedParaHeads::<T, I>::get(parachain, hash).map(|h| h.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +513,7 @@ pub mod pallet {
|
|||||||
parachain: ParaId,
|
parachain: ParaId,
|
||||||
stored_best_head: Option<ParaInfo>,
|
stored_best_head: Option<ParaInfo>,
|
||||||
updated_at_relay_block_number: RelayBlockNumber,
|
updated_at_relay_block_number: RelayBlockNumber,
|
||||||
updated_head: ParaHead,
|
updated_head_data: ParaStoredHeaderData,
|
||||||
updated_head_hash: ParaHash,
|
updated_head_hash: ParaHash,
|
||||||
) -> Result<UpdateParachainHeadArtifacts, ()> {
|
) -> Result<UpdateParachainHeadArtifacts, ()> {
|
||||||
// check if head has been already updated at better relay chain block. Without this
|
// check if head has been already updated at better relay chain block. Without this
|
||||||
@@ -501,28 +534,29 @@ pub mod pallet {
|
|||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify that the parachain head size is <= `MaxParaHeadSize`
|
// verify that the parachain head data size is <= `MaxParaHeadDataSize`
|
||||||
let updated_head = match StoredParaHeadOf::<T, I>::try_from_inner(updated_head) {
|
let updated_head_data =
|
||||||
Ok(updated_head) => updated_head,
|
match StoredParaHeadDataOf::<T, I>::try_from_inner(updated_head_data) {
|
||||||
Err(e) => {
|
Ok(updated_head_data) => updated_head_data,
|
||||||
log::trace!(
|
Err(e) => {
|
||||||
target: LOG_TARGET,
|
log::trace!(
|
||||||
"{}. The parachain head size for {:?} is {}. It exceeds maximal configured size {}.",
|
target: LOG_TARGET,
|
||||||
err_log_prefix,
|
"{}. The parachain head data size for {:?} is {}. It exceeds maximal configured size {}.",
|
||||||
parachain,
|
err_log_prefix,
|
||||||
e.value_size,
|
parachain,
|
||||||
e.maximal_size,
|
e.value_size,
|
||||||
);
|
e.maximal_size,
|
||||||
|
);
|
||||||
|
|
||||||
Self::deposit_event(Event::RejectedLargeParachainHead {
|
Self::deposit_event(Event::RejectedLargeParachainHead {
|
||||||
parachain,
|
parachain,
|
||||||
parachain_head_hash: updated_head_hash,
|
parachain_head_hash: updated_head_hash,
|
||||||
parachain_head_size: e.value_size as _,
|
parachain_head_size: e.value_size as _,
|
||||||
});
|
});
|
||||||
|
|
||||||
return Err(())
|
return Err(())
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let next_imported_hash_position = stored_best_head
|
let next_imported_hash_position = stored_best_head
|
||||||
.map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position);
|
.map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position);
|
||||||
@@ -543,7 +577,7 @@ pub mod pallet {
|
|||||||
next_imported_hash_position,
|
next_imported_hash_position,
|
||||||
updated_head_hash,
|
updated_head_hash,
|
||||||
);
|
);
|
||||||
ImportedParaHeads::<T, I>::insert(parachain, updated_head_hash, updated_head);
|
ImportedParaHeads::<T, I>::insert(parachain, updated_head_hash, updated_head_data);
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"Updated head of parachain {:?} to {}",
|
"Updated head of parachain {:?} to {}",
|
||||||
@@ -611,8 +645,8 @@ impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
|
|||||||
{
|
{
|
||||||
fn finalized_header_state_root(hash: HashOf<C>) -> Option<HashOf<C>> {
|
fn finalized_header_state_root(hash: HashOf<C>) -> Option<HashOf<C>> {
|
||||||
Pallet::<T, I>::parachain_head(ParaId(C::PARACHAIN_ID), hash)
|
Pallet::<T, I>::parachain_head(ParaId(C::PARACHAIN_ID), hash)
|
||||||
.and_then(|head| HeaderOf::<C>::decode(&mut &head.0[..]).ok())
|
.and_then(|head| head.decode_parachain_head_data::<C>().ok())
|
||||||
.map(|h| *h.state_root())
|
.map(|h| h.state_root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,8 +654,9 @@ impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::mock::{
|
use crate::mock::{
|
||||||
run_test, test_relay_header, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime,
|
run_test, test_relay_header, BigParachainHeader, RegularParachainHasher,
|
||||||
MAXIMAL_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID,
|
RegularParachainHeader, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime,
|
||||||
|
PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID,
|
||||||
};
|
};
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
|
|
||||||
@@ -641,7 +676,8 @@ mod tests {
|
|||||||
weights::Weight,
|
weights::Weight,
|
||||||
};
|
};
|
||||||
use frame_system::{EventRecord, Pallet as System, Phase};
|
use frame_system::{EventRecord, Pallet as System, Phase};
|
||||||
use sp_runtime::DispatchError;
|
use sp_core::Hasher;
|
||||||
|
use sp_runtime::{traits::Header as HeaderT, DispatchError};
|
||||||
use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut};
|
use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut};
|
||||||
|
|
||||||
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
|
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
|
||||||
@@ -716,12 +752,42 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn head_data(parachain: u32, head_number: u32) -> ParaHead {
|
fn head_data(parachain: u32, head_number: u32) -> ParaHead {
|
||||||
ParaHead((parachain, head_number).encode())
|
ParaHead(
|
||||||
|
RegularParachainHeader::new(
|
||||||
|
head_number as _,
|
||||||
|
Default::default(),
|
||||||
|
RegularParachainHasher::hash(&(parachain, head_number).encode()),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.encode(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn large_head_data(parachain: u32, head_number: u32) -> ParaHead {
|
fn stored_head_data(parachain: u32, head_number: u32) -> ParaStoredHeaderData {
|
||||||
|
ParaStoredHeaderData(
|
||||||
|
(head_number as u64, RegularParachainHasher::hash(&(parachain, head_number).encode()))
|
||||||
|
.encode(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn big_head_data(parachain: u32, head_number: u32) -> ParaHead {
|
||||||
ParaHead(
|
ParaHead(
|
||||||
(parachain, head_number, vec![42u8; MAXIMAL_PARACHAIN_HEAD_SIZE as usize]).encode(),
|
BigParachainHeader::new(
|
||||||
|
head_number as _,
|
||||||
|
Default::default(),
|
||||||
|
RegularParachainHasher::hash(&(parachain, head_number).encode()),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.encode(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn big_stored_head_data(parachain: u32, head_number: u32) -> ParaStoredHeaderData {
|
||||||
|
ParaStoredHeaderData(
|
||||||
|
(head_number as u128, RegularParachainHasher::hash(&(parachain, head_number).encode()))
|
||||||
|
.encode(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,7 +889,7 @@ mod tests {
|
|||||||
initial_best_head(1).best_head_hash.head_hash
|
initial_best_head(1).best_head_hash.head_hash
|
||||||
)
|
)
|
||||||
.map(|h| h.into_inner()),
|
.map(|h| h.into_inner()),
|
||||||
Some(head_data(1, 0))
|
Some(stored_head_data(1, 0))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(
|
ImportedParaHeads::<TestRuntime>::get(
|
||||||
@@ -836,7 +902,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(ParaId(3), head_hash(3, 10))
|
ImportedParaHeads::<TestRuntime>::get(ParaId(3), head_hash(3, 10))
|
||||||
.map(|h| h.into_inner()),
|
.map(|h| h.into_inner()),
|
||||||
Some(head_data(3, 10))
|
Some(stored_head_data(3, 10))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -886,7 +952,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 5).hash())
|
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 5).hash())
|
||||||
.map(|h| h.into_inner()),
|
.map(|h| h.into_inner()),
|
||||||
Some(head_data(1, 5))
|
Some(stored_head_data(1, 5))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 10).hash())
|
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 10).hash())
|
||||||
@@ -921,12 +987,12 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 5).hash())
|
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 5).hash())
|
||||||
.map(|h| h.into_inner()),
|
.map(|h| h.into_inner()),
|
||||||
Some(head_data(1, 5))
|
Some(stored_head_data(1, 5))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 10).hash())
|
ImportedParaHeads::<TestRuntime>::get(ParaId(1), head_data(1, 10).hash())
|
||||||
.map(|h| h.into_inner()),
|
.map(|h| h.into_inner()),
|
||||||
Some(head_data(1, 10))
|
Some(stored_head_data(1, 10))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::<TestRuntime>::events(),
|
System::<TestRuntime>::events(),
|
||||||
@@ -1153,10 +1219,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn does_nothing_when_parachain_head_is_too_large() {
|
fn does_nothing_when_parachain_head_is_too_large() {
|
||||||
let (state_root, proof, parachains) =
|
let (state_root, proof, parachains) =
|
||||||
prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (2, large_head_data(1, 5))]);
|
prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (4, big_head_data(1, 5))]);
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
// start with relay block #0 and try to import head#5 of parachain#1 and untracked
|
// start with relay block #0 and try to import head#5 of parachain#1 and big parachain
|
||||||
// parachain
|
|
||||||
initialize(state_root);
|
initialize(state_root);
|
||||||
let result = Pallet::<TestRuntime>::submit_parachain_heads(
|
let result = Pallet::<TestRuntime>::submit_parachain_heads(
|
||||||
RuntimeOrigin::signed(1),
|
RuntimeOrigin::signed(1),
|
||||||
@@ -1175,7 +1240,7 @@ mod tests {
|
|||||||
next_imported_hash_position: 1,
|
next_imported_hash_position: 1,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(2)), None);
|
assert_eq!(ParasInfo::<TestRuntime>::get(ParaId(4)), None);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
System::<TestRuntime>::events(),
|
System::<TestRuntime>::events(),
|
||||||
vec![
|
vec![
|
||||||
@@ -1190,9 +1255,9 @@ mod tests {
|
|||||||
EventRecord {
|
EventRecord {
|
||||||
phase: Phase::Initialization,
|
phase: Phase::Initialization,
|
||||||
event: TestEvent::Parachains(Event::RejectedLargeParachainHead {
|
event: TestEvent::Parachains(Event::RejectedLargeParachainHead {
|
||||||
parachain: ParaId(2),
|
parachain: ParaId(4),
|
||||||
parachain_head_hash: large_head_data(1, 5).hash(),
|
parachain_head_hash: big_head_data(1, 5).hash(),
|
||||||
parachain_head_size: large_head_data(1, 5).encoded_size() as u32,
|
parachain_head_size: big_stored_head_data(1, 5).encoded_size() as u32,
|
||||||
}),
|
}),
|
||||||
topics: vec![],
|
topics: vec![],
|
||||||
},
|
},
|
||||||
@@ -1294,7 +1359,7 @@ mod tests {
|
|||||||
import_parachain_1_head(0, state_root_5, parachains_5, proof_5).expect("ok");
|
import_parachain_1_head(0, state_root_5, parachains_5, proof_5).expect("ok");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
||||||
Some(head_data(1, 5))
|
Some(stored_head_data(1, 5))
|
||||||
);
|
);
|
||||||
|
|
||||||
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
|
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
|
||||||
@@ -1310,7 +1375,7 @@ mod tests {
|
|||||||
),);
|
),);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
||||||
Some(head_data(1, 5))
|
Some(stored_head_data(1, 5))
|
||||||
);
|
);
|
||||||
|
|
||||||
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
|
// then if someone is pretending to provide updated head#10 of parachain#1 at relay
|
||||||
@@ -1326,7 +1391,7 @@ mod tests {
|
|||||||
),);
|
),);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
Pallet::<TestRuntime>::best_parachain_head(ParaId(1)),
|
||||||
Some(head_data(1, 10))
|
Some(stored_head_data(1, 10))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,12 @@
|
|||||||
// 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 bp_polkadot_core::parachains::ParaId;
|
use bp_polkadot_core::parachains::ParaId;
|
||||||
use bp_runtime::Chain;
|
use bp_runtime::{Chain, Parachain};
|
||||||
use frame_support::{
|
use frame_support::{construct_runtime, parameter_types, traits::ConstU32, weights::Weight};
|
||||||
construct_runtime, parameter_types,
|
|
||||||
traits::{ConstU32, IsInVec},
|
|
||||||
weights::Weight,
|
|
||||||
};
|
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
testing::{Header, H256},
|
testing::{Header, H256},
|
||||||
traits::{BlakeTwo256, Header as HeaderT, IdentityLookup},
|
traits::{BlakeTwo256, Header as HeaderT, IdentityLookup},
|
||||||
Perbill,
|
MultiSignature, Perbill,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate as pallet_bridge_parachains;
|
use crate as pallet_bridge_parachains;
|
||||||
@@ -40,7 +36,109 @@ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRunt
|
|||||||
|
|
||||||
pub const PARAS_PALLET_NAME: &str = "Paras";
|
pub const PARAS_PALLET_NAME: &str = "Paras";
|
||||||
pub const UNTRACKED_PARACHAIN_ID: u32 = 10;
|
pub const UNTRACKED_PARACHAIN_ID: u32 = 10;
|
||||||
pub const MAXIMAL_PARACHAIN_HEAD_SIZE: u32 = 512;
|
// use exact expected encoded size: `vec_len_size + header_number_size + state_root_hash_size`
|
||||||
|
pub const MAXIMAL_PARACHAIN_HEAD_DATA_SIZE: u32 = 1 + 8 + 32;
|
||||||
|
|
||||||
|
pub type RegularParachainHeader = sp_runtime::testing::Header;
|
||||||
|
pub type RegularParachainHasher = BlakeTwo256;
|
||||||
|
pub type BigParachainHeader = sp_runtime::generic::Header<u128, BlakeTwo256>;
|
||||||
|
|
||||||
|
pub struct Parachain1;
|
||||||
|
|
||||||
|
impl Chain for Parachain1 {
|
||||||
|
type BlockNumber = u64;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = RegularParachainHasher;
|
||||||
|
type Header = RegularParachainHeader;
|
||||||
|
type AccountId = u64;
|
||||||
|
type Balance = u64;
|
||||||
|
type Index = u64;
|
||||||
|
type Signature = MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parachain for Parachain1 {
|
||||||
|
const PARACHAIN_ID: u32 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Parachain2;
|
||||||
|
|
||||||
|
impl Chain for Parachain2 {
|
||||||
|
type BlockNumber = u64;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = RegularParachainHasher;
|
||||||
|
type Header = RegularParachainHeader;
|
||||||
|
type AccountId = u64;
|
||||||
|
type Balance = u64;
|
||||||
|
type Index = u64;
|
||||||
|
type Signature = MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parachain for Parachain2 {
|
||||||
|
const PARACHAIN_ID: u32 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Parachain3;
|
||||||
|
|
||||||
|
impl Chain for Parachain3 {
|
||||||
|
type BlockNumber = u64;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = RegularParachainHasher;
|
||||||
|
type Header = RegularParachainHeader;
|
||||||
|
type AccountId = u64;
|
||||||
|
type Balance = u64;
|
||||||
|
type Index = u64;
|
||||||
|
type Signature = MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parachain for Parachain3 {
|
||||||
|
const PARACHAIN_ID: u32 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this parachain is using u128 as block number and stored head data size exceeds limit
|
||||||
|
pub struct BigParachain;
|
||||||
|
|
||||||
|
impl Chain for BigParachain {
|
||||||
|
type BlockNumber = u128;
|
||||||
|
type Hash = H256;
|
||||||
|
type Hasher = RegularParachainHasher;
|
||||||
|
type Header = BigParachainHeader;
|
||||||
|
type AccountId = u64;
|
||||||
|
type Balance = u64;
|
||||||
|
type Index = u64;
|
||||||
|
type Signature = MultiSignature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Weight::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parachain for BigParachain {
|
||||||
|
const PARACHAIN_ID: u32 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
construct_runtime! {
|
construct_runtime! {
|
||||||
pub enum TestRuntime where
|
pub enum TestRuntime where
|
||||||
@@ -68,7 +166,7 @@ impl frame_system::Config for TestRuntime {
|
|||||||
type RuntimeCall = RuntimeCall;
|
type RuntimeCall = RuntimeCall;
|
||||||
type BlockNumber = TestNumber;
|
type BlockNumber = TestNumber;
|
||||||
type Hash = H256;
|
type Hash = H256;
|
||||||
type Hashing = BlakeTwo256;
|
type Hashing = RegularParachainHasher;
|
||||||
type AccountId = AccountId;
|
type AccountId = AccountId;
|
||||||
type Lookup = IdentityLookup<Self::AccountId>;
|
type Lookup = IdentityLookup<Self::AccountId>;
|
||||||
type Header = Header;
|
type Header = Header;
|
||||||
@@ -122,9 +220,9 @@ impl pallet_bridge_parachains::Config for TestRuntime {
|
|||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
|
type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1;
|
||||||
type ParasPalletName = ParasPalletName;
|
type ParasPalletName = ParasPalletName;
|
||||||
type TrackedParachains = IsInVec<GetTenFirstParachains>;
|
type ParaStoredHeaderDataBuilder = (Parachain1, Parachain2, Parachain3, BigParachain);
|
||||||
type HeadsToKeep = HeadsToKeep;
|
type HeadsToKeep = HeadsToKeep;
|
||||||
type MaxParaHeadSize = frame_support::traits::ConstU32<MAXIMAL_PARACHAIN_HEAD_SIZE>;
|
type MaxParaHeadDataSize = frame_support::traits::ConstU32<MAXIMAL_PARACHAIN_HEAD_DATA_SIZE>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -70,8 +70,12 @@ pub const SESSION_LENGTH: BlockNumber = 4;
|
|||||||
/// Maximal number of GRANDPA authorities at Rialto.
|
/// Maximal number of GRANDPA authorities at Rialto.
|
||||||
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet.
|
/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rialto
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 1024;
|
/// parachains.
|
||||||
|
///
|
||||||
|
/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some
|
||||||
|
/// reserve.
|
||||||
|
pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128;
|
||||||
|
|
||||||
/// Re-export `time_units` to make usage easier.
|
/// Re-export `time_units` to make usage easier.
|
||||||
pub use time_units::*;
|
pub use time_units::*;
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ pub const PARAS_PALLET_NAME: &str = "Paras";
|
|||||||
/// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains.
|
/// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains.
|
||||||
pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa";
|
pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa";
|
||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet.
|
/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rococo
|
||||||
|
/// parachains.
|
||||||
///
|
///
|
||||||
/// Let's assume that the largest header is header that enacts new authorities set with
|
/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some
|
||||||
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
/// reserve.
|
||||||
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128;
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
|
||||||
|
|
||||||
/// Maximal number of GRANDPA authorities at Rococo.
|
/// Maximal number of GRANDPA authorities at Rococo.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ bp-runtime = { path = "../runtime", default-features = false }
|
|||||||
|
|
||||||
# Substrate Based Dependencies
|
# Substrate Based Dependencies
|
||||||
|
|
||||||
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -22,5 +23,6 @@ default = ["std"]
|
|||||||
std = [
|
std = [
|
||||||
"bp-polkadot-core/std",
|
"bp-polkadot-core/std",
|
||||||
"bp-runtime/std",
|
"bp-runtime/std",
|
||||||
|
"frame-support/std",
|
||||||
"sp-api/std",
|
"sp-api/std",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,11 +19,42 @@
|
|||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
pub use bp_polkadot_core::*;
|
pub use bp_polkadot_core::*;
|
||||||
use bp_runtime::decl_bridge_finality_runtime_apis;
|
use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain};
|
||||||
|
use frame_support::weights::Weight;
|
||||||
|
|
||||||
/// Westend Chain
|
/// Westend Chain
|
||||||
pub type Westend = PolkadotLike;
|
pub type Westend = PolkadotLike;
|
||||||
|
|
||||||
|
/// Westmint parachain definition
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Westmint;
|
||||||
|
|
||||||
|
// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend
|
||||||
|
// primitives here.
|
||||||
|
impl Chain for Westmint {
|
||||||
|
type BlockNumber = BlockNumber;
|
||||||
|
type Hash = Hash;
|
||||||
|
type Hasher = Hasher;
|
||||||
|
type Header = Header;
|
||||||
|
|
||||||
|
type AccountId = AccountId;
|
||||||
|
type Balance = Balance;
|
||||||
|
type Index = Nonce;
|
||||||
|
type Signature = Signature;
|
||||||
|
|
||||||
|
fn max_extrinsic_size() -> u32 {
|
||||||
|
Westend::max_extrinsic_size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_extrinsic_weight() -> Weight {
|
||||||
|
Westend::max_extrinsic_weight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parachain for Westmint {
|
||||||
|
const PARACHAIN_ID: u32 = WESTMINT_PARACHAIN_ID;
|
||||||
|
}
|
||||||
|
|
||||||
/// Name of the parachains pallet at the Westend runtime.
|
/// Name of the parachains pallet at the Westend runtime.
|
||||||
pub const PARAS_PALLET_NAME: &str = "Paras";
|
pub const PARAS_PALLET_NAME: &str = "Paras";
|
||||||
|
|
||||||
@@ -39,10 +70,9 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 100_000;
|
|||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet.
|
/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet.
|
||||||
///
|
///
|
||||||
/// Let's assume that the largest header is header that enacts new authorities set with
|
/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some
|
||||||
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
/// reserve.
|
||||||
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128;
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
|
||||||
|
|
||||||
/// 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 = 2000;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
pub use bp_polkadot_core::*;
|
pub use bp_polkadot_core::*;
|
||||||
pub use bp_rococo::{
|
pub use bp_rococo::{
|
||||||
SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME,
|
SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE, PARAS_PALLET_NAME,
|
||||||
};
|
};
|
||||||
use bp_runtime::decl_bridge_finality_runtime_apis;
|
use bp_runtime::decl_bridge_finality_runtime_apis;
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] }
|
||||||
|
impl-trait-for-tuples = "0.2"
|
||||||
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
|
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
# Bridge dependencies
|
# Bridge dependencies
|
||||||
|
|
||||||
|
bp-header-chain = { path = "../header-chain", default-features = false }
|
||||||
bp-polkadot-core = { path = "../polkadot-core", default-features = false }
|
bp-polkadot-core = { path = "../polkadot-core", default-features = false }
|
||||||
bp-runtime = { path = "../runtime", default-features = false }
|
bp-runtime = { path = "../runtime", default-features = false }
|
||||||
|
|
||||||
@@ -19,14 +21,19 @@ bp-runtime = { path = "../runtime", default-features = false }
|
|||||||
|
|
||||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = [
|
std = [
|
||||||
|
"bp-header-chain/std",
|
||||||
"bp-polkadot-core/std",
|
"bp-polkadot-core/std",
|
||||||
"bp-runtime/std",
|
"bp-runtime/std",
|
||||||
"codec/std",
|
"codec/std",
|
||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"scale-info/std",
|
"scale-info/std",
|
||||||
"sp-core/std",
|
"sp-core/std",
|
||||||
|
"sp-runtime/std",
|
||||||
|
"sp-std/std",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -18,15 +18,22 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
pub use bp_header_chain::StoredHeaderData;
|
||||||
|
|
||||||
use bp_polkadot_core::{
|
use bp_polkadot_core::{
|
||||||
parachains::{ParaHash, ParaHead, ParaId},
|
parachains::{ParaHash, ParaHead, ParaId},
|
||||||
BlockNumber as RelayBlockNumber,
|
BlockNumber as RelayBlockNumber,
|
||||||
};
|
};
|
||||||
use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider};
|
use bp_runtime::{
|
||||||
|
BlockNumberOf, Chain, HashOf, HeaderOf, Parachain, StorageDoubleMapKeyProvider,
|
||||||
|
StorageMapKeyProvider,
|
||||||
|
};
|
||||||
use codec::{Decode, Encode, MaxEncodedLen};
|
use codec::{Decode, Encode, MaxEncodedLen};
|
||||||
use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat};
|
use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat};
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use sp_core::storage::StorageKey;
|
use sp_core::storage::StorageKey;
|
||||||
|
use sp_runtime::traits::Header as HeaderT;
|
||||||
|
use sp_std::{marker::PhantomData, prelude::*};
|
||||||
|
|
||||||
/// Best known parachain head hash.
|
/// Best known parachain head hash.
|
||||||
#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
|
#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
|
||||||
@@ -86,5 +93,60 @@ impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider {
|
|||||||
type Key1 = ParaId;
|
type Key1 = ParaId;
|
||||||
type Hasher2 = Blake2_128Concat;
|
type Hasher2 = Blake2_128Concat;
|
||||||
type Key2 = ParaHash;
|
type Key2 = ParaHash;
|
||||||
type Value = ParaHead;
|
type Value = ParaStoredHeaderData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stored data of the parachain head. It is encoded version of the
|
||||||
|
/// `bp_runtime::StoredHeaderData` structure.
|
||||||
|
///
|
||||||
|
/// We do not know exact structure of the parachain head, so we always store encoded version
|
||||||
|
/// of the `bp_runtime::StoredHeaderData`. It is only decoded when we talk about specific parachain.
|
||||||
|
#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)]
|
||||||
|
pub struct ParaStoredHeaderData(pub Vec<u8>);
|
||||||
|
|
||||||
|
impl ParaStoredHeaderData {
|
||||||
|
/// Decode stored parachain head data.
|
||||||
|
pub fn decode_parachain_head_data<C: Chain>(
|
||||||
|
&self,
|
||||||
|
) -> Result<StoredHeaderData<BlockNumberOf<C>, HashOf<C>>, codec::Error> {
|
||||||
|
StoredHeaderData::<BlockNumberOf<C>, HashOf<C>>::decode(&mut &self.0[..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stored parachain head data builder.
|
||||||
|
pub trait ParaStoredHeaderDataBuilder {
|
||||||
|
/// Try to build head data from self.
|
||||||
|
fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper for using single parachain as `ParaStoredHeaderDataBuilder`.
|
||||||
|
pub struct SingleParaStoredHeaderDataBuilder<C: Parachain>(PhantomData<C>);
|
||||||
|
|
||||||
|
impl<C: Parachain> ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder<C> {
|
||||||
|
fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
|
||||||
|
if para_id == ParaId(C::PARACHAIN_ID) {
|
||||||
|
let header = HeaderOf::<C>::decode(&mut ¶_head.0[..]).ok()?;
|
||||||
|
return Some(ParaStoredHeaderData(
|
||||||
|
StoredHeaderData { number: *header.number(), state_root: *header.state_root() }
|
||||||
|
.encode(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tries to build header data from each tuple member, short-circuiting on first successful one.
|
||||||
|
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
|
||||||
|
#[tuple_types_custom_trait_bound(Parachain)]
|
||||||
|
impl ParaStoredHeaderDataBuilder for C {
|
||||||
|
fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option<ParaStoredHeaderData> {
|
||||||
|
for_tuples!( #(
|
||||||
|
let maybe_para_head = SingleParaStoredHeaderDataBuilder::<C>::try_build(para_id, para_head);
|
||||||
|
if let Some(maybe_para_head) = maybe_para_head {
|
||||||
|
return Some(maybe_para_head);
|
||||||
|
}
|
||||||
|
)* );
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,9 +66,7 @@ impl From<u32> for ParaId {
|
|||||||
///
|
///
|
||||||
/// This is an equivalent of the `polkadot_parachain::HeadData`.
|
/// This is an equivalent of the `polkadot_parachain::HeadData`.
|
||||||
///
|
///
|
||||||
/// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. Keep in mind
|
/// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header.
|
||||||
/// that in Polkadot it is twice-encoded (so `header.encode().encode()`). We'll also do it to keep
|
|
||||||
/// it binary-compatible (implies hash-compatibility) with other parachain pallets.
|
|
||||||
#[derive(
|
#[derive(
|
||||||
PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default,
|
PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default,
|
||||||
)]
|
)]
|
||||||
|
|||||||
@@ -111,10 +111,7 @@ pub trait Chain: Send + Sync + 'static {
|
|||||||
+ AsPrimitive<usize>
|
+ AsPrimitive<usize>
|
||||||
+ Default
|
+ Default
|
||||||
+ Saturating
|
+ Saturating
|
||||||
+ MaxEncodedLen
|
+ MaxEncodedLen;
|
||||||
// original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but
|
|
||||||
// `sp_runtime::generic::Era` requires block number -> `u64` conversion.
|
|
||||||
+ Into<u64>;
|
|
||||||
|
|
||||||
/// A type that fulfills the abstract idea of what a Substrate hash is.
|
/// A type that fulfills the abstract idea of what a Substrate hash is.
|
||||||
// Constraits come from the associated Hash type of `sp_runtime::traits::Header`
|
// Constraits come from the associated Hash type of `sp_runtime::traits::Header`
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ use frame_system::RawOrigin;
|
|||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use sp_core::{hash::H256, storage::StorageKey};
|
use sp_core::{hash::H256, storage::StorageKey};
|
||||||
use sp_io::hashing::blake2_256;
|
use sp_io::hashing::blake2_256;
|
||||||
use sp_runtime::traits::{BadOrigin, Header as HeaderT};
|
use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto};
|
||||||
use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec};
|
use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec};
|
||||||
|
|
||||||
pub use chain::{
|
pub use chain::{
|
||||||
@@ -124,6 +124,9 @@ impl<Hash: Copy, Number: Copy> HeaderId<Hash, Number> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Header id used by the chain.
|
||||||
|
pub type HeaderIdOf<C> = HeaderId<HashOf<C>, BlockNumberOf<C>>;
|
||||||
|
|
||||||
/// Generic header id provider.
|
/// Generic header id provider.
|
||||||
pub trait HeaderIdProvider<Header: HeaderT> {
|
pub trait HeaderIdProvider<Header: HeaderT> {
|
||||||
// Get the header id.
|
// Get the header id.
|
||||||
@@ -225,7 +228,9 @@ pub enum TransactionEra<BlockNumber, BlockHash> {
|
|||||||
Mortal(HeaderId<BlockHash, BlockNumber>, u32),
|
Mortal(HeaderId<BlockHash, BlockNumber>, u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BlockNumber: Copy + Into<u64>, BlockHash: Copy> TransactionEra<BlockNumber, BlockHash> {
|
impl<BlockNumber: Copy + UniqueSaturatedInto<u64>, BlockHash: Copy>
|
||||||
|
TransactionEra<BlockNumber, BlockHash>
|
||||||
|
{
|
||||||
/// Prepare transaction era, based on mortality period and current best block number.
|
/// Prepare transaction era, based on mortality period and current best block number.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
best_block_id: HeaderId<BlockHash, BlockNumber>,
|
best_block_id: HeaderId<BlockHash, BlockNumber>,
|
||||||
@@ -253,8 +258,10 @@ impl<BlockNumber: Copy + Into<u64>, BlockHash: Copy> TransactionEra<BlockNumber,
|
|||||||
pub fn frame_era(&self) -> sp_runtime::generic::Era {
|
pub fn frame_era(&self) -> sp_runtime::generic::Era {
|
||||||
match *self {
|
match *self {
|
||||||
TransactionEra::Immortal => sp_runtime::generic::Era::immortal(),
|
TransactionEra::Immortal => sp_runtime::generic::Era::immortal(),
|
||||||
|
// `unique_saturated_into` is fine here - mortality `u64::MAX` is not something we
|
||||||
|
// expect to see on any chain
|
||||||
TransactionEra::Mortal(header_id, period) =>
|
TransactionEra::Mortal(header_id, period) =>
|
||||||
sp_runtime::generic::Era::mortal(period as _, header_id.0.into()),
|
sp_runtime::generic::Era::mortal(period as _, header_id.0.unique_saturated_into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,13 +44,10 @@ pub use crate::{
|
|||||||
transaction_tracker::TransactionTracker,
|
transaction_tracker::TransactionTracker,
|
||||||
};
|
};
|
||||||
pub use bp_runtime::{
|
pub use bp_runtime::{
|
||||||
AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf,
|
AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderIdOf,
|
||||||
IndexOf, SignatureOf, TransactionEra, TransactionEraOf,
|
HeaderOf, IndexOf, SignatureOf, TransactionEra, TransactionEraOf,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Header id used by the chain.
|
|
||||||
pub type HeaderIdOf<C> = relay_utils::HeaderId<HashOf<C>, BlockNumberOf<C>>;
|
|
||||||
|
|
||||||
/// Substrate-over-websocket connection params.
|
/// Substrate-over-websocket connection params.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ConnectionParams {
|
pub struct ConnectionParams {
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
//! Metrics for headers synchronization relay loop.
|
//! Metrics for headers synchronization relay loop.
|
||||||
|
|
||||||
use relay_utils::metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry};
|
use relay_utils::{
|
||||||
|
metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry},
|
||||||
|
UniqueSaturatedInto,
|
||||||
|
};
|
||||||
|
|
||||||
/// Headers sync metrics.
|
/// Headers sync metrics.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -61,13 +64,19 @@ impl SyncLoopMetrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update best block number at source.
|
/// Update best block number at source.
|
||||||
pub fn update_best_block_at_source<Number: Into<u64>>(&self, source_best_number: Number) {
|
pub fn update_best_block_at_source<Number: UniqueSaturatedInto<u64>>(
|
||||||
self.best_source_block_number.set(source_best_number.into());
|
&self,
|
||||||
|
source_best_number: Number,
|
||||||
|
) {
|
||||||
|
self.best_source_block_number.set(source_best_number.unique_saturated_into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update best block number at target.
|
/// Update best block number at target.
|
||||||
pub fn update_best_block_at_target<Number: Into<u64>>(&self, target_best_number: Number) {
|
pub fn update_best_block_at_target<Number: UniqueSaturatedInto<u64>>(
|
||||||
self.best_target_block_number.set(target_best_number.into());
|
&self,
|
||||||
|
target_best_number: Number,
|
||||||
|
) {
|
||||||
|
self.best_target_block_number.set(target_best_number.unique_saturated_into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update using-same-fork flag.
|
/// Update using-same-fork flag.
|
||||||
|
|||||||
@@ -33,12 +33,10 @@ use parachains_relay::{
|
|||||||
};
|
};
|
||||||
use relay_substrate_client::{
|
use relay_substrate_client::{
|
||||||
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf,
|
AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf,
|
||||||
HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionTracker,
|
HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction,
|
||||||
UnsignedTransaction,
|
|
||||||
};
|
};
|
||||||
use relay_utils::{relay_loop::Client as RelayClient, HeaderId};
|
use relay_utils::{relay_loop::Client as RelayClient, HeaderId};
|
||||||
use sp_core::{Bytes, Pair};
|
use sp_core::{Bytes, Pair};
|
||||||
use sp_runtime::traits::Header as HeaderT;
|
|
||||||
|
|
||||||
/// Substrate client as parachain heads source.
|
/// Substrate client as parachain heads source.
|
||||||
pub struct ParachainsTarget<P: SubstrateParachainsPipeline> {
|
pub struct ParachainsTarget<P: SubstrateParachainsPipeline> {
|
||||||
@@ -132,7 +130,7 @@ where
|
|||||||
.map(|para_info| para_info.best_head_hash);
|
.map(|para_info| para_info.best_head_hash);
|
||||||
|
|
||||||
if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) {
|
if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) {
|
||||||
let imported_para_head = self
|
let imported_para_head_number = self
|
||||||
.client
|
.client
|
||||||
.storage_double_map_value::<ImportedParaHeadsKeyProvider>(
|
.storage_double_map_value::<ImportedParaHeadsKeyProvider>(
|
||||||
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
|
P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME,
|
||||||
@@ -142,10 +140,11 @@ where
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.and_then(|maybe_encoded_head| match maybe_encoded_head {
|
.and_then(|maybe_encoded_head| match maybe_encoded_head {
|
||||||
Some(encoded_head) =>
|
Some(encoded_head) => encoded_head
|
||||||
HeaderOf::<P::SourceParachain>::decode(&mut &encoded_head.0[..])
|
.decode_parachain_head_data::<P::SourceParachain>()
|
||||||
.map(Some)
|
.map(|head| head.number)
|
||||||
.map_err(Self::Error::ResponseParseFailed),
|
.map(Some)
|
||||||
|
.map_err(Self::Error::ResponseParseFailed),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
})
|
})
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
@@ -159,9 +158,8 @@ where
|
|||||||
e
|
e
|
||||||
})
|
})
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
if let Some(imported_para_head) = imported_para_head {
|
if let Some(imported_para_head_number) = imported_para_head_number {
|
||||||
metrics
|
metrics.update_best_parachain_block_at_target(para_id, imported_para_head_number);
|
||||||
.update_best_parachain_block_at_target(para_id, *imported_para_head.number());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,10 +65,9 @@ impl MessageLaneLoopMetrics {
|
|||||||
/// Update source client state metrics.
|
/// Update source client state metrics.
|
||||||
pub fn update_source_state<P: MessageLane>(&self, source_client_state: SourceClientState<P>) {
|
pub fn update_source_state<P: MessageLane>(&self, source_client_state: SourceClientState<P>) {
|
||||||
self.source_to_target_finality_metrics
|
self.source_to_target_finality_metrics
|
||||||
.update_best_block_at_source(source_client_state.best_self.0.into());
|
.update_best_block_at_source(source_client_state.best_self.0);
|
||||||
self.target_to_source_finality_metrics.update_best_block_at_target(
|
self.target_to_source_finality_metrics
|
||||||
source_client_state.best_finalized_peer_at_best_self.0.into(),
|
.update_best_block_at_target(source_client_state.best_finalized_peer_at_best_self.0);
|
||||||
);
|
|
||||||
self.target_to_source_finality_metrics.update_using_same_fork(
|
self.target_to_source_finality_metrics.update_using_same_fork(
|
||||||
source_client_state.best_finalized_peer_at_best_self.1 ==
|
source_client_state.best_finalized_peer_at_best_self.1 ==
|
||||||
source_client_state.actual_best_finalized_peer_at_best_self.1,
|
source_client_state.actual_best_finalized_peer_at_best_self.1,
|
||||||
@@ -78,10 +77,9 @@ impl MessageLaneLoopMetrics {
|
|||||||
/// Update target client state metrics.
|
/// Update target client state metrics.
|
||||||
pub fn update_target_state<P: MessageLane>(&self, target_client_state: TargetClientState<P>) {
|
pub fn update_target_state<P: MessageLane>(&self, target_client_state: TargetClientState<P>) {
|
||||||
self.target_to_source_finality_metrics
|
self.target_to_source_finality_metrics
|
||||||
.update_best_block_at_source(target_client_state.best_self.0.into());
|
.update_best_block_at_source(target_client_state.best_self.0);
|
||||||
self.source_to_target_finality_metrics.update_best_block_at_target(
|
self.source_to_target_finality_metrics
|
||||||
target_client_state.best_finalized_peer_at_best_self.0.into(),
|
.update_best_block_at_target(target_client_state.best_finalized_peer_at_best_self.0);
|
||||||
);
|
|
||||||
self.source_to_target_finality_metrics.update_using_same_fork(
|
self.source_to_target_finality_metrics.update_using_same_fork(
|
||||||
target_client_state.best_finalized_peer_at_best_self.1 ==
|
target_client_state.best_finalized_peer_at_best_self.1 ==
|
||||||
target_client_state.actual_best_finalized_peer_at_best_self.1,
|
target_client_state.actual_best_finalized_peer_at_best_self.1,
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
// 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 bp_polkadot_core::parachains::ParaId;
|
use bp_polkadot_core::parachains::ParaId;
|
||||||
use relay_utils::metrics::{
|
use relay_utils::{
|
||||||
metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64,
|
metrics::{metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64},
|
||||||
|
UniqueSaturatedInto,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parachains sync metrics.
|
/// Parachains sync metrics.
|
||||||
@@ -50,12 +51,12 @@ impl ParachainsLoopMetrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update best block number at source.
|
/// Update best block number at source.
|
||||||
pub fn update_best_parachain_block_at_source<Number: Into<u64>>(
|
pub fn update_best_parachain_block_at_source<Number: UniqueSaturatedInto<u64>>(
|
||||||
&self,
|
&self,
|
||||||
parachain: ParaId,
|
parachain: ParaId,
|
||||||
block_number: Number,
|
block_number: Number,
|
||||||
) {
|
) {
|
||||||
let block_number = block_number.into();
|
let block_number = block_number.unique_saturated_into();
|
||||||
let label = parachain_label(¶chain);
|
let label = parachain_label(¶chain);
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "bridge-metrics",
|
target: "bridge-metrics",
|
||||||
@@ -67,12 +68,12 @@ impl ParachainsLoopMetrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update best block number at target.
|
/// Update best block number at target.
|
||||||
pub fn update_best_parachain_block_at_target<Number: Into<u64>>(
|
pub fn update_best_parachain_block_at_target<Number: UniqueSaturatedInto<u64>>(
|
||||||
&self,
|
&self,
|
||||||
parachain: ParaId,
|
parachain: ParaId,
|
||||||
block_number: Number,
|
block_number: Number,
|
||||||
) {
|
) {
|
||||||
let block_number = block_number.into();
|
let block_number = block_number.unique_saturated_into();
|
||||||
let label = parachain_label(¶chain);
|
let label = parachain_label(¶chain);
|
||||||
log::trace!(
|
log::trace!(
|
||||||
target: "bridge-metrics",
|
target: "bridge-metrics",
|
||||||
|
|||||||
@@ -29,4 +29,5 @@ bp-runtime = { path = "../../primitives/runtime" }
|
|||||||
|
|
||||||
# Substrate dependencies
|
# Substrate dependencies
|
||||||
|
|
||||||
|
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
pub use bp_runtime::HeaderId;
|
pub use bp_runtime::HeaderId;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use relay_loop::{relay_loop, relay_metrics};
|
pub use relay_loop::{relay_loop, relay_metrics};
|
||||||
|
pub use sp_runtime::traits::UniqueSaturatedInto;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use backoff::{backoff::Backoff, ExponentialBackoff};
|
use backoff::{backoff::Backoff, ExponentialBackoff};
|
||||||
@@ -51,7 +52,7 @@ pub mod relay_loop;
|
|||||||
pub trait BlockNumberBase:
|
pub trait BlockNumberBase:
|
||||||
'static
|
'static
|
||||||
+ From<u32>
|
+ From<u32>
|
||||||
+ Into<u64>
|
+ UniqueSaturatedInto<u64>
|
||||||
+ Ord
|
+ Ord
|
||||||
+ Clone
|
+ Clone
|
||||||
+ Copy
|
+ Copy
|
||||||
@@ -73,7 +74,7 @@ pub trait BlockNumberBase:
|
|||||||
impl<T> BlockNumberBase for T where
|
impl<T> BlockNumberBase for T where
|
||||||
T: 'static
|
T: 'static
|
||||||
+ From<u32>
|
+ From<u32>
|
||||||
+ Into<u64>
|
+ UniqueSaturatedInto<u64>
|
||||||
+ Ord
|
+ Ord
|
||||||
+ Clone
|
+ Clone
|
||||||
+ Copy
|
+ Copy
|
||||||
|
|||||||
Reference in New Issue
Block a user