Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BlockNumberProvider to salary pallet config #7000

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,6 @@ impl pallet_salary::Config<AmbassadorSalaryInstance> for Runtime {
type PayoutPeriod = ConstU32<{ 15 * DAYS }>;
// Total monthly salary budget.
type Budget = ConstU128<{ 10_000 * DOLLARS }>;

type BlockNumberProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Runtime>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ impl pallet_salary::Config<FellowshipSalaryInstance> for Runtime {
type PayoutPeriod = ConstU32<{ 15 * DAYS }>;
// Total monthly salary budget.
type Budget = ConstU128<{ 100_000 * USDT_UNITS }>;

type BlockNumberProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Runtime>;
}

parameter_types! {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ extern crate alloc;
pub use ambassador::pallet_ambassador_origins;

use alloc::{vec, vec::Vec};
use ambassador::AmbassadorCoreInstance;
use ambassador::{AmbassadorCoreInstance, AmbassadorSalaryInstance};
use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
use fellowship::{pallet_fellowship_origins, Fellows, FellowshipCoreInstance};
use fellowship::{
pallet_fellowship_origins, Fellows, FellowshipCoreInstance, FellowshipSalaryInstance,
};
use impls::{AllianceProposalProvider, EqualOrGreatestRootCmp};
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
Expand Down Expand Up @@ -762,8 +764,58 @@ type Migrations = (
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, FellowshipCoreInstance>,
// unreleased
pallet_core_fellowship::migration::MigrateV0ToV1<Runtime, AmbassadorCoreInstance>,
// unreleased
pallet_salary::migration::MigrateV0ToV1<
Runtime,
SalaryBlockNumberConverter,
FellowshipSalaryInstance,
>,
pallet_salary::migration::MigrateV0ToV1<
Runtime,
SalaryBlockNumberConverter,
AmbassadorSalaryInstance,
>,
);

// Helpers for the salary pallet v0->v1 storage migration.
use sp_runtime::traits::BlockNumberProvider;
type SalaryLocalBlockNumber = <System as BlockNumberProvider>::BlockNumber;
type SalaryNewBlockNumber = <cumulus_pallet_parachain_system::RelaychainDataProvider<Runtime>
as BlockNumberProvider>::BlockNumber;
pub struct SalaryBlockNumberConverter;
impl pallet_salary::migration::v1::ConvertBlockNumber<SalaryLocalBlockNumber, SalaryNewBlockNumber>
for SalaryBlockNumberConverter
{
/// Simply convert the types. Cycle index storage item uses block number but is agnostic to the
/// time that denotes for instance.
fn convert(local: SalaryLocalBlockNumber) -> SalaryNewBlockNumber {
local
}

/// The equivalent moment in time from the perspective of the relay chain, starting from a
/// local moment in time (system block number).
fn equivalent_moment_in_time(local_moment: SalaryLocalBlockNumber) -> SalaryNewBlockNumber {
let local_block_number = System::block_number();
let local_duration = u32::abs_diff(local_block_number, local_moment);
let relay_duration = Self::equivalent_block_duration(local_duration); // 6s to 6s
let relay_block_number = ParachainSystem::last_relay_block_number();
if local_block_number >= local_moment {
// Moment was in past.
relay_block_number.saturating_sub(relay_duration)
} else {
// Moment is in future.
relay_block_number.saturating_add(relay_duration)
}
}

/// The equivalent duration from the perspective of the relay chain, starting from
/// a local duration (number of block). Identity function for Westend, since both
/// relay and collectives chain run 6s block times.
fn equivalent_block_duration(local_duration: SalaryLocalBlockNumber) -> SalaryNewBlockNumber {
local_duration
}
}

/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Expand Down
15 changes: 15 additions & 0 deletions prdoc/pr_7000.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
title: 'Adds BlockNumberProvider to pallet-core-fellowship'
doc:
- audience: Runtime Dev
description: |-
This PR adds a parameter 'BlockNumberProvider' to the pallet-salary
config such that a block provider can be set for use in the pallet. This would
usually be the frame system pallet or the appropriate relay chain. Previously
it defaulted to the frame system pallet.
crates:
- name: pallet-salary
bump: major
- name: collectives-westend-runtime
bump: minor
- name: kitchensink-runtime
bump: patch
1 change: 1 addition & 0 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,7 @@ impl pallet_salary::Config for Runtime {
type RegistrationPeriod = ConstU32<200>;
type PayoutPeriod = ConstU32<200>;
type Budget = Budget;
type BlockNumberProvider = System;
}

impl pallet_core_fellowship::Config for Runtime {
Expand Down
29 changes: 19 additions & 10 deletions substrate/frame/salary/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
#![cfg(feature = "runtime-benchmarks")]

use super::*;
use crate::Pallet as Salary;
use crate::{BlockNumberFor as SalaryBlockNumberFor, Pallet as Salary};

use frame_benchmarking::v2::*;
use frame_system::{Pallet as System, RawOrigin};
use frame_system::RawOrigin;
use sp_core::Get;
use sp_runtime::traits::BlockNumberProvider;

const SEED: u32 = 0;

Expand All @@ -47,6 +48,14 @@ fn ensure_member_with_salary<T: Config<I>, I: 'static>(who: &T::AccountId) {
mod benchmarks {
use super::*;

fn get_block_number<T: Config<I>, I: 'static>() -> SalaryBlockNumberFor<T, I> {
T::BlockNumberProvider::current_block_number()
}

fn set_block_number<T: Config<I>, I: 'static>(n: SalaryBlockNumberFor<T, I>) {
T::BlockNumberProvider::set_block_number(n);
}

#[benchmark]
fn init() {
let caller: T::AccountId = whitelisted_caller();
Expand All @@ -61,7 +70,7 @@ mod benchmarks {
fn bump() {
let caller: T::AccountId = whitelisted_caller();
Salary::<T, I>::init(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + Salary::<T, I>::cycle_period());
set_block_number::<T, I>(get_block_number::<T, I>() + Salary::<T, I>::cycle_period());

#[extrinsic_call]
_(RawOrigin::Signed(caller.clone()));
Expand All @@ -87,7 +96,7 @@ mod benchmarks {
ensure_member_with_salary::<T, I>(&caller);
Salary::<T, I>::init(RawOrigin::Signed(caller.clone()).into()).unwrap();
Salary::<T, I>::induct(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + Salary::<T, I>::cycle_period());
set_block_number::<T, I>(get_block_number::<T, I>() + Salary::<T, I>::cycle_period());
Salary::<T, I>::bump(RawOrigin::Signed(caller.clone()).into()).unwrap();

#[extrinsic_call]
Expand All @@ -102,9 +111,9 @@ mod benchmarks {
ensure_member_with_salary::<T, I>(&caller);
Salary::<T, I>::init(RawOrigin::Signed(caller.clone()).into()).unwrap();
Salary::<T, I>::induct(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + Salary::<T, I>::cycle_period());
set_block_number::<T, I>(get_block_number::<T, I>() + Salary::<T, I>::cycle_period());
Salary::<T, I>::bump(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + T::RegistrationPeriod::get());
set_block_number::<T, I>(get_block_number::<T, I>() + T::RegistrationPeriod::get());

let salary = T::Salary::get_salary(T::Members::rank_of(&caller).unwrap(), &caller);
T::Paymaster::ensure_successful(&caller, (), salary);
Expand All @@ -128,9 +137,9 @@ mod benchmarks {
ensure_member_with_salary::<T, I>(&caller);
Salary::<T, I>::init(RawOrigin::Signed(caller.clone()).into()).unwrap();
Salary::<T, I>::induct(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + Salary::<T, I>::cycle_period());
set_block_number::<T, I>(get_block_number::<T, I>() + Salary::<T, I>::cycle_period());
Salary::<T, I>::bump(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + T::RegistrationPeriod::get());
set_block_number::<T, I>(get_block_number::<T, I>() + T::RegistrationPeriod::get());

let salary = T::Salary::get_salary(T::Members::rank_of(&caller).unwrap(), &caller);
let recipient: T::AccountId = account("recipient", 0, SEED);
Expand All @@ -155,9 +164,9 @@ mod benchmarks {
ensure_member_with_salary::<T, I>(&caller);
Salary::<T, I>::init(RawOrigin::Signed(caller.clone()).into()).unwrap();
Salary::<T, I>::induct(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + Salary::<T, I>::cycle_period());
set_block_number::<T, I>(get_block_number::<T, I>() + Salary::<T, I>::cycle_period());
Salary::<T, I>::bump(RawOrigin::Signed(caller.clone()).into()).unwrap();
System::<T>::set_block_number(System::<T>::block_number() + T::RegistrationPeriod::get());
set_block_number::<T, I>(get_block_number::<T, I>() + T::RegistrationPeriod::get());

let salary = T::Salary::get_salary(T::Members::rank_of(&caller).unwrap(), &caller);
let recipient: T::AccountId = account("recipient", 0, SEED);
Expand Down
53 changes: 35 additions & 18 deletions substrate/frame/salary/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;

use codec::{Decode, Encode, MaxEncodedLen};
use core::marker::PhantomData;
use scale_info::TypeInfo;
Expand All @@ -40,6 +42,7 @@ mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub mod migration;
pub mod weights;

pub use pallet::*;
Expand All @@ -52,15 +55,15 @@ pub type Cycle = u32;
#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
pub struct StatusType<CycleIndex, BlockNumber, Balance> {
/// The index of the "current cycle" (i.e. the last cycle being processed).
cycle_index: CycleIndex,
pub cycle_index: CycleIndex,
/// The first block of the "current cycle" (i.e. the last cycle being processed).
cycle_start: BlockNumber,
pub cycle_start: BlockNumber,
/// The total budget available for all payments in the current cycle.
budget: Balance,
pub budget: Balance,
/// The total amount of the payments registered in the current cycle.
total_registrations: Balance,
pub total_registrations: Balance,
/// The total amount of unregistered payments which have been made in the current cycle.
total_unregistered_paid: Balance,
pub total_unregistered_paid: Balance,
}

/// The state of a specific payment claim.
Expand Down Expand Up @@ -89,9 +92,14 @@ pub struct ClaimantStatus<CycleIndex, Balance, Id> {
pub mod pallet {
use super::*;
use frame_support::{dispatch::Pays, pallet_prelude::*};
use frame_system::pallet_prelude::*;
use frame_system::pallet_prelude::{ensure_signed, OriginFor};
use sp_runtime::traits::BlockNumberProvider;

/// The in-code storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T, I = ()>(PhantomData<(T, I)>);

#[pallet::config]
Expand Down Expand Up @@ -125,27 +133,36 @@ pub mod pallet {
/// The number of blocks between sequential payout cycles is the sum of this and
/// `PayoutPeriod`.
#[pallet::constant]
type RegistrationPeriod: Get<BlockNumberFor<Self>>;
type RegistrationPeriod: Get<BlockNumberFor<Self, I>>;

/// The number of blocks within a cycle which accounts have to claim the payout.
///
/// The number of blocks between sequential payout cycles is the sum of this and
/// `RegistrationPeriod`.
#[pallet::constant]
type PayoutPeriod: Get<BlockNumberFor<Self>>;
type PayoutPeriod: Get<BlockNumberFor<Self, I>>;

/// The total budget per cycle.
///
/// This may change over the course of a cycle without any problem.
#[pallet::constant]
type Budget: Get<BalanceOf<Self, I>>;

/// Provides the current block number.
///
/// This is usually `cumulus_pallet_parachain_system::RelaychainDataProvider` if a
/// parachain, or `frame_system::Pallet` if a solo- or relaychain.
type BlockNumberProvider: BlockNumberProvider;
}

pub type CycleIndexOf<T> = BlockNumberFor<T>;
pub type BlockNumberFor<T, I> =
<<T as Config<I>>::BlockNumberProvider as BlockNumberProvider>::BlockNumber;
pub type CycleIndexOf<T, I> = BlockNumberFor<T, I>;
pub type BalanceOf<T, I> = <<T as Config<I>>::Paymaster as Pay>::Balance;
pub type IdOf<T, I> = <<T as Config<I>>::Paymaster as Pay>::Id;
pub type StatusOf<T, I> = StatusType<CycleIndexOf<T>, BlockNumberFor<T>, BalanceOf<T, I>>;
pub type ClaimantStatusOf<T, I> = ClaimantStatus<CycleIndexOf<T>, BalanceOf<T, I>, IdOf<T, I>>;
pub type StatusOf<T, I> = StatusType<CycleIndexOf<T, I>, BlockNumberFor<T, I>, BalanceOf<T, I>>;
pub type ClaimantStatusOf<T, I> =
ClaimantStatus<CycleIndexOf<T, I>, BalanceOf<T, I>, IdOf<T, I>>;

/// The overall status of the system.
#[pallet::storage]
Expand All @@ -172,7 +189,7 @@ pub mod pallet {
id: <T::Paymaster as Pay>::Id,
},
/// The next cycle begins.
CycleStarted { index: CycleIndexOf<T> },
CycleStarted { index: CycleIndexOf<T, I> },
/// A member swapped their account.
Swapped { who: T::AccountId, new_who: T::AccountId },
}
Expand Down Expand Up @@ -218,7 +235,7 @@ pub mod pallet {
#[pallet::call_index(0)]
pub fn init(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _ = ensure_signed(origin)?;
let now = frame_system::Pallet::<T>::block_number();
let now = T::BlockNumberProvider::current_block_number();
ensure!(!Status::<T, I>::exists(), Error::<T, I>::AlreadyStarted);
let status = StatusType {
cycle_index: Zero::zero(),
Expand All @@ -240,7 +257,7 @@ pub mod pallet {
#[pallet::call_index(1)]
pub fn bump(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _ = ensure_signed(origin)?;
let now = frame_system::Pallet::<T>::block_number();
let now = T::BlockNumberProvider::current_block_number();
let cycle_period = Self::cycle_period();
let mut status = Status::<T, I>::get().ok_or(Error::<T, I>::NotStarted)?;
status.cycle_start.saturating_accrue(cycle_period);
Expand Down Expand Up @@ -286,7 +303,7 @@ pub mod pallet {
let rank = T::Members::rank_of(&who).ok_or(Error::<T, I>::NotMember)?;
let mut status = Status::<T, I>::get().ok_or(Error::<T, I>::NotStarted)?;
let mut claimant = Claimant::<T, I>::get(&who).ok_or(Error::<T, I>::NotInducted)?;
let now = frame_system::Pallet::<T>::block_number();
let now = T::BlockNumberProvider::current_block_number();
ensure!(
now < status.cycle_start + T::RegistrationPeriod::get(),
Error::<T, I>::TooLate
Expand Down Expand Up @@ -386,17 +403,17 @@ pub mod pallet {
pub fn status() -> Option<StatusOf<T, I>> {
Status::<T, I>::get()
}
pub fn last_active(who: &T::AccountId) -> Result<CycleIndexOf<T>, DispatchError> {
pub fn last_active(who: &T::AccountId) -> Result<CycleIndexOf<T, I>, DispatchError> {
Ok(Claimant::<T, I>::get(&who).ok_or(Error::<T, I>::NotInducted)?.last_active)
}
pub fn cycle_period() -> BlockNumberFor<T> {
pub fn cycle_period() -> BlockNumberFor<T, I> {
T::RegistrationPeriod::get() + T::PayoutPeriod::get()
}
fn do_payout(who: T::AccountId, beneficiary: T::AccountId) -> DispatchResult {
let mut status = Status::<T, I>::get().ok_or(Error::<T, I>::NotStarted)?;
let mut claimant = Claimant::<T, I>::get(&who).ok_or(Error::<T, I>::NotInducted)?;

let now = frame_system::Pallet::<T>::block_number();
let now = T::BlockNumberProvider::current_block_number();
ensure!(
now >= status.cycle_start + T::RegistrationPeriod::get(),
Error::<T, I>::TooEarly,
Expand Down
Loading
Loading