mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
only store header state root (pallet-bridge-grandpa) (#1699)
This commit is contained in:
committed by
Bastian Köcher
parent
b94bd8d46b
commit
7014046485
@@ -413,13 +413,8 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
/// Maximal size of SCALE-encoded Rialto header.
|
|
||||||
pub const MaxRialtoHeaderSize: u32 = bp_rialto::MAX_HEADER_SIZE;
|
|
||||||
|
|
||||||
/// Maximal number of authorities at Westend.
|
/// Maximal number of authorities at Westend.
|
||||||
pub const MaxAuthoritiesAtWestend: u32 = bp_westend::MAX_AUTHORITIES_COUNT;
|
pub const MaxAuthoritiesAtWestend: u32 = bp_westend::MAX_AUTHORITIES_COUNT;
|
||||||
/// Maximal size of SCALE-encoded Westend header.
|
|
||||||
pub const MaxWestendHeaderSize: u32 = bp_westend::MAX_HEADER_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RialtoGrandpaInstance = ();
|
pub type RialtoGrandpaInstance = ();
|
||||||
@@ -432,7 +427,6 @@ impl pallet_bridge_grandpa::Config for Runtime {
|
|||||||
type MaxRequests = ConstU32<50>;
|
type MaxRequests = ConstU32<50>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = MaxAuthoritiesAtRialto;
|
type MaxBridgedAuthorities = MaxAuthoritiesAtRialto;
|
||||||
type MaxBridgedHeaderSize = MaxRialtoHeaderSize;
|
|
||||||
|
|
||||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||||
}
|
}
|
||||||
@@ -443,7 +437,6 @@ impl pallet_bridge_grandpa::Config<WestendGrandpaInstance> for Runtime {
|
|||||||
type MaxRequests = ConstU32<50>;
|
type MaxRequests = ConstU32<50>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = MaxAuthoritiesAtWestend;
|
type MaxBridgedAuthorities = MaxAuthoritiesAtWestend;
|
||||||
type MaxBridgedHeaderSize = MaxWestendHeaderSize;
|
|
||||||
|
|
||||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||||
}
|
}
|
||||||
@@ -871,13 +864,13 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
impl bp_rialto::RialtoFinalityApi<Block> for Runtime {
|
impl bp_rialto::RialtoFinalityApi<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>> {
|
||||||
BridgeRialtoGrandpa::best_finalized().map(|header| header.id())
|
BridgeRialtoGrandpa::best_finalized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl bp_westend::WestendFinalityApi<Block> for Runtime {
|
impl bp_westend::WestendFinalityApi<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>> {
|
||||||
BridgeWestendGrandpa::best_finalized().map(|header| header.id())
|
BridgeWestendGrandpa::best_finalized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ use sp_version::NativeVersion;
|
|||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
// A few exports that help ease life for downstream crates.
|
// A few exports that help ease life for downstream crates.
|
||||||
use bp_runtime::{HeaderId, HeaderIdProvider};
|
use bp_runtime::HeaderId;
|
||||||
pub use frame_support::{
|
pub use frame_support::{
|
||||||
construct_runtime,
|
construct_runtime,
|
||||||
dispatch::DispatchClass,
|
dispatch::DispatchClass,
|
||||||
@@ -525,8 +525,6 @@ parameter_types! {
|
|||||||
|
|
||||||
/// Maximal number of authorities at Millau.
|
/// Maximal number of authorities at Millau.
|
||||||
pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT;
|
pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT;
|
||||||
/// Maximal size of SCALE-encoded Millau header.
|
|
||||||
pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MillauGrandpaInstance = ();
|
pub type MillauGrandpaInstance = ();
|
||||||
@@ -539,7 +537,6 @@ impl pallet_bridge_grandpa::Config for Runtime {
|
|||||||
type MaxRequests = ConstU32<50>;
|
type MaxRequests = ConstU32<50>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
||||||
type MaxBridgedHeaderSize = MaxMillauHeaderSize;
|
|
||||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +725,7 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> Option<HeaderId<bp_millau::Hash, bp_millau::BlockNumber>> {
|
fn best_finalized() -> Option<HeaderId<bp_millau::Hash, bp_millau::BlockNumber>> {
|
||||||
BridgeMillauGrandpa::best_finalized().map(|header| header.id())
|
BridgeMillauGrandpa::best_finalized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub mod parachains;
|
|||||||
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_runtime::HeaderId;
|
||||||
use pallet_grandpa::{
|
use pallet_grandpa::{
|
||||||
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
|
||||||
};
|
};
|
||||||
@@ -410,8 +410,6 @@ parameter_types! {
|
|||||||
|
|
||||||
/// Maximal number of authorities at Millau.
|
/// Maximal number of authorities at Millau.
|
||||||
pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT;
|
pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT;
|
||||||
/// Maximal size of SCALE-encoded Millau header.
|
|
||||||
pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MillauGrandpaInstance = ();
|
pub type MillauGrandpaInstance = ();
|
||||||
@@ -424,7 +422,6 @@ impl pallet_bridge_grandpa::Config for Runtime {
|
|||||||
type MaxRequests = ConstU32<50>;
|
type MaxRequests = ConstU32<50>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
||||||
type MaxBridgedHeaderSize = MaxMillauHeaderSize;
|
|
||||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,7 +718,7 @@ impl_runtime_apis! {
|
|||||||
|
|
||||||
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
impl bp_millau::MillauFinalityApi<Block> for Runtime {
|
||||||
fn best_finalized() -> Option<HeaderId<bp_millau::Hash, bp_millau::BlockNumber>> {
|
fn best_finalized() -> Option<HeaderId<bp_millau::Hash, bp_millau::BlockNumber>> {
|
||||||
BridgeMillauGrandpa::best_finalized().map(|header| header.id())
|
BridgeMillauGrandpa::best_finalized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -705,7 +705,6 @@ mod tests {
|
|||||||
use crate::messages_generation::{
|
use crate::messages_generation::{
|
||||||
encode_all_messages, encode_lane_data, prepare_messages_storage_proof,
|
encode_all_messages, encode_lane_data, prepare_messages_storage_proof,
|
||||||
};
|
};
|
||||||
use bp_runtime::HeaderOf;
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
@@ -881,17 +880,17 @@ mod tests {
|
|||||||
struct BridgedHeaderChain;
|
struct BridgedHeaderChain;
|
||||||
|
|
||||||
impl HeaderChain<BridgedUnderlyingChain> for BridgedHeaderChain {
|
impl HeaderChain<BridgedUnderlyingChain> for BridgedHeaderChain {
|
||||||
fn finalized_header(
|
fn finalized_header_state_root(
|
||||||
_hash: HashOf<BridgedChain>,
|
_hash: HashOf<BridgedChain>,
|
||||||
) -> Option<HeaderOf<BridgedUnderlyingChain>> {
|
) -> Option<HashOf<BridgedChain>> {
|
||||||
TEST_BRIDGED_HEADER.with(|h| h.borrow().clone())
|
TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()).map(|h| *h.state_root())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ThisHeaderChain;
|
struct ThisHeaderChain;
|
||||||
|
|
||||||
impl HeaderChain<ThisUnderlyingChain> for ThisHeaderChain {
|
impl HeaderChain<ThisUnderlyingChain> for ThisHeaderChain {
|
||||||
fn finalized_header(_hash: HashOf<ThisChain>) -> Option<HeaderOf<ThisUnderlyingChain>> {
|
fn finalized_header_state_root(_hash: HashOf<ThisChain>) -> Option<HashOf<ThisChain>> {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ impl<
|
|||||||
|
|
||||||
let best_finalized = crate::BestFinalized::<T, I>::get();
|
let best_finalized = crate::BestFinalized::<T, I>::get();
|
||||||
let best_finalized_number = match best_finalized {
|
let best_finalized_number = match best_finalized {
|
||||||
Some((best_finalized_number, _)) => best_finalized_number,
|
Some(best_finalized_id) => best_finalized_id.number(),
|
||||||
None => return InvalidTransaction::Call.into(),
|
None => return InvalidTransaction::Call.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ mod tests {
|
|||||||
mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime},
|
mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime},
|
||||||
BestFinalized,
|
BestFinalized,
|
||||||
};
|
};
|
||||||
|
use bp_runtime::HeaderId;
|
||||||
use bp_test_utils::make_default_justification;
|
use bp_test_utils::make_default_justification;
|
||||||
|
|
||||||
fn validate_block_submit(num: TestNumber) -> bool {
|
fn validate_block_submit(num: TestNumber) -> bool {
|
||||||
@@ -81,7 +82,7 @@ mod tests {
|
|||||||
|
|
||||||
fn sync_to_header_10() {
|
fn sync_to_header_10() {
|
||||||
let header10_hash = sp_core::H256::default();
|
let header10_hash = sp_core::H256::default();
|
||||||
BestFinalized::<TestRuntime, ()>::put((10, header10_hash));
|
BestFinalized::<TestRuntime, ()>::put(HeaderId(10, header10_hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -38,10 +38,11 @@
|
|||||||
|
|
||||||
use storage_types::StoredAuthoritySet;
|
use storage_types::StoredAuthoritySet;
|
||||||
|
|
||||||
use bp_header_chain::{justification::GrandpaJustification, HeaderChain, InitializationData};
|
use bp_header_chain::{
|
||||||
use bp_runtime::{
|
justification::GrandpaJustification, HeaderChain, InitializationData, StoredHeaderData,
|
||||||
BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule,
|
StoredHeaderDataBuilder,
|
||||||
};
|
};
|
||||||
|
use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule};
|
||||||
use finality_grandpa::voter_set::VoterSet;
|
use finality_grandpa::voter_set::VoterSet;
|
||||||
use frame_support::{ensure, fail};
|
use frame_support::{ensure, fail};
|
||||||
use frame_system::ensure_signed;
|
use frame_system::ensure_signed;
|
||||||
@@ -73,13 +74,15 @@ pub type BridgedChain<T, I> = <T as Config<I>>::BridgedChain;
|
|||||||
pub type BridgedBlockNumber<T, I> = BlockNumberOf<<T as Config<I>>::BridgedChain>;
|
pub type BridgedBlockNumber<T, I> = BlockNumberOf<<T as Config<I>>::BridgedChain>;
|
||||||
/// Block hash of the bridged chain.
|
/// Block hash of the bridged chain.
|
||||||
pub type BridgedBlockHash<T, I> = HashOf<<T as Config<I>>::BridgedChain>;
|
pub type BridgedBlockHash<T, I> = HashOf<<T as Config<I>>::BridgedChain>;
|
||||||
|
/// Block id of the bridged chain.
|
||||||
|
pub type BridgedBlockId<T, I> = HeaderId<BridgedBlockHash<T, I>, BridgedBlockNumber<T, I>>;
|
||||||
/// Hasher of the bridged chain.
|
/// Hasher of the bridged chain.
|
||||||
pub type BridgedBlockHasher<T, I> = HasherOf<<T as Config<I>>::BridgedChain>;
|
pub type BridgedBlockHasher<T, I> = HasherOf<<T as Config<I>>::BridgedChain>;
|
||||||
/// Header of the bridged chain.
|
/// Header of the bridged chain.
|
||||||
pub type BridgedHeader<T, I> = HeaderOf<<T as Config<I>>::BridgedChain>;
|
pub type BridgedHeader<T, I> = HeaderOf<<T as Config<I>>::BridgedChain>;
|
||||||
/// Stored header of the bridged chain.
|
/// Header data of the bridged chain that is stored at this chain by this pallet.
|
||||||
pub type StoredBridgedHeader<T, I> =
|
pub type BridgedStoredHeaderData<T, I> =
|
||||||
BoundedStorageValue<<T as Config<I>>::MaxBridgedHeaderSize, BridgedHeader<T, I>>;
|
StoredHeaderData<BridgedBlockNumber<T, I>, BridgedBlockHash<T, I>>;
|
||||||
|
|
||||||
#[frame_support::pallet]
|
#[frame_support::pallet]
|
||||||
pub mod pallet {
|
pub mod pallet {
|
||||||
@@ -115,15 +118,6 @@ pub mod pallet {
|
|||||||
/// Max number of authorities at the bridged chain.
|
/// Max number of authorities at the bridged chain.
|
||||||
#[pallet::constant]
|
#[pallet::constant]
|
||||||
type MaxBridgedAuthorities: Get<u32>;
|
type MaxBridgedAuthorities: Get<u32>;
|
||||||
/// Maximal size (in bytes) of the SCALE-encoded bridged chain header.
|
|
||||||
///
|
|
||||||
/// This constant must be selected with care. The pallet requires mandatory headers to be
|
|
||||||
/// submitted to be able to proceed. Mandatory headers contain public keys of all GRANDPA
|
|
||||||
/// authorities. E.g. for 1024 authorities, the size of encoded keys will be at least 32 KB.
|
|
||||||
/// The same header may also contain other digest items as well, so some reserve here
|
|
||||||
/// is required.
|
|
||||||
#[pallet::constant]
|
|
||||||
type MaxBridgedHeaderSize: Get<u32>;
|
|
||||||
|
|
||||||
/// Weights gathered through benchmarking.
|
/// Weights gathered through benchmarking.
|
||||||
type WeightInfo: WeightInfo;
|
type WeightInfo: WeightInfo;
|
||||||
@@ -178,11 +172,8 @@ pub mod pallet {
|
|||||||
finality_target
|
finality_target
|
||||||
);
|
);
|
||||||
|
|
||||||
let best_finalized = BestFinalized::<T, I>::get();
|
let best_finalized_number = match BestFinalized::<T, I>::get() {
|
||||||
let best_finalized =
|
Some(best_finalized_id) => best_finalized_id.number(),
|
||||||
best_finalized.and_then(|(_, hash)| ImportedHeaders::<T, I>::get(hash));
|
|
||||||
let best_finalized = match best_finalized {
|
|
||||||
Some(best_finalized) => best_finalized,
|
|
||||||
None => {
|
None => {
|
||||||
log::error!(
|
log::error!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
@@ -196,7 +187,7 @@ pub mod pallet {
|
|||||||
// We do a quick check here to ensure that our header chain is making progress and isn't
|
// We do a quick check here to ensure that our header chain is making progress and isn't
|
||||||
// "travelling back in time" (which could be indicative of something bad, e.g a
|
// "travelling back in time" (which could be indicative of something bad, e.g a
|
||||||
// hard-fork).
|
// hard-fork).
|
||||||
ensure!(best_finalized.number() < number, <Error<T, I>>::OldHeader);
|
ensure!(best_finalized_number < *number, <Error<T, I>>::OldHeader);
|
||||||
|
|
||||||
let authority_set = <CurrentAuthoritySet<T, I>>::get();
|
let authority_set = <CurrentAuthoritySet<T, I>>::get();
|
||||||
let set_id = authority_set.set_id;
|
let set_id = authority_set.set_id;
|
||||||
@@ -204,20 +195,8 @@ pub mod pallet {
|
|||||||
|
|
||||||
let is_authorities_change_enacted =
|
let is_authorities_change_enacted =
|
||||||
try_enact_authority_change::<T, I>(&finality_target, set_id)?;
|
try_enact_authority_change::<T, I>(&finality_target, set_id)?;
|
||||||
let finality_target = StoredBridgedHeader::<T, I>::try_from_inner(*finality_target)
|
|
||||||
.map_err(|e| {
|
|
||||||
log::error!(
|
|
||||||
target: LOG_TARGET,
|
|
||||||
"Size of header {:?} ({}) is larger that the configured value {}",
|
|
||||||
hash,
|
|
||||||
e.value_size,
|
|
||||||
e.maximal_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
Error::<T, I>::TooLargeHeader
|
|
||||||
})?;
|
|
||||||
<RequestCount<T, I>>::mutate(|count| *count += 1);
|
<RequestCount<T, I>>::mutate(|count| *count += 1);
|
||||||
insert_header::<T, I>(finality_target, hash);
|
insert_header::<T, I>(*finality_target, hash);
|
||||||
log::info!(
|
log::info!(
|
||||||
target: LOG_TARGET,
|
target: LOG_TARGET,
|
||||||
"Successfully imported finalized header with hash {:?}!",
|
"Successfully imported finalized header with hash {:?}!",
|
||||||
@@ -302,8 +281,9 @@ pub mod pallet {
|
|||||||
|
|
||||||
/// Hash of the best finalized header.
|
/// Hash of the best finalized header.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
|
#[pallet::getter(fn best_finalized)]
|
||||||
pub type BestFinalized<T: Config<I>, I: 'static = ()> =
|
pub type BestFinalized<T: Config<I>, I: 'static = ()> =
|
||||||
StorageValue<_, (BridgedBlockNumber<T, I>, BridgedBlockHash<T, I>), OptionQuery>;
|
StorageValue<_, BridgedBlockId<T, I>, OptionQuery>;
|
||||||
|
|
||||||
/// A ring buffer of imported hashes. Ordered by the insertion time.
|
/// A ring buffer of imported hashes. Ordered by the insertion time.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
@@ -315,10 +295,10 @@ pub mod pallet {
|
|||||||
pub(super) type ImportedHashesPointer<T: Config<I>, I: 'static = ()> =
|
pub(super) type ImportedHashesPointer<T: Config<I>, I: 'static = ()> =
|
||||||
StorageValue<_, u32, ValueQuery>;
|
StorageValue<_, u32, ValueQuery>;
|
||||||
|
|
||||||
/// Headers which have been imported into the pallet.
|
/// Relevant fields of imported headers.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
pub type ImportedHeaders<T: Config<I>, I: 'static = ()> =
|
pub type ImportedHeaders<T: Config<I>, I: 'static = ()> =
|
||||||
StorageMap<_, Identity, BridgedBlockHash<T, I>, StoredBridgedHeader<T, I>>;
|
StorageMap<_, Identity, BridgedBlockHash<T, I>, BridgedStoredHeaderData<T, I>>;
|
||||||
|
|
||||||
/// The current GRANDPA Authority set.
|
/// The current GRANDPA Authority set.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
@@ -394,8 +374,6 @@ pub mod pallet {
|
|||||||
AlreadyInitialized,
|
AlreadyInitialized,
|
||||||
/// Too many authorities in the set.
|
/// Too many authorities in the set.
|
||||||
TooManyAuthoritiesInSet,
|
TooManyAuthoritiesInSet,
|
||||||
/// Too large header.
|
|
||||||
TooLargeHeader,
|
|
||||||
/// Error generated by the `OwnedBridgeModule` trait.
|
/// Error generated by the `OwnedBridgeModule` trait.
|
||||||
BridgeModule(bp_runtime::OwnedBridgeModuleError),
|
BridgeModule(bp_runtime::OwnedBridgeModuleError),
|
||||||
}
|
}
|
||||||
@@ -489,13 +467,13 @@ pub mod pallet {
|
|||||||
/// Note this function solely takes care of updating the storage and pruning old entries,
|
/// Note this function solely takes care of updating the storage and pruning old entries,
|
||||||
/// but does not verify the validity of such import.
|
/// but does not verify the validity of such import.
|
||||||
pub(crate) fn insert_header<T: Config<I>, I: 'static>(
|
pub(crate) fn insert_header<T: Config<I>, I: 'static>(
|
||||||
header: StoredBridgedHeader<T, I>,
|
header: BridgedHeader<T, I>,
|
||||||
hash: BridgedBlockHash<T, I>,
|
hash: BridgedBlockHash<T, I>,
|
||||||
) {
|
) {
|
||||||
let index = <ImportedHashesPointer<T, I>>::get();
|
let index = <ImportedHashesPointer<T, I>>::get();
|
||||||
let pruning = <ImportedHashes<T, I>>::try_get(index);
|
let pruning = <ImportedHashes<T, I>>::try_get(index);
|
||||||
<BestFinalized<T, I>>::put((*header.number(), hash));
|
<BestFinalized<T, I>>::put(HeaderId(*header.number(), hash));
|
||||||
<ImportedHeaders<T, I>>::insert(hash, header);
|
<ImportedHeaders<T, I>>::insert(hash, header.build());
|
||||||
<ImportedHashes<T, I>>::insert(index, hash);
|
<ImportedHashes<T, I>>::insert(index, hash);
|
||||||
|
|
||||||
// Update ring buffer pointer and remove old header.
|
// Update ring buffer pointer and remove old header.
|
||||||
@@ -526,21 +504,10 @@ pub mod pallet {
|
|||||||
Error::TooManyAuthoritiesInSet
|
Error::TooManyAuthoritiesInSet
|
||||||
})?;
|
})?;
|
||||||
let initial_hash = header.hash();
|
let initial_hash = header.hash();
|
||||||
let header = StoredBridgedHeader::<T, I>::try_from_inner(*header).map_err(|e| {
|
|
||||||
log::error!(
|
|
||||||
target: LOG_TARGET,
|
|
||||||
"Failed to initialize bridge. Size of header {:?} ({}) is larger that the configured value {}",
|
|
||||||
initial_hash,
|
|
||||||
e.value_size,
|
|
||||||
e.maximal_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
Error::<T, I>::TooLargeHeader
|
|
||||||
})?;
|
|
||||||
|
|
||||||
<InitialHash<T, I>>::put(initial_hash);
|
<InitialHash<T, I>>::put(initial_hash);
|
||||||
<ImportedHashesPointer<T, I>>::put(0);
|
<ImportedHashesPointer<T, I>>::put(0);
|
||||||
insert_header::<T, I>(header, initial_hash);
|
insert_header::<T, I>(*header, initial_hash);
|
||||||
|
|
||||||
<CurrentAuthoritySet<T, I>>::put(authority_set);
|
<CurrentAuthoritySet<T, I>>::put(authority_set);
|
||||||
|
|
||||||
@@ -568,34 +535,19 @@ pub mod pallet {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
);
|
);
|
||||||
let hash = header.hash();
|
let hash = header.hash();
|
||||||
insert_header::<T, I>(
|
insert_header::<T, I>(header, hash);
|
||||||
StoredBridgedHeader::<T, I>::try_from_inner(header)
|
|
||||||
.expect("only used from benchmarks; benchmarks are correct; qed"),
|
|
||||||
hash,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
|
||||||
/// Get the best finalized header the pallet knows of.
|
|
||||||
pub fn best_finalized() -> Option<BridgedHeader<T, I>> {
|
|
||||||
let (_, hash) = <BestFinalized<T, I>>::get()?;
|
|
||||||
<ImportedHeaders<T, I>>::get(hash).map(|h| h.into_inner())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a particular header is known to the bridge pallet.
|
|
||||||
pub fn is_known_header(hash: BridgedBlockHash<T, I>) -> bool {
|
|
||||||
<ImportedHeaders<T, I>>::contains_key(hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bridge GRANDPA pallet as header chain.
|
/// Bridge GRANDPA pallet as header chain.
|
||||||
pub type GrandpaChainHeaders<T, I> = Pallet<T, I>;
|
pub type GrandpaChainHeaders<T, I> = Pallet<T, I>;
|
||||||
|
|
||||||
impl<T: Config<I>, I: 'static> HeaderChain<BridgedChain<T, I>> for GrandpaChainHeaders<T, I> {
|
impl<T: Config<I>, I: 'static> HeaderChain<BridgedChain<T, I>> for GrandpaChainHeaders<T, I> {
|
||||||
fn finalized_header(hash: HashOf<BridgedChain<T, I>>) -> Option<HeaderOf<BridgedChain<T, I>>> {
|
fn finalized_header_state_root(
|
||||||
ImportedHeaders::<T, I>::get(hash).map(|h| h.into_inner())
|
header_hash: HashOf<BridgedChain<T, I>>,
|
||||||
|
) -> Option<HashOf<BridgedChain<T, I>>> {
|
||||||
|
ImportedHeaders::<T, I>::get(header_hash).map(|h| h.state_root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,7 +605,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::mock::{
|
use crate::mock::{
|
||||||
run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime,
|
run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime,
|
||||||
MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE,
|
MAX_BRIDGED_AUTHORITIES,
|
||||||
};
|
};
|
||||||
use bp_runtime::BasicOperatingMode;
|
use bp_runtime::BasicOperatingMode;
|
||||||
use bp_test_utils::{
|
use bp_test_utils::{
|
||||||
@@ -742,10 +694,6 @@ mod tests {
|
|||||||
Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] }
|
Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn large_digest() -> Digest {
|
|
||||||
Digest { logs: vec![DigestItem::Other(vec![42; MAX_HEADER_SIZE as _])] }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn init_root_or_owner_origin_can_initialize_pallet() {
|
fn init_root_or_owner_origin_can_initialize_pallet() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
@@ -808,25 +756,6 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn init_fails_if_header_is_too_large() {
|
|
||||||
run_test(|| {
|
|
||||||
let mut genesis = test_header(0);
|
|
||||||
genesis.digest = large_digest();
|
|
||||||
let init_data = InitializationData {
|
|
||||||
header: Box::new(genesis),
|
|
||||||
authority_list: authority_list(),
|
|
||||||
set_id: 1,
|
|
||||||
operating_mode: BasicOperatingMode::Normal,
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_noop!(
|
|
||||||
Pallet::<TestRuntime>::initialize(RuntimeOrigin::root(), init_data),
|
|
||||||
Error::<TestRuntime>::TooLargeHeader,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pallet_rejects_transactions_if_halted() {
|
fn pallet_rejects_transactions_if_halted() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
@@ -1073,31 +1002,6 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn importing_header_rejects_header_if_it_is_too_large() {
|
|
||||||
run_test(|| {
|
|
||||||
initialize_substrate_bridge();
|
|
||||||
|
|
||||||
// Need to update the header digest to indicate that our header signals an authority set
|
|
||||||
// change. However, the change doesn't happen until the next block.
|
|
||||||
let mut header = test_header(2);
|
|
||||||
header.digest = large_digest();
|
|
||||||
|
|
||||||
// Create a valid justification for the header
|
|
||||||
let justification = make_default_justification(&header);
|
|
||||||
|
|
||||||
// Should not be allowed to import this header
|
|
||||||
assert_err!(
|
|
||||||
Pallet::<TestRuntime>::submit_finality_proof(
|
|
||||||
RuntimeOrigin::signed(1),
|
|
||||||
Box::new(header),
|
|
||||||
justification
|
|
||||||
),
|
|
||||||
<Error<TestRuntime>>::TooLargeHeader
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() {
|
fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
@@ -1121,11 +1025,8 @@ mod tests {
|
|||||||
header.set_state_root(state_root);
|
header.set_state_root(state_root);
|
||||||
|
|
||||||
let hash = header.hash();
|
let hash = header.hash();
|
||||||
<BestFinalized<TestRuntime>>::put((2, hash));
|
<BestFinalized<TestRuntime>>::put(HeaderId(2, hash));
|
||||||
<ImportedHeaders<TestRuntime>>::insert(
|
<ImportedHeaders<TestRuntime>>::insert(hash, header.build());
|
||||||
hash,
|
|
||||||
StoredBridgedHeader::<TestRuntime, ()>::try_from_inner(header).unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_ok!(
|
assert_ok!(
|
||||||
Pallet::<TestRuntime>::parse_finalized_storage_proof(hash, storage_proof, |_| (),),
|
Pallet::<TestRuntime>::parse_finalized_storage_proof(hash, storage_proof, |_| (),),
|
||||||
@@ -1220,7 +1121,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().unwrap();
|
let first_header_hash = Pallet::<TestRuntime>::best_finalized().unwrap().hash();
|
||||||
next_block();
|
next_block();
|
||||||
|
|
||||||
assert_ok!(submit_finality_proof(2));
|
assert_ok!(submit_finality_proof(2));
|
||||||
@@ -1235,8 +1136,8 @@ mod tests {
|
|||||||
assert_ok!(submit_finality_proof(6));
|
assert_ok!(submit_finality_proof(6));
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
!Pallet::<TestRuntime>::is_known_header(first_header.hash()),
|
!ImportedHeaders::<TestRuntime, ()>::contains_key(first_header_hash),
|
||||||
"First header should be pruned."
|
"First header should be pruned.",
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ type Block = frame_system::mocking::MockBlock<TestRuntime>;
|
|||||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
|
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
|
||||||
|
|
||||||
pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048;
|
pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048;
|
||||||
pub const MAX_HEADER_SIZE: u32 = 65536;
|
|
||||||
|
|
||||||
use crate as grandpa;
|
use crate as grandpa;
|
||||||
|
|
||||||
@@ -94,7 +93,6 @@ impl grandpa::Config for TestRuntime {
|
|||||||
type MaxRequests = MaxRequests;
|
type MaxRequests = MaxRequests;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<MAX_BRIDGED_AUTHORITIES>;
|
type MaxBridgedAuthorities = frame_support::traits::ConstU32<MAX_BRIDGED_AUTHORITIES>;
|
||||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<MAX_HEADER_SIZE>;
|
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ pub mod pallet {
|
|||||||
>::get(relay_block_hash)
|
>::get(relay_block_hash)
|
||||||
.ok_or(Error::<T, I>::UnknownRelayChainBlock)?;
|
.ok_or(Error::<T, I>::UnknownRelayChainBlock)?;
|
||||||
ensure!(
|
ensure!(
|
||||||
*relay_block.number() == relay_block_number,
|
relay_block.number == relay_block_number,
|
||||||
Error::<T, I>::InvalidRelayChainBlockNumber,
|
Error::<T, I>::InvalidRelayChainBlockNumber,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -604,9 +604,10 @@ pub struct ParachainHeaders<T, I, C>(PhantomData<(T, I, C)>);
|
|||||||
impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
|
impl<T: Config<I>, I: 'static, C: Parachain<Hash = ParaHash>> HeaderChain<C>
|
||||||
for ParachainHeaders<T, I, C>
|
for ParachainHeaders<T, I, C>
|
||||||
{
|
{
|
||||||
fn finalized_header(hash: HashOf<C>) -> Option<HeaderOf<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| Decode::decode(&mut &head.0[..]).ok())
|
.and_then(|head| HeaderOf::<C>::decode(&mut &head.0[..]).ok())
|
||||||
|
.map(|h| *h.state_root())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance1> for TestRun
|
|||||||
type MaxRequests = ConstU32<2>;
|
type MaxRequests = ConstU32<2>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
||||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>;
|
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +108,6 @@ impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance2> for TestRun
|
|||||||
type MaxRequests = ConstU32<2>;
|
type MaxRequests = ConstU32<2>;
|
||||||
type HeadersToKeep = HeadersToKeep;
|
type HeadersToKeep = HeadersToKeep;
|
||||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
||||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>;
|
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,9 +81,6 @@ pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES;
|
|||||||
/// Maximal number of GRANDPA authorities at Millau.
|
/// Maximal number of GRANDPA authorities at Millau.
|
||||||
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
||||||
|
|
||||||
/// Maximal SCALE-encoded header size (in bytes) at Millau.
|
|
||||||
pub const MAX_HEADER_SIZE: u32 = 1024;
|
|
||||||
|
|
||||||
/// Re-export `time_units` to make usage easier.
|
/// Re-export `time_units` to make usage easier.
|
||||||
pub use time_units::*;
|
pub use time_units::*;
|
||||||
|
|
||||||
|
|||||||
@@ -70,11 +70,8 @@ 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 header size (in bytes) at Rialto.
|
|
||||||
pub const MAX_HEADER_SIZE: u32 = 1024;
|
|
||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet.
|
/// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet.
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE;
|
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 1024;
|
||||||
|
|
||||||
/// 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,15 +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 header size (in bytes) at Rococo.
|
/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet.
|
||||||
///
|
///
|
||||||
/// Let's assume that the largest header is header that enacts new authorities set with
|
/// Let's assume that the largest header is header that enacts new authorities set with
|
||||||
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
||||||
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
||||||
pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet.
|
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE;
|
|
||||||
|
|
||||||
/// Maximal number of GRANDPA authorities at Rococo.
|
/// Maximal number of GRANDPA authorities at Rococo.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -37,15 +37,12 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains
|
|||||||
/// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration.
|
/// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration.
|
||||||
pub const MAX_AUTHORITIES_COUNT: u32 = 100_000;
|
pub const MAX_AUTHORITIES_COUNT: u32 = 100_000;
|
||||||
|
|
||||||
/// Maximal SCALE-encoded header size (in bytes) at Westend.
|
/// 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
|
/// Let's assume that the largest header is header that enacts new authorities set with
|
||||||
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have
|
||||||
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
||||||
pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
||||||
|
|
||||||
/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet.
|
|
||||||
pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE;
|
|
||||||
|
|
||||||
/// 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,8 +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_HEADER_SIZE, MAX_NESTED_PARACHAIN_HEAD_SIZE,
|
SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME,
|
||||||
PARAS_PALLET_NAME,
|
|
||||||
};
|
};
|
||||||
use bp_runtime::decl_bridge_finality_runtime_apis;
|
use bp_runtime::decl_bridge_finality_runtime_apis;
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker};
|
use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, StorageProofChecker};
|
||||||
use codec::{Codec, Decode, Encode, EncodeLike};
|
use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen};
|
||||||
use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug};
|
use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug};
|
||||||
use frame_support::PalletError;
|
use frame_support::PalletError;
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
@@ -52,19 +52,43 @@ impl From<HeaderChainError> for &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Header data that we're storing on-chain.
|
||||||
|
///
|
||||||
|
/// Even though we may store full header, our applications (XCM) only use couple of header
|
||||||
|
/// fields. Extracting those values makes on-chain storage and PoV smaller, which is good.
|
||||||
|
#[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
|
||||||
|
pub struct StoredHeaderData<Number, Hash> {
|
||||||
|
/// Header number.
|
||||||
|
pub number: Number,
|
||||||
|
/// Header state root.
|
||||||
|
pub state_root: Hash,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stored header data builder.
|
||||||
|
pub trait StoredHeaderDataBuilder<Number, Hash> {
|
||||||
|
/// Build header data from self.
|
||||||
|
fn build(&self) -> StoredHeaderData<Number, Hash>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: HeaderT> StoredHeaderDataBuilder<H::Number, H::Hash> for H {
|
||||||
|
fn build(&self) -> StoredHeaderData<H::Number, H::Hash> {
|
||||||
|
StoredHeaderData { number: *self.number(), state_root: *self.state_root() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Substrate header chain, abstracted from the way it is stored.
|
/// Substrate header chain, abstracted from the way it is stored.
|
||||||
pub trait HeaderChain<C: Chain> {
|
pub trait HeaderChain<C: Chain> {
|
||||||
/// Returns finalized header by its hash.
|
/// Returns state (storage) root of given finalized header.
|
||||||
fn finalized_header(hash: HashOf<C>) -> Option<HeaderOf<C>>;
|
fn finalized_header_state_root(header_hash: HashOf<C>) -> Option<HashOf<C>>;
|
||||||
/// Parse storage proof using finalized header.
|
/// Parse storage proof using finalized header.
|
||||||
fn parse_finalized_storage_proof<R>(
|
fn parse_finalized_storage_proof<R>(
|
||||||
hash: HashOf<C>,
|
header_hash: HashOf<C>,
|
||||||
storage_proof: StorageProof,
|
storage_proof: StorageProof,
|
||||||
parse: impl FnOnce(StorageProofChecker<HasherOf<C>>) -> R,
|
parse: impl FnOnce(StorageProofChecker<HasherOf<C>>) -> R,
|
||||||
) -> Result<R, HeaderChainError> {
|
) -> Result<R, HeaderChainError> {
|
||||||
let header = Self::finalized_header(hash).ok_or(HeaderChainError::UnknownHeader)?;
|
let state_root = Self::finalized_header_state_root(header_hash)
|
||||||
let storage_proof_checker =
|
.ok_or(HeaderChainError::UnknownHeader)?;
|
||||||
bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof)
|
let storage_proof_checker = bp_runtime::StorageProofChecker::new(state_root, storage_proof)
|
||||||
.map_err(|_| HeaderChainError::StorageRootMismatch)?;
|
.map_err(|_| HeaderChainError::StorageRootMismatch)?;
|
||||||
|
|
||||||
Ok(parse(storage_proof_checker))
|
Ok(parse(storage_proof_checker))
|
||||||
|
|||||||
@@ -96,10 +96,34 @@ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-deriva
|
|||||||
|
|
||||||
/// Generic header Id.
|
/// Generic header Id.
|
||||||
#[derive(
|
#[derive(
|
||||||
RuntimeDebug, Default, Clone, Encode, Decode, Copy, Eq, Hash, PartialEq, PartialOrd, Ord,
|
RuntimeDebug,
|
||||||
|
Default,
|
||||||
|
Clone,
|
||||||
|
Encode,
|
||||||
|
Decode,
|
||||||
|
Copy,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
MaxEncodedLen,
|
||||||
|
PartialEq,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
TypeInfo,
|
||||||
)]
|
)]
|
||||||
pub struct HeaderId<Hash, Number>(pub Number, pub Hash);
|
pub struct HeaderId<Hash, Number>(pub Number, pub Hash);
|
||||||
|
|
||||||
|
impl<Hash: Copy, Number: Copy> HeaderId<Hash, Number> {
|
||||||
|
/// Return header number.
|
||||||
|
pub fn number(&self) -> Number {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return header hash.
|
||||||
|
pub fn hash(&self) -> Hash {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user