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
Prev Previous commit
Next Next commit
Rejig 'turnout' as 'support'
  • Loading branch information
gavofyork committed Apr 13, 2022
commit e6c0f02a95430a429422fadd42290a5256c34480
2 changes: 1 addition & 1 deletion bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ impl pallet_referenda::TracksInfo<Balance, BlockNumber> for TracksInfo {
begin: Perbill::from_percent(100),
delta: Perbill::from_percent(50),
},
min_turnout: pallet_referenda::Curve::LinearDecreasing {
min_support: pallet_referenda::Curve::LinearDecreasing {
begin: Perbill::from_percent(100),
delta: Perbill::from_percent(100),
},
Expand Down
61 changes: 38 additions & 23 deletions frame/conviction-voting/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub struct Tally<
pub ayes: Votes,
/// The number of nay votes, expressed in terms of post-conviction lock-vote.
pub nays: Votes,
/// The amount of funds currently expressing its opinion. Pre-conviction.
pub turnout: Votes,
/// The basic number of aye votes, expressed pre-conviction.
pub support: Votes,
/// Dummy.
dummy: PhantomData<Total>,
}
Expand All @@ -77,8 +77,8 @@ impl<
self.ayes
}

fn turnout(&self) -> Perbill {
Perbill::from_rational(self.turnout, Total::get())
fn support(&self) -> Perbill {
Perbill::from_rational(self.support, Total::get())
}

fn approval(&self) -> Perbill {
Expand All @@ -87,14 +87,15 @@ impl<

#[cfg(feature = "runtime-benchmarks")]
fn unanimity() -> Self {
Self { ayes: Total::get(), nays: Zero::zero(), turnout: Total::get(), dummy: PhantomData }
Self { ayes: Total::get(), nays: Zero::zero(), support: Total::get(), dummy: PhantomData }
}

#[cfg(feature = "runtime-benchmarks")]
fn from_requirements(turnout: Perbill, approval: Perbill) -> Self {
let turnout = turnout.mul_ceil(Total::get());
let ayes = approval.mul_ceil(turnout);
Self { ayes, nays: turnout - ayes, turnout, dummy: PhantomData }
fn from_requirements(support: Perbill, approval: Perbill) -> Self {
let support = support.mul_ceil(Total::get());
let ayes = approval.mul_ceil(support);
// TODO
Self { ayes, nays: support - ayes, support, dummy: PhantomData }
}
}

Expand All @@ -117,30 +118,37 @@ impl<
Self {
ayes: if vote.aye { votes } else { Zero::zero() },
nays: if vote.aye { Zero::zero() } else { votes },
turnout: capital,
support: capital,
dummy: PhantomData,
}
}

pub fn from_parts(ayes: Votes, nays: Votes, turnout: Votes) -> Self {
Self { ayes, nays, turnout, dummy: PhantomData }
pub fn from_parts(ayes_with_conviction: Votes, nays_with_conviction: Votes, ayes: Votes) -> Self {
Self {
ayes: ayes_with_conviction,
nays: nays_with_conviction,
support: ayes,
dummy: PhantomData,
}
}

/// Add an account's vote into the tally.
pub fn add(&mut self, vote: AccountVote<Votes>) -> Option<()> {
match vote {
AccountVote::Standard { vote, balance } => {
let Delegations { votes, capital } = vote.conviction.votes(balance);
self.turnout = self.turnout.checked_add(&capital)?;
match vote.aye {
true => self.ayes = self.ayes.checked_add(&votes)?,
true => {
self.support = self.support.checked_add(&capital)?;
self.ayes = self.ayes.checked_add(&votes)?
},
false => self.nays = self.nays.checked_add(&votes)?,
}
},
AccountVote::Split { aye, nay } => {
let aye = Conviction::None.votes(aye);
let nay = Conviction::None.votes(nay);
self.turnout = self.turnout.checked_add(&aye.capital)?.checked_add(&nay.capital)?;
self.support = self.support.checked_add(&aye.capital)?;
self.ayes = self.ayes.checked_add(&aye.votes)?;
self.nays = self.nays.checked_add(&nay.votes)?;
},
Expand All @@ -153,16 +161,19 @@ impl<
match vote {
AccountVote::Standard { vote, balance } => {
let Delegations { votes, capital } = vote.conviction.votes(balance);
self.turnout = self.turnout.checked_sub(&capital)?;
match vote.aye {
true => self.ayes = self.ayes.checked_sub(&votes)?,
true => {
self.support = self.support.checked_sub(&capital)?;
self.ayes = self.ayes.checked_sub(&votes)?
},
false => self.nays = self.nays.checked_sub(&votes)?,
}
},
// TODO: abstain.
AccountVote::Split { aye, nay } => {
let aye = Conviction::None.votes(aye);
let nay = Conviction::None.votes(nay);
self.turnout = self.turnout.checked_sub(&aye.capital)?.checked_sub(&nay.capital)?;
self.support = self.support.checked_sub(&aye.capital)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a change of definition, not a bug right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turnout implies all votes, support implies only aye votes?

Copy link
Member Author

@gavofyork gavofyork May 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. From the PR's summary:

Referenda/ConvictionVoting Pallets

Change "turnout" to "support"; now it only counts aye votes, rather than aye + nay in order to avoid situation where it's counter-productive to vote against.

self.ayes = self.ayes.checked_sub(&aye.votes)?;
self.nays = self.nays.checked_sub(&nay.votes)?;
},
Expand All @@ -172,18 +183,22 @@ impl<

/// Increment some amount of votes.
pub fn increase(&mut self, approve: bool, delegations: Delegations<Votes>) {
self.turnout = self.turnout.saturating_add(delegations.capital);
match approve {
true => self.ayes = self.ayes.saturating_add(delegations.votes),
true => {
self.support = self.support.saturating_add(delegations.capital);
self.ayes = self.ayes.saturating_add(delegations.votes);
},
false => self.nays = self.nays.saturating_add(delegations.votes),
}
}

/// Decrement some amount of votes.
pub fn reduce(&mut self, approve: bool, delegations: Delegations<Votes>) {
self.turnout = self.turnout.saturating_sub(delegations.capital);
match approve {
true => self.ayes = self.ayes.saturating_sub(delegations.votes),
true => {
self.support = self.support.saturating_sub(delegations.capital);
self.ayes = self.ayes.saturating_sub(delegations.votes);
},
false => self.nays = self.nays.saturating_sub(delegations.votes),
}
}
Expand All @@ -196,7 +211,7 @@ impl<
pub struct Delegations<Balance> {
/// The number of votes (this is post-conviction).
pub votes: Balance,
/// The amount of raw capital, used for the turnout.
/// The amount of raw capital, used for the support.
pub capital: Balance,
}

Expand Down
4 changes: 2 additions & 2 deletions frame/referenda/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ fn info<T: Config>(index: ReferendumIndex) -> &'static TrackInfoOf<T> {
}

fn make_passing_after<T: Config>(index: ReferendumIndex, period_portion: Perbill) {
let turnout = info::<T>(index).min_turnout.threshold(period_portion);
let support = info::<T>(index).min_support.threshold(period_portion);
let approval = info::<T>(index).min_approval.threshold(period_portion);
Referenda::<T>::access_poll(index, |status| {
if let PollStatus::Ongoing(tally, ..) = status {
*tally = T::Tally::from_requirements(turnout, approval);
*tally = T::Tally::from_requirements(support, approval);
}
});
}
Expand Down
22 changes: 13 additions & 9 deletions frame/referenda/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
//! In order to become concluded, one of three things must happen:
//! - The referendum should remain in an unbroken _Passing_ state for a period of time. This
//! is known as the _Confirmation Period_ and is determined by the track. A referendum is considered
//! _Passing_ when there is a sufficiently high turnout and approval, given the amount of time it
//! _Passing_ when there is a sufficiently high support and approval, given the amount of time it
//! has been being decided. Generally the threshold for what counts as being "sufficiently high"
//! will reduce over time. The curves setting these thresholds are determined by the track. In this
//! case, the referendum is considered _Approved_ and the proposal is scheduled for dispatch.
Expand All @@ -54,6 +54,10 @@
//!
//! Once a referendum is concluded, the decision deposit may be refunded.
//!
//! ## Terms
//! - *Support*: The number of aye-votes, pre-conviction, as a proportion of the total number of
//! pre-conviction votes able to be cast in the population.
//!
//! - [`Config`]
//! - [`Call`]

Expand Down Expand Up @@ -723,7 +727,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
&status.tally,
Zero::zero(),
track.decision_period,
&track.min_turnout,
&track.min_support,
&track.min_approval,
);
status.in_queue = false;
Expand Down Expand Up @@ -930,7 +934,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
&status.tally,
now.saturating_sub(deciding.since),
track.decision_period,
&track.min_turnout,
&track.min_support,
&track.min_approval,
);
branch = if is_passing {
Expand Down Expand Up @@ -1014,10 +1018,10 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
deciding.confirming.unwrap_or_else(|| {
// Set alarm to the point where the current voting would make it pass.
let approval = tally.approval();
let turnout = tally.turnout();
let support = tally.support();
let until_approval = track.min_approval.delay(approval);
let until_turnout = track.min_turnout.delay(turnout);
let offset = until_turnout.max(until_approval);
let until_support = track.min_support.delay(support);
let offset = until_support.max(until_approval);
deciding.since.saturating_add(offset * track.decision_period)
})
}
Expand Down Expand Up @@ -1062,16 +1066,16 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
}

/// Determine whether the given `tally` would result in a referendum passing at `elapsed` blocks
/// into a total decision `period`, given the two curves for `turnout_needed` and
/// into a total decision `period`, given the two curves for `support_needed` and
/// `approval_needed`.
fn is_passing(
tally: &T::Tally,
elapsed: T::BlockNumber,
period: T::BlockNumber,
turnout_needed: &Curve,
support_needed: &Curve,
approval_needed: &Curve,
) -> bool {
let x = Perbill::from_rational(elapsed.min(period), period);
turnout_needed.passing(x, tally.turnout()) && approval_needed.passing(x, tally.approval())
support_needed.passing(x, tally.support()) && approval_needed.passing(x, tally.approval())
}
}
16 changes: 8 additions & 8 deletions frame/referenda/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ impl TracksInfo<u64, u64> for TestTracksInfo {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(50),
},
min_turnout: Curve::LinearDecreasing {
min_support: Curve::LinearDecreasing {
length: Perbill::from_percent(100),
floor: Perbill::from_percent(100),
},
Expand All @@ -195,7 +195,7 @@ impl TracksInfo<u64, u64> for TestTracksInfo {
length: Perbill::from_percent(55),
floor: Perbill::from_percent(5),
},
min_turnout: Curve::LinearDecreasing {
min_support: Curve::LinearDecreasing {
length: Perbill::from_percent(10),
floor: Perbill::from_percent(10),
},
Expand Down Expand Up @@ -264,8 +264,8 @@ impl VoteTally<u32> for Tally {
self.ayes
}

fn turnout(&self) -> Perbill {
Perbill::from_percent(self.ayes + self.nays)
fn support(&self) -> Perbill {
Perbill::from_percent(self.ayes)
}

fn approval(&self) -> Perbill {
Expand All @@ -278,10 +278,10 @@ impl VoteTally<u32> for Tally {
}

#[cfg(feature = "runtime-benchmarks")]
fn from_requirements(turnout: Perbill, approval: Perbill) -> Self {
let turnout = turnout.mul_ceil(100u32);
let ayes = approval.mul_ceil(turnout);
Self { ayes, nays: turnout - ayes }
fn from_requirements(support: Perbill, approval: Perbill) -> Self {
let ayes = support.mul_ceil(100u32);
let nays = (ayes * 1_000_000_000u64 / approval.deconstruct() as u64) - ayes;
Self { ayes, nays }
}
}

Expand Down
42 changes: 21 additions & 21 deletions frame/referenda/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ pub struct TrackInfo<Balance, Moment> {
/// Minimum aye votes as percentage of overall conviction-weighted votes needed for
/// approval as a function of time into decision period.
pub min_approval: Curve,
/// Minimum turnout as percentage of overall population that is needed for
/// approval as a function of time into decision period.
pub min_turnout: Curve,
/// Minimum pre-conviction aye-votes ("support") as percentage of overall population that is
/// needed for approval as a function of time into decision period.
pub min_support: Curve,
}

/// Information on the voting tracks.
Expand Down Expand Up @@ -493,45 +493,45 @@ mod tests {
}

const TIP_APP: Curve = Curve::make_linear(10, 28, percent(50));
const TIP_QUO: Curve = Curve::make_reciprocal(1, 28, percent(4), percent(0));
const TIP_SUP: Curve = Curve::make_reciprocal(1, 28, percent(4), percent(0));
const ROOT_APP: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50));
const ROOT_QUO: Curve = Curve::make_linear(28, 28, percent(0));
const ROOT_SUP: Curve = Curve::make_linear(28, 28, percent(0));
const WHITE_APP: Curve = Curve::make_reciprocal(16, 28 * 24, percent(96), percent(50));
const WHITE_QUO: Curve = Curve::make_reciprocal(1, 28, percent(20), percent(10));
const WHITE_SUP: Curve = Curve::make_reciprocal(1, 28, percent(20), percent(10));
const SMALL_APP: Curve = Curve::make_linear(10, 28, percent(50));
const SMALL_QUO: Curve = Curve::make_reciprocal(8, 28, percent(1), percent(0));
const SMALL_SUP: Curve = Curve::make_reciprocal(8, 28, percent(1), percent(0));
const MID_APP: Curve = Curve::make_linear(17, 28, percent(50));
const MID_QUO: Curve = Curve::make_reciprocal(12, 28, percent(1), percent(0));
const MID_SUP: Curve = Curve::make_reciprocal(12, 28, percent(1), percent(0));
const BIG_APP: Curve = Curve::make_linear(23, 28, percent(50));
const BIG_QUO: Curve = Curve::make_reciprocal(16, 28, percent(1), percent(0));
const BIG_SUP: Curve = Curve::make_reciprocal(16, 28, percent(1), percent(0));
const HUGE_APP: Curve = Curve::make_linear(28, 28, percent(50));
const HUGE_QUO: Curve = Curve::make_reciprocal(20, 28, percent(1), percent(0));
const HUGE_SUP: Curve = Curve::make_reciprocal(20, 28, percent(1), percent(0));
const PARAM_APP: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50));
const PARAM_QUO: Curve = Curve::make_reciprocal(7, 28, percent(10), percent(0));
const PARAM_SUP: Curve = Curve::make_reciprocal(7, 28, percent(10), percent(0));
const ADMIN_APP: Curve = Curve::make_linear(17, 28, percent(50));
const ADMIN_QUO: Curve = Curve::make_reciprocal(12, 28, percent(1), percent(0));
const ADMIN_SUP: Curve = Curve::make_reciprocal(12, 28, percent(1), percent(0));

