diff --git a/bridges/modules/grandpa/src/benchmarking.rs b/bridges/modules/grandpa/src/benchmarking.rs index 11033373ce47..a458abf524d5 100644 --- a/bridges/modules/grandpa/src/benchmarking.rs +++ b/bridges/modules/grandpa/src/benchmarking.rs @@ -138,5 +138,19 @@ benchmarks_instance_pallet! { assert!(!>::contains_key(genesis_header.hash())); } + force_set_pallet_state { + let set_id = 100; + let authorities = accounts(T::BridgedChain::MAX_AUTHORITIES_COUNT as u16) + .iter() + .map(|id| (AuthorityId::from(*id), 1)) + .collect::>(); + let (header, _) = prepare_benchmark_data::(1, 1); + let expected_hash = header.hash(); + }: force_set_pallet_state(RawOrigin::Root, set_id, authorities, Box::new(header)) + verify { + assert_eq!(>::get().unwrap().1, expected_hash); + assert_eq!(>::get().set_id, set_id); + } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/bridges/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs index a927882aaaa2..90b1422136bb 100644 --- a/bridges/modules/grandpa/src/lib.rs +++ b/bridges/modules/grandpa/src/lib.rs @@ -44,7 +44,7 @@ use bp_header_chain::{ }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use frame_support::{dispatch::PostDispatchInfo, ensure, DefaultNoBound}; -use sp_consensus_grandpa::SetId; +use sp_consensus_grandpa::{AuthorityList, SetId}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, @@ -360,6 +360,42 @@ pub mod pallet { Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } + + /// Set current authorities set and best finalized bridged header to given values + /// (almost) without any checks. This call can fail only if: + /// + /// - the call origin is not a root or a pallet owner; + /// + /// - there are too many authorities in the new set. + /// + /// No other checks are made. Previously imported headers stay in the storage and + /// are still accessible after the call. + #[pallet::call_index(5)] + #[pallet::weight(T::WeightInfo::force_set_pallet_state())] + pub fn force_set_pallet_state( + origin: OriginFor, + new_current_set_id: SetId, + new_authorities: AuthorityList, + new_best_header: Box>, + ) -> DispatchResult { + Self::ensure_owner_or_root(origin)?; + + // save new authorities set. It only fails if there are too many authorities + // in the new set + save_authorities_set::( + CurrentAuthoritySet::::get().set_id, + new_current_set_id, + new_authorities, + )?; + + // save new best header. It may be older than the best header that is already + // known to the pallet - it changes nothing (except for the fact that previously + // imported headers may still be used to prove something) + let new_best_header_hash = new_best_header.hash(); + insert_header::(*new_best_header, new_best_header_hash); + + Ok(()) + } } /// Number of free header submissions that we may yet accept in the current block. @@ -592,33 +628,45 @@ pub mod pallet { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); - // TODO [#788]: Stop manually increasing the `set_id` here. - let next_authorities = StoredAuthoritySet:: { - authorities: change - .next_authorities - .try_into() - .map_err(|_| Error::::TooManyAuthoritiesInSet)?, - set_id: current_set_id + 1, - }; - // Since our header schedules a change and we know the delay is 0, it must also enact // the change. - >::put(&next_authorities); - - log::info!( - target: LOG_TARGET, - "Transitioned from authority set {} to {}! New authorities are: {:?}", + // TODO [#788]: Stop manually increasing the `set_id` here. + return save_authorities_set::( current_set_id, current_set_id + 1, - next_authorities, + change.next_authorities, ); - - return Ok(Some(next_authorities.into())) }; Ok(None) } + /// Save new authorities set. + pub(crate) fn save_authorities_set, I: 'static>( + old_current_set_id: SetId, + new_current_set_id: SetId, + new_authorities: AuthorityList, + ) -> Result, DispatchError> { + let next_authorities = StoredAuthoritySet:: { + authorities: new_authorities + .try_into() + .map_err(|_| Error::::TooManyAuthoritiesInSet)?, + set_id: new_current_set_id, + }; + + >::put(&next_authorities); + + log::info!( + target: LOG_TARGET, + "Transitioned from authority set {} to {}! New authorities are: {:?}", + old_current_set_id, + new_current_set_id, + next_authorities, + ); + + Ok(Some(next_authorities.into())) + } + /// Verify a GRANDPA justification (finality proof) for a given header. /// /// Will use the GRANDPA current authorities known to the pallet. @@ -1700,4 +1748,98 @@ mod tests { assert_eq!(FreeHeadersRemaining::::get(), Some(0)); }) } + + #[test] + fn force_set_pallet_state_works() { + run_test(|| { + let header25 = test_header(25); + let header50 = test_header(50); + let ok_new_set_id = 100; + let ok_new_authorities = authority_list(); + let bad_new_set_id = 100; + let bad_new_authorities: Vec<_> = std::iter::repeat((ALICE.into(), 1)) + .take(MAX_BRIDGED_AUTHORITIES as usize + 1) + .collect(); + + // initialize and import several headers + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof(30)); + + // wrong origin => error + assert_noop!( + Pallet::::force_set_pallet_state( + RuntimeOrigin::signed(1), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header50.clone()), + ), + DispatchError::BadOrigin, + ); + + // too many authorities in the set => error + assert_noop!( + Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + bad_new_set_id, + bad_new_authorities.clone(), + Box::new(header50.clone()), + ), + Error::::TooManyAuthoritiesInSet, + ); + + // force import header 50 => ok + assert_ok!(Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header50.clone()), + ),); + + // force import header 25 after 50 => ok + assert_ok!(Pallet::::force_set_pallet_state( + RuntimeOrigin::root(), + ok_new_set_id, + ok_new_authorities.clone(), + Box::new(header25.clone()), + ),); + + // we may import better headers + assert_noop!(submit_finality_proof(20), Error::::OldHeader); + assert_ok!(submit_finality_proof_with_set_id(26, ok_new_set_id)); + + // we can even reimport header #50. It **will cause** some issues during pruning + // (see below) + assert_ok!(submit_finality_proof_with_set_id(50, ok_new_set_id)); + + // and all headers are available. Even though there are 4 headers, the ring + // buffer thinks that there are 5, because we've imported header $50 twice + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(30).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(50).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(25).hash() + ) + .is_some()); + assert!(GrandpaChainHeaders::::finalized_header_state_root( + test_header(26).hash() + ) + .is_some()); + + // next header import will prune header 30 + assert_ok!(submit_finality_proof_with_set_id(70, ok_new_set_id)); + // next header import will prune header 50 + assert_ok!(submit_finality_proof_with_set_id(80, ok_new_set_id)); + // next header import will prune header 25 + assert_ok!(submit_finality_proof_with_set_id(90, ok_new_set_id)); + // next header import will prune header 26 + assert_ok!(submit_finality_proof_with_set_id(100, ok_new_set_id)); + // next header import will prune header 50 again. But it is fine + assert_ok!(submit_finality_proof_with_set_id(110, ok_new_set_id)); + }); + } } diff --git a/bridges/modules/grandpa/src/weights.rs b/bridges/modules/grandpa/src/weights.rs index a75e7b5a8e4a..9719bc9c022e 100644 --- a/bridges/modules/grandpa/src/weights.rs +++ b/bridges/modules/grandpa/src/weights.rs @@ -51,6 +51,7 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_bridge_grandpa. pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; + fn force_set_pallet_state() -> Weight; } /// Weights for `pallet_bridge_grandpa` that are generated using one of the Bridge testnets. @@ -109,6 +110,30 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } + + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: + /// Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: + /// Some(4), added: 499, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHashes` + /// (r:1 w:1) Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), + /// `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), + /// added: 531, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 + /// w:2) Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: + /// Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 62_232_000 picoseconds. + Weight::from_parts(78_755_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(6)) + } } // For backwards compatibility and tests @@ -164,4 +189,28 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } + + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: + /// Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: + /// Some(4), added: 499, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHashes` + /// (r:1 w:1) Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), + /// `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), + /// added: 531, mode: `MaxEncodedLen`) Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 + /// w:2) Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: + /// Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 62_232_000 picoseconds. + Weight::from_parts(78_755_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(RocksDbWeight::get().reads(3)) + .saturating_add(RocksDbWeight::get().writes(6)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs index 8c2435599f59..257e2dcac2fb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_bridge_grandpa.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-itmxxexx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,12 +48,14 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bridge_grandpa`. pub struct WeightInfo(PhantomData); impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:0) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::PalletOperatingMode` (r:1 w:0) /// Proof: `BridgeWestendGrandpa::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:1 w:1) /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) - /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:0) - /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::FreeHeadersRemaining` (r:1 w:0) + /// Proof: `BridgeWestendGrandpa::FreeHeadersRemaining` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeWestendGrandpa::ImportedHashes` (r:1 w:1) @@ -62,18 +64,36 @@ impl pallet_bridge_grandpa::WeightInfo for WeightInfo Weight { + fn submit_finality_proof(p: u32, _v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `335 + p * (60 ±0)` + // Measured: `440 + p * (60 ±0)` // Estimated: `51735` - // Minimum execution time: 310_124_000 picoseconds. - Weight::from_parts(18_294_977, 0) + // Minimum execution time: 306_046_000 picoseconds. + Weight::from_parts(384_361_000, 0) .saturating_add(Weight::from_parts(0, 51735)) - // Standard Error: 5_665 - .saturating_add(Weight::from_parts(55_380_719, 0).saturating_mul(p.into())) - // Standard Error: 94_494 - .saturating_add(Weight::from_parts(2_765_959, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Standard Error: 14_298 + .saturating_add(Weight::from_parts(49_045_748, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } + /// Storage: `BridgeWestendGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHashes` (r:1 w:1) + /// Proof: `BridgeWestendGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeWestendGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendGrandpa::ImportedHeaders` (r:0 w:2) + /// Proof: `BridgeWestendGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `452` + // Estimated: `51735` + // Minimum execution time: 94_965_000 picoseconds. + Weight::from_parts(113_633_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(6)) + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs index e87ed668dfc7..348d651396c0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_bridge_grandpa.rs @@ -16,10 +16,10 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-05-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-itmxxexx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-unxyhko3-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -48,12 +48,14 @@ use core::marker::PhantomData; /// Weight functions for `pallet_bridge_grandpa`. pub struct WeightInfo(PhantomData); impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:0) + /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::PalletOperatingMode` (r:1 w:0) /// Proof: `BridgeRococoGrandpa::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(1), added: 496, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::BestFinalized` (r:1 w:1) /// Proof: `BridgeRococoGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) - /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:0) - /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::FreeHeadersRemaining` (r:1 w:0) + /// Proof: `BridgeRococoGrandpa::FreeHeadersRemaining` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::ImportedHashesPointer` (r:1 w:1) /// Proof: `BridgeRococoGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `BridgeRococoGrandpa::ImportedHashes` (r:1 w:1) @@ -64,16 +66,36 @@ impl pallet_bridge_grandpa::WeightInfo for WeightInfo Weight { // Proof Size summary in bytes: - // Measured: `231 + p * (60 ±0)` + // Measured: `270 + p * (60 ±0)` // Estimated: `51735` - // Minimum execution time: 303_549_000 picoseconds. - Weight::from_parts(306_232_000, 0) + // Minimum execution time: 294_098_000 picoseconds. + Weight::from_parts(31_208_540, 0) .saturating_add(Weight::from_parts(0, 51735)) - // Standard Error: 4_641 - .saturating_add(Weight::from_parts(55_196_301, 0).saturating_mul(p.into())) - // Standard Error: 35_813 - .saturating_add(Weight::from_parts(70_584, 0).saturating_mul(v.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Standard Error: 8_832 + .saturating_add(Weight::from_parts(40_930_987, 0).saturating_mul(p.into())) + // Standard Error: 147_319 + .saturating_add(Weight::from_parts(2_663_839, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(5)) } + /// Storage: `BridgeRococoGrandpa::CurrentAuthoritySet` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::CurrentAuthoritySet` (`max_values`: Some(1), `max_size`: Some(50250), added: 50745, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHashesPointer` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::ImportedHashesPointer` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHashes` (r:1 w:1) + /// Proof: `BridgeRococoGrandpa::ImportedHashes` (`max_values`: Some(1024), `max_size`: Some(36), added: 1521, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::BestFinalized` (r:0 w:1) + /// Proof: `BridgeRococoGrandpa::BestFinalized` (`max_values`: Some(1), `max_size`: Some(36), added: 531, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoGrandpa::ImportedHeaders` (r:0 w:2) + /// Proof: `BridgeRococoGrandpa::ImportedHeaders` (`max_values`: Some(1024), `max_size`: Some(68), added: 1553, mode: `MaxEncodedLen`) + fn force_set_pallet_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `282` + // Estimated: `51735` + // Minimum execution time: 112_875_000 picoseconds. + Weight::from_parts(120_861_000, 0) + .saturating_add(Weight::from_parts(0, 51735)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(6)) + } } diff --git a/prdoc/pr_4465.prdoc b/prdoc/pr_4465.prdoc new file mode 100644 index 000000000000..cbeff09f871f --- /dev/null +++ b/prdoc/pr_4465.prdoc @@ -0,0 +1,19 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Bridge: added force_set_pallet_state call to pallet-bridge-grandpa" + +doc: + - audience: Runtime Dev + description: | + Added `force_set_pallet_state` to the `pallet-bridge-grandpa`. It is only callable by the + root (governance or sudo) and may be used to update current authorities set and the best + finalized header without any additional checks. + +crates: + - name: pallet-bridge-grandpa + bump: major + - name: bridge-hub-rococo-runtime + bump: minor + - name: bridge-hub-westend-runtime + bump: minor