Fix the broken weight multiplier update function (#6334)

* Initial draft, has some todos left

* remove ununsed import

* Apply suggestions from code review

* Some refactors with migration

* Fix more test and cleanup

* Fix for companion

* Apply suggestions from code review

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Update bin/node/runtime/src/impls.rs

* Fix weight

* Add integrity test

* length is not affected.

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
This commit is contained in:
Kian Paimani
2020-06-17 15:20:17 +02:00
committed by GitHub
parent 67c9ac9393
commit 82bdf1a891
10 changed files with 458 additions and 253 deletions
+24 -31
View File
@@ -19,14 +19,11 @@ use codec::{Encode, Decode, Joiner};
use frame_support::{
StorageValue, StorageMap,
traits::Currency,
weights::{
GetDispatchInfo, DispatchInfo, DispatchClass, constants::ExtrinsicBaseWeight,
WeightToFeePolynomial,
},
weights::{GetDispatchInfo, DispatchInfo, DispatchClass},
};
use sp_core::{NeverNativeValue, traits::Externalities, storage::well_known_keys};
use sp_runtime::{
ApplyExtrinsicResult, FixedI128, FixedPointNumber,
ApplyExtrinsicResult,
traits::Hash as HashT,
transaction_validity::InvalidTransaction,
};
@@ -35,7 +32,7 @@ use frame_system::{self, EventRecord, Phase};
use node_runtime::{
Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
System, TransactionPayment, Event, TransactionByteFee,
System, TransactionPayment, Event,
constants::currency::*,
};
use node_primitives::{Balance, Hash};
@@ -52,16 +49,17 @@ use self::common::{*, sign};
/// test code paths that differ between native and wasm versions.
pub const BLOATY_CODE: &[u8] = node_runtime::WASM_BINARY_BLOATY;
/// Default transfer fee
fn transfer_fee<E: Encode>(extrinsic: &E, fee_multiplier: FixedI128) -> Balance {
let length_fee = TransactionByteFee::get() * (extrinsic.encode().len() as Balance);
let base_weight = ExtrinsicBaseWeight::get();
let base_fee = <Runtime as pallet_transaction_payment::Trait>::WeightToFee::calc(&base_weight);
let weight = default_transfer_call().get_dispatch_info().weight;
let weight_fee = <Runtime as pallet_transaction_payment::Trait>::WeightToFee::calc(&weight);
base_fee + fee_multiplier.saturating_mul_acc_int(length_fee + weight_fee)
/// Default transfer fee. This will use the same logic that is implemented in transaction-payment module.
///
/// Note that reads the multiplier from storage directly, hence to get the fee of `extrinsic`
/// at block `n`, it must be called prior to executing block `n` to do the calculation with the
/// correct multiplier.
fn transfer_fee<E: Encode>(extrinsic: &E) -> Balance {
TransactionPayment::compute_fee(
extrinsic.encode().len() as u32,
&default_transfer_call().get_dispatch_info(),
0,
)
}
fn xt() -> UncheckedExtrinsic {
@@ -242,7 +240,7 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
).0;
assert!(r.is_ok());
let fm = t.execute_with(TransactionPayment::next_fee_multiplier);
let fees = t.execute_with(|| transfer_fee(&xt()));
let r = executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -254,7 +252,6 @@ fn successful_execution_with_native_equivalent_code_gives_ok() {
assert!(r.is_ok());
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
@@ -286,7 +283,7 @@ fn successful_execution_with_foreign_code_gives_ok() {
).0;
assert!(r.is_ok());
let fm = t.execute_with(TransactionPayment::next_fee_multiplier);
let fees = t.execute_with(|| transfer_fee(&xt()));
let r = executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -298,7 +295,6 @@ fn successful_execution_with_foreign_code_gives_ok() {
assert!(r.is_ok());
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
@@ -311,7 +307,7 @@ fn full_native_block_import_works() {
let (block1, block2) = blocks();
let mut alice_last_known_balance: Balance = Default::default();
let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier);
let mut fees = t.execute_with(|| transfer_fee(&xt()));
executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -322,7 +318,6 @@ fn full_native_block_import_works() {
).0.unwrap();
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS);
alice_last_known_balance = Balances::total_balance(&alice());
@@ -361,7 +356,7 @@ fn full_native_block_import_works() {
assert_eq!(System::events(), events);
});
fm = t.execute_with(TransactionPayment::next_fee_multiplier);
fees = t.execute_with(|| transfer_fee(&xt()));
executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -372,7 +367,6 @@ fn full_native_block_import_works() {
).0.unwrap();
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm);
assert_eq!(
Balances::total_balance(&alice()),
alice_last_known_balance - 10 * DOLLARS - fees,
@@ -450,7 +444,7 @@ fn full_wasm_block_import_works() {
let (block1, block2) = blocks();
let mut alice_last_known_balance: Balance = Default::default();
let mut fm = t.execute_with(TransactionPayment::next_fee_multiplier);
let mut fees = t.execute_with(|| transfer_fee(&xt()));
executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -461,12 +455,12 @@ fn full_wasm_block_import_works() {
).0.unwrap();
t.execute_with(|| {
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt(), fm));
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS);
alice_last_known_balance = Balances::total_balance(&alice());
});
fm = t.execute_with(TransactionPayment::next_fee_multiplier);
fees = t.execute_with(|| transfer_fee(&xt()));
executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -479,11 +473,11 @@ fn full_wasm_block_import_works() {
t.execute_with(|| {
assert_eq!(
Balances::total_balance(&alice()),
alice_last_known_balance - 10 * DOLLARS - transfer_fee(&xt(), fm),
alice_last_known_balance - 10 * DOLLARS - fees,
);
assert_eq!(
Balances::total_balance(&bob()),
179 * DOLLARS - 1 * transfer_fee(&xt(), fm),
179 * DOLLARS - 1 * fees,
);
});
}
@@ -755,7 +749,7 @@ fn successful_execution_gives_ok() {
assert_eq!(Balances::total_balance(&alice()), 111 * DOLLARS);
});
let fm = t.execute_with(TransactionPayment::next_fee_multiplier);
let fees = t.execute_with(|| transfer_fee(&xt()));
let r = executor_call::<NeverNativeValue, fn() -> _>(
&mut t,
@@ -770,7 +764,6 @@ fn successful_execution_gives_ok() {
.expect("Extrinsic failed");
t.execute_with(|| {
let fees = transfer_fee(&xt(), fm);
assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - fees);
assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS);
});
+6 -6
View File
@@ -22,9 +22,9 @@ use frame_support::{
weights::{GetDispatchInfo, constants::ExtrinsicBaseWeight, IdentityFee, WeightToFeePolynomial},
};
use sp_core::NeverNativeValue;
use sp_runtime::{FixedPointNumber, FixedI128, Perbill};
use sp_runtime::{Perbill, FixedPointNumber};
use node_runtime::{
CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment,
CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment, Multiplier,
TransactionByteFee,
constants::currency::*,
};
@@ -38,8 +38,8 @@ use self::common::{*, sign};
fn fee_multiplier_increases_and_decreases_on_big_weight() {
let mut t = new_test_ext(COMPACT_CODE, false);
// initial fee multiplier must be zero
let mut prev_multiplier = FixedI128::from_inner(0);
// initial fee multiplier must be one.
let mut prev_multiplier = Multiplier::one();
t.execute_with(|| {
assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier);
@@ -59,7 +59,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
},
CheckedExtrinsic {
signed: Some((charlie(), signed_extra(0, 0))),
function: Call::System(frame_system::Call::fill_block(Perbill::from_percent(90))),
function: Call::System(frame_system::Call::fill_block(Perbill::from_percent(60))),
}
]
);
@@ -122,7 +122,7 @@ fn fee_multiplier_increases_and_decreases_on_big_weight() {
}
#[test]
fn transaction_fee_is_correct_ultimate() {
fn transaction_fee_is_correct() {
// This uses the exact values of substrate-node.
//
// weight of transfer call as of now: 1_000_000
+148 -150
View File
@@ -18,11 +18,9 @@
//! Some configurable implementations as associated type for the substrate runtime.
use node_primitives::Balance;
use sp_runtime::traits::{Convert, Saturating};
use sp_runtime::{FixedPointNumber, Perquintill};
use frame_support::traits::{OnUnbalanced, Currency, Get};
use pallet_transaction_payment::Multiplier;
use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance};
use sp_runtime::traits::Convert;
use frame_support::traits::{OnUnbalanced, Currency};
use crate::{Balances, Authorship, NegativeImbalance};
pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
@@ -47,89 +45,63 @@ impl Convert<u128, Balance> for CurrencyToVoteHandler {
fn convert(x: u128) -> Balance { x * Self::factor() }
}
/// Update the given multiplier based on the following formula
///
/// diff = (previous_block_weight - target_weight)/max_weight
/// v = 0.00004
/// next_weight = weight * (1 + (v * diff) + (v * diff)^2 / 2)
///
/// Where `target_weight` must be given as the `Get` implementation of the `T` generic type.
/// https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#relay-chain-transaction-fees
pub struct TargetedFeeAdjustment<T>(sp_std::marker::PhantomData<T>);
impl<T: Get<Perquintill>> Convert<Multiplier, Multiplier> for TargetedFeeAdjustment<T> {
fn convert(multiplier: Multiplier) -> Multiplier {
let max_weight = MaximumBlockWeight::get();
let block_weight = System::block_weight().total().min(max_weight);
let target_weight = (T::get() * max_weight) as u128;
let block_weight = block_weight as u128;
// determines if the first_term is positive
let positive = block_weight >= target_weight;
let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight);
// safe, diff_abs cannot exceed u64.
let diff = Multiplier::saturating_from_rational(diff_abs, max_weight.max(1));
let diff_squared = diff.saturating_mul(diff);
// 0.00004 = 4/100_000 = 40_000/10^9
let v = Multiplier::saturating_from_rational(4, 100_000);
// 0.00004^2 = 16/10^10 Taking the future /2 into account... 8/10^10
let v_squared_2 = Multiplier::saturating_from_rational(8, 10_000_000_000u64);
let first_term = v.saturating_mul(diff);
let second_term = v_squared_2.saturating_mul(diff_squared);
if positive {
// Note: this is merely bounded by how big the multiplier and the inner value can go,
// not by any economical reasoning.
let excess = first_term.saturating_add(second_term);
multiplier.saturating_add(excess)
} else {
// Defensive-only: first_term > second_term. Safe subtraction.
let negative = first_term.saturating_sub(second_term);
multiplier.saturating_sub(negative)
// despite the fact that apply_to saturates weight (final fee cannot go below 0)
// it is crucially important to stop here and don't further reduce the weight fee
// multiplier. While at -1, it means that the network is so un-congested that all
// transactions have no weight fee. We stop here and only increase if the network
// became more busy.
.max(Multiplier::saturating_from_integer(-1))
}
}
}
#[cfg(test)]
mod tests {
mod multiplier_tests {
use super::*;
use sp_runtime::assert_eq_error_rate;
use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime};
use crate::{constants::currency::*, TransactionPayment, TargetBlockFullness};
use sp_runtime::{assert_eq_error_rate, FixedPointNumber};
use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
use crate::{
constants::{currency::*, time::*},
TransactionPayment, MaximumBlockWeight, AvailableBlockRatio, Runtime, TargetBlockFullness,
AdjustmentVariable, System, MinimumMultiplier,
};
use frame_support::weights::{Weight, WeightToFeePolynomial};
fn max() -> Weight {
MaximumBlockWeight::get()
AvailableBlockRatio::get() * MaximumBlockWeight::get()
}
fn min_multiplier() -> Multiplier {
MinimumMultiplier::get()
}
fn target() -> Weight {
TargetBlockFullness::get() * max()
}
// poc reference implementation.
fn fee_multiplier_update(block_weight: Weight, previous: Multiplier) -> Multiplier {
// update based on runtime impl.
fn runtime_multiplier_update(fm: Multiplier) -> Multiplier {
TargetedFeeAdjustment::<
Runtime,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
>::convert(fm)
}
// update based on reference impl.
fn truth_value_update(block_weight: Weight, previous: Multiplier) -> Multiplier {
let accuracy = Multiplier::accuracy() as f64;
let previous_float = previous.into_inner() as f64 / accuracy;
// bump if it is zero.
let previous_float = previous_float.max(min_multiplier().into_inner() as f64 / accuracy);
// maximum tx weight
let m = max() as f64;
// block weight always truncated to max weight
let block_weight = (block_weight as f64).min(m);
let v: f64 = 0.00004;
let v: f64 = AdjustmentVariable::get().to_fraction();
// Ideal saturation in terms of weight
let ss = target() as f64;
// Current saturation in terms of weight
let s = block_weight;
let fm = v * (s/m - ss/m) + v.powi(2) * (s/m - ss/m).powi(2) / 2.0;
let addition_fm = Multiplier::from_inner((fm * Multiplier::accuracy() as f64).round() as i128);
previous.saturating_add(addition_fm)
let t1 = v * (s/m - ss/m);
let t2 = v.powi(2) * (s/m - ss/m).powi(2) / 2.0;
let next_float = previous_float * (1.0 + t1 + t2);
Multiplier::from_fraction(next_float)
}
fn run_with_system_weight<F>(w: Weight, assertions: F) where F: Fn() -> () {
@@ -142,11 +114,12 @@ mod tests {
}
#[test]
fn fee_multiplier_update_poc_works() {
let fm = Multiplier::saturating_from_rational(0, 1);
fn truth_value_update_poc_works() {
let fm = Multiplier::saturating_from_rational(1, 2);
let test_set = vec![
(0, fm.clone()),
(100, fm.clone()),
(1000, fm.clone()),
(target(), fm.clone()),
(max() / 2, fm.clone()),
(max(), fm.clone()),
@@ -154,37 +127,71 @@ mod tests {
test_set.into_iter().for_each(|(w, fm)| {
run_with_system_weight(w, || {
assert_eq_error_rate!(
fee_multiplier_update(w, fm),
TargetedFeeAdjustment::<TargetBlockFullness>::convert(fm),
// Error is only 1 in 10^18
Multiplier::from_inner(1),
truth_value_update(w, fm),
runtime_multiplier_update(fm),
// Error is only 1 in 100^18
Multiplier::from_inner(100),
);
})
})
}
#[test]
fn empty_chain_simulation() {
// just a few txs per_block.
let block_weight = 0;
run_with_system_weight(block_weight, || {
let mut fm = Multiplier::default();
fn multiplier_can_grow_from_zero() {
// if the min is too small, then this will not change, and we are doomed forever.
// the weight is 1/100th bigger than target.
run_with_system_weight(target() * 101 / 100, || {
let next = runtime_multiplier_update(min_multiplier());
assert!(next > min_multiplier(), "{:?} !>= {:?}", next, min_multiplier());
})
}
#[test]
fn multiplier_cannot_go_below_limit() {
// will not go any further below even if block is empty.
run_with_system_weight(0, || {
let next = runtime_multiplier_update(min_multiplier());
assert_eq!(next, min_multiplier());
})
}
#[test]
fn time_to_reach_zero() {
// blocks per 24h in substrate-node: 28,800 (k)
// s* = 0.1875
// The bound from the research in an empty chain is:
// v <~ (p / k(0 - s*))
// p > v * k * -0.1875
// to get p == -1 we'd need
// -1 > 0.00001 * k * -0.1875
// 1 < 0.00001 * k * 0.1875
// 10^9 / 1875 < k
// k > 533_333 ~ 18,5 days.
run_with_system_weight(0, || {
// start from 1, the default.
let mut fm = Multiplier::one();
let mut iterations: u64 = 0;
loop {
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(fm);
let next = runtime_multiplier_update(fm);
fm = next;
if fm == Multiplier::saturating_from_integer(-1) { break; }
if fm == min_multiplier() { break; }
iterations += 1;
}
println!("iteration {}, new fm = {:?}. Weight fee is now zero", iterations, fm);
assert!(iterations > 50_000, "This assertion is just a warning; Don't panic. \
Current substrate/polkadot node are configured with a _slow adjusting fee_ \
mechanism. Hence, it is really unlikely that fees collapse to zero even on an \
empty chain in less than at least of couple of thousands of empty blocks. But this \
simulation indicates that fees collapsed to zero after {} almost-empty blocks. \
Check it",
iterations,
);
assert!(iterations > 533_333);
})
}
#[test]
fn min_change_per_day() {
run_with_system_weight(max(), || {
let mut fm = Multiplier::one();
// See the example in the doc of `TargetedFeeAdjustment`. are at least 0.234, hence
// `fm > 1.234`.
for _ in 0..DAYS {
let next = runtime_multiplier_update(fm);
fm = next;
}
assert!(fm > Multiplier::saturating_from_rational(1234, 1000));
})
}
@@ -196,17 +203,17 @@ mod tests {
// almost full. The entire quota of normal transactions is taken.
let block_weight = AvailableBlockRatio::get() * max() - 100;
// Default substrate minimum.
let tx_weight = 10_000;
// Default substrate weight.
let tx_weight = frame_support::weights::constants::ExtrinsicBaseWeight::get();
run_with_system_weight(block_weight, || {
// initial value configured on module
let mut fm = Multiplier::default();
let mut fm = Multiplier::one();
assert_eq!(fm, TransactionPayment::next_fee_multiplier());
let mut iterations: u64 = 0;
loop {
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(fm);
let next = runtime_multiplier_update(fm);
// if no change, panic. This should never happen in this case.
if fm == next { panic!("The fee should ever increase"); }
fm = next;
@@ -230,95 +237,86 @@ mod tests {
#[test]
fn stateless_weight_mul() {
// This test will show that heavy blocks have a weight multiplier greater than 0
// and light blocks will have a weight multiplier less than 0.
let fm = Multiplier::saturating_from_rational(1, 2);
run_with_system_weight(target() / 4, || {
// `fee_multiplier_update` is enough as it is the absolute truth value.
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::default());
assert_eq!(
let next = runtime_multiplier_update(fm);
assert_eq_error_rate!(
next,
fee_multiplier_update(target() / 4 ,Multiplier::default())
truth_value_update(target() / 4 , fm),
Multiplier::from_inner(100),
);
// Light block. Fee is reduced a little.
assert!(next < Multiplier::zero())
// Light block. Multiplier is reduced a little.
assert!(next < fm);
});
run_with_system_weight(target() / 2, || {
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::default());
assert_eq!(
next,
fee_multiplier_update(target() / 2 ,Multiplier::default())
);
// Light block. Fee is reduced a little.
assert!(next < Multiplier::zero())
run_with_system_weight(target() / 2, || {
let next = runtime_multiplier_update(fm);
assert_eq_error_rate!(
next,
truth_value_update(target() / 2 , fm),
Multiplier::from_inner(100),
);
// Light block. Multiplier is reduced a little.
assert!(next < fm);
});
run_with_system_weight(target(), || {
// ideal. Original fee. No changes.
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::default());
assert_eq!(next, Multiplier::zero())
let next = runtime_multiplier_update(fm);
assert_eq_error_rate!(
next,
truth_value_update(target(), fm),
Multiplier::from_inner(100),
);
// ideal. No changes.
assert_eq!(next, fm)
});
run_with_system_weight(target() * 2, || {
// More than ideal. Fee is increased.
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::default());
assert_eq!(
let next = runtime_multiplier_update(fm);
assert_eq_error_rate!(
next,
fee_multiplier_update(target() * 2 ,Multiplier::default())
truth_value_update(target() * 2 , fm),
Multiplier::from_inner(100),
);
// Heavy block. Fee is increased a little.
assert!(next > Multiplier::zero())
assert!(next > fm);
});
}
#[test]
fn stateful_weight_mul_grow_to_infinity() {
fn weight_mul_grow_on_big_block() {
run_with_system_weight(target() * 2, || {
let mut original = Multiplier::default();
let mut original = Multiplier::zero();
let mut next = Multiplier::default();
(0..1_000).for_each(|_| {
next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(original);
assert_eq!(
next = runtime_multiplier_update(original);
assert_eq_error_rate!(
next,
fee_multiplier_update(target() * 2, original),
truth_value_update(target() * 2, original),
Multiplier::from_inner(100),
);
// must always increase
assert!(next > original);
assert!(next > original, "{:?} !>= {:?}", next, original);
original = next;
});
});
}
#[test]
fn stateful_weight_mil_collapse_to_minus_one() {
run_with_system_weight(0, || {
let mut original = Multiplier::default(); // 0
fn weight_mul_decrease_on_small_block() {
run_with_system_weight(target() / 2, || {
let mut original = Multiplier::saturating_from_rational(1, 2);
let mut next;
// decreases
next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(original);
assert_eq!(
next,
fee_multiplier_update(0, original),
);
assert!(next < original);
original = next;
// keeps decreasing
next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(original);
assert_eq!(
next,
fee_multiplier_update(0, original),
);
assert!(next < original);
// ... stops going down at -1
assert_eq!(
TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::saturating_from_integer(-1)),
Multiplier::saturating_from_integer(-1)
);
for _ in 0..100 {
// decreases
next = runtime_multiplier_update(original);
assert!(next < original, "{:?} !<= {:?}", next, original);
original = next;
}
})
}
@@ -347,8 +345,8 @@ mod tests {
Weight::max_value(),
].into_iter().for_each(|i| {
run_with_system_weight(i, || {
let next = TargetedFeeAdjustment::<TargetBlockFullness>::convert(Multiplier::default());
let truth = fee_multiplier_update(i, Multiplier::default());
let next = runtime_multiplier_update(Multiplier::one());
let truth = truth_value_update(i, Multiplier::one());
assert_eq_error_rate!(truth, next, Multiplier::from_inner(50_000_000));
});
});
@@ -359,7 +357,7 @@ mod tests {
.into_iter()
.for_each(|i| {
run_with_system_weight(i, || {
let fm = TargetedFeeAdjustment::<TargetBlockFullness>::convert(max_fm);
let fm = runtime_multiplier_update(max_fm);
// won't grow. The convert saturates everything.
assert_eq!(fm, max_fm);
})
+8 -13
View File
@@ -44,8 +44,8 @@ pub use node_primitives::{AccountId, Signature};
use node_primitives::{AccountIndex, Balance, BlockNumber, Hash, Index, Moment};
use sp_api::impl_runtime_apis;
use sp_runtime::{
Permill, Perbill, Perquintill, Percent, PerThing, ApplyExtrinsicResult,
impl_opaque_keys, generic, create_runtime_str, ModuleId,
Permill, Perbill, Perquintill, Percent, ApplyExtrinsicResult,
impl_opaque_keys, generic, create_runtime_str, ModuleId, FixedPointNumber,
};
use sp_runtime::curve::PiecewiseLinear;
use sp_runtime::transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority};
@@ -61,6 +61,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};
use pallet_contracts_rpc_runtime_api::ContractExecResult;
use pallet_session::{historical as pallet_session_historical};
use sp_inherents::{InherentData, CheckInherentsResult};
@@ -77,7 +78,7 @@ pub use pallet_staking::StakerStatus;
/// Implementations of some helper traits passed into runtime modules as associated types.
pub mod impls;
use impls::{CurrencyToVoteHandler, Author, TargetedFeeAdjustment};
use impls::{CurrencyToVoteHandler, Author};
/// Constant values used within the runtime.
pub mod constants;
@@ -295,23 +296,17 @@ impl pallet_balances::Trait for Runtime {
parameter_types! {
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(1, 100_000);
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000_000u128);
}
// for a sane configuration, this should always be less than `AvailableBlockRatio`.
const_assert!(
TargetBlockFullness::get().deconstruct() <
(AvailableBlockRatio::get().deconstruct() as <Perquintill as PerThing>::Inner)
* (<Perquintill as PerThing>::ACCURACY / <Perbill as PerThing>::ACCURACY as <Perquintill as PerThing>::Inner)
);
impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = DealWithFees;
type TransactionByteFee = TransactionByteFee;
// In the Substrate node, a weight of 10_000_000 (smallest non-zero weight)
// is mapped to 10_000_000 units of fees, hence:
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = TargetedFeeAdjustment<TargetBlockFullness>;
type FeeMultiplierUpdate =
TargetedFeeAdjustment<Self, TargetBlockFullness, AdjustmentVariable, MinimumMultiplier>;
}
parameter_types! {