Skip to content

Commit

Permalink
Minor Uniques pallet improvements and XCM v3 preparations (paritytech…
Browse files Browse the repository at this point in the history
…#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>
  • Loading branch information
2 people authored and grishasobol committed Mar 28, 2022
1 parent 82fda9d commit 2339a1f
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 113 deletions.
9 changes: 6 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ use frame_election_provider_support::onchain;
use frame_support::{
construct_runtime, parameter_types,
traits::{
ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf, EqualPrivilegeOnly, Everything,
Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing, OnUnbalanced,
U128CurrencyToVote,
AsEnsureOriginWithArg, ConstU128, ConstU16, ConstU32, Currency, EnsureOneOf,
EqualPrivilegeOnly, Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem,
LockIdentifier, Nothing, OnUnbalanced, U128CurrencyToVote,
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
Expand Down Expand Up @@ -1348,6 +1348,9 @@ impl pallet_uniques::Config for Runtime {
type KeyLimit = KeyLimit;
type ValueLimit = ValueLimit;
type WeightInfo = pallet_uniques::weights::SubstrateWeight<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
}

impl pallet_transaction_storage::Config for Runtime {
Expand Down
10 changes: 7 additions & 3 deletions frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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::{
Expand Down
48 changes: 48 additions & 0 deletions frame/support/src/traits/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand All @@ -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
Expand Down
150 changes: 129 additions & 21 deletions frame/support/src/traits/members.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,52 @@ 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 {
fn contains(_: &T) -> bool {
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 {}
Expand All @@ -40,56 +79,125 @@ impl<T> Contains<T> for Nothing {
false
}
}
impl<A, B> ContainsPair<A, B> for Nothing {
fn contains(_: &A, _: &B) -> bool {
false
}
}

#[deprecated = "Use `Everything` instead"]
pub type AllowAll = Everything;
#[deprecated = "Use `Nothing` instead"]
pub type DenyAll = Nothing;
#[deprecated = "Use `Contains` instead"]
pub trait Filter<T> {
fn filter(t: &T) -> bool;
/// 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)
}
}
#[allow(deprecated)]
impl<T, C: Contains<T>> Filter<T> for C {
fn filter(t: &T) -> bool {
Self::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)
}
}

#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
impl<T> Contains<T> for Tuple {
/// 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 {
for_tuples!( #(
if Tuple::contains(t) { return true }
)* );
false
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_type {
( pub type $n:ident: impl Contains<$t:ty> = { $phead:pat_param $( | $ptail:pat )* } ; ) => {
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;
#[deprecated = "Use `Nothing` instead"]
pub type DenyAll = Nothing;
#[deprecated = "Use `Contains` instead"]
pub trait Filter<T> {
fn filter(t: &T) -> bool;
}
#[allow(deprecated)]
impl<T, C: Contains<T>> Filter<T> for C {
fn filter(t: &T) -> bool {
Self::contains(t)
}
}

#[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);
}
Expand Down
9 changes: 6 additions & 3 deletions frame/support/src/traits/tokens/nonfungible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion frame/support/src/traits/tokens/nonfungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down
Loading

0 comments on commit 2339a1f

Please sign in to comment.