Extended Balance Type for Staking's Election (#2134)

* First draft of extended balance type

* Test cleanup.

* Update staking docs.

* Add a good failing test case for quintill

* Bring back saturating.

* Some final fixes

* A few more.

* Update wasm; Bump spec;

* Re-bump.

* Custom lossy conversion from currency to vote

* remove print

* Fix reverse conversion issue.

* void. Re-trigger ci.
This commit is contained in:
Kian Peymani
2019-03-29 20:00:15 +04:30
committed by Gav Wood
parent 086d55397b
commit 958cc7efea
10 changed files with 474 additions and 389 deletions
+18 -52
View File
@@ -254,82 +254,48 @@ impl From<codec::Compact<Perbill>> for Perbill {
}
}
/// Perquintill is parts-per-quintillion. It stores a value between 0 and 1 in fixed point and
/// PerU128 is parts-per-u128-max-value. It stores a value between 0 and 1 in fixed point and
/// provides a means to multiply some other value by that.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)]
pub struct Perquintill(u64);
pub struct PerU128(u128);
const QUINTILLION: u64 = 1_000_000_000_000_000_000;
const U128: u128 = u128::max_value();
impl Perquintill {
impl PerU128 {
/// Nothing.
pub fn zero() -> Self { Self(0) }
/// Everything.
pub fn one() -> Self { Self(QUINTILLION) }
pub fn one() -> Self { Self(U128) }
/// Construct new instance where `x` is in quintillionths. Value equivalent to `x / 1,000,000,000,000,000,000`.
pub fn from_quintillionths(x: u64) -> Self { Self(x.min(QUINTILLION)) }
/// Construct new instance where `x` is in billionths. Value equivalent to `x / 1,000,000,000`.
pub fn from_billionths(x: u64) -> Self { Self(x.min(1_000_000_000) * 1_000_000_000 ) }
/// Construct new instance where `x` is in millionths. Value equivalent to `x / 1,000,000`.
pub fn from_millionths(x: u64) -> Self { Self(x.min(1_000_000) * 1000_000_000_000) }
/// Construct new instance where `x` is parts in u128::max_value. Equal to x/U128::max_value.
pub fn from_max_value(x: u128) -> Self { Self(x) }
/// Construct new instance where `x` is denominator and the nominator is 1.
pub fn from_xth(x: u64) -> Self { Self(QUINTILLION / x.min(QUINTILLION)) }
#[cfg(feature = "std")]
/// Construct new instance whose value is equal to `x` (between 0 and 1).
pub fn from_fraction(x: f64) -> Self { Self((x.max(0.0).min(1.0) * QUINTILLION as f64) as u64) }
pub fn from_xth(x: u128) -> Self { Self(U128/x.max(1)) }
}
impl ::rstd::ops::Deref for Perquintill {
type Target = u64;
impl ::rstd::ops::Deref for PerU128 {
type Target = u128;
fn deref(&self) -> &u64 {
fn deref(&self) -> &u128 {
&self.0
}
}
impl<N> ::rstd::ops::Mul<N> for Perquintill
where
N: traits::As<u64>
{
type Output = N;
fn mul(self, b: N) -> Self::Output {
<N as traits::As<u64>>::sa(b.as_().saturating_mul(self.0) / QUINTILLION)
}
}
#[cfg(feature = "std")]
impl From<f64> for Perquintill {
fn from(x: f64) -> Perquintill {
Perquintill::from_fraction(x)
}
}
#[cfg(feature = "std")]
impl From<f32> for Perquintill {
fn from(x: f32) -> Perquintill {
Perquintill::from_fraction(x as f64)
}
}
impl codec::CompactAs for Perquintill {
type As = u64;
fn encode_as(&self) -> &u64 {
impl codec::CompactAs for PerU128 {
type As = u128;
fn encode_as(&self) -> &u128 {
&self.0
}
fn decode_from(x: u64) -> Perquintill {
Perquintill(x)
fn decode_from(x: u128) -> PerU128 {
Self(x)
}
}
impl From<codec::Compact<Perquintill>> for Perquintill {
fn from(x: codec::Compact<Perquintill>) -> Perquintill {
impl From<codec::Compact<PerU128>> for PerU128 {
fn from(x: codec::Compact<PerU128>) -> PerU128 {
x.0
}
}
@@ -152,6 +152,35 @@ impl<A, B: Default> Convert<A, B> for () {
fn convert(_: A) -> B { Default::default() }
}
/// A structure that converts the currency type into a lossy u64
/// And back from u128
pub struct CurrencyToVoteHandler;
impl Convert<u128, u64> for CurrencyToVoteHandler {
fn convert(x: u128) -> u64 {
if x >> 96 == 0 {
// Remove dust; divide by 2^32
(x >> 32) as u64
} else {
u64::max_value()
}
}
}
impl Convert<u128, u128> for CurrencyToVoteHandler {
fn convert(x: u128) -> u128 {
// if it practically fits in u64
if x >> 64 == 0 {
// Add zero dust; multiply by 2^32
x << 32
}
else {
// 0000_0000_FFFF_FFFF_FFFF_FFFF_0000_0000
(u64::max_value() << 32) as u128
}
}
}
/// A structure that performs identity conversion.
pub struct Identity;
impl<T> Convert<T, T> for Identity {