From fab2344f49140986ea25ef7d8d1a4f3383727ce4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Dec 2022 14:03:23 +0300 Subject: [PATCH] only store header state root (pallet-bridge-grandpa) (#1699) --- bin/millau/runtime/src/lib.rs | 11 +- bin/rialto-parachain/runtime/src/lib.rs | 7 +- bin/rialto/runtime/src/lib.rs | 7 +- bin/runtime-common/src/messages.rs | 9 +- modules/grandpa/src/extension.rs | 5 +- modules/grandpa/src/lib.rs | 163 +++++------------------- modules/grandpa/src/mock.rs | 2 - modules/parachains/src/lib.rs | 7 +- modules/parachains/src/mock.rs | 2 - primitives/chain-millau/src/lib.rs | 3 - primitives/chain-rialto/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 7 +- primitives/chain-westend/src/lib.rs | 7 +- primitives/chain-wococo/src/lib.rs | 3 +- primitives/header-chain/src/lib.rs | 42 ++++-- primitives/runtime/src/lib.rs | 26 +++- 16 files changed, 113 insertions(+), 193 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3c2a21d59d2..2e20afb6457 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -413,13 +413,8 @@ 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. 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 = (); @@ -432,7 +427,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtRialto; - type MaxBridgedHeaderSize = MaxRialtoHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -443,7 +437,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtWestend; - type MaxBridgedHeaderSize = MaxWestendHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -871,13 +864,13 @@ impl_runtime_apis! { impl bp_rialto::RialtoFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeRialtoGrandpa::best_finalized().map(|header| header.id()) + BridgeRialtoGrandpa::best_finalized() } } impl bp_westend::WestendFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeWestendGrandpa::best_finalized().map(|header| header.id()) + BridgeWestendGrandpa::best_finalized() } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index a30864e038a..3d19dd4e75d 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -45,7 +45,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. -use bp_runtime::{HeaderId, HeaderIdProvider}; +use bp_runtime::HeaderId; pub use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -525,8 +525,6 @@ parameter_types! { /// 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 = (); @@ -539,7 +537,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; - type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -728,7 +725,7 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized().map(|header| header.id()) + BridgeMillauGrandpa::best_finalized() } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dd4d254f17b..0b91faf2eaa 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -33,7 +33,7 @@ pub mod parachains; pub mod xcm_config; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use bp_runtime::{HeaderId, HeaderIdProvider}; +use bp_runtime::HeaderId; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -410,8 +410,6 @@ parameter_types! { /// 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,7 +422,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; - type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -721,7 +718,7 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized().map(|header| header.id()) + BridgeMillauGrandpa::best_finalized() } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3530e683140..a0a75692ba0 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -705,7 +705,6 @@ mod tests { use crate::messages_generation::{ encode_all_messages, encode_lane_data, prepare_messages_storage_proof, }; - use bp_runtime::HeaderOf; use codec::{Decode, Encode}; use frame_support::weights::Weight; use sp_core::H256; @@ -881,17 +880,17 @@ mod tests { struct BridgedHeaderChain; impl HeaderChain for BridgedHeaderChain { - fn finalized_header( + fn finalized_header_state_root( _hash: HashOf, - ) -> Option> { - TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()) + ) -> Option> { + TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()).map(|h| *h.state_root()) } } struct ThisHeaderChain; impl HeaderChain for ThisHeaderChain { - fn finalized_header(_hash: HashOf) -> Option> { + fn finalized_header_state_root(_hash: HashOf) -> Option> { unreachable!() } } diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index c0f02da751e..87075ee5d58 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -40,7 +40,7 @@ impl< let best_finalized = crate::BestFinalized::::get(); 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(), }; @@ -66,6 +66,7 @@ mod tests { mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, BestFinalized, }; + use bp_runtime::HeaderId; use bp_test_utils::make_default_justification; fn validate_block_submit(num: TestNumber) -> bool { @@ -81,7 +82,7 @@ mod tests { fn sync_to_header_10() { let header10_hash = sp_core::H256::default(); - BestFinalized::::put((10, header10_hash)); + BestFinalized::::put(HeaderId(10, header10_hash)); } #[test] diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 2402b2512e2..54bf5a8810c 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -38,10 +38,11 @@ use storage_types::StoredAuthoritySet; -use bp_header_chain::{justification::GrandpaJustification, HeaderChain, InitializationData}; -use bp_runtime::{ - BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule, +use bp_header_chain::{ + justification::GrandpaJustification, HeaderChain, InitializationData, StoredHeaderData, + StoredHeaderDataBuilder, }; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; use frame_system::ensure_signed; @@ -73,13 +74,15 @@ pub type BridgedChain = >::BridgedChain; pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; /// Block hash of the bridged chain. pub type BridgedBlockHash = HashOf<>::BridgedChain>; +/// Block id of the bridged chain. +pub type BridgedBlockId = HeaderId, BridgedBlockNumber>; /// Hasher of the bridged chain. pub type BridgedBlockHasher = HasherOf<>::BridgedChain>; /// Header of the bridged chain. pub type BridgedHeader = HeaderOf<>::BridgedChain>; -/// Stored header of the bridged chain. -pub type StoredBridgedHeader = - BoundedStorageValue<>::MaxBridgedHeaderSize, BridgedHeader>; +/// Header data of the bridged chain that is stored at this chain by this pallet. +pub type BridgedStoredHeaderData = + StoredHeaderData, BridgedBlockHash>; #[frame_support::pallet] pub mod pallet { @@ -115,15 +118,6 @@ pub mod pallet { /// 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; @@ -178,11 +172,8 @@ pub mod pallet { finality_target ); - let best_finalized = BestFinalized::::get(); - let best_finalized = - best_finalized.and_then(|(_, hash)| ImportedHeaders::::get(hash)); - let best_finalized = match best_finalized { - Some(best_finalized) => best_finalized, + let best_finalized_number = match BestFinalized::::get() { + Some(best_finalized_id) => best_finalized_id.number(), None => { log::error!( 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 // "travelling back in time" (which could be indicative of something bad, e.g a // hard-fork). - ensure!(best_finalized.number() < number, >::OldHeader); + ensure!(best_finalized_number < *number, >::OldHeader); let authority_set = >::get(); let set_id = authority_set.set_id; @@ -204,20 +195,8 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; - let finality_target = StoredBridgedHeader::::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::::TooLargeHeader - })?; >::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 {:?}!", @@ -302,8 +281,9 @@ pub mod pallet { /// Hash of the best finalized header. #[pallet::storage] + #[pallet::getter(fn best_finalized)] pub type BestFinalized, I: 'static = ()> = - StorageValue<_, (BridgedBlockNumber, BridgedBlockHash), OptionQuery>; + StorageValue<_, BridgedBlockId, OptionQuery>; /// A ring buffer of imported hashes. Ordered by the insertion time. #[pallet::storage] @@ -315,10 +295,10 @@ pub mod pallet { pub(super) type ImportedHashesPointer, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; - /// Headers which have been imported into the pallet. + /// Relevant fields of imported headers. #[pallet::storage] pub type ImportedHeaders, I: 'static = ()> = - StorageMap<_, Identity, BridgedBlockHash, StoredBridgedHeader>; + StorageMap<_, Identity, BridgedBlockHash, BridgedStoredHeaderData>; /// The current GRANDPA Authority set. #[pallet::storage] @@ -394,8 +374,6 @@ pub mod pallet { AlreadyInitialized, /// Too many authorities in the set. TooManyAuthoritiesInSet, - /// Too large header. - TooLargeHeader, /// Error generated by the `OwnedBridgeModule` trait. 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, /// but does not verify the validity of such import. pub(crate) fn insert_header, I: 'static>( - header: StoredBridgedHeader, + header: BridgedHeader, hash: BridgedBlockHash, ) { let index = >::get(); let pruning = >::try_get(index); - >::put((*header.number(), hash)); - >::insert(hash, header); + >::put(HeaderId(*header.number(), hash)); + >::insert(hash, header.build()); >::insert(index, hash); // Update ring buffer pointer and remove old header. @@ -526,21 +504,10 @@ pub mod pallet { Error::TooManyAuthoritiesInSet })?; let initial_hash = header.hash(); - let header = StoredBridgedHeader::::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::::TooLargeHeader - })?; >::put(initial_hash); >::put(0); - insert_header::(header, initial_hash); + insert_header::(*header, initial_hash); >::put(authority_set); @@ -568,34 +535,19 @@ pub mod pallet { Default::default(), ); let hash = header.hash(); - insert_header::( - StoredBridgedHeader::::try_from_inner(header) - .expect("only used from benchmarks; benchmarks are correct; qed"), - hash, - ); + insert_header::(header, hash); } } } -impl, I: 'static> Pallet { - /// Get the best finalized header the pallet knows of. - pub fn best_finalized() -> Option> { - let (_, hash) = >::get()?; - >::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) -> bool { - >::contains_key(hash) - } -} - /// Bridge GRANDPA pallet as header chain. pub type GrandpaChainHeaders = Pallet; impl, I: 'static> HeaderChain> for GrandpaChainHeaders { - fn finalized_header(hash: HashOf>) -> Option>> { - ImportedHeaders::::get(hash).map(|h| h.into_inner()) + fn finalized_header_state_root( + header_hash: HashOf>, + ) -> Option>> { + ImportedHeaders::::get(header_hash).map(|h| h.state_root) } } @@ -653,7 +605,7 @@ mod tests { use super::*; use crate::mock::{ run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime, - MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE, + MAX_BRIDGED_AUTHORITIES, }; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ @@ -742,10 +694,6 @@ mod tests { 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(|| { @@ -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::::initialize(RuntimeOrigin::root(), init_data), - Error::::TooLargeHeader, - ); - }); - } - #[test] fn pallet_rejects_transactions_if_halted() { 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::::submit_finality_proof( - RuntimeOrigin::signed(1), - Box::new(header), - justification - ), - >::TooLargeHeader - ); - }); - } - #[test] fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { @@ -1121,11 +1025,8 @@ mod tests { header.set_state_root(state_root); let hash = header.hash(); - >::put((2, hash)); - >::insert( - hash, - StoredBridgedHeader::::try_from_inner(header).unwrap(), - ); + >::put(HeaderId(2, hash)); + >::insert(hash, header.build()); assert_ok!( Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), @@ -1220,7 +1121,7 @@ mod tests { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1)); - let first_header = Pallet::::best_finalized().unwrap(); + let first_header_hash = Pallet::::best_finalized().unwrap().hash(); next_block(); assert_ok!(submit_finality_proof(2)); @@ -1235,8 +1136,8 @@ mod tests { assert_ok!(submit_finality_proof(6)); assert!( - !Pallet::::is_known_header(first_header.hash()), - "First header should be pruned." + !ImportedHeaders::::contains_key(first_header_hash), + "First header should be pruned.", ); }) } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 12a40a688f6..ba6f176e823 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -34,7 +34,6 @@ 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; @@ -94,7 +93,6 @@ impl grandpa::Config for TestRuntime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32; type WeightInfo = (); } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index e6625476a3d..9ca2ac0f482 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -275,7 +275,7 @@ pub mod pallet { >::get(relay_block_hash) .ok_or(Error::::UnknownRelayChainBlock)?; ensure!( - *relay_block.number() == relay_block_number, + relay_block.number == relay_block_number, Error::::InvalidRelayChainBlockNumber, ); @@ -604,9 +604,10 @@ pub struct ParachainHeaders(PhantomData<(T, I, C)>); impl, I: 'static, C: Parachain> HeaderChain for ParachainHeaders { - fn finalized_header(hash: HashOf) -> Option> { + fn finalized_header_state_root(hash: HashOf) -> Option> { Pallet::::parachain_head(ParaId(C::PARACHAIN_ID), hash) - .and_then(|head| Decode::decode(&mut &head.0[..]).ok()) + .and_then(|head| HeaderOf::::decode(&mut &head.0[..]).ok()) + .map(|h| *h.state_root()) } } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 4e17a71bcdc..6e8df019fff 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -100,7 +100,6 @@ impl pallet_bridge_grandpa::Config for TestRun type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } @@ -109,7 +108,6 @@ impl pallet_bridge_grandpa::Config for TestRun type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index ceb4be21b81..2a4139e07cb 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -81,9 +81,6 @@ 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 = 1024; - /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index dfb727829d9..4aea107777a 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -70,11 +70,8 @@ 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 = 1024; - /// 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. pub use time_units::*; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 6fd7228fd75..32e4e30ca4a 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -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. 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 /// `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; - -/// 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; +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; /// Maximal number of GRANDPA authorities at Rococo. /// diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 9f4a98baedc..6df4d5ff6d5 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -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. 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 /// `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; - -/// 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; +pub const MAX_NESTED_PARACHAIN_HEAD_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/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 0436b03c036..c4dc6da13f0 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -20,8 +20,7 @@ pub use bp_polkadot_core::*; pub use bp_rococo::{ - SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_HEADER_SIZE, MAX_NESTED_PARACHAIN_HEAD_SIZE, - PARAS_PALLET_NAME, + SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, }; use bp_runtime::decl_bridge_finality_runtime_apis; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 2b4e0802a5a..99243663264 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,8 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker}; -use codec::{Codec, Decode, Encode, EncodeLike}; +use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, StorageProofChecker}; +use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; use frame_support::PalletError; use scale_info::TypeInfo; @@ -52,20 +52,44 @@ impl From 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 { + /// Header number. + pub number: Number, + /// Header state root. + pub state_root: Hash, +} + +/// Stored header data builder. +pub trait StoredHeaderDataBuilder { + /// Build header data from self. + fn build(&self) -> StoredHeaderData; +} + +impl StoredHeaderDataBuilder for H { + fn build(&self) -> StoredHeaderData { + StoredHeaderData { number: *self.number(), state_root: *self.state_root() } + } +} + /// Substrate header chain, abstracted from the way it is stored. pub trait HeaderChain { - /// Returns finalized header by its hash. - fn finalized_header(hash: HashOf) -> Option>; + /// Returns state (storage) root of given finalized header. + fn finalized_header_state_root(header_hash: HashOf) -> Option>; /// Parse storage proof using finalized header. fn parse_finalized_storage_proof( - hash: HashOf, + header_hash: HashOf, storage_proof: StorageProof, parse: impl FnOnce(StorageProofChecker>) -> R, ) -> Result { - let header = Self::finalized_header(hash).ok_or(HeaderChainError::UnknownHeader)?; - let storage_proof_checker = - bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| HeaderChainError::StorageRootMismatch)?; + let state_root = Self::finalized_header_state_root(header_hash) + .ok_or(HeaderChainError::UnknownHeader)?; + let storage_proof_checker = bp_runtime::StorageProofChecker::new(state_root, storage_proof) + .map_err(|_| HeaderChainError::StorageRootMismatch)?; Ok(parse(storage_proof_checker)) } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 75d75c2beff..34f521a7273 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -96,10 +96,34 @@ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-deriva /// Generic header Id. #[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(pub Number, pub Hash); +impl HeaderId { + /// Return header number. + pub fn number(&self) -> Number { + self.0 + } + + /// Return header hash. + pub fn hash(&self) -> Hash { + self.1 + } +} + /// Generic header id provider. pub trait HeaderIdProvider { // Get the header id.