-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Weight annotation. #3157
Weight annotation. #3157
Changes from 1 commit
b042a93
37f6ae0
2e5b1f4
b7646ec
a871c9f
8e7c803
a824b56
5de080f
a8789b9
7d96429
30b4ba7
2a9c9df
342efb5
b8f564e
07fdfe2
7f33006
36063fe
7a0fbc9
84fa279
f4d4579
def6425
d12713a
3350f9c
b788507
b9b6b53
045681e
bfcfa36
107801f
c100df9
f5d33c6
0c1c268
6a0a1d4
b06ef82
c3e0ee3
5b0c715
e683829
ce11fc5
0b592e2
ee970d1
58191a3
67b268a
0d9133f
ec6554f
a25e4be
5724771
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,7 +49,7 @@ mod tests { | |
| use node_primitives::{Hash, BlockNumber, AccountId, Balance, Index}; | ||
| use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; | ||
| use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; | ||
| use runtime_primitives::weights::{WeightMultiplier, SimpleDispatchInfo, GetDispatchInfo, WeighData, Weight}; | ||
| use runtime_primitives::weights::{WeightMultiplier, GetDispatchInfo, Weight}; | ||
| use {balances, contracts, indices, staking, system, timestamp}; | ||
| use contracts::ContractAddressFor; | ||
| use system::{EventRecord, Phase}; | ||
|
|
@@ -82,22 +82,25 @@ mod tests { | |
|
|
||
| type TestExternalities<H> = CoreTestExternalities<H, u64>; | ||
|
|
||
| /// Default transfer fee | ||
| fn transfer_fee<E: Encode>(extrinsic: &E) -> Balance { | ||
| let length_fee = <TransactionBaseFee as Get<Balance>>::get() + | ||
| <TransactionByteFee as Get<Balance>>::get() * | ||
| (extrinsic.encode().len() as Balance); | ||
| let weight_fee = default_transfer_call().get_dispatch_info().weight as Balance; | ||
| // TODO: with this we have 100% accurate fee estimation. Should probably be able to get rid | ||
| // of `assert_eq_error_rate!` now. But it makes test mockup much more complicated because | ||
| // the fee for each block can only be estimated _before_ that block. | ||
| let mut weight_fee = default_transfer_call().get_dispatch_info().weight as Balance; | ||
| weight_fee = weight_fee * 1_000_000 as Balance; | ||
kianenigma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // NOTE: we don't need this anymore, but in case needed, this makes the fee accurate over | ||
| // multiple blocks. | ||
| // weight_fee = <system::Module<Runtime>>::next_weight_multiplier().apply_to(weight_fee as u32) as Balance; | ||
| length_fee + weight_fee | ||
| } | ||
|
|
||
| fn multiplier_target() -> Weight { | ||
| /// Get the target weight of the fee multiplier. | ||
| fn _multiplier_target() -> Weight { | ||
kianenigma marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <MaximumBlockWeight as Get<Weight>>::get() / 4 | ||
| } | ||
|
|
||
| /// Default creation fee. | ||
| fn creation_fee() -> Balance { | ||
| <CreationFee as Get<Balance>>::get() | ||
| } | ||
|
|
@@ -972,21 +975,6 @@ mod tests { | |
|
|
||
| let mut tt = new_test_ext(COMPACT_CODE, false); | ||
|
|
||
| // This test can either use `fill_block()`, which is controversial, or should be dropped. | ||
| // NOTE: This assumes that system::remark has the default. | ||
| // let num_to_exhaust = (multiplier_target() + 100) / SimpleDispatchInfo::default().weigh_data(()); | ||
| // println!("++ Generating {} transactions to fill {} weight units", num_to_exhaust, multiplier_target() + 100); | ||
| // let mut xts = (0..num_to_exhaust).map(|i| CheckedExtrinsic { | ||
| // signed: Some((charlie(), signed_extra(i.into(), 0))), | ||
| // function: Call::System(system::Call::remark(vec![0; 1])), | ||
| // }).collect::<Vec<CheckedExtrinsic>>(); | ||
| // xts.insert(0, CheckedExtrinsic { | ||
| // signed: None, | ||
| // function: Call::Timestamp(timestamp::Call::set(42)), | ||
| // }); | ||
|
|
||
| println!("++ Generated all extrinsics. Constructing blocks."); | ||
|
|
||
| // big one in terms of weight. | ||
| let block1 = construct_block( | ||
| &mut tt, | ||
|
|
@@ -1057,6 +1045,85 @@ mod tests { | |
| }); | ||
| } | ||
|
|
||
| #[test] | ||
| fn transaction_fee_is_correct_ultimate() { | ||
| // This uses the exact values of substrate-node. | ||
| // | ||
| // weight of transfer call as of now: 1_000 | ||
| // if weight of cheapest weight would be 10^7, this would be 10^9, which is: | ||
| // - 1 MILLICENTS in substrate node. | ||
| // - 1 milldot based on current polkadot runtime. | ||
| // (this baed on assigning 0.1 CENT to the cheapest tx with `weight = 100`) | ||
| let mut t = TestExternalities::<Blake2Hasher>::new_with_code(COMPACT_CODE, map![ | ||
| blake2_256(&<balances::FreeBalance<Runtime>>::key_for(alice())).to_vec() => { | ||
| (100 * DOLLARS).encode() | ||
| }, | ||
| blake2_256(&<balances::FreeBalance<Runtime>>::key_for(bob())).to_vec() => { | ||
| (10 * DOLLARS).encode() | ||
| }, | ||
| twox_128(<balances::TotalIssuance<Runtime>>::key()).to_vec() => { | ||
| (110 * DOLLARS).encode() | ||
| }, | ||
| twox_128(<indices::NextEnumSet<Runtime>>::key()).to_vec() => vec![0u8; 16], | ||
| blake2_256(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32] | ||
| ]); | ||
|
|
||
| let tip = 1_000_000; | ||
| let xt = sign(CheckedExtrinsic { | ||
| signed: Some((alice(), signed_extra(0, tip))), | ||
| function: Call::Balances(default_transfer_call()), | ||
| }); | ||
|
|
||
| let r = executor().call::<_, NeverNativeValue, fn() -> _>( | ||
| &mut t, | ||
| "Core_initialize_block", | ||
| &vec![].and(&from_block_number(1u64)), | ||
| true, | ||
| None, | ||
| ).0; | ||
|
|
||
| assert!(r.is_ok()); | ||
| let r = executor().call::<_, NeverNativeValue, fn() -> _>( | ||
| &mut t, | ||
| "BlockBuilder_apply_extrinsic", | ||
| &vec![].and(&xt.clone()), | ||
| true, | ||
| None, | ||
| ).0; | ||
| assert!(r.is_ok()); | ||
|
|
||
| runtime_io::with_externalities(&mut t, || { | ||
| assert_eq!(Balances::total_balance(&bob()), (10 + 69) * DOLLARS); | ||
| // Components deducted from alice's balances: | ||
| // - Weight fee | ||
| // - Length fee | ||
| // - Tip | ||
| // - Creation-fee of bob's account. | ||
| let mut balance_alice = (100 - 69) * DOLLARS; | ||
|
|
||
| let length_fee = <TransactionBaseFee as Get<Balance>>::get() + | ||
| <TransactionByteFee as Get<Balance>>::get() * | ||
| (xt.clone().encode().len() as Balance); | ||
| println!("++ len fee = {:?}", length_fee); | ||
| balance_alice -= length_fee; | ||
|
|
||
| // TODO: the 1_000_000 should go away. | ||
| let weight_fee = default_transfer_call().get_dispatch_info().weight as Balance * 1_000_000; | ||
| // we know that weight to fee multiplier is effect-less in block 1. | ||
| assert_eq!(weight_fee as Balance, MILLICENTS); | ||
| balance_alice -= weight_fee; | ||
| println!("++ wei fee = {:?}", weight_fee); | ||
|
|
||
| balance_alice -= tip; | ||
| println!("++ tip fee = {:?}", tip); | ||
|
|
||
| // TODO: why again??? creation fee should not be deducted here. | ||
|
||
| balance_alice -= creation_fee(); | ||
|
|
||
| assert_eq!(Balances::total_balance(&alice()), balance_alice); | ||
| }); | ||
| } | ||
|
|
||
| #[cfg(feature = "benchmarks")] | ||
| mod benches { | ||
| use super::*; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,7 +103,7 @@ pub type DealWithFees = SplitTwoWays< | |
|
|
||
| parameter_types! { | ||
| pub const BlockHashCount: BlockNumber = 250; | ||
| pub const MaximumBlockWeight: Weight = 1_000_000_000; | ||
| pub const MaximumBlockWeight: Weight = 1_000_000; | ||
| pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); | ||
| pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also note that the normal size limit of the node is now 5mb. |
||
| } | ||
|
|
@@ -143,6 +143,7 @@ parameter_types! { | |
| pub const CreationFee: Balance = 1 * CENTS; | ||
| pub const TransactionBaseFee: Balance = 1 * CENTS; | ||
| pub const TransactionByteFee: Balance = 10 * MILLICENTS; | ||
| pub const TransactionWeightFee: Balance = MILLICENTS / 1000; | ||
| } | ||
|
|
||
| impl balances::Trait for Runtime { | ||
|
|
@@ -158,6 +159,7 @@ impl balances::Trait for Runtime { | |
| type CreationFee = CreationFee; | ||
| type TransactionBaseFee = TransactionBaseFee; | ||
| type TransactionByteFee = TransactionByteFee; | ||
| type TransactionWeightFee = TransactionWeightFee; | ||
| } | ||
|
|
||
| parameter_types! { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -206,6 +206,9 @@ pub trait Subtrait<I: Instance = DefaultInstance>: system::Trait { | |
|
|
||
| /// The fee to be paid for making a transaction; the per-byte portion. | ||
| type TransactionByteFee: Get<Self::Balance>; | ||
|
|
||
| /// The amount of fee deducted oer unit of weight. | ||
| type TransactionWeightFee: Get<Self::Balance>; | ||
| } | ||
|
|
||
| pub trait Trait<I: Instance = DefaultInstance>: system::Trait { | ||
|
|
@@ -249,6 +252,9 @@ pub trait Trait<I: Instance = DefaultInstance>: system::Trait { | |
|
|
||
| /// The fee to be paid for making a transaction; the per-byte portion. | ||
| type TransactionByteFee: Get<Self::Balance>; | ||
|
|
||
| /// The amount of fee deducted oer unit of weight. | ||
| type TransactionWeightFee: Get<Self::Balance>; | ||
| } | ||
|
|
||
| impl<T: Trait<I>, I: Instance> Subtrait<I> for T { | ||
|
|
@@ -260,6 +266,7 @@ impl<T: Trait<I>, I: Instance> Subtrait<I> for T { | |
| type CreationFee = T::CreationFee; | ||
| type TransactionBaseFee = T::TransactionBaseFee; | ||
| type TransactionByteFee = T::TransactionByteFee; | ||
| type TransactionWeightFee = T::TransactionWeightFee; | ||
| } | ||
|
|
||
| decl_event!( | ||
|
|
@@ -783,6 +790,7 @@ impl<T: Subtrait<I>, I: Instance> Trait<I> for ElevatedTrait<T, I> { | |
| type CreationFee = T::CreationFee; | ||
| type TransactionBaseFee = T::TransactionBaseFee; | ||
| type TransactionByteFee = T::TransactionByteFee; | ||
| type TransactionWeightFee = T::TransactionWeightFee; | ||
| } | ||
|
|
||
| impl<T: Trait<I>, I: Instance> Currency<T::AccountId> for Module<T, I> | ||
|
|
@@ -1174,20 +1182,24 @@ impl<T: Trait<I>, I: Instance> TakeFees<T, I> { | |
| /// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed | ||
| /// transactions can have a tip. | ||
| fn compute_fee(len: usize, info: DispatchInfo, tip: T::Balance) -> T::Balance { | ||
| // length fee | ||
| let len_fee = if info.pay_length_fee() { | ||
| let len = T::Balance::from(len as u32); | ||
| let base = T::TransactionBaseFee::get(); | ||
| let byte = T::TransactionByteFee::get(); | ||
| base.saturating_add(byte.saturating_mul(len)) | ||
| let per_byte = T::TransactionByteFee::get(); | ||
| base.saturating_add(per_byte.saturating_mul(len)) | ||
| } else { | ||
| Zero::zero() | ||
| }; | ||
|
|
||
| // weight fee | ||
| let weight = info.weight; | ||
| let weight_fee: T::Balance = <system::Module<T>>::next_weight_multiplier() | ||
| .apply_to(weight).saturated_into(); | ||
| let weight_fee = { | ||
| // cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded` | ||
| // maximum of its data type, which is not desired. | ||
| let capped_weight = info.weight.min(<T as system::Trait>::MaximumBlockWeight::get()); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this kinda sucks that every signed extension using weight must cap it itself if they want to. This is because in the details of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also do the same in system I had the assumption that the weight fo one individual tx cannot go beyond the weight of the entire block. Even if thee annotationa sets the weight to infinity the runtime checks interpret it as whatever If this does not exist, then |
||
| let weight_fee: T::Balance = <system::Module<T>>::next_weight_multiplier() | ||
| .apply_to(capped_weight).saturated_into(); | ||
| let per_weight = T::TransactionWeightFee::get(); | ||
| weight_fee.saturating_mul(per_weight) | ||
| }; | ||
|
|
||
| len_fee.saturating_add(weight_fee).saturating_add(tip) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.