diff --git a/substrate/frame/babe/src/default_weights.rs b/substrate/frame/babe/src/default_weights.rs index c7c87b5837..f16f589a77 100644 --- a/substrate/frame/babe/src/default_weights.rs +++ b/substrate/frame/babe/src/default_weights.rs @@ -23,6 +23,10 @@ use frame_support::weights::{ }; impl crate::WeightInfo for () { + fn plan_config_change() -> Weight { + DbWeight::get().writes(1) + } + fn report_equivocation(validator_count: u32) -> Weight { // we take the validator set count from the membership proof to // calculate the weight but we set a floor of 100 validators. diff --git a/substrate/frame/babe/src/lib.rs b/substrate/frame/babe/src/lib.rs index 2794d5b247..9fdb080574 100644 --- a/substrate/frame/babe/src/lib.rs +++ b/substrate/frame/babe/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ weights::{Pays, Weight}, Parameter, }; -use frame_system::{ensure_none, ensure_signed}; +use frame_system::{ensure_none, ensure_root, ensure_signed}; use sp_application_crypto::Public; use sp_runtime::{ generic::DigestItem, @@ -108,6 +108,7 @@ pub trait Config: pallet_timestamp::Config { } pub trait WeightInfo { + fn plan_config_change() -> Weight; fn report_equivocation(validator_count: u32) -> Weight; } @@ -314,6 +315,19 @@ decl_module! { key_owner_proof, ) } + + /// Plan an epoch config change. The epoch config change is recorded and will be enacted on + /// the next call to `enact_epoch_change`. The config will be activated one epoch after. + /// Multiple calls to this method will replace any existing planned config change that had + /// not been enacted yet. + #[weight = ::WeightInfo::plan_config_change()] + fn plan_config_change( + origin, + config: NextConfigDescriptor, + ) { + ensure_root(origin)?; + NextEpochConfig::put(config); + } } } @@ -432,15 +446,6 @@ impl Module { }) } - /// Plan an epoch config change. The epoch config change is recorded and will be enacted on the - /// next call to `enact_epoch_change`. The config will be activated one epoch after. Multiple calls to this - /// method will replace any existing planned config change that had not been enacted yet. - pub fn plan_config_change( - config: NextConfigDescriptor, - ) { - NextEpochConfig::put(config); - } - /// DANGEROUS: Enact an epoch change. Should be done on every block where `should_epoch_change` has returned `true`, /// and the caller is the only caller of this function. /// diff --git a/substrate/frame/babe/src/tests.rs b/substrate/frame/babe/src/tests.rs index 8576389af3..c7261d7f1f 100644 --- a/substrate/frame/babe/src/tests.rs +++ b/substrate/frame/babe/src/tests.rs @@ -231,10 +231,13 @@ fn can_enact_next_config() { assert_eq!(Babe::epoch_index(), 0); go_to_block(2, 7); - Babe::plan_config_change(NextConfigDescriptor::V1 { - c: (1, 4), - allowed_slots: AllowedSlots::PrimarySlots, - }); + Babe::plan_config_change( + Origin::root(), + NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + }, + ).unwrap(); progress_to_block(4); Babe::on_finalize(9); @@ -252,6 +255,39 @@ fn can_enact_next_config() { }); } +#[test] +fn only_root_can_enact_config_change() { + use sp_runtime::DispatchError; + + new_test_ext(1).execute_with(|| { + let next_config = NextConfigDescriptor::V1 { + c: (1, 4), + allowed_slots: AllowedSlots::PrimarySlots, + }; + + let res = Babe::plan_config_change( + Origin::none(), + next_config.clone(), + ); + + assert_eq!(res, Err(DispatchError::BadOrigin)); + + let res = Babe::plan_config_change( + Origin::signed(1), + next_config.clone(), + ); + + assert_eq!(res, Err(DispatchError::BadOrigin)); + + let res = Babe::plan_config_change( + Origin::root(), + next_config, + ); + + assert!(res.is_ok()); + }); +} + #[test] fn can_fetch_current_and_next_epoch_data() { new_test_ext(5).execute_with(|| {