From f38852f6612e2a848bb762a3b69f5bd2f2fb9751 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Oct 2022 11:32:53 +0300 Subject: [PATCH] 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 * Update modules/grandpa/src/storage_types.rs Co-authored-by: Adrian Catangiu * moved max authorities + header size to chain primitives * removed unused code * new -> try_new * fix benchmarks compilation Co-authored-by: Adrian Catangiu --- bridges/bin/millau/runtime/src/lib.rs | 16 ++ .../bin/rialto-parachain/runtime/src/lib.rs | 7 + bridges/bin/rialto/runtime/src/lib.rs | 7 + bridges/modules/grandpa/src/lib.rs | 185 ++++++++++++++++-- bridges/modules/grandpa/src/mock.rs | 5 + bridges/modules/grandpa/src/storage_types.rs | 106 ++++++++++ bridges/modules/parachains/src/mock.rs | 4 + bridges/primitives/chain-millau/src/lib.rs | 6 + bridges/primitives/chain-rialto/src/lib.rs | 6 + bridges/primitives/chain-westend/src/lib.rs | 12 ++ bridges/primitives/header-chain/src/lib.rs | 41 ---- bridges/primitives/runtime/src/chain.rs | 20 +- 12 files changed, 349 insertions(+), 66 deletions(-) create mode 100644 bridges/modules/grandpa/src/storage_types.rs diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 8470efa7e8..538417127e 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -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; } @@ -440,6 +454,8 @@ impl pallet_bridge_grandpa::Config 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; } diff --git a/bridges/bin/rialto-parachain/runtime/src/lib.rs b/bridges/bin/rialto-parachain/runtime/src/lib.rs index b714e6d631..752270f04c 100644 --- a/bridges/bin/rialto-parachain/runtime/src/lib.rs +++ b/bridges/bin/rialto-parachain/runtime/src/lib.rs @@ -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; } diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index 09afe728fd..161b031950 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -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; } diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index 4074421fc5..c4cbadcb38 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -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; + /// Max number of authorities at the bridged chain. + #[pallet::constant] + type MaxBridgedAuthorities: Get; + /// 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; + /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; } #[pallet::pallet] - #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] @@ -180,12 +195,14 @@ pub mod pallet { let authority_set = >::get(); let set_id = authority_set.set_id; - verify_justification::(&justification, hash, *number, authority_set)?; + verify_justification::(&justification, hash, *number, authority_set.into())?; let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; + let finality_target = + StoredBridgedHeader::::try_from_bridged_header(*finality_target)?; >::mutate(|count| *count += 1); - insert_header::(*finality_target, hash); + insert_header::(finality_target, hash); log::info!( target: LOG_TARGET, "Successfully imported finalized header with hash {:?}!", @@ -221,7 +238,7 @@ pub mod pallet { let init_allowed = !>::exists(); ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data.clone()); + initialize_bridge::(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, I: 'static = ()> = - StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; + StorageMap<_, Identity, BridgedBlockHash, StoredBridgedHeader>; /// The current GRANDPA Authority set. #[pallet::storage] pub(super) type CurrentAuthoritySet, I: 'static = ()> = - StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>; + StorageValue<_, StoredAuthoritySet, ValueQuery>; /// Optional pallet owner. /// @@ -333,7 +350,7 @@ pub mod pallet { } if let Some(init_data) = self.init_data.clone() { - initialize_bridge::(init_data); + initialize_bridge::(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(), >::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:: { + authorities: change + .next_authorities + .try_into() + .map_err(|_| Error::::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, I: 'static>( - header: BridgedHeader, + header: StoredBridgedHeader, hash: BridgedBlockHash, ) { let index = >::get(); @@ -475,19 +499,23 @@ pub mod pallet { /// were called by a trusted origin. pub(crate) fn initialize_bridge, I: 'static>( init_params: super::InitializationData>, - ) { + ) -> Result<(), Error> { let super::InitializationData { header, authority_list, set_id, operating_mode } = init_params; + let authority_set = StoredAuthoritySet::::try_new(authority_list, set_id) + .map_err(|_| Error::TooManyAuthoritiesInSet)?; + let header = StoredBridgedHeader::::try_from_bridged_header(*header)?; let initial_hash = header.hash(); >::put(initial_hash); >::put(0); - insert_header::(*header, initial_hash); + insert_header::(header, initial_hash); - let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); >::put(authority_set); >::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::(init_params); + initialize_bridge::(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::(header, hash); + insert_header::( + StoredBridgedHeader::try_from_bridged_header(header) + .expect("only used from benchmarks; benchmarks are correct; qed"), + hash, + ); } } } @@ -521,7 +553,7 @@ impl, I: 'static> Pallet { /// if the pallet has not been initialized yet. pub fn best_finalized() -> Option> { let (_, hash) = >::get()?; - >::get(hash) + >::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, 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::::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::::initialize(Origin::root(), init_data), + Error::::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::::initialize(Origin::root(), init_data), + Error::::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!( >::get(), - bp_header_chain::AuthoritySet::new(next_authorities, next_set_id), + StoredAuthoritySet::::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::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), + >::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::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), + >::TooLargeHeader + ); + }); + } + #[test] fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { @@ -959,7 +1101,10 @@ mod tests { let hash = header.hash(); >::put((2, hash)); - >::insert(hash, header); + >::insert( + hash, + StoredBridgedHeader::try_from_bridged_header(header).unwrap(), + ); assert_ok!( Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), diff --git a/bridges/modules/grandpa/src/mock.rs b/bridges/modules/grandpa/src/mock.rs index a0327761fc..babdd4b792 100644 --- a/bridges/modules/grandpa/src/mock.rs +++ b/bridges/modules/grandpa/src/mock.rs @@ -33,6 +33,9 @@ pub type TestNumber = crate::BridgedBlockNumber; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +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; + type MaxBridgedHeaderSize = frame_support::traits::ConstU32; type WeightInfo = (); } diff --git a/bridges/modules/grandpa/src/storage_types.rs b/bridges/modules/grandpa/src/storage_types.rs new file mode 100644 index 0000000000..5d2cb661d8 --- /dev/null +++ b/bridges/modules/grandpa/src/storage_types.rs @@ -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 . + +//! 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 = + 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, I: 'static> { + /// List of GRANDPA authorities for the current round. + pub authorities: StoredAuthorityList<>::MaxBridgedAuthorities>, + /// Monotonic identifier of the current GRANDPA authority set. + pub set_id: SetId, +} + +impl, I: 'static> StoredAuthoritySet { + /// 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 { + Ok(Self { authorities: TryFrom::try_from(authorities)?, set_id }) + } +} + +impl, I: 'static> PartialEq for StoredAuthoritySet { + fn eq(&self, other: &Self) -> bool { + self.set_id == other.set_id && self.authorities == other.authorities + } +} + +impl, I: 'static> Default for StoredAuthoritySet { + fn default() -> Self { + StoredAuthoritySet { authorities: BoundedVec::default(), set_id: 0 } + } +} + +impl, I: 'static> From> for AuthoritySet { + fn from(t: StoredAuthoritySet) -> 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, I: 'static>(pub BridgedHeader); + +impl, I: 'static> StoredBridgedHeader { + /// Construct `StoredBridgedHeader` from the `BridgedHeader` with all required checks. + pub fn try_from_bridged_header(header: BridgedHeader) -> Result> { + // 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) }`) + if header.encoded_size() > T::MaxBridgedHeaderSize::get() as usize { + Err(Error::TooLargeHeader) + } else { + Ok(StoredBridgedHeader(header)) + } + } +} + +impl, I: 'static> sp_std::ops::Deref for StoredBridgedHeader { + type Target = BridgedHeader; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl, I: 'static> TypeInfo for StoredBridgedHeader { + type Identity = Self; + + fn type_info() -> Type { + BridgedHeader::::type_info() + } +} + +impl, I: 'static> MaxEncodedLen for StoredBridgedHeader { + fn max_encoded_len() -> usize { + T::MaxBridgedHeaderSize::get() as usize + } +} diff --git a/bridges/modules/parachains/src/mock.rs b/bridges/modules/parachains/src/mock.rs index 292856f35a..a31fb4c47f 100644 --- a/bridges/modules/parachains/src/mock.rs +++ b/bridges/modules/parachains/src/mock.rs @@ -95,6 +95,8 @@ impl pallet_bridge_grandpa::Config 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 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 = (); } diff --git a/bridges/primitives/chain-millau/src/lib.rs b/bridges/primitives/chain-millau/src/lib.rs index 2f5b12eed0..60fe218844 100644 --- a/bridges/primitives/chain-millau/src/lib.rs +++ b/bridges/primitives/chain-millau/src/lib.rs @@ -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::*; diff --git a/bridges/primitives/chain-rialto/src/lib.rs b/bridges/primitives/chain-rialto/src/lib.rs index 1b8d19249e..9698da8877 100644 --- a/bridges/primitives/chain-rialto/src/lib.rs +++ b/bridges/primitives/chain-rialto/src/lib.rs @@ -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::*; diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/primitives/chain-westend/src/lib.rs index 08803b7a3d..eeb30709ac 100644 --- a/bridges/primitives/chain-westend/src/lib.rs +++ b/bridges/primitives/chain-westend/src/lib.rs @@ -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; diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index 8ac7972621..f5590ce0a5 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -71,47 +71,6 @@ pub struct InitializationData { 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; -} - -/// A trait for pallets which want to keep track of finalized headers from a bridged chain. -pub trait HeaderChain { - /// Get the best finalized header known to the header chain. - fn best_finalized() -> Option; - - /// 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 HeaderChain for () { - fn best_finalized() -> Option { - 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: Clone + Send + Sync + Debug { /// Return number of header that this proof is generated for. diff --git a/bridges/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs index 7cb0ad976f..be95f17480 100644 --- a/bridges/primitives/runtime/src/chain.rs +++ b/bridges/primitives/runtime/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . 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 + 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; @@ -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; + + TryFrom + + 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;