Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
2c7960e
Add stepped curve for referenda
gavofyork Mar 26, 2022
f756d98
Treasury SpendOrigin
gavofyork Mar 28, 2022
de49a27
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork Apr 4, 2022
788a85f
Add tests
gavofyork Apr 4, 2022
9b967e7
Better Origin Or-gating
gavofyork Apr 4, 2022
b84e299
Reciprocal curve
gavofyork Apr 10, 2022
c8e8a5c
Tests for reciprical and rounding in PerThings
gavofyork Apr 11, 2022
a1a4619
Tweaks and new quad curve
gavofyork Apr 12, 2022
5710058
Const derivation of reciprocal curve parameters
gavofyork Apr 12, 2022
6bde6aa
Remove some unneeded code
gavofyork Apr 12, 2022
abb8a8f
Actually useful linear curve
gavofyork Apr 12, 2022
9cecb07
Fixes
gavofyork Apr 12, 2022
31da176
Provisional curves
gavofyork Apr 12, 2022
e6c0f02
Rejig 'turnout' as 'support'
gavofyork Apr 13, 2022
7aeab6c
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork Apr 13, 2022
ed050ca
Use TypedGet
gavofyork Apr 13, 2022
386977a
Fixes
gavofyork Apr 13, 2022
2cd8a46
Enable curve's ceil to be configured
gavofyork Apr 13, 2022
cb567e5
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork Apr 27, 2022
3f424ae
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 11, 2022
485fd23
Formatting
gavofyork May 11, 2022
f5d6f45
Fixes
gavofyork May 11, 2022
7ce42e8
Fixes
gavofyork May 11, 2022
b25bc5f
Fixes
gavofyork May 11, 2022
45208e0
Remove EnsureOneOf
gavofyork May 11, 2022
35764fb
Fixes
gavofyork May 11, 2022
3b53be6
Fixes
gavofyork May 11, 2022
cbadc3e
Fixes
gavofyork May 12, 2022
940f4b3
Fixes
gavofyork May 12, 2022
a091e9d
Formatting
gavofyork May 12, 2022
73bbf7c
Fixes
gavofyork May 12, 2022
ef59083
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 12, 2022
a291d47
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 17, 2022
8019e33
Update frame/support/src/traits/dispatch.rs
gavofyork May 18, 2022
7596264
Grumbles
gavofyork May 18, 2022
2b4a20a
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 18, 2022
40ca11e
Formatting
gavofyork May 18, 2022
18c6438
Fixes
gavofyork May 18, 2022
ed23dc4
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 19, 2022
d04ebd0
APIs of VoteTally should include class
gavofyork May 19, 2022
91b1094
Fixes
gavofyork May 19, 2022
471b43a
Fix overlay prefix removal result
gavofyork May 18, 2022
92cd9a3
Second part of the overlay prefix removal fix.
gavofyork May 18, 2022
0239621
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 19, 2022
d504d70
Formatting
gavofyork May 19, 2022
cace119
Fixes
gavofyork May 19, 2022
e988654
Add some tests and make clear rounding algo
gavofyork May 19, 2022
38f14fd
Fixes
gavofyork May 20, 2022
064de3d
Formatting
gavofyork May 20, 2022
4f456f8
Revert questionable fix
gavofyork May 24, 2022
697bff5
Introduce test for kill_prefix
gavofyork May 24, 2022
d111c87
Fixes
gavofyork May 25, 2022
244c5f4
Formatting
gavofyork May 25, 2022
656baff
Fixes
gavofyork May 25, 2022
bcce142
Fix possible overflow
gavofyork May 25, 2022
af7b81e
Docs
gavofyork May 25, 2022
ad9a732
Add benchmark test
gavofyork May 25, 2022
fd5e03a
Formatting
gavofyork May 25, 2022
18c72d3
Merge remote-tracking branch 'origin/master' into gav-gov2-tweaks
gavofyork May 29, 2022
db730db
Update frame/referenda/src/types.rs
gavofyork May 30, 2022
c251948
Docs
gavofyork May 30, 2022
4088a11
Merge branch 'gav-gov2-tweaks' of github.com:paritytech/substrate int…
gavofyork May 30, 2022
9b1bd8b
Fixes
gavofyork May 30, 2022
d2730c2
Use latest API in tests
gavofyork May 30, 2022
5f7b13e
Formatting
gavofyork May 30, 2022
b58dbbc
Whitespace
gavofyork May 30, 2022
e1b00d8
Use latest API in tests
gavofyork May 30, 2022
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
Next Next commit
Add stepped curve for referenda
  • Loading branch information
