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

New CurrencyToPower and PowerToVotes #261

Merged
merged 11 commits into from
Feb 14, 2020
Merged
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bin/node/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub type AccountIndex = u32;
pub type Balance = u128;

/// Power of an account.
pub type Power = u128;
pub type Power = u32;

/// Type used for expressing timestamp.
pub type Moment = u64;
Expand Down
26 changes: 2 additions & 24 deletions bin/node/runtime/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use sp_runtime::{
{Fixed64, Perbill},
};

use crate::{constants::supply::TOTAL_POWER, Authorship, Balances, MaximumBlockWeight, NegativeImbalance, System};
use node_primitives::{Balance, Power};
use crate::{Authorship, Balances, MaximumBlockWeight, NegativeImbalance, System};
use node_primitives::Balance;

pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
Expand All @@ -35,28 +35,6 @@ impl OnUnbalanced<NegativeImbalance> for Author {
}
}

/// Struct that handles the conversion of Balance -> `u64`. This is used for staking's election
/// calculation.
pub struct PowerToVoteHandler;

impl PowerToVoteHandler {
fn factor() -> Power {
(TOTAL_POWER / u64::max_value() as Power).max(1)
}
}

impl Convert<Power, u64> for PowerToVoteHandler {
fn convert(x: Power) -> u64 {
(x / Self::factor()) as u64
}
}

impl Convert<u128, Power> for PowerToVoteHandler {
fn convert(x: u128) -> Power {
x * Self::factor()
}
}

/// Convert from weight to balance via a simple coefficient multiplication
/// The associated type C encapsulates a constant in units of balance per weight
pub struct LinearWeightToFee<C>(sp_std::marker::PhantomData<C>);
Expand Down
16 changes: 7 additions & 9 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

/// Implementations of some helper traits passed into runtime modules as associated types.
pub mod impls;
use impls::{Author, LinearWeightToFee, PowerToVoteHandler, TargetedFeeAdjustment};
use impls::{Author, LinearWeightToFee, TargetedFeeAdjustment};
/// Constant values used within the runtime.
pub mod constants;
use constants::{currency::*, supply::*, time::*};
Expand All @@ -49,17 +49,15 @@ use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
use sp_api::impl_runtime_apis;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_core::{
u32_trait::{_1, _2, _3, _4},
u32_trait::{_1, _3, _4},
OpaqueMetadata,
};
use sp_inherents::{CheckInherentsResult, InherentData};
use sp_runtime::transaction_validity::TransactionValidity;
use sp_runtime::{
create_runtime_str,
curve::PiecewiseLinear,
generic, impl_opaque_keys,
create_runtime_str, generic, impl_opaque_keys,
traits::{self, BlakeTwo256, Block as BlockT, NumberFor, OpaqueKeys, SaturatedConversion, StaticLookup},
ApplyExtrinsicResult, Perbill, Permill,
ApplyExtrinsicResult, Perbill,
};
use sp_staking::SessionIndex;
use sp_std::vec::Vec;
Expand Down Expand Up @@ -242,7 +240,7 @@ impl pallet_session::Trait for Runtime {
}

impl pallet_session::historical::Trait for Runtime {
type FullIdentification = Exposure<AccountId, Balance>;
type FullIdentification = Exposure<AccountId, Power>;
type FullIdentificationOf = ExposureOf<Runtime>;
}