#[test]
#[should_panic]
fn check_curves() {
TIP_APP.info(28u32, "Tip Approval");
TIP_QUO.info(28u32, "Tip Quorum");
TIP_SUP.info(28u32, "Tip Support");
ROOT_APP.info(28u32, "Root Approval");
ROOT_QUO.info(28u32, "Root Quorum");
ROOT_SUP.info(28u32, "Root Support");
WHITE_APP.info(28u32, "Whitelist Approval");
WHITE_QUO.info(28u32, "Whitelist Quorum");
WHITE_SUP.info(28u32, "Whitelist Support");
SMALL_APP.info(28u32, "Small Spend Approval");
SMALL_QUO.info(28u32, "Small Spend Quorum");
SMALL_SUP.info(28u32, "Small Spend Support");
MID_APP.info(28u32, "Mid Spend Approval");
MID_QUO.info(28u32, "Mid Spend Quorum");
MID_SUP.info(28u32, "Mid Spend Support");
BIG_APP.info(28u32, "Big Spend Approval");
BIG_QUO.info(28u32, "Big Spend Quorum");
BIG_SUP.info(28u32, "Big Spend Support");
HUGE_APP.info(28u32, "Huge Spend Approval");
HUGE_QUO.info(28u32, "Huge Spend Quorum");
HUGE_SUP.info(28u32, "Huge Spend Support");
PARAM_APP.info(28u32, "Mid-tier Parameter Change Approval");
PARAM_QUO.info(28u32, "Mid-tier Parameter Change Quorum");
PARAM_SUP.info(28u32, "Mid-tier Parameter Change Support");
ADMIN_APP.info(28u32, "Admin (e.g. Cancel Slash) Approval");
ADMIN_QUO.info(28u32, "Admin (e.g. Cancel Slash) Quorum");
ADMIN_SUP.info(28u32, "Admin (e.g. Cancel Slash) Support");
assert!(false);
}

Expand Down
4 changes: 2 additions & 2 deletions frame/support/src/traits/voting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@ impl<B: UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128>> CurrencyToVote<B>

pub trait VoteTally<Votes> {
fn ayes(&self) -> Votes;
fn turnout(&self) -> Perbill;
fn support(&self) -> Perbill;
fn approval(&self) -> Perbill;
#[cfg(feature = "runtime-benchmarks")]
fn unanimity() -> Self;
#[cfg(feature = "runtime-benchmarks")]
fn from_requirements(turnout: Perbill, approval: Perbill) -> Self;
fn from_requirements(support: Perbill, approval: Perbill) -> Self;
}

pub enum PollStatus<Tally, Moment, Class> {
Expand Down