Improve fees module (#1821)

* remove amount associated
* make a new trait to bound some arithmetics to balances or assets:
  It also remove arithmetic bounds of srml-support::traits::Currency.

  To update your code then use srml_support::traits::ArithmeticType like:
  `type Currency: ArithmeticType + Currency<Self::AccountId, Balance=BalanceOf<Self>>; ` 
  with `type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type; `

* improve decl_storage when it explicit serde bound: basically don't try to be smarter than rust and just use where clause.
This commit is contained in:
thiolliere
2019-02-19 17:13:59 +01:00
committed by GitHub
parent 9a2f1b2007
commit 8065116ba5
16 changed files with 48 additions and 100 deletions
@@ -165,7 +165,6 @@ impl balances::Trait for Runtime {
}
impl fees::Trait for Runtime {
type Amount = u128;
type TransferAsset = Balances;
type Event = Event;
}
+1 -2
View File
@@ -61,7 +61,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
spec_version: 29,
impl_version: 30,
impl_version: 31,
apis: RUNTIME_API_VERSIONS,
};
@@ -109,7 +109,6 @@ impl balances::Trait for Runtime {
impl fees::Trait for Runtime {
type Event = Event;
type Amount = Balance;
type TransferAsset = Balances;
}
+6 -2
View File
@@ -29,7 +29,7 @@ use rstd::{cmp, result};
use parity_codec::Codec;
use parity_codec_derive::{Encode, Decode};
use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module, ensure};
use srml_support::traits::{UpdateBalanceOutcome, Currency, EnsureAccountLiquid, OnFreeBalanceZero};
use srml_support::traits::{UpdateBalanceOutcome, Currency, EnsureAccountLiquid, OnFreeBalanceZero, ArithmeticType};
use srml_support::dispatch::Result;
use primitives::traits::{Zero, SimpleArithmetic,
As, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug, TransferAsset};
@@ -40,7 +40,7 @@ mod tests;
pub trait Trait: system::Trait {
/// The balance of an account.
type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As<usize> + As<u64>;
type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + As<usize> + As<u64> + MaybeSerializeDebug;
/// A function which is invoked when the free-balance has fallen below the existential deposit and
/// has been reduced to zero.
@@ -58,6 +58,10 @@ pub trait Trait: system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
impl<T: Trait> ArithmeticType for Module<T> {
type Type = <T as Trait>::Balance;
}
decl_event!(
pub enum Event<T> where
<T as system::Trait>::AccountId,
-1
View File
@@ -91,7 +91,6 @@ impl consensus::Trait for Test {
}
impl fees::Trait for Test {
type Event = MetaEvent;
type Amount = u64;
type TransferAsset = Balances;
}
impl Trait for Test {
+2 -2
View File
@@ -77,11 +77,11 @@ use system::{self, ensure_signed};
// after each vote as all but K entries are cleared. newly registering candidates must use cleared
// entries before they increase the capacity.
use srml_support::decl_module;
use srml_support::{decl_module, traits::ArithmeticType};
pub type VoteIndex = u32;
type BalanceOf<T> = <<T as democracy::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type BalanceOf<T> = <<T as democracy::Trait>::Currency as ArithmeticType>::Type;
pub trait Trait: democracy::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
+3 -3
View File
@@ -24,7 +24,7 @@ use primitives::traits::{Zero, As};
use parity_codec_derive::{Encode, Decode};
use srml_support::{StorageValue, StorageMap, Parameter, Dispatchable, IsSubType};
use srml_support::{decl_module, decl_storage, decl_event, ensure};
use srml_support::traits::{Currency, OnFreeBalanceZero, EnsureAccountLiquid};
use srml_support::traits::{Currency, OnFreeBalanceZero, EnsureAccountLiquid, ArithmeticType};
use srml_support::dispatch::Result;
use system::ensure_signed;
@@ -65,10 +65,10 @@ impl Vote {
}
}
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type;
pub trait Trait: system::Trait + Sized {
type Currency: Currency<<Self as system::Trait>::AccountId>;
type Currency: ArithmeticType + Currency<<Self as system::Trait>::AccountId, Balance=BalanceOf<Self>>;
type Proposal: Parameter + Dispatchable<Origin=Self::Origin> + IsSubType<Module<Self>>;
-1
View File
@@ -324,7 +324,6 @@ mod tests {
}
impl fees::Trait for Runtime {
type Event = MetaEvent;
type Amount = u64;
type TransferAsset = balances::Module<Runtime>;
}
+13 -14
View File
@@ -19,9 +19,9 @@
// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]
use srml_support::{dispatch::Result, Parameter, StorageMap, decl_event, decl_storage, decl_module};
use srml_support::{dispatch::Result, traits::ArithmeticType, StorageMap, decl_event, decl_storage, decl_module};
use runtime_primitives::traits::{
As, Member, SimpleArithmetic, ChargeBytesFee, ChargeFee,
As, ChargeBytesFee, ChargeFee,
TransferAsset, CheckedAdd, CheckedSub, CheckedMul, Zero
};
use system;
@@ -29,15 +29,14 @@ use system;
mod mock;
mod tests;
type AssetOf<T> = <<T as Trait>::TransferAsset as ArithmeticType>::Type;
pub trait Trait: system::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
/// The unit for fee amount
type Amount: Member + Parameter + SimpleArithmetic + Default + Copy + As<u64>;
/// A function does the asset transfer between accounts
type TransferAsset: TransferAsset<Self::AccountId, Amount = Self::Amount>;
type TransferAsset: ArithmeticType + TransferAsset<Self::AccountId, Amount=AssetOf<Self>>;
}
decl_module! {
@@ -58,7 +57,7 @@ decl_module! {
}
decl_event!(
pub enum Event<T> where <T as Trait>::Amount {
pub enum Event<T> where Amount = AssetOf<T> {
/// Fee charged (extrinsic_index, fee_amount)
Charged(u32, Amount),
}
@@ -67,22 +66,22 @@ decl_event!(
decl_storage! {
trait Store for Module<T: Trait> as Fees {
/// The fee to be paid for making a transaction; the base.
pub TransactionBaseFee get(transaction_base_fee) config(): T::Amount;
pub TransactionBaseFee get(transaction_base_fee) config(): AssetOf<T>;
/// The fee to be paid for making a transaction; the per-byte portion.
pub TransactionByteFee get(transaction_byte_fee) config(): T::Amount;
pub TransactionByteFee get(transaction_byte_fee) config(): AssetOf<T>;
/// The `extrinsic_index => accumulated_fees` map, containing records to
/// track the overall charged fees for each transaction.
///
/// All records should be removed at finalise stage.
CurrentTransactionFee get(current_transaction_fee): map u32 => T::Amount;
CurrentTransactionFee get(current_transaction_fee): map u32 => AssetOf<T>;
}
}
impl<T: Trait> ChargeBytesFee<T::AccountId> for Module<T> {
fn charge_base_bytes_fee(transactor: &T::AccountId, encoded_len: usize) -> Result {
let bytes_fee = Self::transaction_byte_fee().checked_mul(
&<T::Amount as As<u64>>::sa(encoded_len as u64)
&<AssetOf<T> as As<u64>>::sa(encoded_len as u64)
).ok_or_else(|| "bytes fee overflow")?;
let overall = Self::transaction_base_fee().checked_add(&bytes_fee).ok_or_else(|| "bytes fee overflow")?;
Self::charge_fee(transactor, overall)
@@ -90,9 +89,9 @@ impl<T: Trait> ChargeBytesFee<T::AccountId> for Module<T> {
}
impl<T: Trait> ChargeFee<T::AccountId> for Module<T> {
type Amount = T::Amount;
type Amount = AssetOf<T>;
fn charge_fee(transactor: &T::AccountId, amount: T::Amount) -> Result {
fn charge_fee(transactor: &T::AccountId, amount: AssetOf<T>) -> Result {
let extrinsic_index = <system::Module<T>>::extrinsic_index().ok_or_else(|| "no extrinsic index found")?;
let current_fee = Self::current_transaction_fee(extrinsic_index);
let new_fee = current_fee.checked_add(&amount).ok_or_else(|| "fee got overflow after charge")?;
@@ -103,7 +102,7 @@ impl<T: Trait> ChargeFee<T::AccountId> for Module<T> {
Ok(())
}
fn refund_fee(transactor: &T::AccountId, amount: T::Amount) -> Result {
fn refund_fee(transactor: &T::AccountId, amount: AssetOf<T>) -> Result {
let extrinsic_index = <system::Module<T>>::extrinsic_index().ok_or_else(|| "no extrinsic index found")?;
let current_fee = Self::current_transaction_fee(extrinsic_index);
let new_fee = current_fee.checked_sub(&amount).ok_or_else(|| "fee got underflow after refund")?;
+6 -3
View File
@@ -25,7 +25,7 @@ use runtime_primitives::{
};
use primitives::{H256, Blake2Hasher};
use runtime_io;
use srml_support::{impl_outer_origin, impl_outer_event};
use srml_support::{impl_outer_origin, impl_outer_event, traits::ArithmeticType};
use crate::{GenesisConfig, Module, Trait, system};
impl_outer_origin!{
@@ -52,6 +52,10 @@ impl<AccountId> TransferAsset<AccountId> for TransferAssetMock {
fn add_to(_: &AccountId, _: Self::Amount) -> Result<(), &'static str> { Ok(()) }
}
impl ArithmeticType for TransferAssetMock {
type Type = u64;
}
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Test;
@@ -69,8 +73,7 @@ impl system::Trait for Test {
type Log = DigestItem;
}
impl Trait for Test {
type Amount = u64;
type Event =TestEvent;
type Event = TestEvent;
type TransferAsset = TransferAssetMock;
}
+3 -3
View File
@@ -25,7 +25,7 @@ use parity_codec::HasCompact;
use parity_codec_derive::{Encode, Decode};
use srml_support::{Parameter, StorageValue, StorageMap, dispatch::Result};
use srml_support::{decl_module, decl_event, decl_storage, ensure};
use srml_support::traits::{Currency, OnDilution, EnsureAccountLiquid, OnFreeBalanceZero};
use srml_support::traits::{Currency, OnDilution, EnsureAccountLiquid, OnFreeBalanceZero, ArithmeticType};
use session::OnSessionChange;
use primitives::Perbill;
use primitives::traits::{Zero, One, Bounded, As, StaticLookup};
@@ -67,11 +67,11 @@ impl<B: Default + HasCompact + Copy> Default for ValidatorPrefs<B> {
}
}
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type;
pub trait Trait: system::Trait + session::Trait {
/// The staking balance.
type Currency: Currency<Self::AccountId>;
type Currency: ArithmeticType + Currency<Self::AccountId, Balance=BalanceOf<Self>>;
/// Some tokens minted.
type OnRewardMinted: OnDilution<BalanceOf<Self>>;
@@ -192,13 +192,10 @@ fn decl_store_extra_genesis(
is_trait_needed = true;
has_trait_field = true;
}
for t in ext::get_non_bound_serde_derive_types(type_infos.value_type, &traitinstance) {
serde_complete_bound.insert(t);
}
serde_complete_bound.insert(type_infos.value_type);
if let DeclStorageTypeInfosKind::Map { key_type, .. } = type_infos.kind {
for t in ext::get_non_bound_serde_derive_types(key_type, &traitinstance) {
serde_complete_bound.insert(t);
}
serde_complete_bound.insert(key_type);
}
let storage_type = type_infos.typ.clone();
config_field.extend(match type_infos.kind {
@@ -285,9 +282,7 @@ fn decl_store_extra_genesis(
has_trait_field = true;
}
for t in ext::get_non_bound_serde_derive_types(extra_type, &traitinstance).into_iter() {
serde_complete_bound.insert(t);
}
serde_complete_bound.insert(extra_type);
let extrafield = &extra_field.content;
genesis_extrafields.extend(quote!{
@@ -315,6 +310,7 @@ fn decl_store_extra_genesis(
let serde_bug_bound = if !serde_complete_bound.is_empty() {
let mut b_ser = String::new();
let mut b_dser = String::new();
// panic!("{:#?}", serde_complete_bound);
serde_complete_bound.into_iter().for_each(|bound| {
let stype = quote!(#bound);
b_ser.push_str(&format!("{} : {}::serde::Serialize, ", stype, scrate));
@@ -327,57 +327,3 @@ pub fn has_parametric_type_def(typ: &syn::Type, ident: &Ident, default: bool) ->
pub fn has_parametric_type(typ: &syn::Type, ident: &Ident) -> bool {
has_parametric_type_def(typ, ident, true)
}
/// Get case where serde does not include bound with serde_derive macros:
/// see https://github.com/serde-rs/serde/issues/1454
pub fn get_non_bound_serde_derive_types(typ: &syn::Type, t: &syn::Ident) -> Vec<syn::Type> {
let mut result = Vec::new();
get_non_bound_serde_derive_types_inner(typ, t, &mut result);
result
}
fn get_non_bound_serde_derive_types_inner(typ: &syn::Type, t: &syn::Ident, result: &mut Vec<syn::Type>) {
match *typ {
syn::Type::Path(ref path) => {
if heuristic_is_associated_path(&path.path,t) {
result.push(typ.clone());
}
for p in path.path.segments.iter() {
if let syn::PathArguments::AngleBracketed(ref args) = p.arguments {
for a in args.args.iter() {
if let syn::GenericArgument::Type(ref ty) = a {
get_non_bound_serde_derive_types_inner(ty, t, result)
}
}
}
}
},
syn::Type::Slice(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::Array(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::Ptr(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::Reference(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::BareFn(..) => (),
syn::Type::Never(..) => (),
syn::Type::Tuple(ref inner) => for e in inner.elems.iter() {
get_non_bound_serde_derive_types_inner(e, t, result)
},
syn::Type::TraitObject(..) => (),
syn::Type::ImplTrait(..) => (),
syn::Type::Paren(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::Group(ref inner) => get_non_bound_serde_derive_types_inner(&inner.elem, t, result),
syn::Type::Infer(..) => (),
syn::Type::Macro(..) => (),
syn::Type::Verbatim(..) => (),
}
}
fn heuristic_is_associated_path(path: &syn::Path,t: &syn::Ident) -> bool {
if let Some(syn::punctuated::Pair::Punctuated(s,_)) = path.segments.first() {
&s.ident == t
} else {
false
}
}
+5 -1
View File
@@ -79,10 +79,14 @@ pub enum UpdateBalanceOutcome {
AccountKilled,
}
pub trait ArithmeticType {
type Type: SimpleArithmetic + As<usize> + As<u64> + Codec + Copy + MaybeSerializeDebug + Default;
}
/// Abstraction over a fungible assets system.
pub trait Currency<AccountId> {
/// The balance of an account.
type Balance: SimpleArithmetic + As<usize> + As<u64> + Codec + Copy + MaybeSerializeDebug + Default;
type Balance;
// PUBLIC IMMUTABLES
+4 -4
View File
@@ -22,12 +22,12 @@
use serde_derive::{Serialize, Deserialize};
use rstd::prelude::*;
use srml_support::{StorageValue, StorageMap, decl_module, decl_storage, decl_event, ensure};
use srml_support::traits::{Currency, OnDilution};
use srml_support::traits::{Currency, OnDilution, ArithmeticType};
use runtime_primitives::{Permill, traits::{Zero, EnsureOrigin, StaticLookup}};
use parity_codec_derive::{Encode, Decode};
use system::ensure_signed;
type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type BalanceOf<T> = <<T as Trait>::Currency as ArithmeticType>::Type;
/// Our module's configuration trait. All our types and consts go in here. If the
/// module is dependent on specific other modules, then their configuration traits
@@ -36,7 +36,7 @@ type BalanceOf<T> = <<T as Trait>::Currency as Currency<<T as system::Trait>::Ac
/// `system::Trait` should always be included in our implied traits.
pub trait Trait: system::Trait {
/// The staking balance.
type Currency: Currency<Self::AccountId>;
type Currency: ArithmeticType + Currency<Self::AccountId, Balance=BalanceOf<Self>>;
/// Origin from which approvals must come.
type ApproveOrigin: EnsureOrigin<Self::Origin>;
@@ -172,7 +172,7 @@ decl_storage! {
decl_event!(
pub enum Event<T>
where
Balance = <<T as Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance,
Balance = BalanceOf<T>,
<T as system::Trait>::AccountId
{
/// New proposal.