diff --git a/bridges/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs index b081eafe9427..82e02118d53f 100644 --- a/bridges/bin/runtime-common/src/mock.rs +++ b/bridges/bin/runtime-common/src/mock.rs @@ -185,6 +185,7 @@ impl pallet_bridge_parachains::Config for TestRuntime { type HeadsToKeep = ConstU32<8>; type MaxParaHeadDataSize = ConstU32<1024>; type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; + type OnNewHead = (); } impl pallet_bridge_messages::Config for TestRuntime { diff --git a/bridges/modules/parachains/src/lib.rs b/bridges/modules/parachains/src/lib.rs index 656f79594803..81f73f4b5f35 100644 --- a/bridges/modules/parachains/src/lib.rs +++ b/bridges/modules/parachains/src/lib.rs @@ -32,7 +32,7 @@ use bp_parachains::{ ParaInfo, ParaStoredHeaderData, RelayBlockHash, RelayBlockHasher, RelayBlockNumber, SubmitParachainHeadsInfo, }; -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain}; use frame_support::{dispatch::PostDispatchInfo, DefaultNoBound}; use pallet_bridge_grandpa::SubmitFinalityProofHelper; @@ -76,7 +76,7 @@ struct UpdateParachainHeadArtifacts { pub mod pallet { use super::*; use bp_parachains::{ - BestParaHeadHash, ImportedParaHeadsKeyProvider, ParaStoredHeaderDataBuilder, + BestParaHeadHash, ImportedParaHeadsKeyProvider, OnNewHead, ParaStoredHeaderDataBuilder, ParasInfoKeyProvider, }; use bp_runtime::{ @@ -252,6 +252,9 @@ pub mod pallet { /// that exceeds this bound. #[pallet::constant] type MaxParaHeadDataSize: Get; + + /// Runtime hook for when a parachain head is updated. + type OnNewHead: OnNewHead; } /// Optional pallet owner. @@ -538,6 +541,7 @@ pub mod pallet { HeaderId(relay_block_number, relay_block_hash), parachain_head_data, parachain_head_hash, + parachain_head, )?; if is_free { @@ -638,6 +642,7 @@ pub mod pallet { new_at_relay_block: HeaderId, new_head_data: ParaStoredHeaderData, new_head_hash: ParaHash, + new_head: ParaHead, ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order @@ -699,7 +704,7 @@ pub mod pallet { next_imported_hash_position, new_head_hash, ); - ImportedParaHeads::::insert(parachain, new_head_hash, updated_head_data); + ImportedParaHeads::::insert(parachain, new_head_hash, &updated_head_data); log::trace!( target: LOG_TARGET, "Updated head of parachain {:?} to {} at relay block {}", @@ -708,6 +713,9 @@ pub mod pallet { new_at_relay_block.0, ); + // trigger callback + T::OnNewHead::on_new_head(parachain, &new_head); + // remove old head let prune_happened = head_hash_to_prune.is_ok(); if let Ok(head_hash_to_prune) = head_hash_to_prune { @@ -815,6 +823,7 @@ pub fn initialize_for_benchmarks, I: 'static, PC: Parachain; + type OnNewHead = (); } #[cfg(feature = "runtime-benchmarks")] diff --git a/bridges/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs index 24067b9640be..716aee1d032e 100644 --- a/bridges/modules/relayers/src/mock.rs +++ b/bridges/modules/relayers/src/mock.rs @@ -255,6 +255,7 @@ impl pallet_bridge_parachains::Config for TestRuntime { type HeadsToKeep = ConstU32<8>; type MaxParaHeadDataSize = ConstU32<1024>; type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; + type OnNewHead = (); } impl pallet_bridge_messages::Config for TestRuntime { diff --git a/bridges/primitives/parachains/src/lib.rs b/bridges/primitives/parachains/src/lib.rs index ec3bf9ca3a0a..38acc588d515 100644 --- a/bridges/primitives/parachains/src/lib.rs +++ b/bridges/primitives/parachains/src/lib.rs @@ -28,7 +28,7 @@ use bp_runtime::{ StorageMapKeyProvider, }; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{Blake2_128Concat, Twox64Concat}; +use frame_support::{weights::Weight, Blake2_128Concat, Twox64Concat}; use scale_info::TypeInfo; use sp_core::storage::StorageKey; use sp_runtime::{traits::Header as HeaderT, RuntimeDebug}; @@ -192,3 +192,19 @@ impl ParaStoredHeaderDataBuilder for C { None } } + +/// Runtime hook for when a parachain head is updated. +pub trait OnNewHead { + /// Called when a parachain head is updated. + /// Returns the weight consumed by this function. + fn on_new_head(id: ParaId, head: &ParaHead) -> Weight; +} + +#[impl_trait_for_tuples::impl_for_tuples(8)] +impl OnNewHead for Tuple { + fn on_new_head(id: ParaId, head: &ParaHead) -> Weight { + let mut weight: Weight = Default::default(); + for_tuples!( #( weight.saturating_accrue(Tuple::on_new_head(id, head)); )* ); + weight + } +} diff --git a/bridges/primitives/polkadot-core/src/parachains.rs b/bridges/primitives/polkadot-core/src/parachains.rs index be13cba3dbeb..70de6e4c5b43 100644 --- a/bridges/primitives/polkadot-core/src/parachains.rs +++ b/bridges/primitives/polkadot-core/src/parachains.rs @@ -67,7 +67,17 @@ impl From for ParaId { /// /// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. #[derive( - PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default, + PartialEq, + Eq, + Clone, + PartialOrd, + Ord, + Encode, + Decode, + DecodeWithMemTracking, + RuntimeDebug, + TypeInfo, + Default, )] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] pub struct ParaHead(pub Vec); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs index bec529404d54..b627f903a2ea 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs @@ -62,6 +62,7 @@ impl pallet_bridge_parachains::Config for Runtim SingleParaStoredHeaderDataBuilder; type HeadsToKeep = ParachainHeadsToKeep; type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; + type OnNewHead = (); } /// Allows collect and claim rewards for relayers diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs index ccae93e261bf..0b2ce0d27c2e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs @@ -126,6 +126,7 @@ impl pallet_bridge_parachains::Config for Runtime SingleParaStoredHeaderDataBuilder; type HeadsToKeep = ParachainHeadsToKeep; type MaxParaHeadDataSize = MaxRococoParaHeadDataSize; + type OnNewHead = (); } /// Add XCM messages support for BridgeHubWestend to support Westend->Rococo XCM messages diff --git a/prdoc/pr_8531.prdoc b/prdoc/pr_8531.prdoc new file mode 100644 index 000000000000..07a9297890c1 --- /dev/null +++ b/prdoc/pr_8531.prdoc @@ -0,0 +1,22 @@ +title: Added `OnNewHead` to `pallet-bridge-parachains` +doc: +- audience: Runtime Dev + description: |- + This PR introduces a new `OnNewHead` hook for `pallet-bridge-parachains`, which is triggered when a new parachain head is relayed. + + It will be used in conjunction with the [syncing mechanism](https://github.com/paritytech/polkadot-sdk/pull/8326), which sends relayed AssetHubRococo headers with `state_root`s to AssetHubWestend for message proof verification. +crates: +- name: pallet-bridge-parachains + bump: major +- name: bp-parachains + bump: minor +- name: bp-polkadot-core + bump: minor +- name: bridge-hub-rococo-runtime + bump: minor +- name: bridge-hub-westend-runtime + bump: minor +- name: bridge-runtime-common + bump: minor +- name: pallet-bridge-relayers + bump: minor