// Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . //! Traits for SRML. //! //! NOTE: If you're looking for `parameter_types`, it has moved in to the top-level module. use rstd::{prelude::*, result, marker::PhantomData, ops::Div, fmt::Debug}; use codec::{FullCodec, Codec, Encode, Decode}; use primitives::u32_trait::Value as U32; use sr_primitives::{ ConsensusEngineId, traits::{MaybeSerializeDeserialize, SimpleArithmetic, Saturating}, }; use crate::dispatch::Parameter; /// Anything that can have a `::len()` method. pub trait Len { /// Return the length of data type. fn len(&self) -> usize; } impl Len for T where ::IntoIter: ExactSizeIterator { fn len(&self) -> usize { self.clone().into_iter().len() } } /// A trait for querying a single fixed value from a type. pub trait Get { /// Return a constant value. fn get() -> T; } impl Get for () { fn get() -> T { T::default() } } /// A trait for querying whether a type can be said to statically "contain" a value. Similar /// in nature to `Get`, except it is designed to be lazy rather than active (you can't ask it to /// enumerate all values that it contains) and work for multiple values rather than just one. pub trait Contains { /// Return `true` if this "contains" the given value `t`. fn contains(t: &T) -> bool; } impl> Contains for T { fn contains(t: &V) -> bool { &Self::get() == t } } /// The account with the given id was killed. #[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnFreeBalanceZero { /// The account was the given id was killed. fn on_free_balance_zero(who: &AccountId); } /// Outcome of a balance update. pub enum UpdateBalanceOutcome { /// Account balance was simply updated. Updated, /// The update led to killing the account. AccountKilled, } /// A trait for finding the author of a block header based on the `PreRuntime` digests contained /// within it. pub trait FindAuthor { /// Find the author of a block based on the pre-runtime digests. fn find_author<'a, I>(digests: I) -> Option where I: 'a + IntoIterator; } impl FindAuthor for () { fn find_author<'a, I>(_: I) -> Option where I: 'a + IntoIterator { None } } /// A trait for verifying the seal of a header and returning the author. pub trait VerifySeal { /// Verify a header and return the author, if any. fn verify_seal(header: &Header) -> Result, &'static str>; } /// Something which can compute and check proofs of /// a historical key owner and return full identification data of that /// key owner. pub trait KeyOwnerProofSystem { /// The proof of membership itself. type Proof: Codec; /// The full identification of a key owner and the stash account. type IdentificationTuple: Codec; /// Prove membership of a key owner in the current block-state. /// /// This should typically only be called off-chain, since it may be /// computationally heavy. /// /// Returns `Some` iff the key owner referred to by the given `key` is a /// member of the current set. fn prove(key: Key) -> Option; /// Check a proof of membership on-chain. Return `Some` iff the proof is /// valid and recent enough to check. fn check_proof(key: Key, proof: Self::Proof) -> Option; } /// Handler for when some currency "account" decreased in balance for /// some reason. /// /// The only reason at present for an increase would be for validator rewards, but /// there may be other reasons in the future or for other chains. /// /// Reasons for decreases include: /// /// - Someone got slashed. /// - Someone paid for a transaction to be included. pub trait OnUnbalanced { /// Handler for some imbalance. Infallible. fn on_unbalanced(amount: Imbalance) { amount.try_drop().unwrap_or_else(Self::on_nonzero_unbalanced) } /// Actually handle a non-zero imbalance. You probably want to implement this rather than /// `on_unbalanced`. fn on_nonzero_unbalanced(amount: Imbalance); } impl OnUnbalanced for () { fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); } } /// Simple boolean for whether an account needs to be kept in existence. #[derive(Copy, Clone, Eq, PartialEq)] pub enum ExistenceRequirement { /// Operation must not result in the account going out of existence. /// /// Note this implies that if the account never existed in the first place, then the operation /// may legitimately leave the account unchanged and still non-existent. KeepAlive, /// Operation may result in account going out of existence. AllowDeath, } /// A type for which some values make sense to be able to drop without further consideration. pub trait TryDrop: Sized { /// Drop an instance cleanly. Only works if its value represents "no-operation". fn try_drop(self) -> Result<(), Self>; } /// A trait for a not-quite Linear Type that tracks an imbalance. /// /// Functions that alter account balances return an object of this trait to /// express how much account balances have been altered in aggregate. If /// dropped, the currency system will take some default steps to deal with /// the imbalance (`balances` module simply reduces or increases its /// total issuance). Your module should generally handle it in some way, /// good practice is to do so in a configurable manner using an /// `OnUnbalanced` type for each situation in which your module needs to /// handle an imbalance. /// /// Imbalances can either be Positive (funds were added somewhere without /// being subtracted elsewhere - e.g. a reward) or Negative (funds deducted /// somewhere without an equal and opposite addition - e.g. a slash or /// system fee payment). /// /// Since they are unsigned, the actual type is always Positive or Negative. /// The trait makes no distinction except to define the `Opposite` type. /// /// New instances of zero value can be created (`zero`) and destroyed /// (`drop_zero`). /// /// Existing instances can be `split` and merged either consuming `self` with /// `merge` or mutating `self` with `subsume`. If the target is an `Option`, /// then `maybe_merge` and `maybe_subsume` might work better. Instances can /// also be `offset` with an `Opposite` that is less than or equal to in value. /// /// You can always retrieve the raw balance value using `peek`. #[must_use] pub trait Imbalance: Sized + TryDrop { /// The oppositely imbalanced type. They come in pairs. type Opposite: Imbalance; /// The zero imbalance. Can be destroyed with `drop_zero`. fn zero() -> Self; /// Drop an instance cleanly. Only works if its `self.value()` is zero. fn drop_zero(self) -> Result<(), Self>; /// Consume `self` and return two independent instances; the first /// is guaranteed to be at most `amount` and the second will be the remainder. fn split(self, amount: Balance) -> (Self, Self); /// Consume `self` and an `other` to return a new instance that combines /// both. fn merge(self, other: Self) -> Self; /// Consume `self` and maybe an `other` to return a new instance that combines /// both. fn maybe_merge(self, other: Option) -> Self { if let Some(o) = other { self.merge(o) } else { self } } /// Consume an `other` to mutate `self` into a new instance that combines /// both. fn subsume(&mut self, other: Self); /// Maybe consume an `other` to mutate `self` into a new instance that combines /// both. fn maybe_subsume(&mut self, other: Option) { if let Some(o) = other { self.subsume(o) } } /// Consume self and along with an opposite counterpart to return /// a combined result. /// /// Returns `Ok` along with a new instance of `Self` if this instance has a /// greater value than the `other`. Otherwise returns `Err` with an instance of /// the `Opposite`. In both cases the value represents the combination of `self` /// and `other`. fn offset(self, other: Self::Opposite) -> Result; /// The raw value of self. fn peek(&self) -> Balance; } /// Either a positive or a negative imbalance. pub enum SignedImbalance>{ /// A positive imbalance (funds have been created but none destroyed). Positive(P), /// A negative imbalance (funds have been destroyed but none created). Negative(P::Opposite), } impl< P: Imbalance, N: Imbalance, B: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default, > SignedImbalance { pub fn zero() -> Self { SignedImbalance::Positive(P::zero()) } pub fn drop_zero(self) -> Result<(), Self> { match self { SignedImbalance::Positive(x) => x.drop_zero().map_err(SignedImbalance::Positive), SignedImbalance::Negative(x) => x.drop_zero().map_err(SignedImbalance::Negative), } } /// Consume `self` and an `other` to return a new instance that combines /// both. pub fn merge(self, other: Self) -> Self { match (self, other) { (SignedImbalance::Positive(one), SignedImbalance::Positive(other)) => SignedImbalance::Positive(one.merge(other)), (SignedImbalance::Negative(one), SignedImbalance::Negative(other)) => SignedImbalance::Negative(one.merge(other)), (SignedImbalance::Positive(one), SignedImbalance::Negative(other)) => if one.peek() > other.peek() { SignedImbalance::Positive(one.offset(other).ok().unwrap_or_else(P::zero)) } else { SignedImbalance::Negative(other.offset(one).ok().unwrap_or_else(N::zero)) }, (one, other) => other.merge(one), } } } /// Split an unbalanced amount two ways between a common divisor. pub struct SplitTwoWays< Balance, Imbalance, Part1, Target1, Part2, Target2, >(PhantomData<(Balance, Imbalance, Part1, Target1, Part2, Target2)>); impl< Balance: From + Saturating + Div, I: Imbalance, Part1: U32, Target1: OnUnbalanced, Part2: U32, Target2: OnUnbalanced, > OnUnbalanced for SplitTwoWays { fn on_nonzero_unbalanced(amount: I) { let total: u32 = Part1::VALUE + Part2::VALUE; let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into(); let (imb1, imb2) = amount.split(amount1); Target1::on_unbalanced(imb1); Target2::on_unbalanced(imb2); } } /// Abstraction over a fungible assets system. pub trait Currency { /// The balance of an account. type Balance: SimpleArithmetic + FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default; /// The opaque token type for an imbalance. This is returned by unbalanced operations /// and must be dealt with. It may be dropped but cannot be cloned. type PositiveImbalance: Imbalance; /// The opaque token type for an imbalance. This is returned by unbalanced operations /// and must be dealt with. It may be dropped but cannot be cloned. type NegativeImbalance: Imbalance; // PUBLIC IMMUTABLES /// The combined balance of `who`. fn total_balance(who: &AccountId) -> Self::Balance; /// Same result as `slash(who, value)` (but without the side-effects) assuming there are no /// balance changes in the meantime and only the reserved balance is not taken into account. fn can_slash(who: &AccountId, value: Self::Balance) -> bool; /// The total amount of issuance in the system. fn total_issuance() -> Self::Balance; /// The minimum balance any single account may have. This is equivalent to the `Balances` module's /// `ExistentialDeposit`. fn minimum_balance() -> Self::Balance; /// Reduce the total issuance by `amount` and return the according imbalance. The imbalance will /// typically be used to reduce an account by the same amount with e.g. `settle`. /// /// This is infallible, but doesn't guarantee that the entire `amount` is burnt, for example /// in the case of underflow. fn burn(amount: Self::Balance) -> Self::PositiveImbalance; /// Increase the total issuance by `amount` and return the according imbalance. The imbalance /// will typically be used to increase an account by the same amount with e.g. /// `resolve_into_existing` or `resolve_creating`. /// /// This is infallible, but doesn't guarantee that the entire `amount` is issued, for example /// in the case of overflow. fn issue(amount: Self::Balance) -> Self::NegativeImbalance; /// The 'free' balance of a given account. /// /// This is the only balance that matters in terms of most operations on tokens. It alone /// is used to determine the balance when in the contract execution environment. When this /// balance falls below the value of `ExistentialDeposit`, then the 'current account' is /// deleted: specifically `FreeBalance`. Further, the `OnFreeBalanceZero` callback /// is invoked, giving a chance to external modules to clean up data associated with /// the deleted account. /// /// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. fn free_balance(who: &AccountId) -> Self::Balance; /// Returns `Ok` iff the account is able to make a withdrawal of the given amount /// for the given reason. Basically, it's just a dry-run of `withdraw`. /// /// `Err(...)` with the reason why not otherwise. fn ensure_can_withdraw( who: &AccountId, _amount: Self::Balance, reasons: WithdrawReasons, new_balance: Self::Balance, ) -> result::Result<(), &'static str>; // PUBLIC MUTABLES (DANGEROUS) /// Transfer some liquid free balance to another staker. /// /// This is a very high-level function. It will ensure all appropriate fees are paid /// and no imbalance in the system remains. fn transfer( source: &AccountId, dest: &AccountId, value: Self::Balance, existence_requirement: ExistenceRequirement, ) -> result::Result<(), &'static str>; /// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the /// free balance. This function cannot fail. /// /// The resulting imbalance is the first item of the tuple returned. /// /// As much funds up to `value` will be deducted as possible. If this is less than `value`, /// then a non-zero second item will be returned. fn slash( who: &AccountId, value: Self::Balance ) -> (Self::NegativeImbalance, Self::Balance); /// Mints `value` to the free balance of `who`. /// /// If `who` doesn't exist, nothing is done and an Err returned. fn deposit_into_existing( who: &AccountId, value: Self::Balance ) -> result::Result; /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on /// success. fn resolve_into_existing( who: &AccountId, value: Self::NegativeImbalance, ) -> result::Result<(), Self::NegativeImbalance> { let v = value.peek(); match Self::deposit_into_existing(who, v) { Ok(opposite) => Ok(drop(value.offset(opposite))), _ => Err(value), } } /// Adds up to `value` to the free balance of `who`. If `who` doesn't exist, it is created. /// /// Infallible. fn deposit_creating( who: &AccountId, value: Self::Balance, ) -> Self::PositiveImbalance; /// Similar to deposit_creating, only accepts a `NegativeImbalance` and returns nothing on /// success. fn resolve_creating( who: &AccountId, value: Self::NegativeImbalance, ) { let v = value.peek(); drop(value.offset(Self::deposit_creating(who, v))); } /// Removes some free balance from `who` account for `reason` if possible. If `liveness` is /// `KeepAlive`, then no less than `ExistentialDeposit` must be left remaining. /// /// This checks any locks, vesting, and liquidity requirements. If the removal is not possible, /// then it returns `Err`. /// /// If the operation is successful, this will return `Ok` with a `NegativeImbalance` whose value /// is `value`. fn withdraw( who: &AccountId, value: Self::Balance, reasons: WithdrawReasons, liveness: ExistenceRequirement, ) -> result::Result; /// Similar to withdraw, only accepts a `PositiveImbalance` and returns nothing on success. fn settle( who: &AccountId, value: Self::PositiveImbalance, reasons: WithdrawReasons, liveness: ExistenceRequirement, ) -> result::Result<(), Self::PositiveImbalance> { let v = value.peek(); match Self::withdraw(who, v, reasons, liveness) { Ok(opposite) => Ok(drop(value.offset(opposite))), _ => Err(value), } } /// Ensure an account's free balance equals some value; this will create the account /// if needed. /// /// Returns a signed imbalance and status to indicate if the account was successfully updated or update /// has led to killing of the account. fn make_free_balance_be( who: &AccountId, balance: Self::Balance, ) -> ( SignedImbalance, UpdateBalanceOutcome, ); } /// A currency where funds can be reserved from the user. pub trait ReservableCurrency: Currency { /// Same result as `reserve(who, value)` (but without the side-effects) assuming there /// are no balance changes in the meantime. fn can_reserve(who: &AccountId, value: Self::Balance) -> bool; /// Deducts up to `value` from reserved balance of `who`. This function cannot fail. /// /// As much funds up to `value` will be deducted as possible. If the reserve balance of `who` /// is less than `value`, then a non-zero second item will be returned. fn slash_reserved( who: &AccountId, value: Self::Balance ) -> (Self::NegativeImbalance, Self::Balance); /// The amount of the balance of a given account that is externally reserved; this can still get /// slashed, but gets slashed last of all. /// /// This balance is a 'reserve' balance that other subsystems use in order to set aside tokens /// that are still 'owned' by the account holder, but which are suspendable. /// /// When this balance falls below the value of `ExistentialDeposit`, then this 'reserve account' /// is deleted: specifically, `ReservedBalance`. /// /// `system::AccountNonce` is also deleted if `FreeBalance` is also zero (it also gets /// collapsed to zero if it ever becomes less than `ExistentialDeposit`. fn reserved_balance(who: &AccountId) -> Self::Balance; /// Moves `value` from balance to reserved balance. /// /// If the free balance is lower than `value`, then no funds will be moved and an `Err` will /// be returned to notify of this. This is different behavior than `unreserve`. fn reserve(who: &AccountId, value: Self::Balance) -> result::Result<(), &'static str>; /// Moves up to `value` from reserved balance to free balance. This function cannot fail. /// /// As much funds up to `value` will be moved as possible. If the reserve balance of `who` /// is less than `value`, then the remaining amount will be returned. /// /// # NOTES /// /// - This is different from `reserve`. /// - If the remaining reserved balance is less than `ExistentialDeposit`, it will /// invoke `on_reserved_too_low` and could reap the account. fn unreserve(who: &AccountId, value: Self::Balance) -> Self::Balance; /// Moves up to `value` from reserved balance of account `slashed` to free balance of account /// `beneficiary`. `beneficiary` must exist for this to succeed. If it does not, `Err` will be /// returned. /// /// As much funds up to `value` will be deducted as possible. If this is less than `value`, /// then `Ok(non_zero)` will be returned. fn repatriate_reserved( slashed: &AccountId, beneficiary: &AccountId, value: Self::Balance ) -> result::Result; } /// An identifier for a lock. Used for disambiguating different locks so that /// they can be individually replaced or removed. pub type LockIdentifier = [u8; 8]; /// A currency whose accounts can have liquidity restrictions. pub trait LockableCurrency: Currency { /// The quantity used to denote time; usually just a `BlockNumber`. type Moment; /// Create a new balance lock on account `who`. /// /// If the new lock is valid (i.e. not already expired), it will push the struct to /// the `Locks` vec in storage. Note that you can lock more funds than a user has. /// /// If the lock `id` already exists, this will update it. fn set_lock( id: LockIdentifier, who: &AccountId, amount: Self::Balance, until: Self::Moment, reasons: WithdrawReasons, ); /// Changes a balance lock (selected by `id`) so that it becomes less liquid in all /// parameters or creates a new one if it does not exist. /// /// Calling `extend_lock` on an existing lock `id` differs from `set_lock` in that it /// applies the most severe constraints of the two, while `set_lock` replaces the lock /// with the new parameters. As in, `extend_lock` will set: /// - maximum `amount` /// - farthest duration (`until`) /// - bitwise mask of all `reasons` fn extend_lock( id: LockIdentifier, who: &AccountId, amount: Self::Balance, until: Self::Moment, reasons: WithdrawReasons, ); /// Remove an existing lock. fn remove_lock( id: LockIdentifier, who: &AccountId, ); } /// A currency whose accounts can have balances which vest over time. pub trait VestingCurrency: Currency { /// The quantity used to denote time; usually just a `BlockNumber`. type Moment; /// Get the amount that is currently being vested and cannot be transferred out of this account. fn vesting_balance(who: &AccountId) -> Self::Balance; /// Adds a vesting schedule to a given account. /// /// If there already exists a vesting schedule for the given account, an `Err` is returned /// and nothing is updated. fn add_vesting_schedule( who: &AccountId, locked: Self::Balance, per_block: Self::Balance, starting_block: Self::Moment, ) -> result::Result<(), &'static str>; /// Remove a vesting schedule for a given account. fn remove_vesting_schedule(who: &AccountId); } bitmask! { /// Reasons for moving funds out of an account. #[derive(Encode, Decode)] pub mask WithdrawReasons: i8 where /// Reason for moving funds out of an account. #[derive(Encode, Decode)] flags WithdrawReason { /// In order to pay for (system) transaction costs. TransactionPayment = 0b00000001, /// In order to transfer ownership. Transfer = 0b00000010, /// In order to reserve some funds for a later return or repatriation Reserve = 0b00000100, /// In order to pay some other (higher-level) fees. Fee = 0b00001000, /// In order to tip a validator for transaction inclusion. Tip = 0b00010000, } } pub trait Time { type Moment: SimpleArithmetic + Parameter + Default + Copy; fn now() -> Self::Moment; } impl WithdrawReasons { /// Choose all variants except for `one`. /// /// ```rust /// # use frame_support::traits::{WithdrawReason, WithdrawReasons}; /// # fn main() { /// assert_eq!( /// WithdrawReason::Fee | WithdrawReason::Transfer | WithdrawReason::Reserve | WithdrawReason::Tip, /// WithdrawReasons::except(WithdrawReason::TransactionPayment), /// ); /// # } /// ``` pub fn except(one: WithdrawReason) -> WithdrawReasons { let mut mask = Self::all(); mask.toggle(one); mask } } /// Trait for type that can handle incremental changes to a set of account IDs. pub trait ChangeMembers { /// A number of members `incoming` just joined the set and replaced some `outgoing` ones. The /// new set is given by `new`, and need not be sorted. fn change_members(incoming: &[AccountId], outgoing: &[AccountId], mut new: Vec) { new.sort_unstable(); Self::change_members_sorted(incoming, outgoing, &new[..]); } /// A number of members `_incoming` just joined the set and replaced some `_outgoing` ones. The /// new set is thus given by `sorted_new` and **must be sorted**. /// /// NOTE: This is the only function that needs to be implemented in `ChangeMembers`. fn change_members_sorted( incoming: &[AccountId], outgoing: &[AccountId], sorted_new: &[AccountId], ); /// Set the new members; they **must already be sorted**. This will compute the diff and use it to /// call `change_members_sorted`. fn set_members_sorted(new_members: &[AccountId], old_members: &[AccountId]) { let (incoming, outgoing) = Self::compute_members_diff(new_members, old_members); Self::change_members_sorted(&incoming[..], &outgoing[..], &new_members); } /// Set the new members; they **must already be sorted**. This will compute the diff and use it to /// call `change_members_sorted`. fn compute_members_diff( new_members: &[AccountId], old_members: &[AccountId] ) -> (Vec, Vec) { let mut old_iter = old_members.iter(); let mut new_iter = new_members.iter(); let mut incoming = Vec::new(); let mut outgoing = Vec::new(); let mut old_i = old_iter.next(); let mut new_i = new_iter.next(); loop { match (old_i, new_i) { (None, None) => break, (Some(old), Some(new)) if old == new => { old_i = old_iter.next(); new_i = new_iter.next(); } (Some(old), Some(new)) if old < new => { outgoing.push(old.clone()); old_i = old_iter.next(); } (Some(old), None) => { outgoing.push(old.clone()); old_i = old_iter.next(); } (_, Some(new)) => { incoming.push(new.clone()); new_i = new_iter.next(); } } } (incoming, outgoing) } } impl ChangeMembers for () { fn change_members(_: &[T], _: &[T], _: Vec) {} fn change_members_sorted(_: &[T], _: &[T], _: &[T]) {} fn set_members_sorted(_: &[T], _: &[T]) {} } /// Trait for type that can handle the initialization of account IDs at genesis. pub trait InitializeMembers { /// Initialize the members to the given `members`. fn initialize_members(members: &[AccountId]); } impl InitializeMembers for () { fn initialize_members(_: &[T]) {} } // A trait that is able to provide randomness. pub trait Randomness { /// Get a "random" value /// /// Being a deterministic blockchain, real randomness is difficult to come by. This gives you /// something that approximates it. `subject` is a context identifier and allows you to get a /// different result to other callers of this function; use it like /// `random(&b"my context"[..])`. fn random(subject: &[u8]) -> Output; /// Get the basic random seed. /// /// In general you won't want to use this, but rather `Self::random` which allows you to give a /// subject for the random result and whose value will be independently low-influence random /// from any other such seeds. fn random_seed() -> Output { Self::random(&[][..]) } }