mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 03:27:58 +00:00
Several tweaks needed for Governance 2.0 (#11124)
* Add stepped curve for referenda * Treasury SpendOrigin * Add tests * Better Origin Or-gating * Reciprocal curve * Tests for reciprical and rounding in PerThings * Tweaks and new quad curve * Const derivation of reciprocal curve parameters * Remove some unneeded code * Actually useful linear curve * Fixes * Provisional curves * Rejig 'turnout' as 'support' * Use TypedGet * Fixes * Enable curve's ceil to be configured * Formatting * Fixes * Fixes * Fixes * Remove EnsureOneOf * Fixes * Fixes * Fixes * Formatting * Fixes * Update frame/support/src/traits/dispatch.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Grumbles * Formatting * Fixes * APIs of VoteTally should include class * Fixes * Fix overlay prefix removal result * Second part of the overlay prefix removal fix. * Formatting * Fixes * Add some tests and make clear rounding algo * Fixes * Formatting * Revert questionable fix * Introduce test for kill_prefix * Fixes * Formatting * Fixes * Fix possible overflow * Docs * Add benchmark test * Formatting * Update frame/referenda/src/types.rs Co-authored-by: Keith Yeung <kungfukeith11@gmail.com> * Docs * Fixes * Use latest API in tests * Formatting * Whitespace * Use latest API in tests Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
@@ -350,6 +350,13 @@ macro_rules! parameter_types {
|
||||
I::from(Self::get())
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::traits::TypedGet for $name {
|
||||
type Type = $type;
|
||||
fn get() -> $type {
|
||||
Self::get()
|
||||
}
|
||||
}
|
||||
};
|
||||
(IMPL $name:ident, $type:ty, $value:expr) => {
|
||||
impl $name {
|
||||
@@ -364,6 +371,13 @@ macro_rules! parameter_types {
|
||||
I::from(Self::get())
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::traits::TypedGet for $name {
|
||||
type Type = $type;
|
||||
fn get() -> $type {
|
||||
Self::get()
|
||||
}
|
||||
}
|
||||
};
|
||||
(IMPL_STORAGE $name:ident, $type:ty, $value:expr) => {
|
||||
impl $name {
|
||||
@@ -397,6 +411,13 @@ macro_rules! parameter_types {
|
||||
I::from(Self::get())
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::traits::TypedGet for $name {
|
||||
type Type = $type;
|
||||
fn get() -> $type {
|
||||
Self::get()
|
||||
}
|
||||
}
|
||||
};
|
||||
(
|
||||
$( #[ $attr:meta ] )*
|
||||
@@ -805,7 +826,7 @@ pub mod tests {
|
||||
};
|
||||
use codec::{Codec, EncodeLike};
|
||||
use frame_support::traits::CrateVersion;
|
||||
use sp_io::TestExternalities;
|
||||
use sp_io::{MultiRemovalResults, TestExternalities};
|
||||
use sp_std::result;
|
||||
|
||||
/// A PalletInfo implementation which just panics.
|
||||
@@ -1066,15 +1087,16 @@ pub mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_map_basic_insert_remove_remove_prefix_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
type DoubleMap = DataDM;
|
||||
fn double_map_basic_insert_remove_remove_prefix_with_commit_should_work() {
|
||||
let key1 = 17u32;
|
||||
let key2 = 18u32;
|
||||
type DoubleMap = DataDM;
|
||||
let mut e = new_test_ext();
|
||||
e.execute_with(|| {
|
||||
// initialized during genesis
|
||||
assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64);
|
||||
|
||||
// get / insert / take
|
||||
let key1 = 17u32;
|
||||
let key2 = 18u32;
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
DoubleMap::insert(&key1, &key2, &4u64);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 4u64);
|
||||
@@ -1082,9 +1104,7 @@ pub mod tests {
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
|
||||
// mutate
|
||||
DoubleMap::mutate(&key1, &key2, |val| {
|
||||
*val = 15;
|
||||
});
|
||||
DoubleMap::mutate(&key1, &key2, |val| *val = 15);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 15u64);
|
||||
|
||||
// remove
|
||||
@@ -1096,13 +1116,62 @@ pub mod tests {
|
||||
DoubleMap::insert(&key1, &(key2 + 1), &4u64);
|
||||
DoubleMap::insert(&(key1 + 1), &key2, &4u64);
|
||||
DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64);
|
||||
});
|
||||
e.commit_all().unwrap();
|
||||
e.execute_with(|| {
|
||||
assert!(matches!(
|
||||
DoubleMap::clear_prefix(&key1, u32::max_value(), None),
|
||||
// Note this is the incorrect answer (for now), since we are using v2 of
|
||||
// `clear_prefix`.
|
||||
// When we switch to v3, then this will become:
|
||||
// sp_io::MultiRemovalResults::NoneLeft { db: 0, total: 2 },
|
||||
sp_io::MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 },
|
||||
MultiRemovalResults { maybe_cursor: None, backend: 2, unique: 2, loops: 2 }
|
||||
));
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
|
||||
assert_eq!(DoubleMap::get(&(key1 + 1), &key2), 4u64);
|
||||
assert_eq!(DoubleMap::get(&(key1 + 1), &(key2 + 1)), 4u64);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_map_basic_insert_remove_remove_prefix_should_work() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let key1 = 17u32;
|
||||
let key2 = 18u32;
|
||||
type DoubleMap = DataDM;
|
||||
|
||||
// initialized during genesis
|
||||
assert_eq!(DoubleMap::get(&15u32, &16u32), 42u64);
|
||||
|
||||
// get / insert / take
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
DoubleMap::insert(&key1, &key2, &4u64);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 4u64);
|
||||
assert_eq!(DoubleMap::take(&key1, &key2), 4u64);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
|
||||
// mutate
|
||||
DoubleMap::mutate(&key1, &key2, |val| *val = 15);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 15u64);
|
||||
|
||||
// remove
|
||||
DoubleMap::remove(&key1, &key2);
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
|
||||
// remove prefix
|
||||
DoubleMap::insert(&key1, &key2, &4u64);
|
||||
DoubleMap::insert(&key1, &(key2 + 1), &4u64);
|
||||
DoubleMap::insert(&(key1 + 1), &key2, &4u64);
|
||||
DoubleMap::insert(&(key1 + 1), &(key2 + 1), &4u64);
|
||||
// all in overlay
|
||||
assert!(matches!(
|
||||
DoubleMap::clear_prefix(&key1, u32::max_value(), None),
|
||||
MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 }
|
||||
));
|
||||
// Note this is the incorrect answer (for now), since we are using v2 of
|
||||
// `clear_prefix`.
|
||||
// When we switch to v3, then this will become:
|
||||
// MultiRemovalResults:: { maybe_cursor: None, backend: 0, unique: 2, loops: 2 },
|
||||
assert!(matches!(
|
||||
DoubleMap::clear_prefix(&key1, u32::max_value(), None),
|
||||
MultiRemovalResults { maybe_cursor: None, backend: 0, unique: 0, loops: 0 }
|
||||
));
|
||||
assert_eq!(DoubleMap::get(&key1, &key2), 0u64);
|
||||
assert_eq!(DoubleMap::get(&key1, &(key2 + 1)), 0u64);
|
||||
@@ -1321,7 +1390,7 @@ pub mod pallet_prelude {
|
||||
},
|
||||
traits::{
|
||||
ConstU32, EnsureOrigin, Get, GetDefault, GetStorageVersion, Hooks, IsType,
|
||||
PalletInfoAccess, StorageInfoTrait, StorageVersion,
|
||||
PalletInfoAccess, StorageInfoTrait, StorageVersion, TypedGet,
|
||||
},
|
||||
weights::{DispatchClass, Pays, Weight},
|
||||
Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity,
|
||||
|
||||
@@ -59,7 +59,7 @@ pub use misc::{
|
||||
ConstU32, ConstU64, ConstU8, DefensiveSaturating, EnsureInherentsAreFirst, EqualPrivilegeOnly,
|
||||
EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, GetBacking, GetDefault, HandleLifetime,
|
||||
IsSubType, IsType, Len, OffchainWorker, OnKilledAccount, OnNewAccount, PreimageProvider,
|
||||
PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime,
|
||||
PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, TypedGet, UnixTime,
|
||||
WrapperKeepOpaque, WrapperOpaque,
|
||||
};
|
||||
#[doc(hidden)]
|
||||
@@ -93,9 +93,11 @@ pub use storage::{
|
||||
};
|
||||
|
||||
mod dispatch;
|
||||
#[allow(deprecated)]
|
||||
pub use dispatch::EnsureOneOf;
|
||||
pub use dispatch::{
|
||||
AsEnsureOriginWithArg, DispatchableWithStorageLayer, EnsureOneOf, EnsureOrigin,
|
||||
EnsureOriginWithArg, OriginTrait, UnfilteredDispatchable,
|
||||
AsEnsureOriginWithArg, DispatchableWithStorageLayer, EitherOf, EitherOfDiverse, EnsureOrigin,
|
||||
EnsureOriginWithArg, NeverEnsureOrigin, OriginTrait, UnfilteredDispatchable,
|
||||
};
|
||||
|
||||
mod voting;
|
||||
|
||||
@@ -43,6 +43,19 @@ pub trait EnsureOrigin<OuterOrigin> {
|
||||
fn successful_origin() -> OuterOrigin;
|
||||
}
|
||||
|
||||
/// `EnsureOrigin` implementation that always fails.
|
||||
pub struct NeverEnsureOrigin<Success>(sp_std::marker::PhantomData<Success>);
|
||||
impl<OO, Success> EnsureOrigin<OO> for NeverEnsureOrigin<Success> {
|
||||
type Success = Success;
|
||||
fn try_origin(o: OO) -> Result<Success, OO> {
|
||||
Err(o)
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn successful_origin() -> OO {
|
||||
panic!("No `successful_origin` possible for `NeverEnsureOrigin`")
|
||||
}
|
||||
}
|
||||
|
||||
/// Some sort of check on the origin is performed by this object.
|
||||
pub trait EnsureOriginWithArg<OuterOrigin, Argument> {
|
||||
/// A return type.
|
||||
@@ -163,13 +176,16 @@ pub trait OriginTrait: Sized {
|
||||
fn signed(by: Self::AccountId) -> Self;
|
||||
}
|
||||
|
||||
/// The "OR gate" implementation of `EnsureOrigin`.
|
||||
/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
|
||||
/// and `R`, with them combined using an `Either` type.
|
||||
///
|
||||
/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
|
||||
pub struct EnsureOneOf<L, R>(sp_std::marker::PhantomData<(L, R)>);
|
||||
///
|
||||
/// Successful origin is derived from the left side.
|
||||
pub struct EitherOfDiverse<L, R>(sp_std::marker::PhantomData<(L, R)>);
|
||||
|
||||
impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
|
||||
EnsureOrigin<OuterOrigin> for EnsureOneOf<L, R>
|
||||
EnsureOrigin<OuterOrigin> for EitherOfDiverse<L, R>
|
||||
{
|
||||
type Success = Either<L::Success, R::Success>;
|
||||
fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
|
||||
@@ -183,17 +199,53 @@ impl<OuterOrigin, L: EnsureOrigin<OuterOrigin>, R: EnsureOrigin<OuterOrigin>>
|
||||
}
|
||||
}
|
||||
|
||||
/// "OR gate" implementation of `EnsureOrigin` allowing for different `Success` types for `L`
|
||||
/// and `R`, with them combined using an `Either` type.
|
||||
///
|
||||
/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
|
||||
///
|
||||
/// Successful origin is derived from the left side.
|
||||
#[deprecated = "Use `EitherOfDiverse` instead"]
|
||||
pub type EnsureOneOf<L, R> = EitherOfDiverse<L, R>;
|
||||
|
||||
/// "OR gate" implementation of `EnsureOrigin`, `Success` type for both `L` and `R` must
|
||||
/// be equal.
|
||||
///
|
||||
/// Origin check will pass if `L` or `R` origin check passes. `L` is tested first.
|
||||
///
|
||||
/// Successful origin is derived from the left side.
|
||||
pub struct EitherOf<L, R>(sp_std::marker::PhantomData<(L, R)>);
|
||||
|
||||
impl<
|
||||
OuterOrigin,
|
||||
L: EnsureOrigin<OuterOrigin>,
|
||||
R: EnsureOrigin<OuterOrigin, Success = L::Success>,
|
||||
> EnsureOrigin<OuterOrigin> for EitherOf<L, R>
|
||||
{
|
||||
type Success = L::Success;
|
||||
fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin> {
|
||||
L::try_origin(o).or_else(|o| R::try_origin(o))
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn successful_origin() -> OuterOrigin {
|
||||
L::successful_origin()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::traits::{ConstBool, ConstU8, TypedGet};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct EnsureSuccess;
|
||||
struct EnsureFail;
|
||||
struct EnsureSuccess<V>(PhantomData<V>);
|
||||
struct EnsureFail<T>(PhantomData<T>);
|
||||
|
||||
impl EnsureOrigin<()> for EnsureSuccess {
|
||||
type Success = ();
|
||||
impl<V: TypedGet> EnsureOrigin<()> for EnsureSuccess<V> {
|
||||
type Success = V::Type;
|
||||
fn try_origin(_: ()) -> Result<Self::Success, ()> {
|
||||
Ok(())
|
||||
Ok(V::get())
|
||||
}
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn successful_origin() -> () {
|
||||
@@ -201,8 +253,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl EnsureOrigin<()> for EnsureFail {
|
||||
type Success = ();
|
||||
impl<T> EnsureOrigin<()> for EnsureFail<T> {
|
||||
type Success = T;
|
||||
fn try_origin(_: ()) -> Result<Self::Success, ()> {
|
||||
Err(())
|
||||
}
|
||||
@@ -213,10 +265,46 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ensure_one_of_test() {
|
||||
assert!(<EnsureOneOf<EnsureSuccess, EnsureSuccess>>::try_origin(()).is_ok());
|
||||
assert!(<EnsureOneOf<EnsureSuccess, EnsureFail>>::try_origin(()).is_ok());
|
||||
assert!(<EnsureOneOf<EnsureFail, EnsureSuccess>>::try_origin(()).is_ok());
|
||||
assert!(<EnsureOneOf<EnsureFail, EnsureFail>>::try_origin(()).is_err());
|
||||
fn either_of_diverse_works() {
|
||||
assert_eq!(
|
||||
EitherOfDiverse::<
|
||||
EnsureSuccess<ConstBool<true>>,
|
||||
EnsureSuccess<ConstU8<0>>,
|
||||
>::try_origin(()).unwrap().left(),
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
EitherOfDiverse::<EnsureSuccess<ConstBool<true>>, EnsureFail<u8>>::try_origin(())
|
||||
.unwrap()
|
||||
.left(),
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
EitherOfDiverse::<EnsureFail<bool>, EnsureSuccess<ConstU8<0>>>::try_origin(())
|
||||
.unwrap()
|
||||
.right(),
|
||||
Some(0u8)
|
||||
);
|
||||
assert!(EitherOfDiverse::<EnsureFail<bool>, EnsureFail<u8>>::try_origin(()).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn either_of_works() {
|
||||
assert_eq!(
|
||||
EitherOf::<
|
||||
EnsureSuccess<ConstBool<true>>,
|
||||
EnsureSuccess<ConstBool<false>>,
|
||||
>::try_origin(()).unwrap(),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
EitherOf::<EnsureSuccess<ConstBool<true>>, EnsureFail<bool>>::try_origin(()).unwrap(),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
EitherOf::<EnsureFail<bool>, EnsureSuccess<ConstBool<false>>>::try_origin(()).unwrap(),
|
||||
false
|
||||
);
|
||||
assert!(EitherOf::<EnsureFail<bool>, EnsureFail<bool>>::try_origin(()).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,6 +387,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for querying a single value from a type defined in the trait.
|
||||
///
|
||||
/// It is not required that the value is constant.
|
||||
pub trait TypedGet {
|
||||
/// The type which is returned.
|
||||
type Type;
|
||||
/// Return the current value.
|
||||
fn get() -> Self::Type;
|
||||
}
|
||||
|
||||
/// A trait for querying a single value from a type.
|
||||
///
|
||||
/// It is not required that the value is constant.
|
||||
@@ -423,6 +433,12 @@ macro_rules! impl_const_get {
|
||||
Some(T)
|
||||
}
|
||||
}
|
||||
impl<const T: $t> TypedGet for $name<T> {
|
||||
type Type = $t;
|
||||
fn get() -> $t {
|
||||
T
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -95,16 +95,18 @@ impl<B: UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128>> CurrencyToVote<B>
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VoteTally<Votes> {
|
||||
fn ayes(&self) -> Votes;
|
||||
fn turnout(&self) -> Perbill;
|
||||
fn approval(&self) -> Perbill;
|
||||
pub trait VoteTally<Votes, Class> {
|
||||
fn new(_: Class) -> Self;
|
||||
fn ayes(&self, class: Class) -> Votes;
|
||||
fn support(&self, class: Class) -> Perbill;
|
||||
fn approval(&self, class: Class) -> Perbill;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn unanimity() -> Self;
|
||||
fn unanimity(class: Class) -> Self;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn from_requirements(turnout: Perbill, approval: Perbill) -> Self;
|
||||
fn rejection(class: Class) -> Self;
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
fn from_requirements(support: Perbill, approval: Perbill, class: Class) -> Self;
|
||||
}
|
||||
|
||||
pub enum PollStatus<Tally, Moment, Class> {
|
||||
None,
|
||||
Ongoing(Tally, Class),
|
||||
|
||||
Reference in New Issue
Block a user