gavofyork committed Mar 26, 2022
commit 2c7960e8d2a8caaca8f67f01fe9f67c31ebee62f
139 changes: 102 additions & 37 deletions frame/referenda/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::*;
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
use frame_support::{traits::schedule::Anon, Parameter};
use scale_info::TypeInfo;
use sp_runtime::RuntimeDebug;
use sp_runtime::{RuntimeDebug, PerThing};
use sp_std::fmt::Debug;

pub type BalanceOf<T, I = ()> =
Expand Down Expand Up @@ -91,40 +91,6 @@ impl<T: Ord, S: Get<u32>> InsertSorted<T> for BoundedVec<T, S> {
}
}

#[cfg(test)]
mod tests {
use super::*;
use frame_support::traits::ConstU32;

#[test]
fn insert_sorted_works() {
let mut b: BoundedVec<u32, ConstU32<6>> = vec![20, 30, 40].try_into().unwrap();
assert!(b.insert_sorted_by_key(10, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40][..]);

assert!(b.insert_sorted_by_key(60, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 60][..]);

assert!(b.insert_sorted_by_key(50, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]);

assert!(!b.insert_sorted_by_key(9, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(11, |&x| x));
assert_eq!(&b[..], &[11, 20, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(21, |&x| x));
assert_eq!(&b[..], &[20, 21, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(61, |&x| x));
assert_eq!(&b[..], &[21, 30, 40, 50, 60, 61][..]);

assert!(b.insert_sorted_by_key(51, |&x| x));
assert_eq!(&b[..], &[30, 40, 50, 51, 60, 61][..]);
}
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct DecidingStatus<BlockNumber> {
/// When this referendum began being "decided". If confirming, then the
Expand Down Expand Up @@ -284,19 +250,29 @@ impl<
pub enum Curve {
/// Linear curve starting at `(0, begin)`, ending at `(period, begin - delta)`.
LinearDecreasing { begin: Perbill, delta: Perbill },
/// Stepped curve, beginning at `(0, begin)`, then remaining constant for `period`, at which
/// point it steps down to `(period, begin - step)`. It then remains constant for another
/// `period` before stepping down to `(period * 2, begin - step * 2)`. This pattern continues
/// but the `y` component has a lower limit of `end`.
SteppedDecreasing { begin: Perbill, end: Perbill, step: Perbill, period: Perbill },
}

impl Curve {
/// Determine the `y` value for the given `x` value.
pub(crate) fn threshold(&self, x: Perbill) -> Perbill {
match self {
Self::LinearDecreasing { begin, delta } => *begin - (*delta * x).min(*begin),
Self::SteppedDecreasing { begin, end, step, period } =>
(*begin - (step.int_mul(x.int_div(*period))).min(*begin)).max(*end),
}
}

/// Determine the smallest `x` value such that `passing` returns `true` when passed along with
/// the given `y` value.
///
/// If `passing` never returns `true` for any value of `x` when paired with `y`, then
/// `Perbill::one` may be returned.
///
/// ```nocompile
/// let c = Curve::LinearDecreasing { begin: Perbill::one(), delta: Perbill::one() };
/// // ^^^ Can be any curve.
Expand All @@ -309,9 +285,15 @@ impl Curve {
match self {
Self::LinearDecreasing { begin, delta } =>
if delta.is_zero() {
return *delta
*delta
} else {
return (*begin - y.min(*begin)).min(*delta) / *delta
(*begin - y.min(*begin)).min(*delta) / *delta
},
Self::SteppedDecreasing { begin, end, step, period } =>
if y < *end {
Perbill::one()
} else {
period.int_mul((*begin - y.min(*begin) + step.less_epsilon().unwrap_or(Zero::zero())).int_div(*step))
},
}
}
Expand All @@ -334,6 +316,89 @@ impl Debug for Curve {
(*begin - *delta) * 100u32,
)
},
Self::SteppedDecreasing { begin, end, step, period } => {
write!(
f,
"Stepped[(0, {}%) -> (1, {}%) by ({}%, {}%)]",
*begin * 100u32,
*end * 100u32,
*period * 100u32,
*step * 100u32,
)
},
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use sp_runtime::PerThing;
use frame_support::traits::ConstU32;

#[test]
fn insert_sorted_works() {
let mut b: BoundedVec<u32, ConstU32<6>> = vec![20, 30, 40].try_into().unwrap();
assert!(b.insert_sorted_by_key(10, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40][..]);

assert!(b.insert_sorted_by_key(60, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 60][..]);

assert!(b.insert_sorted_by_key(50, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]);

assert!(!b.insert_sorted_by_key(9, |&x| x));
assert_eq!(&b[..], &[10, 20, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(11, |&x| x));
assert_eq!(&b[..], &[11, 20, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(21, |&x| x));
assert_eq!(&b[..], &[20, 21, 30, 40, 50, 60][..]);

assert!(b.insert_sorted_by_key(61, |&x| x));
assert_eq!(&b[..], &[21, 30, 40, 50, 60, 61][..]);

assert!(b.insert_sorted_by_key(51, |&x| x));
assert_eq!(&b[..], &[30, 40, 50, 51, 60, 61][..]);
}

#[test]
fn stepped_decreasing_works() {
let percent = |x| Perbill::from_percent(x);
let c = Curve::SteppedDecreasing {
begin: percent(80),
end: percent(30),
step: percent(10),
period: percent(15),
};
assert_eq!(c.threshold(percent(0)), percent(80));
assert_eq!(c.threshold(percent(15).less_epsilon().unwrap()), percent(80));
assert_eq!(c.threshold(percent(15)), percent(70));
assert_eq!(c.threshold(percent(30).less_epsilon().unwrap()), percent(70));
assert_eq!(c.threshold(percent(30)), percent(60));
assert_eq!(c.threshold(percent(45).less_epsilon().unwrap()), percent(60));
assert_eq!(c.threshold(percent(45)), percent(50));
assert_eq!(c.threshold(percent(60).less_epsilon().unwrap()), percent(50));
assert_eq!(c.threshold(percent(60)), percent(40));
assert_eq!(c.threshold(percent(75).less_epsilon().unwrap()), percent(40));
assert_eq!(c.threshold(percent(75)), percent(30));
assert_eq!(c.threshold(percent(100)), percent(30));

assert_eq!(c.delay(percent(100)), percent(0));
assert_eq!(c.delay(percent(80)), percent(0));
assert_eq!(c.delay(percent(80).less_epsilon().unwrap()), percent(15));
assert_eq!(c.delay(percent(70)), percent(15));
assert_eq!(c.delay(percent(70).less_epsilon().unwrap()), percent(30));
assert_eq!(c.delay(percent(60)), percent(30));
assert_eq!(c.delay(percent(60).less_epsilon().unwrap()), percent(45));
assert_eq!(c.delay(percent(50)), percent(45));
assert_eq!(c.delay(percent(50).less_epsilon().unwrap()), percent(60));
assert_eq!(c.delay(percent(40)), percent(60));
assert_eq!(c.delay(percent(40).less_epsilon().unwrap()), percent(75));
assert_eq!(c.delay(percent(30)), percent(75));
assert_eq!(c.delay(percent(30).less_epsilon().unwrap()), percent(100));
assert_eq!(c.delay(percent(0)), percent(100));
}
}
17 changes: 17 additions & 0 deletions primitives/arithmetic/src/per_things.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ pub trait PerThing:
self.deconstruct() == Self::ACCURACY
}

/// Return the next lower value to `self` or an error with the same value if `self` is already
/// zero.
fn less_epsilon(self) -> Result<Self, Self> {
if self.is_zero() { return Err(self) }
Ok(Self::from_parts(self.deconstruct() - One::one()))
}

/// Build this type from a percent. Equivalent to `Self::from_parts(x * Self::ACCURACY / 100)`
/// but more accurate and can cope with potential type overflows.
fn from_percent(x: Self::Inner) -> Self {
Expand Down Expand Up @@ -589,6 +596,16 @@ macro_rules! implement_per_thing {
<Self as PerThing>::from_rational(p, q)
}

/// Integer multiplication with another value, saturating at 1.
pub fn int_mul(self, b: $type) -> Self {
PerThing::from_parts(self.0.saturating_mul(b))
}

/// Integer division with another value, rounding down.
pub fn int_div(self, b: Self) -> $type {
self.0 / b.0
}

/// See [`PerThing::mul_floor`].
pub fn mul_floor<N>(self, b: N) -> N
where
Expand Down