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

Apply WeightToFeePolynomials to pallet_transaction_payment's length fee #10785

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 1 addition & 5 deletions bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ();
}

Expand Down
4 changes: 2 additions & 2 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use frame_support::{
},
weights::{
constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, IdentityFee, Weight,
ConstantMultiplier, DispatchClass, IdentityFee, Weight,
},
PalletId, RuntimeDebug,
};
Expand Down Expand Up @@ -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>;
}
Expand Down
2 changes: 1 addition & 1 deletion frame/balances/src/tests_composite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ();
}

Expand Down
2 changes: 1 addition & 1 deletion frame/balances/src/tests_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ();
}

Expand Down
2 changes: 1 addition & 1 deletion frame/balances/src/tests_reentrancy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ();
}

Expand Down
6 changes: 4 additions & 2 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {}
Expand Down
42 changes: 41 additions & 1 deletion frame/support/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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);
}
}
2 changes: 1 addition & 1 deletion frame/transaction-payment/asset-tx-payment/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
}
Expand Down
49 changes: 32 additions & 17 deletions frame/transaction-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>;
kianenigma marked this conversation as resolved.
Show resolved Hide resolved

/// A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their
/// `priority`
///
Expand Down Expand Up @@ -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;
}
Expand All @@ -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]
Expand Down Expand Up @@ -510,32 +515,29 @@ 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 {
FeeDetails { inclusion_fee: None, tip }
}
}

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.
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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 = ();
}

Expand Down
3 changes: 1 addition & 2 deletions frame/transaction-payment/src/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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,
Expand Down