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

) { self.source_to_target_finality_metrics - .update_best_block_at_source(source_client_state.best_self.0.into()); - self.target_to_source_finality_metrics.update_best_block_at_target( - source_client_state.best_finalized_peer_at_best_self.0.into(), - ); + .update_best_block_at_source(source_client_state.best_self.0); + self.target_to_source_finality_metrics + .update_best_block_at_target(source_client_state.best_finalized_peer_at_best_self.0); self.target_to_source_finality_metrics.update_using_same_fork( source_client_state.best_finalized_peer_at_best_self.1 == source_client_state.actual_best_finalized_peer_at_best_self.1, @@ -78,10 +77,9 @@ impl MessageLaneLoopMetrics { /// Update target client state metrics. pub fn update_target_state(&self, target_client_state: TargetClientState

) { self.target_to_source_finality_metrics - .update_best_block_at_source(target_client_state.best_self.0.into()); - self.source_to_target_finality_metrics.update_best_block_at_target( - target_client_state.best_finalized_peer_at_best_self.0.into(), - ); + .update_best_block_at_source(target_client_state.best_self.0); + self.source_to_target_finality_metrics + .update_best_block_at_target(target_client_state.best_finalized_peer_at_best_self.0); self.source_to_target_finality_metrics.update_using_same_fork( target_client_state.best_finalized_peer_at_best_self.1 == target_client_state.actual_best_finalized_peer_at_best_self.1, diff --git a/bridges/relays/parachains/src/parachains_loop_metrics.rs b/bridges/relays/parachains/src/parachains_loop_metrics.rs index ff8bace274439..5df996b4ddd1f 100644 --- a/bridges/relays/parachains/src/parachains_loop_metrics.rs +++ b/bridges/relays/parachains/src/parachains_loop_metrics.rs @@ -15,8 +15,9 @@ // along with Parity Bridges Common. If not, see . use bp_polkadot_core::parachains::ParaId; -use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, +use relay_utils::{ + metrics::{metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64}, + UniqueSaturatedInto, }; /// Parachains sync metrics. @@ -50,12 +51,12 @@ impl ParachainsLoopMetrics { } /// Update best block number at source. - pub fn update_best_parachain_block_at_source>( + pub fn update_best_parachain_block_at_source>( &self, parachain: ParaId, block_number: Number, ) { - let block_number = block_number.into(); + let block_number = block_number.unique_saturated_into(); let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", @@ -67,12 +68,12 @@ impl ParachainsLoopMetrics { } /// Update best block number at target. - pub fn update_best_parachain_block_at_target>( + pub fn update_best_parachain_block_at_target>( &self, parachain: ParaId, block_number: Number, ) { - let block_number = block_number.into(); + let block_number = block_number.unique_saturated_into(); let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", diff --git a/bridges/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml index ebbfa74c6ff81..09cec37090069 100644 --- a/bridges/relays/utils/Cargo.toml +++ b/bridges/relays/utils/Cargo.toml @@ -29,4 +29,5 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate dependencies +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/utils/src/lib.rs b/bridges/relays/utils/src/lib.rs index 42bf86ebf5b37..16e1a18bab7d4 100644 --- a/bridges/relays/utils/src/lib.rs +++ b/bridges/relays/utils/src/lib.rs @@ -19,6 +19,7 @@ pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; +pub use sp_runtime::traits::UniqueSaturatedInto; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; @@ -51,7 +52,7 @@ pub mod relay_loop; pub trait BlockNumberBase: 'static + From - + Into + + UniqueSaturatedInto + Ord + Clone + Copy @@ -73,7 +74,7 @@ pub trait BlockNumberBase: impl BlockNumberBase for T where T: 'static + From - + Into + + UniqueSaturatedInto + Ord + Clone + Copy