mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 22:11:06 +00:00
Lazy reaping (#4895)
* Squash and rebase from gav-lazy-reaping * Bump version * Bump runtime again * Docs. * Remove old functions * Update frame/balances/src/lib.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/contracts/src/lib.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Warnings * Bump runtime version * Update frame/democracy/src/lib.rs Co-Authored-By: Shawn Tabrizi <shawntabrizi@gmail.com> * Update frame/system/src/lib.rs * Clean up OnReapAccount * Use frame_support debug * Bump spec * Renames and fix * Fix * Fix rename * Fix * Increase time for test Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> Co-authored-by: Benjamin Kampmann <ben.kampmann@googlemail.com>
This commit is contained in:
@@ -30,7 +30,7 @@ use frame_support::{
|
||||
weights::SimpleDispatchInfo,
|
||||
traits::{
|
||||
Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get,
|
||||
OnReapAccount, OnUnbalanced, BalanceStatus
|
||||
OnUnbalanced, BalanceStatus
|
||||
}
|
||||
};
|
||||
use frame_system::{self as system, ensure_signed, ensure_root};
|
||||
@@ -260,6 +260,24 @@ impl<BlockNumber: Parameter, Hash: Parameter> ReferendumInfo<BlockNumber, Hash>
|
||||
}
|
||||
}
|
||||
|
||||
/// State of a proxy voting account.
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)]
|
||||
pub enum ProxyState<AccountId> {
|
||||
/// Account is open to becoming a proxy but is not yet assigned.
|
||||
Open(AccountId),
|
||||
/// Account is actively being a proxy.
|
||||
Active(AccountId),
|
||||
}
|
||||
|
||||
impl<AccountId> ProxyState<AccountId> {
|
||||
fn as_active(self) -> Option<AccountId> {
|
||||
match self {
|
||||
ProxyState::Active(a) => Some(a),
|
||||
ProxyState::Open(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as Democracy {
|
||||
/// The number of (public) proposals that have been made so far.
|
||||
@@ -299,7 +317,7 @@ decl_storage! {
|
||||
|
||||
/// Who is able to vote for whom. Value is the fund-holding account, key is the
|
||||
/// vote-transaction-sending account.
|
||||
pub Proxy get(fn proxy): map hasher(blake2_256) T::AccountId => Option<T::AccountId>;
|
||||
pub Proxy get(fn proxy): map hasher(blake2_256) T::AccountId => Option<ProxyState<T::AccountId>>;
|
||||
|
||||
/// Get the account (and lock periods) to which another account is delegating vote.
|
||||
pub Delegations get(fn delegations):
|
||||
@@ -423,6 +441,12 @@ decl_error! {
|
||||
NotLocked,
|
||||
/// The lock on the account to be unlocked has not yet expired.
|
||||
NotExpired,
|
||||
/// A proxy-pairing was attempted to an account that was not open.
|
||||
NotOpen,
|
||||
/// A proxy-pairing was attempted to an account that was open to another account.
|
||||
WrongOpen,
|
||||
/// A proxy-de-pairing was attempted to an account that was not active.
|
||||
NotActive
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,8 +549,9 @@ decl_module! {
|
||||
#[compact] ref_index: ReferendumIndex,
|
||||
vote: Vote
|
||||
) -> DispatchResult {
|
||||
let who = Self::proxy(ensure_signed(origin)?).ok_or(Error::<T>::NotProxy)?;
|
||||
Self::do_vote(who, ref_index, vote)
|
||||
let who = ensure_signed(origin)?;
|
||||
let voter = Self::proxy(who).and_then(|a| a.as_active()).ok_or(Error::<T>::NotProxy)?;
|
||||
Self::do_vote(voter, ref_index, vote)
|
||||
}
|
||||
|
||||
/// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same
|
||||
@@ -659,42 +684,65 @@ decl_module! {
|
||||
}
|
||||
}
|
||||
|
||||
/// Specify a proxy. Called by the stash.
|
||||
/// Specify a proxy that is already open to us. Called by the stash.
|
||||
///
|
||||
/// NOTE: Used to be called `set_proxy`.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One extra DB entry.
|
||||
/// # </weight>
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
|
||||
fn set_proxy(origin, proxy: T::AccountId) {
|
||||
fn activate_proxy(origin, proxy: T::AccountId) {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(!<Proxy<T>>::contains_key(&proxy), Error::<T>::AlreadyProxy);
|
||||
<Proxy<T>>::insert(proxy, who)
|
||||
Proxy::<T>::try_mutate(&proxy, |a| match a.take() {
|
||||
None => Err(Error::<T>::NotOpen),
|
||||
Some(ProxyState::Active(_)) => Err(Error::<T>::AlreadyProxy),
|
||||
Some(ProxyState::Open(x)) if &x == &who => {
|
||||
*a = Some(ProxyState::Active(who));
|
||||
Ok(())
|
||||
}
|
||||
Some(ProxyState::Open(_)) => Err(Error::<T>::WrongOpen),
|
||||
})?;
|
||||
}
|
||||
|
||||
/// Clear the proxy. Called by the proxy.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One DB clear.
|
||||
/// # </weight>
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
|
||||
fn resign_proxy(origin) {
|
||||
let who = ensure_signed(origin)?;
|
||||
<Proxy<T>>::remove(who);
|
||||
}
|
||||
|
||||
/// Clear the proxy. Called by the stash.
|
||||
/// NOTE: Used to be called `resign_proxy`.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One DB clear.
|
||||
/// # </weight>
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
|
||||
fn remove_proxy(origin, proxy: T::AccountId) {
|
||||
fn close_proxy(origin) {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(
|
||||
&Self::proxy(&proxy).ok_or(Error::<T>::NotProxy)? == &who,
|
||||
Error::<T>::WrongProxy,
|
||||
);
|
||||
<Proxy<T>>::remove(proxy);
|
||||
Proxy::<T>::mutate(&who, |a| {
|
||||
if a.is_some() {
|
||||
system::Module::<T>::dec_ref(&who);
|
||||
}
|
||||
*a = None;
|
||||
});
|
||||
}
|
||||
|
||||
/// Deactivate the proxy, but leave open to this account. Called by the stash.
|
||||
///
|
||||
/// The proxy must already be active.
|
||||
///
|
||||
/// NOTE: Used to be called `remove_proxy`.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One DB clear.
|
||||
/// # </weight>
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
|
||||
fn deactivate_proxy(origin, proxy: T::AccountId) {
|
||||
let who = ensure_signed(origin)?;
|
||||
Proxy::<T>::try_mutate(&proxy, |a| match a.take() {
|
||||
None | Some(ProxyState::Open(_)) => Err(Error::<T>::NotActive),
|
||||
Some(ProxyState::Active(x)) if &x == &who => {
|
||||
*a = Some(ProxyState::Open(who));
|
||||
Ok(())
|
||||
}
|
||||
Some(ProxyState::Active(_)) => Err(Error::<T>::WrongProxy),
|
||||
})?;
|
||||
}
|
||||
|
||||
/// Delegate vote.
|
||||
@@ -818,6 +866,30 @@ decl_module! {
|
||||
Locks::<T>::remove(&target);
|
||||
Self::deposit_event(RawEvent::Unlocked(target));
|
||||
}
|
||||
|
||||
/// Become a proxy.
|
||||
///
|
||||
/// This must be called prior to a later `activate_proxy`.
|
||||
///
|
||||
/// Origin must be a Signed.
|
||||
///
|
||||
/// - `target`: The account whose votes will later be proxied.
|
||||
///
|
||||
/// `close_proxy` must be called before the account can be destroyed.
|
||||
///
|
||||
/// # <weight>
|
||||
/// - One extra DB entry.
|
||||
/// # </weight>
|
||||
#[weight = SimpleDispatchInfo::FixedNormal(100_000)]
|
||||
fn open_proxy(origin, target: T::AccountId) {
|
||||
let who = ensure_signed(origin)?;
|
||||
Proxy::<T>::mutate(&who, |a| {
|
||||
if a.is_none() {
|
||||
system::Module::<T>::inc_ref(&who);
|
||||
}
|
||||
*a = Some(ProxyState::Open(target));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,7 +1007,12 @@ impl<T: Trait> Module<T> {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn force_proxy(stash: T::AccountId, proxy: T::AccountId) {
|
||||
<Proxy<T>>::insert(proxy, stash)
|
||||
Proxy::<T>::mutate(&proxy, |o| {
|
||||
if o.is_none() {
|
||||
system::Module::<T>::inc_ref(&proxy);
|
||||
}
|
||||
*o = Some(ProxyState::Active(stash))
|
||||
})
|
||||
}
|
||||
|
||||
/// Start a referendum.
|
||||
@@ -1162,12 +1239,6 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> OnReapAccount<T::AccountId> for Module<T> {
|
||||
fn on_reap_account(who: &T::AccountId) {
|
||||
<Proxy<T>>::remove(who)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -1229,7 +1300,7 @@ mod tests {
|
||||
type ModuleToIndex = ();
|
||||
type AccountData = pallet_balances::AccountData<u64>;
|
||||
type OnNewAccount = ();
|
||||
type OnReapAccount = Balances;
|
||||
type OnKilledAccount = ();
|
||||
}
|
||||
parameter_types! {
|
||||
pub const ExistentialDeposit: u64 = 1;
|
||||
@@ -1968,29 +2039,45 @@ mod tests {
|
||||
fn proxy_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(Democracy::proxy(10), None);
|
||||
assert_ok!(Democracy::set_proxy(Origin::signed(1), 10));
|
||||
assert_eq!(Democracy::proxy(10), Some(1));
|
||||
assert!(System::allow_death(&10));
|
||||
|
||||
assert_noop!(Democracy::activate_proxy(Origin::signed(1), 10), Error::<Test>::NotOpen);
|
||||
|
||||
assert_ok!(Democracy::open_proxy(Origin::signed(10), 1));
|
||||
assert!(!System::allow_death(&10));
|
||||
assert_eq!(Democracy::proxy(10), Some(ProxyState::Open(1)));
|
||||
|
||||
assert_noop!(Democracy::activate_proxy(Origin::signed(2), 10), Error::<Test>::WrongOpen);
|
||||
assert_ok!(Democracy::activate_proxy(Origin::signed(1), 10));
|
||||
assert_eq!(Democracy::proxy(10), Some(ProxyState::Active(1)));
|
||||
|
||||
// Can't set when already set.
|
||||
assert_noop!(Democracy::set_proxy(Origin::signed(2), 10), Error::<Test>::AlreadyProxy);
|
||||
assert_noop!(Democracy::activate_proxy(Origin::signed(2), 10), Error::<Test>::AlreadyProxy);
|
||||
|
||||
// But this works because 11 isn't proxying.
|
||||
assert_ok!(Democracy::set_proxy(Origin::signed(2), 11));
|
||||
assert_eq!(Democracy::proxy(10), Some(1));
|
||||
assert_eq!(Democracy::proxy(11), Some(2));
|
||||
assert_ok!(Democracy::open_proxy(Origin::signed(11), 2));
|
||||
assert_ok!(Democracy::activate_proxy(Origin::signed(2), 11));
|
||||
assert_eq!(Democracy::proxy(10), Some(ProxyState::Active(1)));
|
||||
assert_eq!(Democracy::proxy(11), Some(ProxyState::Active(2)));
|
||||
|
||||
// 2 cannot fire 1's proxy:
|
||||
assert_noop!(Democracy::remove_proxy(Origin::signed(2), 10), Error::<Test>::WrongProxy);
|
||||
assert_noop!(Democracy::deactivate_proxy(Origin::signed(2), 10), Error::<Test>::WrongProxy);
|
||||
|
||||
// 1 fires his proxy:
|
||||
assert_ok!(Democracy::remove_proxy(Origin::signed(1), 10));
|
||||
assert_eq!(Democracy::proxy(10), None);
|
||||
assert_eq!(Democracy::proxy(11), Some(2));
|
||||
// 1 deactivates their proxy:
|
||||
assert_ok!(Democracy::deactivate_proxy(Origin::signed(1), 10));
|
||||
assert_eq!(Democracy::proxy(10), Some(ProxyState::Open(1)));
|
||||
// but the proxy account cannot be killed until the proxy is closed.
|
||||
assert!(!System::allow_death(&10));
|
||||
|
||||
// 11 resigns:
|
||||
assert_ok!(Democracy::resign_proxy(Origin::signed(11)));
|
||||
// and then 10 closes it completely:
|
||||
assert_ok!(Democracy::close_proxy(Origin::signed(10)));
|
||||
assert_eq!(Democracy::proxy(10), None);
|
||||
assert!(System::allow_death(&10));
|
||||
|
||||
// 11 just closes without 2's "permission".
|
||||
assert_ok!(Democracy::close_proxy(Origin::signed(11)));
|
||||
assert_eq!(Democracy::proxy(11), None);
|
||||
assert!(System::allow_death(&11));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2002,7 +2089,8 @@ mod tests {
|
||||
|
||||
fast_forward_to(2);
|
||||
let r = 0;
|
||||
assert_ok!(Democracy::set_proxy(Origin::signed(1), 10));
|
||||
assert_ok!(Democracy::open_proxy(Origin::signed(10), 1));
|
||||
assert_ok!(Democracy::activate_proxy(Origin::signed(1), 10));
|
||||
assert_ok!(Democracy::proxy_vote(Origin::signed(10), r, AYE));
|
||||
|
||||
assert_eq!(Democracy::voters_for(r), vec![1]);
|
||||
|
||||
Reference in New Issue
Block a user