Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

decouple transaction payment and currency #6912

Merged
27 commits merged into from
Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
370ab13
wip: setup types
weichweich Aug 10, 2020
96137cb
fix types
weichweich Aug 10, 2020
006ffcd
make tx payment pallet independent from balances
weichweich Aug 11, 2020
052d951
fix dependent tests
weichweich Aug 11, 2020
78b503b
comments
weichweich Aug 11, 2020
9bb1b46
restructure a bit and include more info
weichweich Aug 13, 2020
1d08e13
clean up ugly phantom
weichweich Aug 17, 2020
af9bda7
reduce complexity
weichweich Aug 18, 2020
96af556
minor doc improvements
weichweich Aug 18, 2020
308c220
use shorthand
weichweich Aug 18, 2020
c724904
doc
weichweich Aug 18, 2020
99eb079
fix line lenght and style
weichweich Aug 18, 2020
7ccb276
Merge remote-tracking branch 'upstream/master' into aw-tx-payment-no-…
weichweich Oct 2, 2020
d8713c1
readd BalanceOf
weichweich Oct 2, 2020
bfff36d
some clarifications and readability improvements
weichweich Oct 2, 2020
88a48d0
move balance type to OnChargeTransaction
weichweich Oct 2, 2020
b1fdb6c
remove noise
weichweich Oct 2, 2020
1794b5f
fix style
weichweich Oct 2, 2020
ada1d06
Apply suggestions from code review
weichweich Oct 5, 2020
623b449
Improve naming and documentation
weichweich Oct 5, 2020
b657448
Merge remote-tracking branch 'upstream/master' into aw-tx-payment-no-…
weichweich Oct 5, 2020
7bad69c
Apply suggestions from code review
weichweich Oct 12, 2020
1bda8a8
Merge remote-tracking branch 'upstream/master' into aw-tx-payment-no-…
weichweich Oct 12, 2020
4f77443
Merge remote-tracking branch 'upstream/master' into aw-tx-payment-no-…
weichweich Oct 30, 2020
2367a3e
always call withdraw_fee
weichweich Oct 30, 2020
e5f1c64
move NegativeImbalanceOf to payment module
weichweich Oct 30, 2020
1b73d2b
fix unused import
weichweich Oct 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub use frame_support::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
},
};
use pallet_transaction_payment::CurrencyAdapter;

/// Import the template pallet.
pub use template;
Expand Down Expand Up @@ -249,8 +250,7 @@ parameter_types! {
}

impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = ();
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
Expand Down
5 changes: 2 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use pallet_grandpa::fg_primitives;
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment, CurrencyAdapter};
use pallet_session::{historical as pallet_session_historical};
use sp_inherents::{InherentData, CheckInherentsResult};
use static_assertions::const_assert;
Expand Down Expand Up @@ -360,8 +360,7 @@ parameter_types! {
}

impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = DealWithFees;
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate =
Expand Down
4 changes: 2 additions & 2 deletions frame/balances/src/tests_composite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use sp_io;
use frame_support::{impl_outer_origin, impl_outer_event, parameter_types};
use frame_support::traits::Get;
use frame_support::weights::{Weight, DispatchInfo, IdentityFee};
use pallet_transaction_payment::CurrencyAdapter;
use std::cell::RefCell;
use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};

Expand Down Expand Up @@ -97,8 +98,7 @@ parameter_types! {
pub const TransactionByteFee: u64 = 1;
}
impl pallet_transaction_payment::Trait for Test {
type Currency = Module<Test>;
type OnTransactionPayment = ();
type OnChargeTransaction = CurrencyAdapter<Module<Test>, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<u64>;
type FeeMultiplierUpdate = ();
Expand Down
4 changes: 2 additions & 2 deletions frame/balances/src/tests_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use frame_support::traits::{Get, StorageMapShim};
use frame_support::weights::{Weight, DispatchInfo, IdentityFee};
use std::cell::RefCell;
use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};
use pallet_transaction_payment::CurrencyAdapter;

