Minor Uniques pallet improvements and XCM v3 preparations (#10896)

* Introduce Helper to Uniques for benchmark stuff

* Fixes

* Formatting

* Featuregate the Helper, include ContainsPair

* Introduce & use EnsureOriginWithArg

* Benchmarking

* Docs

* More ContainsBoth helpers

* Formatting

* Formatting

* Fixes

Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Gavin Wood
2022-03-07 09:12:03 +01:00
committed by GitHub
parent 6f59a8b183
commit 2c373c1e16
12 changed files with 422 additions and 118 deletions
+7 -3
View File
@@ -34,8 +34,9 @@ mod members;
#[allow(deprecated)]
pub use members::{AllowAll, DenyAll, Filter};
pub use members::{
AsContains, ChangeMembers, Contains, ContainsLengthBound, Everything, InitializeMembers,
IsInVec, Nothing, SortedMembers,
AsContains, ChangeMembers, Contains, ContainsLengthBound, ContainsPair, Everything,
EverythingBut, FromContainsPair, InitializeMembers, InsideBoth, IsInVec, Nothing,
SortedMembers, TheseExcept,
};
mod validation;
@@ -89,7 +90,10 @@ pub use storage::{
};
mod dispatch;
pub use dispatch::{EnsureOneOf, EnsureOrigin, OriginTrait, UnfilteredDispatchable};
pub use dispatch::{
AsEnsureOriginWithArg, EnsureOneOf, EnsureOrigin, EnsureOriginWithArg, OriginTrait,
UnfilteredDispatchable,
};
mod voting;
pub use voting::{
@@ -27,10 +27,12 @@ use sp_runtime::{
pub trait EnsureOrigin<OuterOrigin> {
/// A return type.
type Success;
/// Perform the origin check.
fn ensure_origin(o: OuterOrigin) -> Result<Self::Success, BadOrigin> {
Self::try_origin(o).map_err(|_| BadOrigin)
}
/// Perform the origin check.
fn try_origin(o: OuterOrigin) -> Result<Self::Success, OuterOrigin>;
@@ -41,6 +43,52 @@ pub trait EnsureOrigin<OuterOrigin> {
fn successful_origin() -> OuterOrigin;
}
/// Some sort of check on the origin is performed by this object.
pub trait EnsureOriginWithArg<OuterOrigin, Argument> {
/// A return type.
type Success;
/// Perform the origin check.
fn ensure_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, BadOrigin> {
Self::try_origin(o, a).map_err(|_| BadOrigin)
}
/// Perform the origin check, returning the origin value if unsuccessful. This allows chaining.
fn try_origin(o: OuterOrigin, a: &Argument) -> Result<Self::Success, OuterOrigin>;
/// Returns an outer origin capable of passing `try_origin` check.
///
/// ** Should be used for benchmarking only!!! **
#[cfg(feature = "runtime-benchmarks")]
fn successful_origin(a: &Argument) -> OuterOrigin;
}
pub struct AsEnsureOriginWithArg<EO>(sp_std::marker::PhantomData<EO>);
impl<OuterOrigin, Argument, EO: EnsureOrigin<OuterOrigin>>
EnsureOriginWithArg<OuterOrigin, Argument> for AsEnsureOriginWithArg<EO>
{
/// A return type.
type Success = EO::Success;
/// Perform the origin check.
fn ensure_origin(o: OuterOrigin, _: &Argument) -> Result<Self::Success, BadOrigin> {
EO::ensure_origin(o)
}
/// Perform the origin check, returning the origin value if unsuccessful. This allows chaining.
fn try_origin(o: OuterOrigin, _: &Argument) -> Result<Self::Success, OuterOrigin> {
EO::try_origin(o)
}
/// Returns an outer origin capable of passing `try_origin` check.
///
/// ** Should be used for benchmarking only!!! **
#[cfg(feature = "runtime-benchmarks")]
fn successful_origin(_: &Argument) -> OuterOrigin {
EO::successful_origin()
}
}
/// Type that can be dispatched with an origin but without checking the origin filter.
///
/// Implemented for pallet dispatchable type by `decl_module` and for runtime dispatchable by
+134 -26
View File
@@ -25,6 +25,40 @@ pub trait Contains<T> {
fn contains(t: &T) -> bool;
}
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
impl<T> Contains<T> for Tuple {
fn contains(t: &T) -> bool {
for_tuples!( #(
if Tuple::contains(t) { return true }
)* );
false
}
}
/// A trait for querying whether a type can be said to "contain" a pair-value.
pub trait ContainsPair<A, B> {
/// Return `true` if this "contains" the pair-value `(a, b)`.
fn contains(a: &A, b: &B) -> bool;
}
#[impl_trait_for_tuples::impl_for_tuples(0, 30)]
impl<A, B> ContainsPair<A, B> for Tuple {
fn contains(a: &A, b: &B) -> bool {
for_tuples!( #(
if Tuple::contains(a, b) { return true }
)* );
false
}
}
/// Converter `struct` to use a `ContainsPair` implementation for a `Contains` bound.
pub struct FromContainsPair<CP>(PhantomData<CP>);
impl<A, B, CP: ContainsPair<A, B>> Contains<(A, B)> for FromContainsPair<CP> {
fn contains((ref a, ref b): &(A, B)) -> bool {
CP::contains(a, b)
}
}
/// A [`Contains`] implementation that contains every value.
pub enum Everything {}
impl<T> Contains<T> for Everything {
@@ -32,6 +66,11 @@ impl<T> Contains<T> for Everything {
true
}
}
impl<A, B> ContainsPair<A, B> for Everything {
fn contains(_: &A, _: &B) -> bool {
true
}
}
/// A [`Contains`] implementation that contains no value.
pub enum Nothing {}
@@ -40,6 +79,99 @@ impl<T> Contains<T> for Nothing {
false
}
}
impl<A, B> ContainsPair<A, B> for Nothing {
fn contains(_: &A, _: &B) -> bool {
false
}
}
/// A [`Contains`] implementation that contains everything except the values in `Exclude`.
pub struct EverythingBut<Exclude>(PhantomData<Exclude>);
impl<T, Exclude: Contains<T>> Contains<T> for EverythingBut<Exclude> {
fn contains(t: &T) -> bool {
!Exclude::contains(t)
}
}
impl<A, B, Exclude: ContainsPair<A, B>> ContainsPair<A, B> for EverythingBut<Exclude> {
fn contains(a: &A, b: &B) -> bool {
!Exclude::contains(a, b)
}
}
/// A [`Contains`] implementation that contains all members of `These` excepting any members in
/// `Except`.
pub struct TheseExcept<These, Except>(PhantomData<(These, Except)>);
impl<T, These: Contains<T>, Except: Contains<T>> Contains<T> for TheseExcept<These, Except> {
fn contains(t: &T) -> bool {
These::contains(t) && !Except::contains(t)
}
}
impl<A, B, These: ContainsPair<A, B>, Except: ContainsPair<A, B>> ContainsPair<A, B>
for TheseExcept<These, Except>
{
fn contains(a: &A, b: &B) -> bool {
These::contains(a, b) && !Except::contains(a, b)
}
}
/// A [`Contains`] implementation which contains all members of `These` which are also members of
/// `Those`.
pub struct InsideBoth<These, Those>(PhantomData<(These, Those)>);
impl<T, These: Contains<T>, Those: Contains<T>> Contains<T> for InsideBoth<These, Those> {
fn contains(t: &T) -> bool {
These::contains(t) && Those::contains(t)
}
}
impl<A, B, These: ContainsPair<A, B>, Those: ContainsPair<A, B>> ContainsPair<A, B>
for InsideBoth<These, Those>
{
fn contains(a: &A, b: &B) -> bool {
These::contains(a, b) && Those::contains(a, b)
}
}
/// Create a type which implements the `Contains` trait for a particular type with syntax similar
/// to `matches!`.
#[macro_export]
macro_rules! match_types {
(
pub type $n:ident: impl Contains<$t:ty> = {
$phead:pat_param $( | $ptail:pat )*
};
$( $rest:tt )*
) => {
pub struct $n;
impl $crate::traits::Contains<$t> for $n {
fn contains(l: &$t) -> bool {
matches!(l, $phead $( | $ptail )* )
}
}
$crate::match_types!( $( $rest )* );
};
(
pub type $n:ident: impl ContainsPair<$a:ty, $b:ty> = {
$phead:pat_param $( | $ptail:pat )*
};
$( $rest:tt )*
) => {
pub struct $n;
impl $crate::traits::ContainsPair<$a, $b> for $n {
fn contains(a: &$a, b: &$b) -> bool {
matches!((a, b), $phead $( | $ptail )* )
}
}
$crate::match_types!( $( $rest )* );
};
() => {}
}
/// Create a type which implements the `Contains` trait for a particular type with syntax similar
/// to `matches!`.
#[macro_export]
#[deprecated = "Use `match_types!` instead"]
macro_rules! match_type {
($( $x:tt )*) => { $crate::match_types!( $( $x )* ); }
}
#[deprecated = "Use `Everything` instead"]
pub type AllowAll = Everything;
@@ -56,40 +188,16 @@ impl<T, C: Contains<T>> Filter<T> for C {
}
}
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
impl<T> Contains<T> for Tuple {
fn contains(t: &T) -> bool {
for_tuples!( #(
if Tuple::contains(t) { return true }
)* );
false
}
}
/// Create a type which implements the `Contains` trait for a particular type with syntax similar
/// to `matches!`.
#[macro_export]
macro_rules! match_type {
( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat_param $( | $ptail:pat )* } ; ) => {
pub struct $n;
impl $crate::traits::Contains<$t> for $n {
fn contains(l: &$t) -> bool {
matches!(l, $phead $( | $ptail )* )
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
match_type! {
match_types! {
pub type OneOrTenToTwenty: impl Contains<u8> = { 1 | 10..=20 };
}
#[test]
fn match_type_works() {
fn match_types_works() {
for i in 0..=255 {
assert_eq!(OneOrTenToTwenty::contains(&i), i == 1 || i >= 10 && i <= 20);
}
@@ -85,7 +85,10 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
/// Burn some asset `instance`.
///
/// By default, this is not a supported operation.
fn burn_from(_instance: &Self::InstanceId) -> DispatchResult {
fn burn(
_instance: &Self::InstanceId,
_maybe_check_owner: Option<&AccountId>,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
@@ -166,8 +169,8 @@ impl<
fn mint_into(instance: &Self::InstanceId, who: &AccountId) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId>>::mint_into(&A::get(), instance, who)
}
fn burn_from(instance: &Self::InstanceId) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId>>::burn_from(&A::get(), instance)
fn burn(instance: &Self::InstanceId, maybe_check_owner: Option<&AccountId>) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId>>::burn(&A::get(), instance, maybe_check_owner)
}
fn set_attribute(instance: &Self::InstanceId, key: &[u8], value: &[u8]) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId>>::set_attribute(&A::get(), instance, key, value)
@@ -165,7 +165,11 @@ pub trait Mutate<AccountId>: Inspect<AccountId> {
/// Burn some asset `instance` of `class`.
///
/// By default, this is not a supported operation.
fn burn_from(_class: &Self::ClassId, _instance: &Self::InstanceId) -> DispatchResult {
fn burn(
_class: &Self::ClassId,
_instance: &Self::InstanceId,
_maybe_check_owner: Option<&AccountId>,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}