mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-09 09:27:59 +00:00
Remove pallet::without_storage_info from bridge GRANDPA pallet (#1478)
* remove pallet::without_storage_info from bridge GRANDPA pallet * StoredBridgedHeader * spelling * fix benchmarks * MAX_BRIDGED_AUTHORITIES: 256 -> 2048 * Update modules/grandpa/src/storage_types.rs Co-authored-by: Adrian Catangiu <adrian@parity.io> * Update modules/grandpa/src/storage_types.rs Co-authored-by: Adrian Catangiu <adrian@parity.io> * moved max authorities + header size to chain primitives * removed unused code * new -> try_new * fix benchmarks compilation Co-authored-by: Adrian Catangiu <adrian@parity.io>
This commit is contained in:
committed by
Bastian Köcher
parent
6f9bda5db0
commit
f38852f661
@@ -426,11 +426,25 @@ parameter_types! {
|
||||
pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32;
|
||||
}
|
||||
|
||||
parameter_types! {
|
||||
/// Maximal number of authorities at Rialto.
|
||||
pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT;
|
||||
/// Maximal size of SCALE-encoded Rialto header.
|
||||
pub const MaxRialtoHeaderSize: u32 = bp_rialto::MAX_HEADER_SIZE;
|
||||
|
||||
/// Maximal number of authorities at Westend.
|
||||
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 = ();
|
||||
impl pallet_bridge_grandpa::Config for Runtime {
|
||||
type BridgedChain = bp_rialto::Rialto;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = MaxAuthoritiesAtRialto;
|
||||
type MaxBridgedHeaderSize = MaxRialtoHeaderSize;
|
||||
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||
}
|
||||
@@ -440,6 +454,8 @@ impl pallet_bridge_grandpa::Config<WestendGrandpaInstance> for Runtime {
|
||||
type BridgedChain = bp_westend::Westend;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = MaxAuthoritiesAtWestend;
|
||||
type MaxBridgedHeaderSize = MaxWestendHeaderSize;
|
||||
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||
}
|
||||
|
||||
@@ -531,6 +531,11 @@ parameter_types! {
|
||||
/// Assuming the worst case of every header being finalized, we will keep headers at least for a
|
||||
/// week.
|
||||
pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32;
|
||||
|
||||
/// Maximal number of authorities at Millau.
|
||||
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 = ();
|
||||
@@ -538,6 +543,8 @@ impl pallet_bridge_grandpa::Config for Runtime {
|
||||
type BridgedChain = bp_millau::Millau;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
||||
type MaxBridgedHeaderSize = MaxMillauHeaderSize;
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||
}
|
||||
|
||||
|
||||
@@ -417,6 +417,11 @@ parameter_types! {
|
||||
/// Assuming the worst case of every header being finalized, we will keep headers at least for a
|
||||
/// week.
|
||||
pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32;
|
||||
|
||||
/// Maximal number of authorities at Millau.
|
||||
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 = ();
|
||||
@@ -424,6 +429,8 @@ impl pallet_bridge_grandpa::Config for Runtime {
|
||||
type BridgedChain = bp_millau::Millau;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = MaxAuthoritiesAtMillau;
|
||||
type MaxBridgedHeaderSize = MaxMillauHeaderSize;
|
||||
type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight<Runtime>;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
// Runtime-generated enums
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
|
||||
use storage_types::{StoredAuthoritySet, StoredBridgedHeader};
|
||||
|
||||
use bp_header_chain::{justification::GrandpaJustification, InitializationData};
|
||||
use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule};
|
||||
use finality_grandpa::voter_set::VoterSet;
|
||||
@@ -48,6 +50,7 @@ use sp_std::{boxed::Box, convert::TryInto};
|
||||
mod extension;
|
||||
#[cfg(test)]
|
||||
mod mock;
|
||||
mod storage_types;
|
||||
|
||||
/// Module, containing weights for this pallet.
|
||||
pub mod weights;
|
||||
@@ -102,12 +105,24 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type HeadersToKeep: Get<u32>;
|
||||
|
||||
/// Max number of authorities at the bridged chain.
|
||||
#[pallet::constant]
|
||||
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.
|
||||
type WeightInfo: WeightInfo;
|
||||
}
|
||||
|
||||
#[pallet::pallet]
|
||||
#[pallet::without_storage_info]
|
||||
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);
|
||||
|
||||
#[pallet::hooks]
|
||||
@@ -180,12 +195,14 @@ pub mod pallet {
|
||||
|
||||
let authority_set = <CurrentAuthoritySet<T, I>>::get();
|
||||
let set_id = authority_set.set_id;
|
||||
verify_justification::<T, I>(&justification, hash, *number, authority_set)?;
|
||||
verify_justification::<T, I>(&justification, hash, *number, authority_set.into())?;
|
||||
|
||||
let is_authorities_change_enacted =
|
||||
try_enact_authority_change::<T, I>(&finality_target, set_id)?;
|
||||
let finality_target =
|
||||
StoredBridgedHeader::<T, I>::try_from_bridged_header(*finality_target)?;
|
||||
<RequestCount<T, I>>::mutate(|count| *count += 1);
|
||||
insert_header::<T, I>(*finality_target, hash);
|
||||
insert_header::<T, I>(finality_target, hash);
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
"Successfully imported finalized header with hash {:?}!",
|
||||
@@ -221,7 +238,7 @@ pub mod pallet {
|
||||
|
||||
let init_allowed = !<BestFinalized<T, I>>::exists();
|
||||
ensure!(init_allowed, <Error<T, I>>::AlreadyInitialized);
|
||||
initialize_bridge::<T, I>(init_data.clone());
|
||||
initialize_bridge::<T, I>(init_data.clone())?;
|
||||
|
||||
log::info!(
|
||||
target: LOG_TARGET,
|
||||
@@ -286,12 +303,12 @@ pub mod pallet {
|
||||
/// Headers which have been imported into the pallet.
|
||||
#[pallet::storage]
|
||||
pub type ImportedHeaders<T: Config<I>, I: 'static = ()> =
|
||||
StorageMap<_, Identity, BridgedBlockHash<T, I>, BridgedHeader<T, I>>;
|
||||
StorageMap<_, Identity, BridgedBlockHash<T, I>, StoredBridgedHeader<T, I>>;
|
||||
|
||||
/// The current GRANDPA Authority set.
|
||||
#[pallet::storage]
|
||||
pub(super) type CurrentAuthoritySet<T: Config<I>, I: 'static = ()> =
|
||||
StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>;
|
||||
StorageValue<_, StoredAuthoritySet<T, I>, ValueQuery>;
|
||||
|
||||
/// Optional pallet owner.
|
||||
///
|
||||
@@ -333,7 +350,7 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
if let Some(init_data) = self.init_data.clone() {
|
||||
initialize_bridge::<T, I>(init_data);
|
||||
initialize_bridge::<T, I>(init_data).expect("genesis config is correct; qed");
|
||||
} else {
|
||||
// Since the bridge hasn't been initialized we shouldn't allow anyone to perform
|
||||
// transactions.
|
||||
@@ -364,6 +381,10 @@ pub mod pallet {
|
||||
AlreadyInitialized,
|
||||
/// The storage proof doesn't contains storage root. So it is invalid for given header.
|
||||
StorageRootMismatch,
|
||||
/// Too many authorities in the set.
|
||||
TooManyAuthoritiesInSet,
|
||||
/// Too large header.
|
||||
TooLargeHeader,
|
||||
/// Error generated by the `OwnedBridgeModule` trait.
|
||||
BridgeModule(bp_runtime::OwnedBridgeModuleError),
|
||||
}
|
||||
@@ -392,8 +413,11 @@ pub mod pallet {
|
||||
ensure!(change.delay == Zero::zero(), <Error<T, I>>::UnsupportedScheduledChange);
|
||||
|
||||
// TODO [#788]: Stop manually increasing the `set_id` here.
|
||||
let next_authorities = bp_header_chain::AuthoritySet {
|
||||
authorities: change.next_authorities,
|
||||
let next_authorities = StoredAuthoritySet::<T, I> {
|
||||
authorities: change
|
||||
.next_authorities
|
||||
.try_into()
|
||||
.map_err(|_| Error::<T, I>::TooManyAuthoritiesInSet)?,
|
||||
set_id: current_set_id + 1,
|
||||
};
|
||||
|
||||
@@ -454,7 +478,7 @@ pub mod pallet {
|
||||
/// Note this function solely takes care of updating the storage and pruning old entries,
|
||||
/// but does not verify the validity of such import.
|
||||
pub(crate) fn insert_header<T: Config<I>, I: 'static>(
|
||||
header: BridgedHeader<T, I>,
|
||||
header: StoredBridgedHeader<T, I>,
|
||||
hash: BridgedBlockHash<T, I>,
|
||||
) {
|
||||
let index = <ImportedHashesPointer<T, I>>::get();
|
||||
@@ -475,19 +499,23 @@ pub mod pallet {
|
||||
/// were called by a trusted origin.
|
||||
pub(crate) fn initialize_bridge<T: Config<I>, I: 'static>(
|
||||
init_params: super::InitializationData<BridgedHeader<T, I>>,
|
||||
) {
|
||||
) -> Result<(), Error<T, I>> {
|
||||
let super::InitializationData { header, authority_list, set_id, operating_mode } =
|
||||
init_params;
|
||||
let authority_set = StoredAuthoritySet::<T, I>::try_new(authority_list, set_id)
|
||||
.map_err(|_| Error::TooManyAuthoritiesInSet)?;
|
||||
let header = StoredBridgedHeader::<T, I>::try_from_bridged_header(*header)?;
|
||||
|
||||
let initial_hash = header.hash();
|
||||
<InitialHash<T, I>>::put(initial_hash);
|
||||
<ImportedHashesPointer<T, I>>::put(0);
|
||||
insert_header::<T, I>(*header, initial_hash);
|
||||
insert_header::<T, I>(header, initial_hash);
|
||||
|
||||
let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id);
|
||||
<CurrentAuthoritySet<T, I>>::put(authority_set);
|
||||
|
||||
<PalletOperatingMode<T, I>>::put(operating_mode);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
@@ -496,7 +524,7 @@ pub mod pallet {
|
||||
) {
|
||||
let start_number = *init_params.header.number();
|
||||
let end_number = start_number + T::HeadersToKeep::get().into();
|
||||
initialize_bridge::<T, I>(init_params);
|
||||
initialize_bridge::<T, I>(init_params).expect("benchmarks are correct");
|
||||
|
||||
let mut number = start_number;
|
||||
while number < end_number {
|
||||
@@ -509,7 +537,11 @@ pub mod pallet {
|
||||
Default::default(),
|
||||
);
|
||||
let hash = header.hash();
|
||||
insert_header::<T, I>(header, hash);
|
||||
insert_header::<T, I>(
|
||||
StoredBridgedHeader::try_from_bridged_header(header)
|
||||
.expect("only used from benchmarks; benchmarks are correct; qed"),
|
||||
hash,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -521,7 +553,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
|
||||
/// if the pallet has not been initialized yet.
|
||||
pub fn best_finalized() -> Option<BridgedHeader<T, I>> {
|
||||
let (_, hash) = <BestFinalized<T, I>>::get()?;
|
||||
<ImportedHeaders<T, I>>::get(hash)
|
||||
<ImportedHeaders<T, I>>::get(hash).map(|h| h.0)
|
||||
}
|
||||
|
||||
/// Check if a particular header is known to the bridge pallet.
|
||||
@@ -591,13 +623,17 @@ pub fn initialize_for_benchmarks<T: Config<I>, I: 'static>(header: BridgedHeader
|
||||
* benchmarks */
|
||||
set_id: 0,
|
||||
operating_mode: bp_runtime::BasicOperatingMode::Normal,
|
||||
});
|
||||
})
|
||||
.expect("only used from benchmarks; benchmarks are correct; qed");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime};
|
||||
use crate::mock::{
|
||||
run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime,
|
||||
MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE,
|
||||
};
|
||||
use bp_runtime::BasicOperatingMode;
|
||||
use bp_test_utils::{
|
||||
authority_list, generate_owned_bridge_module_tests, make_default_justification,
|
||||
@@ -673,6 +709,22 @@ mod tests {
|
||||
Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] }
|
||||
}
|
||||
|
||||
fn many_authorities_log() -> Digest {
|
||||
let consensus_log =
|
||||
ConsensusLog::<TestNumber>::ScheduledChange(sp_finality_grandpa::ScheduledChange {
|
||||
next_authorities: std::iter::repeat((ALICE.into(), 1))
|
||||
.take(MAX_BRIDGED_AUTHORITIES as usize + 1)
|
||||
.collect(),
|
||||
delay: 0,
|
||||
});
|
||||
|
||||
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]
|
||||
fn init_root_or_owner_origin_can_initialize_pallet() {
|
||||
run_test(|| {
|
||||
@@ -715,6 +767,45 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn init_fails_if_there_are_too_many_authorities_in_the_set() {
|
||||
run_test(|| {
|
||||
let genesis = test_header(0);
|
||||
let init_data = InitializationData {
|
||||
header: Box::new(genesis),
|
||||
authority_list: std::iter::repeat(authority_list().remove(0))
|
||||
.take(MAX_BRIDGED_AUTHORITIES as usize + 1)
|
||||
.collect(),
|
||||
set_id: 1,
|
||||
operating_mode: BasicOperatingMode::Normal,
|
||||
};
|
||||
|
||||
assert_noop!(
|
||||
Pallet::<TestRuntime>::initialize(Origin::root(), init_data),
|
||||
Error::<TestRuntime>::TooManyAuthoritiesInSet,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[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(Origin::root(), init_data),
|
||||
Error::<TestRuntime>::TooLargeHeader,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pallet_rejects_transactions_if_halted() {
|
||||
run_test(|| {
|
||||
@@ -880,7 +971,8 @@ mod tests {
|
||||
// Make sure that the authority set actually changed upon importing our header
|
||||
assert_eq!(
|
||||
<CurrentAuthoritySet<TestRuntime>>::get(),
|
||||
bp_header_chain::AuthoritySet::new(next_authorities, next_set_id),
|
||||
StoredAuthoritySet::<TestRuntime, ()>::try_new(next_authorities, next_set_id)
|
||||
.unwrap(),
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -935,6 +1027,56 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn importing_header_rejects_header_with_too_many_authorities() {
|
||||
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 = many_authorities_log();
|
||||
|
||||
// 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(
|
||||
Origin::signed(1),
|
||||
Box::new(header),
|
||||
justification
|
||||
),
|
||||
<Error<TestRuntime>>::TooManyAuthoritiesInSet
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[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(
|
||||
Origin::signed(1),
|
||||
Box::new(header),
|
||||
justification
|
||||
),
|
||||
<Error<TestRuntime>>::TooLargeHeader
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() {
|
||||
run_test(|| {
|
||||
@@ -959,7 +1101,10 @@ mod tests {
|
||||
|
||||
let hash = header.hash();
|
||||
<BestFinalized<TestRuntime>>::put((2, hash));
|
||||
<ImportedHeaders<TestRuntime>>::insert(hash, header);
|
||||
<ImportedHeaders<TestRuntime>>::insert(
|
||||
hash,
|
||||
StoredBridgedHeader::try_from_bridged_header(header).unwrap(),
|
||||
);
|
||||
|
||||
assert_ok!(
|
||||
Pallet::<TestRuntime>::parse_finalized_storage_proof(hash, storage_proof, |_| (),),
|
||||
|
||||
@@ -33,6 +33,9 @@ pub type TestNumber = crate::BridgedBlockNumber<TestRuntime, ()>;
|
||||
type Block = frame_system::mocking::MockBlock<TestRuntime>;
|
||||
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
|
||||
|
||||
pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048;
|
||||
pub const MAX_HEADER_SIZE: u32 = 65536;
|
||||
|
||||
use crate as grandpa;
|
||||
|
||||
construct_runtime! {
|
||||
@@ -91,6 +94,8 @@ impl grandpa::Config for TestRuntime {
|
||||
type BridgedChain = TestBridgedChain;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<MAX_BRIDGED_AUTHORITIES>;
|
||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<MAX_HEADER_SIZE>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Bridges Common.
|
||||
|
||||
// Parity Bridges Common is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Bridges Common is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Wrappers for public types that are implementing `MaxEncodedLen`
|
||||
|
||||
use crate::{BridgedHeader, Config, Error};
|
||||
|
||||
use bp_header_chain::AuthoritySet;
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound};
|
||||
use scale_info::{Type, TypeInfo};
|
||||
use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId};
|
||||
|
||||
/// A bounded list of Grandpa authorities with associated weights.
|
||||
pub type StoredAuthorityList<MaxBridgedAuthorities> =
|
||||
BoundedVec<(AuthorityId, AuthorityWeight), MaxBridgedAuthorities>;
|
||||
|
||||
/// A bounded GRANDPA Authority List and ID.
|
||||
#[derive(Clone, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, RuntimeDebugNoBound)]
|
||||
#[scale_info(skip_type_params(T, I))]
|
||||
pub struct StoredAuthoritySet<T: Config<I>, I: 'static> {
|
||||
/// List of GRANDPA authorities for the current round.
|
||||
pub authorities: StoredAuthorityList<<T as Config<I>>::MaxBridgedAuthorities>,
|
||||
/// Monotonic identifier of the current GRANDPA authority set.
|
||||
pub set_id: SetId,
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> StoredAuthoritySet<T, I> {
|
||||
/// Try to create a new bounded GRANDPA Authority Set from unbounded list.
|
||||
///
|
||||
/// Returns error if number of authorities in the provided list is too large.
|
||||
pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result<Self, ()> {
|
||||
Ok(Self { authorities: TryFrom::try_from(authorities)?, set_id })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> PartialEq for StoredAuthoritySet<T, I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.set_id == other.set_id && self.authorities == other.authorities
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> Default for StoredAuthoritySet<T, I> {
|
||||
fn default() -> Self {
|
||||
StoredAuthoritySet { authorities: BoundedVec::default(), set_id: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> From<StoredAuthoritySet<T, I>> for AuthoritySet {
|
||||
fn from(t: StoredAuthoritySet<T, I>) -> Self {
|
||||
AuthoritySet { authorities: t.authorities.into(), set_id: t.set_id }
|
||||
}
|
||||
}
|
||||
|
||||
/// A bounded chain header.
|
||||
#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebugNoBound)]
|
||||
pub struct StoredBridgedHeader<T: Config<I>, I: 'static>(pub BridgedHeader<T, I>);
|
||||
|
||||
impl<T: Config<I>, I: 'static> StoredBridgedHeader<T, I> {
|
||||
/// Construct `StoredBridgedHeader` from the `BridgedHeader` with all required checks.
|
||||
pub fn try_from_bridged_header(header: BridgedHeader<T, I>) -> Result<Self, Error<T, I>> {
|
||||
// this conversion is heavy (since we do encoding here), so we may want to optimize it later
|
||||
// (e.g. by introducing custom Encode implementation, and turning `StoredBridgedHeader` into
|
||||
// `enum StoredBridgedHeader { Decoded(BridgedHeader), Encoded(Vec<u8>) }`)
|
||||
if header.encoded_size() > T::MaxBridgedHeaderSize::get() as usize {
|
||||
Err(Error::TooLargeHeader)
|
||||
} else {
|
||||
Ok(StoredBridgedHeader(header))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> sp_std::ops::Deref for StoredBridgedHeader<T, I> {
|
||||
type Target = BridgedHeader<T, I>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> TypeInfo for StoredBridgedHeader<T, I> {
|
||||
type Identity = Self;
|
||||
|
||||
fn type_info() -> Type {
|
||||
BridgedHeader::<T, I>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config<I>, I: 'static> MaxEncodedLen for StoredBridgedHeader<T, I> {
|
||||
fn max_encoded_len() -> usize {
|
||||
T::MaxBridgedHeaderSize::get() as usize
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,8 @@ impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance1> for TestRun
|
||||
type BridgedChain = TestBridgedChain;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
@@ -102,6 +104,8 @@ impl pallet_bridge_grandpa::Config<pallet_bridge_grandpa::Instance2> for TestRun
|
||||
type BridgedChain = TestBridgedChain;
|
||||
type MaxRequests = MaxRequests;
|
||||
type HeadersToKeep = HeadersToKeep;
|
||||
type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>;
|
||||
type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,12 @@ pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000;
|
||||
/// conditions.
|
||||
pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES;
|
||||
|
||||
/// Maximal number of GRANDPA authorities at Millau.
|
||||
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
||||
|
||||
/// Maximal SCALE-encoded header size (in bytes) at Millau.
|
||||
pub const MAX_HEADER_SIZE: u32 = 512;
|
||||
|
||||
/// Re-export `time_units` to make usage easier.
|
||||
pub use time_units::*;
|
||||
|
||||
|
||||
@@ -100,6 +100,12 @@ pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000;
|
||||
/// conditions.
|
||||
pub const SESSION_LENGTH: BlockNumber = 4;
|
||||
|
||||
/// Maximal number of GRANDPA authorities at Rialto.
|
||||
pub const MAX_AUTHORITIES_COUNT: u32 = 5;
|
||||
|
||||
/// Maximal SCALE-encoded header size (in bytes) at Rialto.
|
||||
pub const MAX_HEADER_SIZE: u32 = 512;
|
||||
|
||||
/// Re-export `time_units` to make usage easier.
|
||||
pub use time_units::*;
|
||||
|
||||
|
||||
@@ -58,6 +58,18 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains
|
||||
/// conditions.
|
||||
pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES;
|
||||
|
||||
/// Maximal number of GRANDPA authorities at Westend.
|
||||
///
|
||||
/// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration.
|
||||
pub const MAX_AUTHORITIES_COUNT: u32 = 100_000;
|
||||
|
||||
/// Maximal SCALE-encoded header size (in bytes) at Westend.
|
||||
///
|
||||
/// 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
|
||||
/// some fixed reserve for other things (digest, block hash and number, ...) as well.
|
||||
pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40;
|
||||
|
||||
/// Identifier of Westmint parachain at the Westend relay chain.
|
||||
pub const WESTMINT_PARACHAIN_ID: u32 = 2000;
|
||||
|
||||
|
||||
@@ -71,47 +71,6 @@ pub struct InitializationData<H: HeaderT> {
|
||||
pub operating_mode: BasicOperatingMode,
|
||||
}
|
||||
|
||||
/// base trait for verifying transaction inclusion proofs.
|
||||
pub trait InclusionProofVerifier {
|
||||
/// Transaction type.
|
||||
type Transaction: Parameter;
|
||||
/// Transaction inclusion proof type.
|
||||
type TransactionInclusionProof: Parameter;
|
||||
|
||||
/// Verify that transaction is a part of given block.
|
||||
///
|
||||
/// Returns Some(transaction) if proof is valid and None otherwise.
|
||||
fn verify_transaction_inclusion_proof(
|
||||
proof: &Self::TransactionInclusionProof,
|
||||
) -> Option<Self::Transaction>;
|
||||
}
|
||||
|
||||
/// A trait for pallets which want to keep track of finalized headers from a bridged chain.
|
||||
pub trait HeaderChain<H, E> {
|
||||
/// Get the best finalized header known to the header chain.
|
||||
fn best_finalized() -> Option<H>;
|
||||
|
||||
/// Get the best authority set known to the header chain.
|
||||
fn authority_set() -> AuthoritySet;
|
||||
|
||||
/// Write a header finalized by GRANDPA to the underlying pallet storage.
|
||||
fn append_header(header: H) -> Result<(), E>;
|
||||
}
|
||||
|
||||
impl<H: Default, E> HeaderChain<H, E> for () {
|
||||
fn best_finalized() -> Option<H> {
|
||||
None
|
||||
}
|
||||
|
||||
fn authority_set() -> AuthoritySet {
|
||||
AuthoritySet::default()
|
||||
}
|
||||
|
||||
fn append_header(_header: H) -> Result<(), E> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Abstract finality proof that is justifying block finality.
|
||||
pub trait FinalityProof<Number>: Clone + Send + Sync + Debug {
|
||||
/// Return number of header that this proof is generated for.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::HeaderIdProvider;
|
||||
use codec::{Decode, Encode};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::{weights::Weight, Parameter};
|
||||
use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero};
|
||||
use sp_runtime::{
|
||||
@@ -111,6 +111,7 @@ pub trait Chain: Send + Sync + 'static {
|
||||
+ AsPrimitive<usize>
|
||||
+ Default
|
||||
+ Saturating
|
||||
+ MaxEncodedLen
|
||||
// original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but
|
||||
// `sp_runtime::generic::Era` requires block number -> `u64` conversion.
|
||||
+ Into<u64>;
|
||||
@@ -130,7 +131,8 @@ pub trait Chain: Send + Sync + 'static {
|
||||
+ SimpleBitOps
|
||||
+ AsRef<[u8]>
|
||||
+ AsMut<[u8]>
|
||||
+ MaybeMallocSizeOf;
|
||||
+ MaybeMallocSizeOf
|
||||
+ MaxEncodedLen;
|
||||
|
||||
/// A type that fulfills the abstract idea of what a Substrate hasher (a type
|
||||
/// that produces hashes) is.
|
||||
@@ -148,7 +150,13 @@ pub trait Chain: Send + Sync + 'static {
|
||||
+ MaybeSerializeDeserialize;
|
||||
|
||||
/// The user account identifier type for the runtime.
|
||||
type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord;
|
||||
type AccountId: Parameter
|
||||
+ Member
|
||||
+ MaybeSerializeDeserialize
|
||||
+ Debug
|
||||
+ MaybeDisplay
|
||||
+ Ord
|
||||
+ MaxEncodedLen;
|
||||
/// Balance of an account in native tokens.
|
||||
///
|
||||
/// The chain may support multiple tokens, but this particular type is for token that is used
|
||||
@@ -165,7 +173,8 @@ pub trait Chain: Send + Sync + 'static {
|
||||
+ PartialOrd
|
||||
+ SaturatingAdd
|
||||
+ Zero
|
||||
+ TryFrom<sp_core::U256>;
|
||||
+ TryFrom<sp_core::U256>
|
||||
+ MaxEncodedLen;
|
||||
/// Index of a transaction used by the chain.
|
||||
type Index: Parameter
|
||||
+ Member
|
||||
@@ -175,7 +184,8 @@ pub trait Chain: Send + Sync + 'static {
|
||||
+ MaybeDisplay
|
||||
+ MaybeSerializeDeserialize
|
||||
+ AtLeast32Bit
|
||||
+ Copy;
|
||||
+ Copy
|
||||
+ MaxEncodedLen;
|
||||
/// Signature type, used on this chain.
|
||||
type Signature: Parameter + Verify;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user