diff --git a/substrate/frame/beefy/src/default_weights.rs b/substrate/frame/beefy/src/default_weights.rs
index 091d58f47f97888b43259bcb62c44905fae568e3..8042f0c932eb6603c88e1ff5f4525743c347b9bb 100644
--- a/substrate/frame/beefy/src/default_weights.rs
+++ b/substrate/frame/beefy/src/default_weights.rs
@@ -49,4 +49,8 @@ impl crate::WeightInfo for () {
 			// fetching set id -> session index mappings
 			.saturating_add(DbWeight::get().reads(2))
 	}
+
+	fn set_new_genesis() -> Weight {
+		DbWeight::get().writes(1)
+	}
 }
diff --git a/substrate/frame/beefy/src/lib.rs b/substrate/frame/beefy/src/lib.rs
index 77e74436dd6710416d7418f3dca2198dced68428..0760446753a688516a2c4ce75727ebb4b3cd06a8 100644
--- a/substrate/frame/beefy/src/lib.rs
+++ b/substrate/frame/beefy/src/lib.rs
@@ -33,7 +33,7 @@ use frame_system::{
 use log;
 use sp_runtime::{
 	generic::DigestItem,
-	traits::{IsMember, Member},
+	traits::{IsMember, Member, One},
 	RuntimeAppPublic,
 };
 use sp_session::{GetSessionNumber, GetValidatorCount};
@@ -62,7 +62,7 @@ const LOG_TARGET: &str = "runtime::beefy";
 #[frame_support::pallet]
 pub mod pallet {
 	use super::*;
-	use frame_system::pallet_prelude::BlockNumberFor;
+	use frame_system::{ensure_root, pallet_prelude::BlockNumberFor};
 
 	#[pallet::config]
 	pub trait Config: frame_system::Config {
@@ -152,8 +152,8 @@ pub mod pallet {
 		StorageMap<_, Twox64Concat, sp_consensus_beefy::ValidatorSetId, SessionIndex>;
 
 	/// Block number where BEEFY consensus is enabled/started.
-	/// By changing this (through governance or sudo), BEEFY consensus is effectively
-	/// restarted from the new block number.
+	/// By changing this (through privileged `set_new_genesis()`), BEEFY consensus is effectively
+	/// restarted from the newly set block number.
 	#[pallet::storage]
 	#[pallet::getter(fn genesis_block)]
 	pub(super) type GenesisBlock<T: Config> =
@@ -174,7 +174,7 @@ pub mod pallet {
 		fn default() -> Self {
 			// BEEFY genesis will be first BEEFY-MANDATORY block,
 			// use block number one instead of chain-genesis.
-			let genesis_block = Some(sp_runtime::traits::One::one());
+			let genesis_block = Some(One::one());
 			Self { authorities: Vec::new(), genesis_block }
 		}
 	}
@@ -198,6 +198,8 @@ pub mod pallet {
 		InvalidEquivocationProof,
 		/// A given equivocation report is valid but already previously reported.
 		DuplicateOffenceReport,
+		/// Submitted configuration is invalid.
+		InvalidConfiguration,
 	}
 
 	#[pallet::call]
@@ -265,6 +267,23 @@ pub mod pallet {
 			)?;
 			Ok(Pays::No.into())
 		}
+
+		/// Reset BEEFY consensus by setting a new BEEFY genesis at `delay_in_blocks` blocks in the
+		/// future.
+		///
+		/// Note: `delay_in_blocks` has to be at least 1.
+		#[pallet::call_index(2)]
+		#[pallet::weight(<T as Config>::WeightInfo::set_new_genesis())]
+		pub fn set_new_genesis(
+			origin: OriginFor<T>,
+			delay_in_blocks: BlockNumberFor<T>,
+		) -> DispatchResult {
+			ensure_root(origin)?;
+			ensure!(delay_in_blocks >= One::one(), Error::<T>::InvalidConfiguration);
+			let genesis_block = frame_system::Pallet::<T>::block_number() + delay_in_blocks;
+			GenesisBlock::<T>::put(Some(genesis_block));
+			Ok(())
+		}
 	}
 
 	#[pallet::validate_unsigned]
@@ -452,4 +471,5 @@ impl<T: Config> IsMember<T::BeefyId> for Pallet<T> {
 
 pub trait WeightInfo {
 	fn report_equivocation(validator_count: u32, max_nominators_per_validator: u32) -> Weight;
+	fn set_new_genesis() -> Weight;
 }
diff --git a/substrate/frame/beefy/src/tests.rs b/substrate/frame/beefy/src/tests.rs
index e04dc330d0c07cb7258323b34db0086c6226ffb2..bf1b204e0260e29a2ce473416a43d0b641f8a7b9 100644
--- a/substrate/frame/beefy/src/tests.rs
+++ b/substrate/frame/beefy/src/tests.rs
@@ -791,3 +791,25 @@ fn valid_equivocation_reports_dont_pay_fees() {
 		assert_eq!(post_info.pays_fee, Pays::Yes);
 	})
 }
+
+#[test]
+fn set_new_genesis_works() {
+	let authorities = test_authorities();
+
+	new_test_ext_raw_authorities(authorities).execute_with(|| {
+		start_era(1);
+
+		let new_genesis_delay = 10u64;
+		// the call for setting new genesis should work
+		assert_ok!(Beefy::set_new_genesis(RuntimeOrigin::root(), new_genesis_delay,));
+		let expected = System::block_number() + new_genesis_delay;
+		// verify new genesis was set
+		assert_eq!(Beefy::genesis_block(), Some(expected));
+
+		// setting delay < 1 should fail
+		assert_err!(
+			Beefy::set_new_genesis(RuntimeOrigin::root(), 0u64,),
+			Error::<Test>::InvalidConfiguration,
+		);
+	});
+}