Apply WeightToFeePolynomials to pallet_transaction_payment's length fee (#10785)

* Apply WeightToFeePolynomials to length fee

* Remove TransactionByteFee

* Add test cases for ConstantModifierFee

* Restore import

* Use pallet::constant_name

* Remove irrelevant TODO comment

* Update frame/support/src/weights.rs

* Update frame/transaction-payment/src/lib.rs

* Update frame/transaction-payment/src/lib.rs

* Update frame/transaction-payment/src/lib.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* s/ConstantModifierFee/ConstantMultiplier/

* Impl LengthToFee for test configs

* fmt

* Remove unused import

* Impl WeightToFeePolynomial for byte fee in ExtBuilder

* Remove unused import

* fix doc

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Stephen Shelton
2022-04-07 11:24:59 +00:00
committed by GitHub
parent b438b47f1a
commit ca1261ee21
10 changed files with 85 additions and 33 deletions
@@ -249,15 +249,11 @@ impl pallet_balances::Config for Runtime {
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const TransactionByteFee: Balance = 1;
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
}
+2 -2
View File
@@ -35,7 +35,7 @@ use frame_support::{
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
ConstantMultiplier, DispatchClass, IdentityFee, Weight,
},
PalletId, RuntimeDebug,
};
@@ -444,9 +444,9 @@ parameter_types! {
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate =
TargetedFeeAdjustment<Self, TargetBlockFullness, AdjustmentVariable, MinimumMultiplier>;
}
@@ -78,9 +78,9 @@ impl frame_system::Config for Test {
impl pallet_transaction_payment::Config for Test {
type OnChargeTransaction = CurrencyAdapter<Pallet<Test>, ()>;
type TransactionByteFee = ConstU64<1>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<u64>;
type LengthToFee = IdentityFee<u64>;
type FeeMultiplierUpdate = ();
}
+1 -1
View File
@@ -79,9 +79,9 @@ impl frame_system::Config for Test {
impl pallet_transaction_payment::Config for Test {
type OnChargeTransaction = CurrencyAdapter<Pallet<Test>, ()>;
type TransactionByteFee = ConstU64<1>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<u64>;
type LengthToFee = IdentityFee<u64>;
type FeeMultiplierUpdate = ();
}
@@ -85,9 +85,9 @@ impl frame_system::Config for Test {
impl pallet_transaction_payment::Config for Test {
type OnChargeTransaction = CurrencyAdapter<Pallet<Test>, ()>;
type TransactionByteFee = ConstU64<1>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<u64>;
type LengthToFee = IdentityFee<u64>;
type FeeMultiplierUpdate = ();
}
+4 -2
View File
@@ -576,7 +576,9 @@ mod tests {
ConstU32, ConstU64, ConstU8, Currency, LockIdentifier, LockableCurrency,
WithdrawReasons,
},
weights::{IdentityFee, RuntimeDbWeight, Weight, WeightToFeePolynomial},
weights::{
ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFeePolynomial,
},
};
use frame_system::{Call as SystemCall, ChainContext, LastRuntimeUpgradeInfo};
use pallet_balances::Call as BalancesCall;
@@ -787,9 +789,9 @@ mod tests {
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee = IdentityFee<Balance>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type FeeMultiplierUpdate = ();
}
impl custom::Config for Runtime {}
+41 -1
View File
@@ -132,7 +132,10 @@ mod extrinsic_weights;
mod paritydb_weights;
mod rocksdb_weights;
use crate::dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo};
use crate::{
dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo},
traits::Get,
};
use codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
@@ -709,6 +712,34 @@ where
}
}
/// Implementor of [`WeightToFeePolynomial`] that uses a constant multiplier.
/// # Example
///
/// ```
/// # use frame_support::traits::ConstU128;
/// # use frame_support::weights::ConstantMultiplier;
/// // Results in a multiplier of 10 for each unit of weight (or length)
/// type LengthToFee = ConstantMultiplier::<u128, ConstU128<10u128>>;
/// ```
pub struct ConstantMultiplier<T, M>(sp_std::marker::PhantomData<(T, M)>);
impl<T, M> WeightToFeePolynomial for ConstantMultiplier<T, M>
where
T: BaseArithmetic + From<u32> + Copy + Unsigned,
M: Get<T>,
{
type Balance = T;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
smallvec!(WeightToFeeCoefficient {
coeff_integer: M::get(),
coeff_frac: Perbill::zero(),
negative: false,
degree: 1,
})
}
}
/// A struct holding value for each `DispatchClass`.
#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
pub struct PerDispatchClass<T> {
@@ -983,4 +1014,13 @@ mod tests {
assert_eq!(IdentityFee::<Balance>::calc(&50), 50);
assert_eq!(IdentityFee::<Balance>::calc(&Weight::max_value()), Balance::max_value());
}
#[test]
fn constant_fee_works() {
use crate::traits::ConstU128;
assert_eq!(ConstantMultiplier::<u128, ConstU128<100u128>>::calc(&0), 0);
assert_eq!(ConstantMultiplier::<u128, ConstU128<10u128>>::calc(&50), 500);
assert_eq!(ConstantMultiplier::<u128, ConstU128<1024u128>>::calc(&16), 16384);
assert_eq!(ConstantMultiplier::<u128, ConstU128<{ u128::MAX }>>::calc(&2), u128::MAX);
}
}
@@ -145,8 +145,8 @@ impl WeightToFeePolynomial for WeightToFee {
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = WeightToFee;
type LengthToFee = WeightToFee;
type FeeMultiplierUpdate = ();
type OperationalFeeMultiplier = ConstU8<5>;
}
+32 -17
View File
@@ -260,10 +260,6 @@ pub mod pallet {
/// 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.
#[pallet::constant]
type TransactionByteFee: Get<BalanceOf<Self>>;
/// A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their
/// `priority`
///
@@ -291,6 +287,9 @@ pub mod pallet {
/// Convert a weight value into a deductible fee based on the currency type.
type WeightToFee: WeightToFeePolynomial<Balance = BalanceOf<Self>>;
/// Convert a length value into a deductible fee based on the currency type.
type LengthToFee: WeightToFeePolynomial<Balance = BalanceOf<Self>>;
/// Update the multiplier of the next block, based on the previous block's weight.
type FeeMultiplierUpdate: MultiplierUpdate;
}
@@ -302,6 +301,12 @@ pub mod pallet {
fn weight_to_fee_polynomial() -> Vec<WeightToFeeCoefficient<BalanceOf<T>>> {
T::WeightToFee::polynomial().to_vec()
}
/// The polynomial that is applied in order to derive fee from length.
#[pallet::constant_name(LengthToFee)]
fn length_to_fee_polynomial() -> Vec<WeightToFeeCoefficient<BalanceOf<T>>> {
T::LengthToFee::polynomial().to_vec()
}
}
#[pallet::type_value]
@@ -510,25 +515,18 @@ where
class: DispatchClass,
) -> FeeDetails<BalanceOf<T>> {
if pays_fee == Pays::Yes {
let len = <BalanceOf<T>>::from(len);
let per_byte = T::TransactionByteFee::get();
// length fee. this is not adjusted.
let fixed_len_fee = per_byte.saturating_mul(len);
// the adjustable part of the fee.
let unadjusted_weight_fee = Self::weight_to_fee(weight);
let multiplier = Self::next_fee_multiplier();
// final adjusted weight fee.
let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee);
// length fee. this is adjusted via `LengthToFee`.
let len_fee = Self::length_to_fee(len);
let base_fee = Self::weight_to_fee(T::BlockWeights::get().get(class).base_extrinsic);
FeeDetails {
inclusion_fee: Some(InclusionFee {
base_fee,
len_fee: fixed_len_fee,
adjusted_weight_fee,
}),
inclusion_fee: Some(InclusionFee { base_fee, len_fee, adjusted_weight_fee }),
tip,
}
} else {
@@ -536,6 +534,10 @@ where
}
}
fn length_to_fee(length: u32) -> BalanceOf<T> {
T::LengthToFee::calc(&(length as Weight))
}
fn weight_to_fee(weight: Weight) -> BalanceOf<T> {
// cap the weight to the maximum defined in runtime, otherwise it will be the
// `Bounded` maximum of its data type, which is not desired.
@@ -835,8 +837,8 @@ mod tests {
}
parameter_types! {
pub static TransactionByteFee: u64 = 1;
pub static WeightToFee: u64 = 1;
pub static TransactionByteFee: u64 = 1;
pub static OperationalFeeMultiplier: u8 = 5;
}
@@ -892,6 +894,19 @@ mod tests {
}
}
impl WeightToFeePolynomial for TransactionByteFee {
type Balance = u64;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
smallvec![WeightToFeeCoefficient {
degree: 1,
coeff_frac: Perbill::zero(),
coeff_integer: TRANSACTION_BYTE_FEE.with(|v| *v.borrow()),
negative: false,
}]
}
}
thread_local! {
static TIP_UNBALANCED_AMOUNT: RefCell<u64> = RefCell::new(0);
static FEE_UNBALANCED_AMOUNT: RefCell<u64> = RefCell::new(0);
@@ -913,9 +928,9 @@ mod tests {
impl Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = WeightToFee;
type LengthToFee = TransactionByteFee;
type FeeMultiplierUpdate = ();
}
@@ -12,7 +12,7 @@ use sp_runtime::{
use sp_std::{fmt::Debug, marker::PhantomData};
use frame_support::{
traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReasons},
traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReasons},
unsigned::TransactionValidityError,
};
@@ -73,7 +73,6 @@ pub struct CurrencyAdapter<C, OU>(PhantomData<(C, OU)>);
impl<T, C, OU> OnChargeTransaction<T> for CurrencyAdapter<C, OU>
where
T: Config,
T::TransactionByteFee: Get<<C as Currency<<T as frame_system::Config>::AccountId>>::Balance>,
C: Currency<<T as frame_system::Config>::AccountId>,
C::PositiveImbalance: Imbalance<
<C as Currency<<T as frame_system::Config>::AccountId>>::Balance,