Weight annotation. (#3157)

* Make extrinsics extensible.

Also Remove old extrinsic types.

* Rest of mockup. Add tips.

* Fix some build issues

* Runtiem builds :)

* Substrate builds.

* Fix a doc test

* Compact encoding

* Extract out the era logic into an extension

* Weight Check signed extension. (#3115)

* Weight signed extension.

* Revert a bit + test for check era.

* Update Cargo.toml

* Update node/cli/src/factory_impl.rs

* Update node/executor/src/lib.rs

* Update node/executor/src/lib.rs

* Don't use len for weight - use data.

* Operational Transaction; second attempt (#3138)

* working poc added.

* some fixes.

* Update doc.

* Fix all tests + final logic.

* more refactoring.

* nits.

* System block limit in bytes.

* Silent the storage macro warnings.

* More logic more tests.

* Fix import.

* Refactor names.

* Fix build.

* Update srml/balances/src/lib.rs

* Final refactor.

* Bump transaction version

* Fix weight mult test.

* Fix more tests and improve doc.

* Bump.

* Make some tests work again.

* Fix subkey.

* Remove todos + bump.

* First draft of annotating weights.

* Refactor weight to u64.

* More refactoring and tests.

* New convert for weight to fee

* more tests.

* remove merge redundancy.

* Fix system test.

* Bring back subkey stuff.

* a few stress tests.

* fix some of the grumbles.

* Final nits.

* Update srml/system/src/lib.rs

Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com>

* Scale weights by 1000.

* Bump.

* Fix decl_storage test.
This commit is contained in:
Kian Peymani
2019-07-25 11:58:47 +02:00
committed by Bastian Köcher
parent 80472956f8
commit 002acb9373
44 changed files with 844 additions and 259 deletions
+23 -8
View File
@@ -161,10 +161,10 @@ use srml_support::traits::{
use srml_support::dispatch::Result;
use primitives::traits::{
Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug,
Saturating, Bounded, SignedExtension, SaturatedConversion, DispatchError
Saturating, Bounded, SignedExtension, SaturatedConversion, DispatchError, Convert,
};
use primitives::transaction_validity::{TransactionPriority, ValidTransaction};
use primitives::weights::DispatchInfo;
use primitives::weights::{DispatchInfo, SimpleDispatchInfo, Weight};
use system::{IsDeadAccount, OnNewAccount, ensure_signed, ensure_root};
mod mock;
@@ -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>;
/// Convert a weight value into a deductible fee based on the currency type.
type WeightToFee: Convert<Weight, 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>;
/// Convert a weight value into a deductible fee based on the currency type.
type WeightToFee: Convert<Weight, 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 WeightToFee = T::WeightToFee;
}
decl_event!(
@@ -428,6 +435,7 @@ decl_module! {
/// `T::DustRemoval::on_unbalanced` and `T::OnFreeBalanceZero::on_free_balance_zero`.
///
/// # </weight>
#[weight = SimpleDispatchInfo::FixedNormal(1_000_000)]
pub fn transfer(
origin,
dest: <T::Lookup as StaticLookup>::Source,
@@ -451,6 +459,7 @@ decl_module! {
/// - Independent of the arguments.
/// - Contains a limited number of reads and writes.
/// # </weight>
#[weight = SimpleDispatchInfo::FixedOperational(500_000)]
fn set_balance(
origin,
who: <T::Lookup as StaticLookup>::Source,
@@ -766,6 +775,7 @@ impl<T: Subtrait<I>, I: Instance> system::Trait for ElevatedTrait<T, I> {
type BlockHashCount = T::BlockHashCount;
type MaximumBlockWeight = T::MaximumBlockWeight;
type MaximumBlockLength = T::MaximumBlockLength;
type AvailableBlockRatio = T::AvailableBlockRatio;
}
impl<T: Subtrait<I>, I: Instance> Trait<I> for ElevatedTrait<T, I> {
type Balance = T::Balance;
@@ -780,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 WeightToFee = T::WeightToFee;
}
impl<T: Trait<I>, I: Instance> Currency<T::AccountId> for Module<T, I>
@@ -1171,19 +1182,23 @@ 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).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());
let weight_update = <system::Module<T>>::next_weight_multiplier();
let adjusted_weight = weight_update.apply_to(capped_weight);
T::WeightToFee::convert(adjusted_weight)
};
len_fee.saturating_add(weight_fee).saturating_add(tip)
}
+18 -2
View File
@@ -18,7 +18,7 @@
#![cfg(test)]
use primitives::{traits::IdentityLookup, testing::Header, weights::{DispatchInfo, Weight}};
use primitives::{Perbill, traits::{Convert, IdentityLookup}, testing::Header, weights::{DispatchInfo, Weight}};
use substrate_primitives::{H256, Blake2Hasher};
use runtime_io;
use srml_support::{impl_outer_origin, parameter_types};
@@ -36,6 +36,8 @@ thread_local! {
static CREATION_FEE: RefCell<u64> = RefCell::new(0);
static TRANSACTION_BASE_FEE: RefCell<u64> = RefCell::new(0);
static TRANSACTION_BYTE_FEE: RefCell<u64> = RefCell::new(1);
static TRANSACTION_WEIGHT_FEE: RefCell<u64> = RefCell::new(1);
static WEIGHT_TO_FEE: RefCell<u64> = RefCell::new(1);
}
pub struct ExistentialDeposit;
@@ -63,6 +65,13 @@ impl Get<u64> for TransactionByteFee {
fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) }
}
pub struct WeightToFee(u64);
impl Convert<Weight, u64> for WeightToFee {
fn convert(t: Weight) -> u64 {
WEIGHT_TO_FEE.with(|v| *v.borrow() * (t as u64))
}
}
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Runtime;
@@ -70,6 +79,7 @@ parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
impl system::Trait for Runtime {
type Origin = Origin;
@@ -85,6 +95,7 @@ impl system::Trait for Runtime {
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
}
impl Trait for Runtime {
type Balance = u64;
@@ -99,11 +110,13 @@ impl Trait for Runtime {
type CreationFee = CreationFee;
type TransactionBaseFee = TransactionBaseFee;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = WeightToFee;
}
pub struct ExtBuilder {
transaction_base_fee: u64,
transaction_byte_fee: u64,
weight_to_fee: u64,
existential_deposit: u64,
transfer_fee: u64,
creation_fee: u64,
@@ -115,6 +128,7 @@ impl Default for ExtBuilder {
Self {
transaction_base_fee: 0,
transaction_byte_fee: 0,
weight_to_fee: 0,
existential_deposit: 0,
transfer_fee: 0,
creation_fee: 0,
@@ -124,9 +138,10 @@ impl Default for ExtBuilder {
}
}
impl ExtBuilder {
pub fn transaction_fees(mut self, base_fee: u64, byte_fee: u64) -> Self {
pub fn transaction_fees(mut self, base_fee: u64, byte_fee: u64, weight_fee: u64) -> Self {
self.transaction_base_fee = base_fee;
self.transaction_byte_fee = byte_fee;
self.weight_to_fee = weight_fee;
self
}
pub fn existential_deposit(mut self, existential_deposit: u64) -> Self {
@@ -159,6 +174,7 @@ impl ExtBuilder {
CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee);
TRANSACTION_BASE_FEE.with(|v| *v.borrow_mut() = self.transaction_base_fee);
TRANSACTION_BYTE_FEE.with(|v| *v.borrow_mut() = self.transaction_byte_fee);
WEIGHT_TO_FEE.with(|v| *v.borrow_mut() = self.weight_to_fee);
}
pub fn build(self) -> runtime_io::TestExternalities<Blake2Hasher> {
self.set_associated_consts();
+27 -5
View File
@@ -114,7 +114,7 @@ fn lock_reasons_should_work() {
with_externalities(
&mut ExtBuilder::default()
.existential_deposit(1)
.monied(true).transaction_fees(0, 1)
.monied(true).transaction_fees(0, 1, 0)
.build(),
|| {
Balances::set_lock(ID_1, &1, 10, u64::max_value(), WithdrawReason::Transfer.into());
@@ -752,15 +752,37 @@ fn signed_extension_take_fees_work() {
with_externalities(
&mut ExtBuilder::default()
.existential_deposit(10)
.transaction_fees(10, 1)
.transaction_fees(10, 1, 5)
.monied(true)
.build(),
|| {
let len = 10;
assert!(TakeFees::<Runtime>::from(0).pre_dispatch(&1, info_from_weight(0), len).is_ok());
assert_eq!(Balances::free_balance(&1), 100 - 20);
assert!(TakeFees::<Runtime>::from(5 /* tipped */).pre_dispatch(&1, info_from_weight(0), len).is_ok());
assert!(TakeFees::<Runtime>::from(0).pre_dispatch(&1, info_from_weight(5), len).is_ok());
assert_eq!(Balances::free_balance(&1), 100 - 20 - 25);
assert!(TakeFees::<Runtime>::from(5 /* tipped */).pre_dispatch(&1, info_from_weight(3), len).is_ok());
assert_eq!(Balances::free_balance(&1), 100 - 20 - 25 - 20 - 5 - 15);
}
);
}
#[test]
fn signed_extension_take_fees_is_bounded() {
with_externalities(
&mut ExtBuilder::default()
.existential_deposit(1000)
.transaction_fees(0, 0, 1)
.monied(true)
.build(),
|| {
use primitives::weights::Weight;
// maximum weight possible
assert!(TakeFees::<Runtime>::from(0).pre_dispatch(&1, info_from_weight(Weight::max_value()), 10).is_ok());
// fee will be proportional to what is the actual maximum weight in the runtime.
assert_eq!(
Balances::free_balance(&1),
(10000 - <Runtime as system::Trait>::MaximumBlockWeight::get()) as u64
);
}
);
}