use frame_system as system;
impl_outer_origin!{
Expand Down Expand Up @@ -97,8 +98,7 @@ parameter_types! {
pub const TransactionByteFee: u64 = 1;
}
impl pallet_transaction_payment::Trait for Test {
type Currency = Module<Test>;
type OnTransactionPayment = ();
type OnChargeTransaction = CurrencyAdapter<Module<Test>, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<u64>;
type FeeMultiplierUpdate = ();
Expand Down
4 changes: 2 additions & 2 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ mod tests {
traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons},
};
use frame_system::{Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo};
use pallet_transaction_payment::CurrencyAdapter;
use pallet_balances::Call as BalancesCall;
use hex_literal::hex;
const TEST_KEY: &[u8] = &*b":test:key:";
Expand Down Expand Up @@ -632,8 +633,7 @@ mod tests {
pub const TransactionByteFee: Balance = 0;
}
impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = ();
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
Expand Down
115 changes: 48 additions & 67 deletions frame/transaction-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@
//! - A means of updating the fee for the next block, via defining a multiplier, based on the
//! final state of the chain at the end of the previous block. This can be configured via
//! [`Trait::FeeMultiplierUpdate`]
//! - How the fees are paid via [`Trait::OnChargeTransaction`].

#![cfg_attr(not(feature = "std"), no_std)]

use sp_std::prelude::*;
use codec::{Encode, Decode};
use frame_support::{
decl_storage, decl_module,
traits::{Currency, Get, OnUnbalanced, ExistenceRequirement, WithdrawReasons, Imbalance},
traits::Get,
weights::{
Weight, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Pays, WeightToFeePolynomial,
WeightToFeeCoefficient,
Expand All @@ -46,23 +47,23 @@ use frame_support::{
use sp_runtime::{
FixedU128, FixedPointNumber, FixedPointOperand, Perquintill, RuntimeDebug,
transaction_validity::{
TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError,
TransactionValidity,
TransactionPriority, ValidTransaction, TransactionValidityError, TransactionValidity,
},
traits::{
Zero, Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable,
Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable,
DispatchInfoOf, PostDispatchInfoOf,
},
};
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;

mod payment;
pub use payment::*;

/// Fee multiplier.
pub type Multiplier = FixedU128;

type BalanceOf<T> =
athei marked this conversation as resolved.
Show resolved Hide resolved
<<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
type NegativeImbalanceOf<T> =
<<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;
<<T as Trait>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;

/// A struct to update the weight multiplier per block. It implements `Convert<Multiplier,
/// Multiplier>`, meaning that it can convert the previous multiplier to the next one. This should
Expand Down Expand Up @@ -213,13 +214,13 @@ impl Default for Releases {
}

pub trait Trait: frame_system::Trait {
/// The currency type in which fees will be paid.
type Currency: Currency<Self::AccountId> + Send + Sync;

/// Handler for the unbalanced reduction when taking transaction fees. This is either one or
/// two separate imbalances, the first is the transaction fee paid, the second is the tip paid,
/// if any.
type OnTransactionPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
/// Handler for withdrawing, refunding and depositing the transaction fee.
/// Transaction fees are withdrawn before the transaction is executed.
/// After the transaction was executed the transaction weight can be
/// adjusted, depending on the used resources by the transaction. If the
/// transaction weight is lower than expected, parts of the transaction fee
/// might be refunded. In the end the fees can be deposited.
type OnChargeTransaction: OnChargeTransaction<Self>;

/// The fee to be paid for making a transaction; the per-byte portion.
type TransactionByteFee: Get<BalanceOf<Self>>;
Expand Down Expand Up @@ -442,30 +443,21 @@ impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> where
fn withdraw_fee(
&self,
who: &T::AccountId,
call: &T::Call,
info: &DispatchInfoOf<T::Call>,
len: usize,
) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {
) -> Result<
(
BalanceOf<T>,
<<T as Trait>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo,
),
TransactionValidityError,
> {
let tip = self.0;
let fee = Module::<T>::compute_fee(len as u32, info, tip);

// Only mess with balances if fee is not zero.
if fee.is_zero() {
return Ok((fee, None));
}

match T::Currency::withdraw(
who,
fee,
if tip.is_zero() {
WithdrawReasons::TRANSACTION_PAYMENT
} else {
WithdrawReasons::TRANSACTION_PAYMENT | WithdrawReasons::TIP
},
ExistenceRequirement::KeepAlive,
) {
Ok(imbalance) => Ok((fee, Some(imbalance))),
Err(_) => Err(InvalidTransaction::Payment.into()),
}
<<T as Trait>::OnChargeTransaction as OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)
.map(|i| (fee, i))
}

/// Get an appropriate priority for a transaction with the given length and info.
Expand Down Expand Up @@ -505,17 +497,24 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
type AccountId = T::AccountId;
type Call = T::Call;
type AdditionalSigned = ();
type Pre = (BalanceOf<T>, Self::AccountId, Option<NegativeImbalanceOf<T>>, BalanceOf<T>);
type Pre = (
// tip
BalanceOf<T>,
// who paid the fee
Self::AccountId,
// imbalance resulting from withdrawing the fee
<<T as Trait>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo,
);
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }

fn validate(
&self,
who: &Self::AccountId,
_call: &Self::Call,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> TransactionValidity {
let (fee, _) = self.withdraw_fee(who, info, len)?;
let (fee, _) = self.withdraw_fee(who, call, info, len)?;
Ok(ValidTransaction {
priority: Self::get_priority(len, info, fee),
..Default::default()
Expand All @@ -525,12 +524,12 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
fn pre_dispatch(
self,
who: &Self::AccountId,
_call: &Self::Call,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize
) -> Result<Self::Pre, TransactionValidityError> {
let (fee, imbalance) = self.withdraw_fee(who, info, len)?;
Ok((self.0, who.clone(), imbalance, fee))
let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
Ok((self.0, who.clone(), imbalance))
}

fn post_dispatch(
Expand All @@ -540,32 +539,14 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> whe
len: usize,
_result: &DispatchResult,
) -> Result<(), TransactionValidityError> {
let (tip, who, imbalance, fee) = pre;
if let Some(payed) = imbalance {
let actual_fee = Module::<T>::compute_actual_fee(
len as u32,
info,
post_info,
tip,
);
let refund = fee.saturating_sub(actual_fee);
let actual_payment = match T::Currency::deposit_into_existing(&who, refund) {
Ok(refund_imbalance) => {
// The refund cannot be larger than the up front payed max weight.
// `PostDispatchInfo::calc_unspent` guards against such a case.
match payed.offset(refund_imbalance) {
Ok(actual_payment) => actual_payment,
Err(_) => return Err(InvalidTransaction::Payment.into()),
}
}
// We do not recreate the account using the refund. The up front payment
// is gone in that case.
Err(_) => payed,
};
let imbalances = actual_payment.split(tip);
T::OnTransactionPayment::on_unbalanceds(Some(imbalances.0).into_iter()
.chain(Some(imbalances.1)));
}
let (tip, who, imbalance) = pre;
let actual_fee = Module::<T>::compute_actual_fee(
len as u32,
info,
post_info,
tip,
);
T::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;
Ok(())
}
}
Expand All @@ -580,6 +561,7 @@ mod tests {
DispatchClass, DispatchInfo, PostDispatchInfo, GetDispatchInfo, Weight,
WeightToFeePolynomial, WeightToFeeCoefficients, WeightToFeeCoefficient,
},
traits::Currency,
};
use pallet_balances::Call as BalancesCall;
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
Expand Down Expand Up @@ -699,8 +681,7 @@ mod tests {
}

impl Trait for Runtime {
type Currency = pallet_balances::Module<Runtime>;
type OnTransactionPayment = ();
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = WeightToFee;
type FeeMultiplierUpdate = ();
Expand Down
Loading