Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Some refactors with migration
  • Loading branch information
kianenigma committed Jun 15, 2020
commit a8e22d527da2d1f52f5b5595b3059fecc42d1034
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions bin/node/executor/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use frame_support::{
};
use sp_core::{NeverNativeValue, traits::Externalities, storage::well_known_keys};
use sp_runtime::{
ApplyExtrinsicResult, FixedI128, FixedPointNumber,
ApplyExtrinsicResult, FixedPointNumber,
traits::Hash as HashT,
transaction_validity::InvalidTransaction,
};
Expand All @@ -35,7 +35,7 @@ use frame_system::{self, EventRecord, Phase};

use node_runtime::{
Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances,
System, TransactionPayment, Event, TransactionByteFee,
System, TransactionPayment, Event, TransactionByteFee, Multiplier,
constants::currency::*,
};
use node_primitives::{Balance, Hash};
Expand All @@ -53,7 +53,7 @@ use self::common::{*, sign};
pub const BLOATY_CODE: &[u8] = node_runtime::WASM_BINARY_BLOATY;

/// Default transfer fee
fn transfer_fee<E: Encode>(extrinsic: &E, fee_multiplier: FixedI128) -> Balance {
fn transfer_fee<E: Encode>(extrinsic: &E, fee_multiplier: Multiplier) -> Balance {
let length_fee = TransactionByteFee::get() * (extrinsic.encode().len() as Balance);

let base_weight = ExtrinsicBaseWeight::get();
Expand Down
6 changes: 3 additions & 3 deletions bin/node/executor/tests/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
use node_runtime::{
CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment,
CheckedExtrinsic, Call, Runtime, Balances, TransactionPayment, Multiplier,
TransactionByteFee,
constants::currency::*,
};
Expand All @@ -39,7 +39,7 @@ 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);
let mut prev_multiplier = Multiplier::from_inner(0);

t.execute_with(|| {
assert_eq!(TransactionPayment::next_fee_multiplier(), prev_multiplier);
Expand Down
131 changes: 25 additions & 106 deletions bin/node/runtime/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, AvailableBlockRatio, 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 {
Expand All @@ -47,126 +45,47 @@ impl Convert<u128, Balance> for CurrencyToVoteHandler {
fn convert(x: u128) -> Balance { x * Self::factor() }
}

/// 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
/// be called on `on_finalize` of a block, prior to potentially cleaning the weight data from the
/// system module.
///
/// given:
/// s = previous block weight
/// s'= ideal block weight
/// m = maximum block weight
/// diff = (s - s')/m
/// v = 0.00001
/// t1 = (v * diff)
/// t2 = (v * diff)^2 / 2
/// then:
/// next_multiplier = prev_multiplier * (1 + t1 + t2)
///
/// Where `(s', v)` must be given as the `Get` implementation of the `T` generic type.
///
/// note that `s'` is interpreted as a portion in the _normal transaction_ capacity of the block.
/// For example, given `s' == 0.25` and `AvailableBlockRatio = 0.75`, then the target fullness is
/// _0.25 of the normal capacity_ and _0.1875 of the entire block_.
///
/// This implementation implies the bound:
/// - `v ≤ p / k * (s − s')`
/// - or, solving for `p`: `p >= v * k * (s - s')`
///
/// where `p` is the amount of change over `k` blocks.
///
/// Hence:
/// - in an fully congested chain: `p >= v * k * (1 - s')`.
/// - in an empty chain: `p >= v * k * (-s')`.
///
/// For example, when all block are full, and 28800 blocks per day (default in `substrate-node`)
/// and v == 0.00001, s' == 0.25, we'd have:
///
/// p >= 0.00001 * 28800 * 3 / 4
/// p >= 0.216
///
/// Meaning that fees can change by around ~21% per day, given extreme congestion.
///
/// More info can be found at:
/// https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html
pub struct TargetedFeeAdjustment<S, V>(sp_std::marker::PhantomData<(S, V)>);

const PARTS: i128 = 1_000_000_000;
pub const MIN_MULTIPLIER: Multiplier = Multiplier::from_inner(PARTS);

impl<S, V> Convert<Multiplier, Multiplier> for TargetedFeeAdjustment<S, V>
where S: Get<Perquintill>, V: Get<Multiplier>
{
fn convert(previous: Multiplier) -> Multiplier {
// Defensive only. The multiplier in storage should always be at most positive. Nonetheless
// we recover here in case of errors, because any value below this would be stale and can
// never change.
let previous = previous.max(MIN_MULTIPLIER);

let max_weight = AvailableBlockRatio::get() * MaximumBlockWeight::get();
let block_weight = System::block_weight().total().min(max_weight);

let s = S::get();
let v = V::get();

let target_weight = (s * 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);

let v_squared_2 = v.saturating_mul(v) / Multiplier::saturating_from_integer(2);

let first_term = v.saturating_mul(diff);
let second_term = v_squared_2.saturating_mul(diff_squared);

if positive {
let excess = first_term.saturating_add(second_term).saturating_mul(previous);
previous.saturating_add(excess).max(MIN_MULTIPLIER)
} else {
// Defensive-only: first_term > second_term. Safe subtraction.
let negative = first_term.saturating_sub(second_term).saturating_mul(previous);
previous.saturating_sub(negative).max(MIN_MULTIPLIER)
}
}
}

#[cfg(test)]
mod tests {
mod multiplier_tests {
use super::*;
use sp_runtime::assert_eq_error_rate;
use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime};
use sp_runtime::{assert_eq_error_rate, FixedPointNumber};
use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};

use crate::{
constants::{currency::*, time::*},
TransactionPayment,
TargetBlockFullness,
AdjustmentVariable,
TransactionPayment, MaximumBlockWeight, AvailableBlockRatio, Runtime, TargetBlockFullness,
AdjustmentVariable, System, MinimumMultiplier,
};
use frame_support::weights::{Weight, WeightToFeePolynomial};

fn max() -> Weight {
AvailableBlockRatio::get() * MaximumBlockWeight::get()
}

fn min_multiplier() -> Multiplier {
MinimumMultiplier::get()
}

fn target() -> Weight {
TargetBlockFullness::get() * max()
}

// update based on runtime impl.
fn runtime_multiplier_update(fm: Multiplier) -> Multiplier {
TargetedFeeAdjustment::<TargetBlockFullness, AdjustmentVariable>::convert(fm)
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(PARTS as f64 / accuracy);
let previous_float = previous_float.max(min_multiplier().into_inner() as f64 / accuracy);

// maximum tx weight
let m = max() as f64;
Expand Down Expand Up @@ -222,17 +141,17 @@ mod tests {
// if the min is too small, then this will not change, and we are doomed forever.
// the weight is 1/10th bigger than target.
run_with_system_weight(target() * 101 / 100, || {
let next = runtime_multiplier_update(MIN_MULTIPLIER);
assert!(next > MIN_MULTIPLIER, "{:?} !>= {:?}", next, MIN_MULTIPLIER);
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);
let next = runtime_multiplier_update(min_multiplier());
assert_eq!(next, min_multiplier());
})
}

Expand All @@ -255,7 +174,7 @@ mod tests {
loop {
let next = runtime_multiplier_update(fm);
fm = next;
if fm == MIN_MULTIPLIER { break; }
if fm == min_multiplier() { break; }
iterations += 1;
}
assert!(iterations > 533_333);
Expand Down
8 changes: 5 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +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;
use pallet_transaction_payment::Multiplier;
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};
Expand All @@ -78,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;
Expand Down Expand Up @@ -308,14 +308,16 @@ 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_000i128);
}

impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = DealWithFees;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = TargetedFeeAdjustment<TargetBlockFullness, AdjustmentVariable>;
type FeeMultiplierUpdate =
TargetedFeeAdjustment<Self, TargetBlockFullness, AdjustmentVariable, MinimumMultiplier>;
}

parameter_types! {
Expand Down
7 changes: 4 additions & 3 deletions frame/balances/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl sp_runtime::traits::Dispatchable for CallWithDispatchInfo {
type Trait = ();
type Info = frame_support::weights::DispatchInfo;
type PostInfo = frame_support::weights::PostDispatchInfo;

fn dispatch(self, _origin: Self::Origin)
-> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
panic!("Do not use dummy implementation for dispatch.");
Expand All @@ -37,15 +38,15 @@ macro_rules! decl_tests {
($test:ty, $ext_builder:ty, $existential_deposit:expr) => {

use crate::*;
use sp_runtime::{FixedPointNumber, FixedI128, traits::{SignedExtension, BadOrigin}};
use sp_runtime::{FixedPointNumber, traits::{SignedExtension, BadOrigin}};
use frame_support::{
assert_noop, assert_ok, assert_err,
traits::{
LockableCurrency, LockIdentifier, WithdrawReason, WithdrawReasons,
Currency, ReservableCurrency, ExistenceRequirement::AllowDeath, StoredMap
}
};
use pallet_transaction_payment::ChargeTransactionPayment;
use pallet_transaction_payment::{ChargeTransactionPayment, Multiplier};
use frame_system::RawOrigin;

const ID_1: LockIdentifier = *b"1 ";
Expand Down Expand Up @@ -162,7 +163,7 @@ macro_rules! decl_tests {
.monied(true)
.build()
.execute_with(|| {
pallet_transaction_payment::NextFeeMultiplier::put(FixedI128::saturating_from_integer(1));
pallet_transaction_payment::NextFeeMultiplier::put(Multiplier::saturating_from_integer(1));
Balances::set_lock(ID_1, &1, 10, WithdrawReason::Reserve.into());
assert_noop!(
<Balances as Currency<_>>::transfer(&1, &2, 1, AllowDeath),
Expand Down
2 changes: 2 additions & 0 deletions frame/transaction-payment/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.101", optional = true }
sp-std = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/std" }
sp-runtime = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/runtime" }
frame-support = { version = "2.0.0-rc3", default-features = false, path = "../support" }
Expand All @@ -29,6 +30,7 @@ sp-storage = { version = "2.0.0-rc3", path = "../../primitives/storage" }
[features]
default = ["std"]
std = [
"serde",
"codec/std",
"sp-std/std",
"sp-runtime/std",
Expand Down
Loading