Skip to content

Commit

Permalink
staking: Flexible generation of reward curve and associated tweaks (p…
Browse files Browse the repository at this point in the history
…aritytech#8327)

* Initial abstraction

* Alter rest of APIs

* Fixes

* Some extra getters in Gilt pallet.

* Refactor Gilt to avoid u128 conversions

* Simplify and improve pow in per_things

* Add scalar division to per_things

* Renaming from_fraction -> from_float, drop _approximation

* Fixes

* Fixes

* Fixes

* Fixes

* Make stuff build

* Fixes

* Fixes

* Fixes

* Fixes

* Update .gitignore

Co-authored-by: Kian Paimani <[email protected]>

* Update frame/gilt/src/lib.rs

Co-authored-by: Kian Paimani <[email protected]>

* Update frame/gilt/src/mock.rs

Co-authored-by: Kian Paimani <[email protected]>

* Fixes

* Fixes

* Fixes

Co-authored-by: Shawn Tabrizi <[email protected]>
Co-authored-by: Kian Paimani <[email protected]>
  • Loading branch information
3 people authored Mar 16, 2021
1 parent 8a4aeba commit 39b3131
Show file tree
Hide file tree
Showing 32 changed files with 342 additions and 226 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ rls*.log
.cargo/
.cargo-remote.toml
*.bin
*.iml
2 changes: 1 addition & 1 deletion bin/node/runtime/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ mod multiplier_tests {
let t1 = v * (s/m - ss/m);
let t2 = v.powi(2) * (s/m - ss/m).powi(2) / 2.0;
let next_float = previous_float * (1.0 + t1 + t2);
Multiplier::from_fraction(next_float)
Multiplier::from_float(next_float)
}

fn run_with_system_weight<F>(w: Weight, assertions: F) where F: Fn() -> () {
Expand Down
9 changes: 5 additions & 4 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ parameter_types! {
pub const ElectionLookahead: BlockNumber = EPOCH_DURATION_IN_BLOCKS / 4;
pub const MaxIterations: u32 = 10;
// 0.05%. The higher the value, the more strict solution acceptance becomes.
pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000);
pub MinSolutionScoreBump: Perbill = Perbill::from_rational(5u32, 10_000);
pub OffchainSolutionWeightLimit: Weight = RuntimeBlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic.expect("Normal extrinsics have a weight limit configured; qed")
Expand All @@ -496,7 +496,7 @@ impl pallet_staking::Config for Runtime {
pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>
>;
type SessionInterface = Self;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type NextNewSession = Session;
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
type ElectionLookahead = ElectionLookahead;
Expand All @@ -520,7 +520,7 @@ parameter_types! {
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =
pallet_election_provider_multi_phase::FallbackStrategy::Nothing;

pub SolutionImprovementThreshold: Perbill = Perbill::from_rational_approximation(1u32, 10_000);
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(1u32, 10_000);

// miner configs
pub const MultiPhaseUnsignedPriority: TransactionPriority = StakingUnsignedPriority::get() - 1u64;
Expand Down Expand Up @@ -767,7 +767,7 @@ parameter_types! {
pub const DepositPerContract: Balance = TombstoneDeposit::get();
pub const DepositPerStorageByte: Balance = deposit(0, 1);
pub const DepositPerStorageItem: Balance = deposit(1, 0);
pub RentFraction: Perbill = Perbill::from_rational_approximation(1u32, 30 * DAYS);
pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
pub const SurchargeReward: Balance = 150 * MILLICENTS;
pub const SignedClaimHandicap: u32 = 2;
pub const MaxDepth: u32 = 32;
Expand Down Expand Up @@ -1065,6 +1065,7 @@ parameter_types! {
impl pallet_gilt::Config for Runtime {
type Event = Event;
type Currency = Balances;
type CurrencyBalance = Balance;
type AdminOrigin = frame_system::EnsureRoot<AccountId>;
type Deficit = ();
type Surplus = ();
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/equivocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ impl<FullIdentification: Clone> Offence<FullIdentification>

fn slash_fraction(offenders_count: u32, validator_set_count: u32) -> Perbill {
// the formula is min((3k / n)^2, 1)
let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count);
let x = Perbill::from_rational(3 * offenders_count, validator_set_count);
// _ ^ 2
x.square()
}
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ impl<T: Config> frame_support::traits::EstimateNextSessionRotation<T::BlockNumbe
let elapsed = CurrentSlot::get().saturating_sub(Self::current_epoch_start()) + 1;

(
Some(Percent::from_rational_approximation(
Some(Percent::from_rational(
*elapsed,
T::EpochDuration::get(),
)),
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl pallet_staking::Config for Test {
type SlashCancelOrigin = frame_system::EnsureRoot<Self::AccountId>;
type SessionInterface = Self;
type UnixTime = pallet_timestamp::Module<Test>;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
type NextNewSession = Session;
type ElectionLookahead = ElectionLookahead;
Expand Down
2 changes: 1 addition & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ parameter_types! {
pub const DepositPerContract: u64 = 8 * DepositPerStorageByte::get();
pub const DepositPerStorageByte: u64 = 10_000;
pub const DepositPerStorageItem: u64 = 10_000;
pub RentFraction: Perbill = Perbill::from_rational_approximation(4u32, 10_000u32);
pub RentFraction: Perbill = Perbill::from_rational(4u32, 10_000u32);
pub const SurchargeReward: u64 = 500_000;
pub const MaxDepth: u32 = 100;
pub const MaxValueSize: u32 = 16_384;
Expand Down
60 changes: 48 additions & 12 deletions frame/gilt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub mod weights;
pub mod pallet {
use sp_std::prelude::*;
use sp_arithmetic::{Perquintill, PerThing};
use sp_runtime::traits::{Zero, Saturating, SaturatedConversion};
use sp_runtime::traits::{Zero, Saturating};
use frame_support::traits::{Currency, OnUnbalanced, ReservableCurrency};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
Expand All @@ -96,7 +96,13 @@ pub mod pallet {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

/// Currency type that this works on.
type Currency: ReservableCurrency<Self::AccountId>;
type Currency: ReservableCurrency<Self::AccountId, Balance=Self::CurrencyBalance>;

/// Just the `Currency::Balance` type; we have this item to allow us to constrain it to
/// `From<u64>`.
type CurrencyBalance:
sp_runtime::traits::AtLeast32BitUnsigned + codec::FullCodec + Copy
+ MaybeSerializeDeserialize + sp_std::fmt::Debug + Default + From<u64>;

/// Origin required for setting the target proportion to be under gilt.
type AdminOrigin: EnsureOrigin<Self::Origin>;
Expand Down Expand Up @@ -448,11 +454,10 @@ pub mod pallet {
// Multiply the proportion it is by the total issued.
let total_issuance = T::Currency::total_issuance().saturating_sub(T::IgnoredIssuance::get());
ActiveTotal::<T>::mutate(|totals| {
let nongilt_issuance: u128 = total_issuance.saturating_sub(totals.frozen)
.saturated_into();
let nongilt_issuance = total_issuance.saturating_sub(totals.frozen);
let effective_issuance = totals.proportion.left_from_one()
.saturating_reciprocal_mul(nongilt_issuance);
let gilt_value: BalanceOf<T> = (gilt.proportion * effective_issuance).saturated_into();
let gilt_value = gilt.proportion * effective_issuance;

totals.frozen = totals.frozen.saturating_sub(gilt.amount);
totals.proportion = totals.proportion.saturating_sub(gilt.proportion);
Expand Down Expand Up @@ -488,7 +493,40 @@ pub mod pallet {
}
}

/// Issuance information returned by `issuance()`.
pub struct IssuanceInfo<Balance> {
/// The balance held in reserve over all active gilts.
pub reserved: Balance,
/// The issuance not held in reserve for active gilts. Together with `reserved` this sums to
/// `Currency::total_issuance`.
pub non_gilt: Balance,
/// The balance that `reserved` is effectively worth, at present. This is not issued funds
/// and could be less than `reserved` (though in most cases should be greater).
pub effective: Balance,
}

impl<T: Config> Pallet<T> {
/// Get the target amount of Gilts that we're aiming for.
pub fn target() -> Perquintill {
ActiveTotal::<T>::get().target
}

/// Returns information on the issuance of gilts.
pub fn issuance() -> IssuanceInfo<BalanceOf<T>> {
let totals = ActiveTotal::<T>::get();

let total_issuance = T::Currency::total_issuance();
let non_gilt = total_issuance.saturating_sub(totals.frozen);
let effective = totals.proportion.left_from_one()
.saturating_reciprocal_mul(non_gilt);

IssuanceInfo {
reserved: totals.frozen,
non_gilt,
effective,
}
}

/// Attempt to enlarge our gilt-set from bids in order to satisfy our desired target amount
/// of funds frozen into gilts.
pub fn pursue_target(max_bids: u32) -> Weight {
Expand All @@ -497,11 +535,10 @@ pub mod pallet {
let missing = totals.target.saturating_sub(totals.proportion);

let total_issuance = T::Currency::total_issuance().saturating_sub(T::IgnoredIssuance::get());
let nongilt_issuance: u128 = total_issuance.saturating_sub(totals.frozen)
.saturated_into();
let nongilt_issuance = total_issuance.saturating_sub(totals.frozen);
let effective_issuance = totals.proportion.left_from_one()
.saturating_reciprocal_mul(nongilt_issuance);
let intake: BalanceOf<T> = (missing * effective_issuance).saturated_into();
let intake = missing * effective_issuance;

let (bids_taken, queues_hit) = Self::enlarge(intake, max_bids);
let first_from_each_queue = T::WeightInfo::pursue_target_per_queue(queues_hit);
Expand Down Expand Up @@ -550,13 +587,12 @@ pub mod pallet {
qs[queue_index].1 = qs[queue_index].1.saturating_sub(bid.amount);

// Now to activate the bid...
let nongilt_issuance: u128 = total_issuance.saturating_sub(totals.frozen)
.saturated_into();
let nongilt_issuance = total_issuance.saturating_sub(totals.frozen);
let effective_issuance = totals.proportion.left_from_one()
.saturating_reciprocal_mul(nongilt_issuance);
let n: u128 = amount.saturated_into();
let n = amount;
let d = effective_issuance;
let proportion = Perquintill::from_rational_approximation(n, d);
let proportion = Perquintill::from_rational(n, d);
let who = bid.who;
let index = totals.index;
totals.frozen += bid.amount;
Expand Down
1 change: 1 addition & 0 deletions frame/gilt/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ ord_parameter_types! {
impl pallet_gilt::Config for Test {
type Event = Event;
type Currency = Balances;
type CurrencyBalance = <Self as pallet_balances::Config>::Balance;
type AdminOrigin = frame_system::EnsureSignedBy<One, Self::AccountId>;
type Deficit = ();
type Surplus = ();
Expand Down
2 changes: 1 addition & 1 deletion frame/grandpa/src/equivocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ impl<FullIdentification: Clone> Offence<FullIdentification>

fn slash_fraction(offenders_count: u32, validator_set_count: u32) -> Perbill {
// the formula is min((3k / n)^2, 1)
let x = Perbill::from_rational_approximation(3 * offenders_count, validator_set_count);
let x = Perbill::from_rational(3 * offenders_count, validator_set_count);
// _ ^ 2
x.square()
}
Expand Down
2 changes: 1 addition & 1 deletion frame/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ impl pallet_staking::Config for Test {
type SlashCancelOrigin = frame_system::EnsureRoot<Self::AccountId>;
type SessionInterface = Self;
type UnixTime = pallet_timestamp::Module<Test>;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
type NextNewSession = Session;
type ElectionLookahead = ElectionLookahead;
Expand Down
8 changes: 2 additions & 6 deletions frame/im-online/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,7 @@ use frame_support::{
},
Parameter,
};
use frame_system::ensure_none;
use frame_system::offchain::{
SendTransactionTypes,
SubmitTransaction,
};
use frame_system::{ensure_none, offchain::{SendTransactionTypes, SubmitTransaction}};
pub use weights::WeightInfo;

pub mod sr25519 {
Expand Down Expand Up @@ -813,7 +809,7 @@ impl<Offender: Clone> Offence<Offender> for UnresponsivenessOffence<Offender> {
// basically, 10% can be offline with no slash, but after that, it linearly climbs up to 7%
// when 13/30 are offline (around 5% when 1/3 are offline).
if let Some(threshold) = offenders.checked_sub(validator_set_count / 10 + 1) {
let x = Perbill::from_rational_approximation(3 * threshold, validator_set_count);
let x = Perbill::from_rational(3 * threshold, validator_set_count);
x.saturating_mul(Perbill::from_percent(7))
} else {
Perbill::default()
Expand Down
2 changes: 1 addition & 1 deletion frame/offences/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl pallet_staking::Config for Test {
type SlashCancelOrigin = frame_system::EnsureRoot<Self::AccountId>;
type BondingDuration = ();
type SessionInterface = Self;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type NextNewSession = Session;
type ElectionLookahead = ();
type Call = Call;
Expand Down
2 changes: 1 addition & 1 deletion frame/session/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl pallet_staking::Config for Test {
type SlashCancelOrigin = frame_system::EnsureRoot<Self::AccountId>;
type BondingDuration = ();
type SessionInterface = Self;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type NextNewSession = Session;
type ElectionLookahead = ();
type Call = Call;
Expand Down
4 changes: 2 additions & 2 deletions frame/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,12 @@ impl<
// (0% is never returned).
let progress = if now >= offset {
let current = (now - offset) % period.clone() + One::one();
Some(Percent::from_rational_approximation(
Some(Percent::from_rational(
current.clone(),
period.clone(),
))
} else {
Some(Percent::from_rational_approximation(
Some(Percent::from_rational(
now + One::one(),
offset,
))
Expand Down
2 changes: 1 addition & 1 deletion frame/staking/fuzzer/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl pallet_staking::Config for Test {
type SlashCancelOrigin = frame_system::EnsureRoot<Self::AccountId>;
type BondingDuration = ();
type SessionInterface = Self;
type RewardCurve = RewardCurve;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type NextNewSession = Session;
type ElectionLookahead = ();
type Call = Call;
Expand Down
2 changes: 1 addition & 1 deletion frame/staking/src/inflation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn compute_total_payout<N>(
// Milliseconds per year for the Julian year (365.25 days).
const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100;

let portion = Perbill::from_rational_approximation(era_duration as u64, MILLISECONDS_PER_YEAR);
let portion = Perbill::from_rational(era_duration as u64, MILLISECONDS_PER_YEAR);
let payout = portion * yearly_inflation.calculate_for_fraction_times_denominator(
npos_token_staked,
total_tokens.clone(),
Expand Down
Loading

0 comments on commit 39b3131

Please sign in to comment.