From c2d45e7e474c94e77b57c0aefe181fa8708d7965 Mon Sep 17 00:00:00 2001
From: Gabriel Facco de Arruda <arrudagates@gmail.com>
Date: Mon, 11 Dec 2023 20:12:15 -0300
Subject: [PATCH] pallet-vesting: Configurable block number provider (#2403)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This PR makes the block number provider configurable through the Config
trait in pallet-vesting, this gives parachains the option to use the
relay chain block number provider from ParachainSystem.

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
---
 polkadot/runtime/common/src/claims.rs       |  1 +
 polkadot/runtime/common/src/purchase.rs     |  1 +
 polkadot/runtime/rococo/src/lib.rs          |  1 +
 polkadot/runtime/test-runtime/src/lib.rs    |  1 +
 polkadot/runtime/westend/src/lib.rs         |  1 +
 prdoc/pr_2403.prdoc                         |  9 +++++++++
 substrate/bin/node/runtime/src/lib.rs       |  1 +
 substrate/frame/system/src/lib.rs           |  5 +++++
 substrate/frame/vesting/src/benchmarking.rs |  8 ++++----
 substrate/frame/vesting/src/lib.rs          | 13 ++++++++-----
 substrate/frame/vesting/src/mock.rs         |  1 +
 11 files changed, 33 insertions(+), 9 deletions(-)
 create mode 100644 prdoc/pr_2403.prdoc

diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs
index 4f04a79be55..e05c0fe5c4c 100644
--- a/polkadot/runtime/common/src/claims.rs
+++ b/polkadot/runtime/common/src/claims.rs
@@ -801,6 +801,7 @@ mod tests {
 		type MinVestedTransfer = MinVestedTransfer;
 		type WeightInfo = ();
 		type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+		type BlockNumberProvider = System;
 		const MAX_VESTING_SCHEDULES: u32 = 28;
 	}
 
diff --git a/polkadot/runtime/common/src/purchase.rs b/polkadot/runtime/common/src/purchase.rs
index 06b0a0a0211..f43f16b838c 100644
--- a/polkadot/runtime/common/src/purchase.rs
+++ b/polkadot/runtime/common/src/purchase.rs
@@ -573,6 +573,7 @@ mod tests {
 		type MinVestedTransfer = MinVestedTransfer;
 		type WeightInfo = ();
 		type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+		type BlockNumberProvider = System;
 		const MAX_VESTING_SCHEDULES: u32 = 28;
 	}
 
diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs
index 572cdf1aade..26cc6d95449 100644
--- a/polkadot/runtime/rococo/src/lib.rs
+++ b/polkadot/runtime/rococo/src/lib.rs
@@ -744,6 +744,7 @@ impl pallet_vesting::Config for Runtime {
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = weights::pallet_vesting::WeightInfo<Runtime>;
 	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+	type BlockNumberProvider = System;
 	const MAX_VESTING_SCHEDULES: u32 = 28;
 }
 
diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs
index 81b9b63f75b..351a1393fa0 100644
--- a/polkadot/runtime/test-runtime/src/lib.rs
+++ b/polkadot/runtime/test-runtime/src/lib.rs
@@ -463,6 +463,7 @@ impl pallet_vesting::Config for Runtime {
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = ();
 	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+	type BlockNumberProvider = System;
 	const MAX_VESTING_SCHEDULES: u32 = 28;
 }
 
diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs
index 25d4c1d2d6f..11f267a327b 100644
--- a/polkadot/runtime/westend/src/lib.rs
+++ b/polkadot/runtime/westend/src/lib.rs
@@ -948,6 +948,7 @@ impl pallet_vesting::Config for Runtime {
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = weights::pallet_vesting::WeightInfo<Runtime>;
 	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+	type BlockNumberProvider = System;
 	const MAX_VESTING_SCHEDULES: u32 = 28;
 }
 
diff --git a/prdoc/pr_2403.prdoc b/prdoc/pr_2403.prdoc
new file mode 100644
index 00000000000..f1c4d3ecbaf
--- /dev/null
+++ b/prdoc/pr_2403.prdoc
@@ -0,0 +1,9 @@
+title: Configurable block number provider in pallet-vesting
+
+doc:
+  - audience: Runtime Dev
+    description: |
+      Adds `BlockNumberProvider` type to pallet-vesting Config trait, allowing for custom providers instead of hardcoding frame-system.
+      This is particularly useful for parachains wanting to use `cumulus_pallet_parachain_system::RelaychainDataProvider` with `pallet-vesting`.
+
+crates: [ ]
diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs
index eded60adfd7..b8c638ef155 100644
--- a/substrate/bin/node/runtime/src/lib.rs
+++ b/substrate/bin/node/runtime/src/lib.rs
@@ -1552,6 +1552,7 @@ impl pallet_vesting::Config for Runtime {
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = pallet_vesting::weights::SubstrateWeight<Runtime>;
 	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+	type BlockNumberProvider = System;
 	// `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the
 	// highest number of schedules that encodes less than 2^10.
 	const MAX_VESTING_SCHEDULES: u32 = 28;
diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs
index 6624bb43a80..3697e36f3fc 100644
--- a/substrate/frame/system/src/lib.rs
+++ b/substrate/frame/system/src/lib.rs
@@ -1919,6 +1919,11 @@ impl<T: Config> BlockNumberProvider for Pallet<T> {
 	fn current_block_number() -> Self::BlockNumber {
 		Pallet::<T>::block_number()
 	}
+
+	#[cfg(feature = "runtime-benchmarks")]
+	fn set_block_number(n: BlockNumberFor<T>) {
+		Self::set_block_number(n)
+	}
 }
 
 /// Implement StoredMap for a simple single-item, provide-when-not-default system. This works fine
diff --git a/substrate/frame/vesting/src/benchmarking.rs b/substrate/frame/vesting/src/benchmarking.rs
index 34aa04607ad..311590873d9 100644
--- a/substrate/frame/vesting/src/benchmarking.rs
+++ b/substrate/frame/vesting/src/benchmarking.rs
@@ -55,7 +55,7 @@ fn add_vesting_schedules<T: Config>(
 	let source_lookup = T::Lookup::unlookup(source.clone());
 	T::Currency::make_free_balance_be(&source, BalanceOf::<T>::max_value());
 
-	System::<T>::set_block_number(BlockNumberFor::<T>::zero());
+	T::BlockNumberProvider::set_block_number(BlockNumberFor::<T>::zero());
 
 	let mut total_locked: BalanceOf<T> = Zero::zero();
 	for _ in 0..n {
@@ -116,7 +116,7 @@ benchmarks! {
 		add_vesting_schedules::<T>(caller_lookup, s)?;
 
 		// At block 21, everything is unlocked.
-		System::<T>::set_block_number(21u32.into());
+		T::BlockNumberProvider::set_block_number(21u32.into());
 		assert_eq!(
 			Vesting::<T>::vesting_balance(&caller),
 			Some(BalanceOf::<T>::zero()),
@@ -173,7 +173,7 @@ benchmarks! {
 		add_locks::<T>(&other, l as u8);
 		add_vesting_schedules::<T>(other_lookup.clone(), s)?;
 		// At block 21 everything is unlocked.
-		System::<T>::set_block_number(21u32.into());
+		T::BlockNumberProvider::set_block_number(21u32.into());
 
 		assert_eq!(
 			Vesting::<T>::vesting_balance(&other),
@@ -335,7 +335,7 @@ benchmarks! {
 		let total_transferred = add_vesting_schedules::<T>(caller_lookup, s)?;
 
 		// Go to about half way through all the schedules duration. (They all start at 1, and have a duration of 20 or 21).
-		System::<T>::set_block_number(11u32.into());
+		T::BlockNumberProvider::set_block_number(11u32.into());
 		// We expect half the original locked balance (+ any remainder that vests on the last block).
 		let expected_balance = total_transferred / 2u32.into();
 		assert_eq!(
diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs
index dbad7926a30..4101caded41 100644
--- a/substrate/frame/vesting/src/lib.rs
+++ b/substrate/frame/vesting/src/lib.rs
@@ -71,8 +71,8 @@ use frame_system::pallet_prelude::BlockNumberFor;
 use scale_info::TypeInfo;
 use sp_runtime::{
 	traits::{
-		AtLeast32BitUnsigned, Bounded, Convert, MaybeSerializeDeserialize, One, Saturating,
-		StaticLookup, Zero,
+		AtLeast32BitUnsigned, BlockNumberProvider, Bounded, Convert, MaybeSerializeDeserialize,
+		One, Saturating, StaticLookup, Zero,
 	},
 	DispatchError, RuntimeDebug,
 };
@@ -176,6 +176,9 @@ pub mod pallet {
 		/// the unvested amount.
 		type UnvestedFundsAllowedWithdrawReasons: Get<WithdrawReasons>;
 
+		/// Provider for the block number.
+		type BlockNumberProvider: BlockNumberProvider<BlockNumber = BlockNumberFor<Self>>;
+
 		/// Maximum number of vesting schedules an account may have at a given moment.
 		const MAX_VESTING_SCHEDULES: u32;
 	}
@@ -565,7 +568,7 @@ impl<T: Config> Pallet<T> {
 		schedules: Vec<VestingInfo<BalanceOf<T>, BlockNumberFor<T>>>,
 		action: VestingAction,
 	) -> (Vec<VestingInfo<BalanceOf<T>, BlockNumberFor<T>>>, BalanceOf<T>) {
-		let now = <frame_system::Pallet<T>>::block_number();
+		let now = T::BlockNumberProvider::current_block_number();
 
 		let mut total_locked_now: BalanceOf<T> = Zero::zero();
 		let filtered_schedules = action
@@ -649,7 +652,7 @@ impl<T: Config> Pallet<T> {
 				let (mut schedules, mut locked_now) =
 					Self::report_schedule_updates(schedules.to_vec(), action);
 
-				let now = <frame_system::Pallet<T>>::block_number();
+				let now = T::BlockNumberProvider::current_block_number();
 				if let Some(new_schedule) = Self::merge_vesting_info(now, schedule1, schedule2) {
 					// Merging created a new schedule so we:
 					// 1) need to add it to the accounts vesting schedule collection,
@@ -685,7 +688,7 @@ where
 	/// Get the amount that is currently being vested and cannot be transferred out of this account.
 	fn vesting_balance(who: &T::AccountId) -> Option<BalanceOf<T>> {
 		if let Some(v) = Self::vesting(who) {
-			let now = <frame_system::Pallet<T>>::block_number();
+			let now = T::BlockNumberProvider::current_block_number();
 			let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| {
 				schedule.locked_at::<T::BlockNumberToBalance>(now).saturating_add(total)
 			});
diff --git a/substrate/frame/vesting/src/mock.rs b/substrate/frame/vesting/src/mock.rs
index 67444b8d125..3af4a9c962d 100644
--- a/substrate/frame/vesting/src/mock.rs
+++ b/substrate/frame/vesting/src/mock.rs
@@ -96,6 +96,7 @@ impl Config for Test {
 	type MinVestedTransfer = MinVestedTransfer;
 	type WeightInfo = ();
 	type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
+	type BlockNumberProvider = System;
 }
 
 pub struct ExtBuilder {
-- 
GitLab