Expand Down Expand Up @@ -459,7 +457,7 @@ parameter_types! {

impl pallet_staking::Trait for Runtime {
type Time = Timestamp;
type PowerToVote = PowerToVoteHandler;
// type PowerToVotes = PowerToVotesHandler;
type Event = Event;
type SessionsPerEra = SessionsPerEra;
type BondingDurationInEra = BondingDurationInEra;
Expand Down Expand Up @@ -507,7 +505,7 @@ construct_runtime!(
Offences: pallet_offences::{Module, Call, Storage, Event},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
Nicks: pallet_nicks::{Module, Call, Storage, Event<T>},

Balances: pallet_ring::{default, Error},
Kton: pallet_kton::{default, Error},
Staking: pallet_staking::{default, OfflineWorker},
Expand Down
16 changes: 1 addition & 15 deletions frame/staking/src/inflation.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,11 @@
use frame_support::traits::Get;
use sp_core::U256;
use sp_runtime::{
traits::{IntegerSquareRoot, SaturatedConversion},
Perbill, Perquintill,
};
use sp_std::convert::TryInto;

use crate::{KtonBalance, Moment, MomentOf, Power, RingBalance, Trait};

type Balance = u128;

// power is a mixture of ring and kton
// power = ring_ratio * POWER_COUNT / 2 + kton_ratio * POWER_COUNT / 2
pub fn compute_balance_power<T, S>(active: S, pool: S) -> Power
where
T: Trait,
S: TryInto<Balance>,
{
Perquintill::from_rational_approximation(active.saturated_into::<Power>(), pool.saturated_into::<Power>().max(1))
* (T::TotalPower::get() / 2)
}
use crate::{Balance, KtonBalance, Moment, MomentOf, RingBalance, Trait};

// 1 - (99 / 100) ^ sqrt(year)
// <T: Trait + 'static>() -> RingBalance<T>
Expand Down
75 changes: 37 additions & 38 deletions frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,12 @@ mod types {
pub type Points = u32;
/// Type used for expressing timestamp.
pub type Moment = Timestamp;
/// Balance of an account.
pub type Balance = u128;
/// Power of an account.
pub type Power = u128;
pub type Power = u32;
/// Votes of an account.
pub type Votes = u32;

pub type RingBalance<T> = <RingCurrency<T> as Currency<AccountId<T>>>::Balance;
pub type RingPositiveImbalance<T> = <RingCurrency<T> as Currency<AccountId<T>>>::PositiveImbalance;
Expand Down Expand Up @@ -307,21 +311,21 @@ use frame_support::{
};
use frame_system::{self as system, ensure_root, ensure_signed};
use pallet_session::{historical::OnSessionEnding, SelectInitialValidators};
use sp_phragmen::{ExtendedBalance as Votes, PhragmenStakedAssignment};
use sp_phragmen::PhragmenStakedAssignment;
use sp_runtime::{
traits::{
Bounded, CheckedSub, Convert, EnsureOrigin, One, SaturatedConversion, Saturating, SimpleArithmetic,
StaticLookup, Zero,
},
Perbill, RuntimeDebug,
Perbill, Perquintill, RuntimeDebug,
};
#[cfg(feature = "std")]
use sp_runtime::{Deserialize, Serialize};
use sp_staking::{
offence::{Offence, OffenceDetails, OnOffenceHandler, ReportOffence},
SessionIndex,
};
use sp_std::{borrow::ToOwned, marker::PhantomData, vec, vec::Vec};
use sp_std::{borrow::ToOwned, convert::TryInto, marker::PhantomData, vec, vec::Vec};

use darwinia_support::{
LockIdentifier, LockableCurrency, NormalLock, StakingLock, WithdrawLock, WithdrawReason, WithdrawReasons,
Expand Down Expand Up @@ -645,12 +649,12 @@ pub trait Trait: frame_system::Trait {
/// Time used for computing era duration.
type Time: Time;

/// Convert a balance into a number used for election calculation.
/// This must fit into a `u64` but is allowed to be sensibly lossy.
/// TODO: #1377
/// The backward convert should be removed as the new Phragmen API returns ratio.
/// The post-processing needs it but will be moved to off-chain. TODO: #2908
type PowerToVote: Convert<Power, u64> + Convert<u128, Power>;
// /// Convert a balance into a number used for election calculation.
// /// This must fit into a `u64` but is allowed to be sensibly lossy.
// /// TODO: #1377
// /// The backward convert should be removed as the new Phragmen API returns ratio.
// /// The post-processing needs it but will be moved to off-chain. TODO: #2908
// type PowerToVotes: Convert<Power, Votes>;

/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
Expand Down Expand Up @@ -778,7 +782,7 @@ decl_storage! {
config
.stakers
.iter()
.map(|&(_, _, r, _)| inflation::compute_balance_power::<T, _>(r, <Module<T>>::ring_pool()))
.map(|&(_, _, r, _)| <Module<T>>::currency_to_power::<_>(r, <Module<T>>::ring_pool()))
.min()
.unwrap_or_default()
}): Power;
Expand Down Expand Up @@ -1540,13 +1544,22 @@ decl_module! {
impl<T: Trait> Module<T> {
// PUBLIC IMMUTABLES

// power is a mixture of ring and kton
// power = ring_ratio * POWER_COUNT / 2 + kton_ratio * POWER_COUNT / 2
pub fn currency_to_power<S: TryInto<Balance>>(active: S, pool: S) -> Power {
(Perquintill::from_rational_approximation(
active.saturated_into::<Balance>(),
pool.saturated_into::<Balance>().max(1),
) * (T::TotalPower::get() as Balance / 2)) as _
}

/// The total power that can be slashed from a stash account as of right now.
pub fn slashable_power_of(stash: &T::AccountId) -> Power {
pub fn power_of(stash: &T::AccountId) -> Power {
Self::bonded(stash)
.and_then(Self::ledger)
.map(|l| {
inflation::compute_balance_power::<T, _>(l.active_ring, Self::ring_pool())
+ inflation::compute_balance_power::<T, _>(l.active_kton, Self::kton_pool())
Self::currency_to_power::<_>(l.active_ring, Self::ring_pool())
+ Self::currency_to_power::<_>(l.active_kton, Self::kton_pool())
})
.unwrap_or_default()
}
Expand Down Expand Up @@ -1873,12 +1886,13 @@ impl<T: Trait> Module<T> {

all_nominators.extend(nominator_votes);

let maybe_phragmen_result = sp_phragmen::elect::<_, _, _, T::PowerToVote>(
let maybe_phragmen_result = sp_phragmen::elect::<_, _>(
Self::validator_count() as usize,
Self::minimum_validator_count().max(1) as usize,
all_validators,
all_nominators,
Self::slashable_power_of,
Self::power_of,
T::TotalPower::get(),
);

if let Some(phragmen_result) = maybe_phragmen_result {
Expand All @@ -1888,13 +1902,7 @@ impl<T: Trait> Module<T> {
.map(|(s, _)| s.clone())
.collect::<Vec<T::AccountId>>();
let assignments = phragmen_result.assignments;
let to_votes = |p: Power| <T::PowerToVote as Convert<Power, u64>>::convert(p) as Votes;
let to_power = |v: Votes| <T::PowerToVote as Convert<Votes, Power>>::convert(v);
let mut supports = sp_phragmen::build_support_map::<_, _, _, T::PowerToVote>(
&elected_stashes,
&assignments,
Self::slashable_power_of,
);
let mut supports = sp_phragmen::build_support_map::<_, _>(&elected_stashes, &assignments, Self::power_of);

if cfg!(feature = "equalize") {
let mut staked_assignments: Vec<(T::AccountId, Vec<PhragmenStakedAssignment<T::AccountId>>)> =
Expand All @@ -1910,22 +1918,16 @@ impl<T: Trait> Module<T> {
continue;
}
for (c, per_thing) in assignment.iter() {
let nominator_stake = to_votes(Self::slashable_power_of(n));
let nominator_stake = Self::power_of(n);
let other_stake = *per_thing * nominator_stake;
staked_assignment.push((c.clone(), other_stake));
}
staked_assignments.push((n.clone(), staked_assignment));
}

let tolerance = 0_u128;
let tolerance: Votes = 0;
let iterations = 2_usize;
sp_phragmen::equalize::<_, _, T::PowerToVote, _>(
staked_assignments,
&mut supports,
tolerance,
iterations,
Self::slashable_power_of,
);
sp_phragmen::equalize::<_, _>(staked_assignments, &mut supports, tolerance, iterations, Self::power_of);
}

// Clear Stakers.
Expand All @@ -1938,19 +1940,16 @@ impl<T: Trait> Module<T> {
for (c, s) in supports.into_iter() {
// build `struct exposure` from `support`
let exposure = Exposure {
own: to_power(s.own),
own: s.own,
// This might reasonably saturate and we cannot do much about it. The sum of
// someone's stake might exceed the balance type if they have the maximum amount
// of balance and receive some support. This is super unlikely to happen, yet
// we simulate it in some tests.
total: to_power(s.total),
total: s.total,
others: s
.others
.into_iter()
.map(|(who, value)| IndividualExposure {
who,
value: to_power(value),
})
.map(|(who, value)| IndividualExposure { who, value })
.collect::<Vec<IndividualExposure<_, _>>>(),
};
if exposure.total < slot_stake {
Expand Down
2 changes: 2 additions & 0 deletions frame/support/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2018"
[dependencies]
# crates.io
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] }
num-traits = { version = "0.2.8", default-features = false }

# github.com
frame-support = { git = "https://github.com/paritytech/substrate.git", rev = "c2fccb36ffacd118fc3502aa93453580a07dc402", default-features = false }
Expand All @@ -17,6 +18,7 @@ sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate.gi
default = ["std"]
std = [
"codec/std",
"num-traits/std",

"frame-support/std",
"sp-runtime/std",
Expand Down
Loading