diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 0b6321034cda4..922fe7f9defdb 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -182,11 +182,16 @@ impl Permill { /// Everything. pub fn one() -> Self { Self(1_000_000) } + /// create a new raw instance. This can be called at compile time. + pub const fn from_const_parts(parts: u32) -> Self { + Self([parts, 1_000_000][(parts > 1_000_000) as usize]) + } + /// From an explicitly defined number of parts per maximum of the type. - pub fn from_parts(x: u32) -> Self { Self(x.min(1_000_000)) } + pub fn from_parts(parts: u32) -> Self { Self::from_const_parts(parts) } /// Converts from a percent. Equal to `x / 100`. - pub fn from_percent(x: u32) -> Self { Self(x.min(100) * 10_000) } + pub const fn from_percent(x: u32) -> Self { Self([x, 100][(x > 100) as usize] * 10_000) } /// Converts a fraction into `Permill`. #[cfg(feature = "std")] @@ -286,11 +291,16 @@ impl Perbill { /// Everything. pub fn one() -> Self { Self(1_000_000_000) } + /// create a new raw instance. This can be called at compile time. + pub const fn from_const_parts(parts: u32) -> Self { + Self([parts, 1_000_000_000][(parts > 1_000_000_000) as usize]) + } + /// From an explicitly defined number of parts per maximum of the type. - pub fn from_parts(x: u32) -> Self { Self(x.min(1_000_000_000)) } + pub fn from_parts(parts: u32) -> Self { Self::from_const_parts(parts) } /// Converts from a percent. Equal to `x / 100`. - pub fn from_percent(x: u32) -> Self { Self(x.min(100) * 10_000_000) } + pub const fn from_percent(x: u32) -> Self { Self([x, 100][(x > 100) as usize] * 10_000_000) } /// Construct new instance where `x` is in millionths. Value equivalent to `x / 1,000,000`. pub fn from_millionths(x: u32) -> Self { Self(x.min(1_000_000) * 1000) } @@ -411,11 +421,12 @@ impl Fixed64 { /// Performs a saturated multiply and accumulate. /// - /// Returns `n + (self * n)`. + /// Returns a saturated `n + (self * n)`. + /// TODO: generalize this to any weight type. #3189 pub fn saturated_multiply_accumulate(&self, int: u32) -> u32 { let parts = self.0; - let positive = parts > 0; + // natural parts might overflow. let natural_parts = self.clone().saturated_into::(); // fractional parts can always fit into u32. @@ -459,8 +470,8 @@ impl Saturating for Fixed64 { } } -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait for -/// safe addition. +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe addition. impl ops::Add for Fixed64 { type Output = Self; @@ -469,8 +480,8 @@ impl ops::Add for Fixed64 { } } -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait for -/// safe subtraction. +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe subtraction. impl ops::Sub for Fixed64 { type Output = Self; diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index fcafe6dad97de..6ef7844fc9b3b 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -282,7 +282,7 @@ impl GetDispatchInfo for TestXt { fn get_dispatch_info(&self) -> DispatchInfo { // for testing: weight == size. DispatchInfo { - weight: self.encode().len() as u32, + weight: self.encode().len() as _, ..Default::default() } } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index eccf9751322ca..670f8d181d1b5 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -166,7 +166,6 @@ impl Convert for Identity { /// A structure that performs standard conversion using the standard Rust conversion traits. pub struct ConvertInto; - impl> Convert for ConvertInto { fn convert(a: A) -> B { a.into() } } @@ -771,6 +770,9 @@ pub enum DispatchError { /// General error to do with the inability to pay some fees (e.g. account balance too low). Payment, + /// General error to do with the exhaustion of block resources. + Resource, + /// General error to do with the permissions of the sender. NoPermission, @@ -794,11 +796,12 @@ impl From for i8 { fn from(e: DispatchError) -> i8 { match e { DispatchError::Payment => -64, - DispatchError::NoPermission => -65, - DispatchError::BadState => -66, - DispatchError::Stale => -67, - DispatchError::Future => -68, - DispatchError::BadProof => -69, + DispatchError::Resource => -65, + DispatchError::NoPermission => -66, + DispatchError::BadState => -67, + DispatchError::Stale => -68, + DispatchError::Future => -69, + DispatchError::BadProof => -70, } } } diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index c592d9e19546c..45ac59e0d5489 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -163,10 +163,8 @@ impl ClassifyDispatch for SimpleDispatchInfo { impl Default for SimpleDispatchInfo { fn default() -> Self { - // This implies that the weight is currently equal to 100, nothing more - // for all substrate transactions that do NOT explicitly annotate weight. - // TODO #2431 needs to be updated with proper max values. - SimpleDispatchInfo::FixedNormal(100) + // Default weight of all transactions. + SimpleDispatchInfo::FixedNormal(10_000) } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 7947d830a3c58..ceb9ed737b205 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -34,8 +34,7 @@ use substrate_client::{ impl_runtime_apis, }; use runtime_primitives::{ - ApplyResult, - create_runtime_str, + ApplyResult, create_runtime_str, Perbill, transaction_validity::{TransactionValidity, ValidTransaction}, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, @@ -330,6 +329,7 @@ parameter_types! { pub const MinimumPeriod: u64 = 5; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl srml_system::Trait for Runtime { @@ -346,6 +346,7 @@ impl srml_system::Trait for Runtime { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } impl srml_timestamp::Trait for Runtime { diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 332df0ec0dfae..eedcda4d149c4 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -8,17 +8,11 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -use parity_codec::{Encode, Decode}; use rstd::prelude::*; -#[cfg(feature = "std")] -use primitives::bytes; use primitives::{ed25519, sr25519, OpaqueMetadata}; -use sr_primitives::{ - ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, - traits::{self, NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify}, weights::Weight, -}; +use sr_primitives::{ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str}; +use sr_primitives::traits::{NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify, ConvertInto}; +use sr_primitives::weights::Weight; use client::{ block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, runtime_api, impl_runtime_apis @@ -102,8 +96,9 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024; - pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const MaximumBlockWeight: Weight = 1_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; } impl system::Trait for Runtime { @@ -133,6 +128,8 @@ impl system::Trait for Runtime { type MaximumBlockWeight = MaximumBlockWeight; /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. type MaximumBlockLength = MaximumBlockLength; + /// Portion of the block weight that is available to all normal transactions. + type AvailableBlockRatio = AvailableBlockRatio; } impl aura::Trait for Runtime { @@ -166,8 +163,8 @@ parameter_types! { pub const ExistentialDeposit: u128 = 500; pub const TransferFee: u128 = 0; pub const CreationFee: u128 = 0; - pub const TransactionBaseFee: u128 = 1; - pub const TransactionByteFee: u128 = 0; + pub const TransactionBaseFee: u128 = 0; + pub const TransactionByteFee: u128 = 1; } impl balances::Trait for Runtime { @@ -188,6 +185,7 @@ impl balances::Trait for Runtime { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; } impl sudo::Trait for Runtime { diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index 63b5e27b9674e..d0c51443904d9 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -74,6 +74,7 @@ mod tests { use support::{impl_outer_origin, assert_ok, parameter_types}; use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; use sr_primitives::weights::Weight; + use sr_primitives::Perbill; impl_outer_origin! { pub enum Origin for Test {} @@ -88,6 +89,7 @@ mod tests { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl system::Trait for Test { type Origin = Origin; @@ -103,6 +105,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } impl Trait for Test { type Event = (); diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 781495780dd5e..26e54f6ee650c 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -23,8 +23,9 @@ use node_runtime::{ BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig, Perbill, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, SystemConfig, - TechnicalCommitteeConfig, DAYS, DOLLARS, MILLICENTS, WASM_BINARY, + TechnicalCommitteeConfig, WASM_BINARY, }; +use node_runtime::constants::{time::*, currency::*}; pub use node_runtime::GenesisConfig; use substrate_service; use hex_literal::hex; diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index f75e97a8fe2c3..b63def7f124c3 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -263,7 +263,8 @@ mod tests { use babe::CompatibleDigestItem; use consensus_common::{Environment, Proposer, BlockImportParams, BlockOrigin, ForkChoiceStrategy}; use node_primitives::DigestItem; - use node_runtime::{BalancesCall, Call, CENTS, SECS_PER_BLOCK, UncheckedExtrinsic}; + use node_runtime::{BalancesCall, Call, UncheckedExtrinsic}; + use node_runtime::constants::{currency::CENTS, time::SECS_PER_BLOCK}; use parity_codec::{Encode, Decode}; use primitives::{ crypto::Pair as CryptoPair, blake2_256, diff --git a/node/executor/Cargo.toml b/node/executor/Cargo.toml index 345401141913c..2e3ba49d985ea 100644 --- a/node/executor/Cargo.toml +++ b/node/executor/Cargo.toml @@ -34,3 +34,4 @@ wabt = "~0.7.4" [features] benchmarks = [] +stress-test = [] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 7d806735a13a1..9b9352090e066 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -35,31 +35,29 @@ native_executor_instance!( #[cfg(test)] mod tests { - use runtime_io; use super::Executor; + use {balances, contracts, indices, staking, system, timestamp}; + use runtime_io; use substrate_executor::{WasmExecutor, NativeExecutionDispatch}; use parity_codec::{Encode, Decode, Joiner}; use keyring::{AccountKeyring, Ed25519Keyring, Sr25519Keyring}; - use runtime_support::{Hashable, StorageValue, StorageMap, traits::{Currency, Get}}; + use runtime_support::{Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities as CoreTestExternalities}; - use primitives::{ - twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, - NativeOrEncoded - }; + use primitives::{ twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId, Balance, Index}; - use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; + use runtime_primitives::traits::{Header as HeaderT, Hash as HashT, Convert}; use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use runtime_primitives::weights::{WeightMultiplier, SimpleDispatchInfo, WeighData}; - use {balances, contracts, indices, staking, system, timestamp}; + use runtime_primitives::weights::{WeightMultiplier, GetDispatchInfo}; use contracts::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, System, SystemConfig, - GrandpaConfig, IndicesConfig, ContractsConfig, Event, SessionKeys, CreationFee, - CENTS, DOLLARS, MILLICENTS, SignedExtra, TransactionBaseFee, TransactionByteFee, - MaximumBlockWeight, + GrandpaConfig, IndicesConfig, ContractsConfig, Event, SessionKeys, SignedExtra, + TransferFee, TransactionBaseFee, TransactionByteFee, }; + use node_runtime::constants::currency::*; + use node_runtime::impls::WeightToFee; use wabt; use primitives::map; @@ -82,20 +80,18 @@ mod tests { type TestExternalities = CoreTestExternalities; + /// Default transfer fee fn transfer_fee(extrinsic: &E) -> Balance { - let length_fee = >::get() + - >::get() * + let length_fee = TransactionBaseFee::get() + + TransactionByteFee::get() * (extrinsic.encode().len() as Balance); - let weight_fee = SimpleDispatchInfo::default().weigh_data(()) as Balance; - length_fee + weight_fee - } - - fn multiplier_ideal() -> u32 { - >::get() / 4 / 4 - } - fn creation_fee() -> Balance { - >::get() + let weight = default_transfer_call().get_dispatch_info().weight; + // NOTE: this is really hard to apply, since the multiplier of each block needs to be fetched + // before the block, while we compute this after the block. + // weight = >::next_weight_multiplier().apply_to(weight); + let weight_fee = ::WeightToFee::convert(weight); + length_fee + weight_fee + TransferFee::get() } fn alice() -> AccountId { @@ -155,10 +151,14 @@ mod tests { ) } + fn default_transfer_call() -> balances::Call { + balances::Call::transfer::(bob().into(), 69 * DOLLARS) + } + fn xt() -> UncheckedExtrinsic { sign(CheckedExtrinsic { signed: Some((alice(), signed_extra(0, 0))), - function: Call::Balances(balances::Call::transfer::(bob().into(), 69 * DOLLARS)), + function: Call::Balances(default_transfer_call()), }) } @@ -273,7 +273,7 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt()) - creation_fee()); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } @@ -309,7 +309,7 @@ mod tests { assert!(r.is_ok()); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt()) - creation_fee()); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } @@ -552,7 +552,7 @@ mod tests { ).0.unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt()) - creation_fee()); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); let events = vec![ EventRecord { @@ -587,9 +587,18 @@ mod tests { ).0.unwrap(); runtime_io::with_externalities(&mut t, || { - // TODO TODO: this needs investigating: why are we deducting creation fee twice here? and why bob also pays it? - assert_eq!(Balances::total_balance(&alice()), 32 * DOLLARS - 2 * transfer_fee(&xt()) - 2 * creation_fee()); - assert_eq!(Balances::total_balance(&bob()), 179 * DOLLARS - transfer_fee(&xt()) - creation_fee()); + // NOTE: fees differ slightly in tests that execute more than one block due to the + // weight update. Hence, using `assert_eq_error_rate`. + assert_eq_error_rate!( + Balances::total_balance(&alice()), + 32 * DOLLARS - 2 * transfer_fee(&xt()), + 10_000 + ); + assert_eq_error_rate!( + Balances::total_balance(&bob()), + 179 * DOLLARS - transfer_fee(&xt()), + 10_000 + ); let events = vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), @@ -644,15 +653,23 @@ mod tests { WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block1.0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt()) - creation_fee()); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - transfer_fee(&xt())); assert_eq!(Balances::total_balance(&bob()), 169 * DOLLARS); }); WasmExecutor::new().call(&mut t, 8, COMPACT_CODE, "Core_execute_block", &block2.0).unwrap(); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 32 * DOLLARS - 2 * transfer_fee(&xt()) - 2 * creation_fee()); - assert_eq!(Balances::total_balance(&bob()), 179 * DOLLARS - 1 * transfer_fee(&xt()) - creation_fee()); + assert_eq_error_rate!( + Balances::total_balance(&alice()), + 32 * DOLLARS - 2 * transfer_fee(&xt()), + 10_000 + ); + assert_eq_error_rate!( + Balances::total_balance(&bob()), + 179 * DOLLARS - 1 * transfer_fee(&xt()), + 10_000 + ); }); } @@ -814,15 +831,14 @@ mod tests { fn wasm_big_block_import_fails() { let mut t = new_test_ext(COMPACT_CODE, false); - assert!( - WasmExecutor::new().call( - &mut t, - 4, - COMPACT_CODE, - "Core_execute_block", - &block_with_size(42, 0, 120_000).0 - ).is_err() + let result = WasmExecutor::new().call( + &mut t, + 4, + COMPACT_CODE, + "Core_execute_block", + &block_with_size(42, 0, 120_000).0 ); + assert!(result.is_err()); // Err(Wasmi(Trap(Trap { kind: Host(AllocatorOutOfSpace) }))) } #[test] @@ -897,7 +913,7 @@ mod tests { assert_eq!(r, Ok(ApplyOutcome::Success)); runtime_io::with_externalities(&mut t, || { - assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt()) - creation_fee()); + assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt())); assert_eq!(Balances::total_balance(&bob()), 69 * DOLLARS); }); } @@ -947,7 +963,6 @@ mod tests { #[test] - #[ignore] fn weight_multiplier_increases_and_decreases_on_big_weight() { let mut t = new_test_ext(COMPACT_CODE, false); @@ -958,25 +973,22 @@ mod tests { }); let mut tt = new_test_ext(COMPACT_CODE, false); - // NOTE: This assumes that system::remark has the default. - let num_to_exhaust = multiplier_ideal() * 2 / SimpleDispatchInfo::default().weigh_data(()); - println!("++ Generating {} transactions to fill {} weight units", num_to_exhaust, multiplier_ideal() * 2); - - 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::>(); - xts.insert(0, CheckedExtrinsic { - signed: None, - function: Call::Timestamp(timestamp::Call::set(42)), - }); // big one in terms of weight. let block1 = construct_block( &mut tt, 1, GENESIS_HASH.into(), - xts + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(timestamp::Call::set(42)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(0, 0))), + function: Call::System(system::Call::fill_block()), + } + ] ); // small one in terms of weight. @@ -990,12 +1002,14 @@ mod tests { function: Call::Timestamp(timestamp::Call::set(52)), }, CheckedExtrinsic { - signed: Some((charlie(), signed_extra(num_to_exhaust.into(), 0))), + signed: Some((charlie(), signed_extra(1, 0))), function: Call::System(system::Call::remark(vec![0; 1])), } ] ); + println!("++ Block 1 size: {} / Block 2 size {}", block1.0.encode().len(), block2.0.encode().len()); + // execute a big block. executor().call::<_, NeverNativeValue, fn() -> _>( &mut t, @@ -1030,6 +1044,209 @@ 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_000 + // if weight of the 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::::new_with_code(COMPACT_CODE, map![ + blake2_256(&>::key_for(alice())).to_vec() => { + (100 * DOLLARS).encode() + }, + blake2_256(&>::key_for(bob())).to_vec() => { + (10 * DOLLARS).encode() + }, + twox_128(>::key()).to_vec() => { + (110 * DOLLARS).encode() + }, + twox_128(>::key()).to_vec() => vec![0u8; 16], + blake2_256(&>::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::get() + + TransactionByteFee::get() * + (xt.clone().encode().len() as Balance); + balance_alice -= length_fee; + + let weight = default_transfer_call().get_dispatch_info().weight; + let weight_fee = WeightToFee::convert(weight); + + // we know that weight to fee multiplier is effect-less in block 1. + assert_eq!(weight_fee as Balance, MILLICENTS); + balance_alice -= weight_fee; + + balance_alice -= tip; + balance_alice -= TransferFee::get(); + + assert_eq!(Balances::total_balance(&alice()), balance_alice); + }); + } + + #[test] + #[should_panic] + #[cfg(feature = "stress-test")] + fn block_weight_capacity_report() { + // Just report how many transfer calls you could fit into a block. The number should at least + // be a few hundred (250 at the time of writing but can change over time). Runs until panic. + + // execution ext. + let mut t = new_test_ext(COMPACT_CODE, false); + // setup ext. + let mut tt = new_test_ext(COMPACT_CODE, false); + + let factor = 50; + let mut time = 10; + let mut nonce: Index = 0; + let mut block_number = 1; + let mut previous_hash: Hash = GENESIS_HASH.into(); + + loop { + let num_transfers = block_number * factor; + let mut xts = (0..num_transfers).map(|i| CheckedExtrinsic { + signed: Some((charlie(), signed_extra(nonce + i as Index, 0))), + function: Call::Balances(balances::Call::transfer(bob().into(), 0)), + }).collect::>(); + + xts.insert(0, CheckedExtrinsic { + signed: None, + function: Call::Timestamp(timestamp::Call::set(time)), + }); + + // NOTE: this is super slow. Can probably be improved. + let block = construct_block( + &mut tt, + block_number, + previous_hash, + xts + ); + + let len = block.0.len(); + print!( + "++ Executing block with {} transfers. Block size = {} bytes / {} kb / {} mb", + num_transfers, + len, + len / 1024, + len / 1024 / 1024, + ); + + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_execute_block", + &block.0, + true, + None, + ).0; + + println!(" || Result = {:?}", r); + assert!(r.is_ok()); + + previous_hash = block.1; + nonce += num_transfers; + time += 10; + block_number += 1; + } + } + + #[test] + #[should_panic] + #[cfg(feature = "stress-test")] + fn block_length_capacity_report() { + // Just report how big a block can get. Executes until panic. Should be ignored unless if + // manually inspected. The number should at least be a few megabytes (5 at the time of + // writing but can change over time). + + // execution ext. + let mut t = new_test_ext(COMPACT_CODE, false); + // setup ext. + let mut tt = new_test_ext(COMPACT_CODE, false); + + let factor = 256 * 1024; + let mut time = 10; + let mut nonce: Index = 0; + let mut block_number = 1; + let mut previous_hash: Hash = GENESIS_HASH.into(); + + loop { + // NOTE: this is super slow. Can probably be improved. + let block = construct_block( + &mut tt, + block_number, + previous_hash, + vec![ + CheckedExtrinsic { + signed: None, + function: Call::Timestamp(timestamp::Call::set(time)), + }, + CheckedExtrinsic { + signed: Some((charlie(), signed_extra(nonce, 0))), + function: Call::System(system::Call::remark(vec![0u8; (block_number * factor) as usize])), + }, + ] + ); + + let len = block.0.len(); + print!( + "++ Executing block with big remark. Block size = {} bytes / {} kb / {} mb", + len, + len / 1024, + len / 1024 / 1024, + ); + + let r = executor().call::<_, NeverNativeValue, fn() -> _>( + &mut t, + "Core_execute_block", + &block.0, + true, + None, + ).0; + + println!(" || Result = {:?}", r); + assert!(r.is_ok()); + + previous_hash = block.1; + nonce += 1; + time += 10; + block_number += 1; + } + } + #[cfg(feature = "benchmarks")] mod benches { use super::*; diff --git a/node/runtime/src/constants.rs b/node/runtime/src/constants.rs new file mode 100644 index 0000000000000..c030f57121149 --- /dev/null +++ b/node/runtime/src/constants.rs @@ -0,0 +1,52 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! A set of constant values used in substrate runtime. + +/// Money matters. +pub mod currency { + use node_primitives::Balance; + + pub const MILLICENTS: Balance = 1_000_000_000; + pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. + pub const DOLLARS: Balance = 100 * CENTS; +} + +/// Time. +pub mod time { + use node_primitives::Moment; + + pub const SECS_PER_BLOCK: Moment = 6; + pub const MINUTES: Moment = 60 / SECS_PER_BLOCK; + pub const HOURS: Moment = MINUTES * 60; + pub const DAYS: Moment = HOURS * 24; +} + +// CRITICAL NOTE: The system module maintains two constants: a _maximum_ block weight and a +// _ratio_ of it yielding the portion which is accessible to normal transactions (reserving the rest +// for operational ones). `TARGET_BLOCK_FULLNESS` is entirely independent and the system module is +// not aware of if, nor should it care about it. This constant simply denotes on which ratio of the +// _maximum_ block weight we tweak the fees. It does NOT care about the type of the dispatch. +// +// For the system to be configured in a sane way, `TARGET_BLOCK_FULLNESS` should always be less than +// the ratio that `system` module uses to find normal transaction quota. +/// Fee-related. +pub mod fee { + pub use runtime_primitives::Perbill; + + /// The block saturation level. Fees will be updates based on this value. + pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); +} \ No newline at end of file diff --git a/node/runtime/src/impls.rs b/node/runtime/src/impls.rs index 85365b6a7e73e..464f1a424b249 100644 --- a/node/runtime/src/impls.rs +++ b/node/runtime/src/impls.rs @@ -20,8 +20,16 @@ use node_primitives::Balance; use runtime_primitives::weights::{Weight, WeightMultiplier}; use runtime_primitives::traits::{Convert, Saturating}; use runtime_primitives::Fixed64; -use support::traits::Get; -use crate::{Balances, MaximumBlockWeight}; +use support::traits::{OnUnbalanced, Currency}; +use crate::{Balances, Authorship, MaximumBlockWeight, NegativeImbalance}; +use crate::constants::fee::TARGET_BLOCK_FULLNESS; + +pub struct Author; +impl OnUnbalanced for Author { + fn on_unbalanced(amount: NegativeImbalance) { + Balances::resolve_creating(&Authorship::author(), amount); + } +} /// Struct that handles the conversion of Balance -> `u64`. This is used for staking's election /// calculation. @@ -39,32 +47,53 @@ impl Convert for CurrencyToVoteHandler { fn convert(x: u128) -> Balance { x * Self::factor() } } +/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the +/// node's balance type. +/// +/// This should typically create a mapping between the following ranges: +/// - [0, system::MaximumBlockWeight] +/// - [Balance::min, Balance::max] +/// +/// Yet, it can be used for any other sort of change to weight-fee. Some examples being: +/// - Setting it to `0` will essentially disable the weight fee. +/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. +/// +/// By default, substrate node will have a weight range of [0, 1_000_000_000]. +pub struct WeightToFee; +impl Convert for WeightToFee { + fn convert(x: Weight) -> Balance { + // substrate-node a weight of 10_000 (smallest non-zero weight) to be mapped to 10^7 units of + // fees, hence: + Balance::from(x).saturating_mul(1_000) + } +} + /// A struct that updates the weight multiplier based on the saturation level of the previous block. /// This should typically be called once per-block. /// /// This assumes that weight is a numeric value in the u32 range. /// +/// Given `TARGET_BLOCK_FULLNESS = 1/2`, a block saturation greater than 1/2 will cause the system +/// fees to slightly grow and the opposite for block saturations less than 1/2. +/// /// Formula: -/// diff = (ideal_weight - current_block_weight) +/// diff = (target_weight - current_block_weight) /// v = 0.00004 /// next_weight = weight * (1 + (v . diff) + (v . diff)^2 / 2) /// /// https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#relay-chain-transaction-fees pub struct WeightMultiplierUpdateHandler; + impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierUpdateHandler { fn convert(previous_state: (Weight, WeightMultiplier)) -> WeightMultiplier { let (block_weight, multiplier) = previous_state; - // CRITICAL NOTE: what the system module interprets as maximum block weight, and a portion - // of it (1/4 usually) as ideal weight demonstrate the gap in block weights for operational - // transactions. What this weight multiplier interprets as the maximum, is actually the - // maximum that is available to normal transactions. Hence, - let max_weight = >::get() / 4; - let ideal_weight = (max_weight / 4) as u128; + let max_weight = MaximumBlockWeight::get(); + let target_weight = (TARGET_BLOCK_FULLNESS * max_weight) as u128; let block_weight = block_weight as u128; // determines if the first_term is positive - let positive = block_weight >= ideal_weight; - let diff_abs = block_weight.max(ideal_weight) - block_weight.min(ideal_weight); + let positive = block_weight >= target_weight; + let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight); // diff is within u32, safe. let diff = Fixed64::from_rational(diff_abs as i64, max_weight as u64); let diff_squared = diff.saturating_mul(diff); @@ -81,6 +110,8 @@ impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierU 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(WeightMultiplier::from_fixed(excess)) } else { @@ -90,7 +121,7 @@ impl Convert<(Weight, WeightMultiplier), WeightMultiplier> for WeightMultiplierU // 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 are practically free. We stop here and only increase if the network + // transactions have no weight fee. We stop here and only increase if the network // became more busy. .max(WeightMultiplier::from_rational(-1, 1)) } @@ -102,13 +133,15 @@ mod tests { use super::*; use runtime_primitives::weights::Weight; use runtime_primitives::Perbill; + use crate::{MaximumBlockWeight, AvailableBlockRatio, Runtime}; + use crate::constants::currency::*; fn max() -> Weight { - >::get() + MaximumBlockWeight::get() } - fn ideal() -> Weight { - max() / 4 / 4 + fn target() -> Weight { + TARGET_BLOCK_FULLNESS * max() } // poc reference implementation. @@ -120,7 +153,7 @@ mod tests { // maximum tx weight let m = max() as f32; // Ideal saturation in terms of weight - let ss = ideal() as f32; + let ss = target() as f32; // Current saturation in terms of weight let s = block_weight; @@ -130,52 +163,93 @@ mod tests { Perbill::from_parts((fm * 1_000_000_000_f32) as u32) } - fn fm(parts: i64) -> WeightMultiplier { + fn wm(parts: i64) -> WeightMultiplier { WeightMultiplier::from_parts(parts) } + #[test] + fn empty_chain_simulation() { + // just a few txs per_block. + let block_weight = 1000; + let mut wm = WeightMultiplier::default(); + let mut iterations: u64 = 0; + loop { + let next = WeightMultiplierUpdateHandler::convert((block_weight, wm)); + wm = next; + if wm == WeightMultiplier::from_rational(-1, 1) { break; } + iterations += 1; + } + println!("iteration {}, new wm = {:?}. Weight fee is now zero", iterations, wm); + } + + #[test] + #[ignore] + fn congested_chain_simulation() { + // `cargo test congested_chain_simulation -- --nocapture` to get some insight. + // almost full. The entire quota of normal transactions is taken. + let block_weight = AvailableBlockRatio::get() * max(); + let tx_weight = 1000; + let mut wm = WeightMultiplier::default(); + let mut iterations: u64 = 0; + loop { + let next = WeightMultiplierUpdateHandler::convert((block_weight, wm)); + if wm == next { break; } + wm = next; + iterations += 1; + let fee = ::WeightToFee::convert(wm.apply_to(tx_weight)); + println!( + "iteration {}, new wm = {:?}. Fee at this point is: {} millicents, {} cents, {} dollars", + iterations, + wm, + fee / MILLICENTS, + fee / CENTS, + fee / DOLLARS + ); + } + } + #[test] fn stateless_weight_mul() { // Light block. Fee is reduced a little. assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() / 4, WeightMultiplier::default())), - fm(-7500) + WeightMultiplierUpdateHandler::convert((target() / 4, WeightMultiplier::default())), + wm(-7500) ); // a bit more. Fee is decreased less, meaning that the fee increases as the block grows. assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() / 2, WeightMultiplier::default())), - fm(-5000) + WeightMultiplierUpdateHandler::convert((target() / 2, WeightMultiplier::default())), + wm(-5000) ); // ideal. Original fee. No changes. assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() as u32, WeightMultiplier::default())), - fm(0) + WeightMultiplierUpdateHandler::convert((target(), WeightMultiplier::default())), + wm(0) ); // // More than ideal. Fee is increased. assert_eq!( - WeightMultiplierUpdateHandler::convert(((ideal() * 2) as u32, WeightMultiplier::default())), - fm(10000) + WeightMultiplierUpdateHandler::convert(((target() * 2), WeightMultiplier::default())), + wm(10000) ); } #[test] fn stateful_weight_mul_grow_to_infinity() { assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() * 2, WeightMultiplier::default())), - fm(10000) + WeightMultiplierUpdateHandler::convert((target() * 2, WeightMultiplier::default())), + wm(10000) ); assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() * 2, fm(10000))), - fm(20000) + WeightMultiplierUpdateHandler::convert((target() * 2, wm(10000))), + wm(20000) ); assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() * 2, fm(20000))), - fm(30000) + WeightMultiplierUpdateHandler::convert((target() * 2, wm(20000))), + wm(30000) ); // ... assert_eq!( - WeightMultiplierUpdateHandler::convert((ideal() * 2, fm(1_000_000_000))), - fm(1_000_000_000 + 10000) + WeightMultiplierUpdateHandler::convert((target() * 2, wm(1_000_000_000))), + wm(1_000_000_000 + 10000) ); } @@ -183,28 +257,26 @@ mod tests { fn stateful_weight_mil_collapse_to_minus_one() { assert_eq!( WeightMultiplierUpdateHandler::convert((0, WeightMultiplier::default())), - fm(-10000) + wm(-10000) ); assert_eq!( - WeightMultiplierUpdateHandler::convert((0, fm(-10000))), - fm(-20000) + WeightMultiplierUpdateHandler::convert((0, wm(-10000))), + wm(-20000) ); assert_eq!( - WeightMultiplierUpdateHandler::convert((0, fm(-20000))), - fm(-30000) + WeightMultiplierUpdateHandler::convert((0, wm(-20000))), + wm(-30000) ); // ... assert_eq!( - WeightMultiplierUpdateHandler::convert((0, fm(1_000_000_000 * -1))), - fm(-1_000_000_000) + WeightMultiplierUpdateHandler::convert((0, wm(1_000_000_000 * -1))), + wm(-1_000_000_000) ); } #[test] fn weight_to_fee_should_not_overflow_on_large_weights() { - // defensive-only test. at the moment we are not allowing any weight more than - // 4 * 1024 * 1024 in a block. - let kb = 1024_u32; + let kb = 1024 as Weight; let mb = kb * kb; let max_fm = WeightMultiplier::from_fixed(Fixed64::from_natural(i64::max_value())); @@ -214,7 +286,9 @@ mod tests { WeightMultiplierUpdateHandler::convert((i, WeightMultiplier::default())); }); - vec![10 * mb, Weight::max_value() / 2, Weight::max_value()] + // Some values that are all above the target and will cause an increase. + let t = target(); + vec![t + 100, t * 2, t * 4] .into_iter() .for_each(|i| { let fm = WeightMultiplierUpdateHandler::convert(( diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 28c89a6943974..834635a312869 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -22,7 +22,7 @@ use rstd::prelude::*; use support::{ - construct_runtime, parameter_types, traits::{SplitTwoWays, Currency, OnUnbalanced} + construct_runtime, parameter_types, traits::{SplitTwoWays, Currency} }; use substrate_primitives::u32_trait::{_1, _2, _3, _4}; use node_primitives::{ @@ -58,10 +58,13 @@ pub use runtime_primitives::{Permill, Perbill}; pub use support::StorageValue; pub use staking::StakerStatus; -/// Implementations for `Convert` and other helper structs passed into runtime modules as associated -/// types. +/// Implementations of some helper traits passed into runtime modules as associated types. pub mod impls; -use impls::{CurrencyToVoteHandler, WeightMultiplierUpdateHandler}; +use impls::{CurrencyToVoteHandler, WeightMultiplierUpdateHandler, Author, WeightToFee}; + +/// Constant values used within the runtime. +pub mod constants; +use constants::{time::*, currency::*}; // Make the WASM binary available. #[cfg(feature = "std")] @@ -76,8 +79,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 119, - impl_version: 119, + spec_version: 120, + impl_version: 120, apis: RUNTIME_API_VERSIONS, }; @@ -90,20 +93,8 @@ pub fn native_version() -> NativeVersion { } } -pub const MILLICENTS: Balance = 1_000_000_000; -pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. -pub const DOLLARS: Balance = 100 * CENTS; - type NegativeImbalance = >::NegativeImbalance; -pub struct Author; - -impl OnUnbalanced for Author { - fn on_unbalanced(amount: NegativeImbalance) { - Balances::resolve_creating(&Authorship::author(), amount); - } -} - pub type DealWithFees = SplitTwoWays< Balance, NegativeImbalance, @@ -111,15 +102,11 @@ pub type DealWithFees = SplitTwoWays< _1, Author, // 1 part (20%) goes to the block author. >; -pub const SECS_PER_BLOCK: Moment = 6; -pub const MINUTES: Moment = 60 / SECS_PER_BLOCK; -pub const HOURS: Moment = MINUTES * 60; -pub const DAYS: Moment = HOURS * 24; - parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024; - pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const MaximumBlockWeight: Weight = 1_000_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; } impl system::Trait for Runtime { @@ -136,6 +123,7 @@ impl system::Trait for Runtime { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } parameter_types! { @@ -174,6 +162,7 @@ impl balances::Trait for Runtime { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = WeightToFee; } parameter_types! { diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index 940f7cdf3f1c4..6dc5f321e41a4 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -244,7 +244,7 @@ mod tests { use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + use primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; impl_outer_origin! { pub enum Origin for Test {} @@ -259,6 +259,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -273,6 +274,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } impl Trait for Test { diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index 4348f6af2da4e..42f06b564f526 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -19,7 +19,7 @@ #![cfg(test)] use primitives::{ - traits::IdentityLookup, + traits::IdentityLookup, Perbill, testing::{Header, UintAuthorityId}, }; use srml_support::{impl_outer_origin, parameter_types}; @@ -39,6 +39,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(); pub const MinimumPeriod: u64 = 1; } @@ -55,6 +56,7 @@ impl system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } diff --git a/srml/authorship/src/lib.rs b/srml/authorship/src/lib.rs index 50b27f83f6694..39a3e8000a463 100644 --- a/srml/authorship/src/lib.rs +++ b/srml/authorship/src/lib.rs @@ -28,6 +28,7 @@ use srml_support::dispatch::Result as DispatchResult; use parity_codec::{Encode, Decode}; use system::ensure_none; use primitives::traits::{SimpleArithmetic, Header as HeaderT, One, Zero}; +use primitives::weights::SimpleDispatchInfo; pub trait Trait: system::Trait { /// Find the author of a block. @@ -217,6 +218,7 @@ decl_module! { } /// Provide a set of uncles. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_uncles(origin, new_uncles: Vec) -> DispatchResult { ensure_none(origin)?; @@ -326,6 +328,7 @@ mod tests { use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::Header; use primitives::generic::DigestItem; + use primitives::Perbill; use srml_support::{parameter_types, impl_outer_origin, ConsensusEngineId}; impl_outer_origin!{ @@ -339,6 +342,7 @@ mod tests { 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 Test { @@ -354,6 +358,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 48960f1e544eb..cde3fa2d16cfb 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -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: system::Trait { /// The fee to be paid for making a transaction; the per-byte portion. type TransactionByteFee: Get; + + /// Convert a weight value into a deductible fee based on the currency type. + type WeightToFee: Convert; } pub trait Trait: system::Trait { @@ -249,6 +252,9 @@ pub trait Trait: system::Trait { /// The fee to be paid for making a transaction; the per-byte portion. type TransactionByteFee: Get; + + /// Convert a weight value into a deductible fee based on the currency type. + type WeightToFee: Convert; } impl, I: Instance> Subtrait for T { @@ -260,6 +266,7 @@ impl, I: Instance> Subtrait 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 = SimpleDispatchInfo::FixedNormal(1_000_000)] pub fn transfer( origin, dest: ::Source, @@ -451,6 +459,7 @@ decl_module! { /// - Independent of the arguments. /// - Contains a limited number of reads and writes. /// # + #[weight = SimpleDispatchInfo::FixedOperational(500_000)] fn set_balance( origin, who: ::Source, @@ -766,6 +775,7 @@ impl, I: Instance> system::Trait for ElevatedTrait { type BlockHashCount = T::BlockHashCount; type MaximumBlockWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; + type AvailableBlockRatio = T::AvailableBlockRatio; } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; @@ -780,6 +790,7 @@ impl, I: Instance> Trait for ElevatedTrait { type CreationFee = T::CreationFee; type TransactionBaseFee = T::TransactionBaseFee; type TransactionByteFee = T::TransactionByteFee; + type WeightToFee = T::WeightToFee; } impl, I: Instance> Currency for Module @@ -1171,19 +1182,23 @@ impl, I: Instance> TakeFees { /// - (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 = >::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(::MaximumBlockWeight::get()); + let weight_update = >::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) } diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index fecec82180d89..116515c368f53 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -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 = RefCell::new(0); static TRANSACTION_BASE_FEE: RefCell = RefCell::new(0); static TRANSACTION_BYTE_FEE: RefCell = RefCell::new(1); + static TRANSACTION_WEIGHT_FEE: RefCell = RefCell::new(1); + static WEIGHT_TO_FEE: RefCell = RefCell::new(1); } pub struct ExistentialDeposit; @@ -63,6 +65,13 @@ impl Get for TransactionByteFee { fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) } } +pub struct WeightToFee(u64); +impl Convert 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 { self.set_associated_consts(); diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 2828d40e63ff8..595be0e1ca603 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -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::::from(0).pre_dispatch(&1, info_from_weight(0), len).is_ok()); - assert_eq!(Balances::free_balance(&1), 100 - 20); - assert!(TakeFees::::from(5 /* tipped */).pre_dispatch(&1, info_from_weight(0), len).is_ok()); + assert!(TakeFees::::from(0).pre_dispatch(&1, info_from_weight(5), len).is_ok()); assert_eq!(Balances::free_balance(&1), 100 - 20 - 25); + assert!(TakeFees::::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::::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 - ::MaximumBlockWeight::get()) as u64 + ); } ); } diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index d729b8a300f7a..b05b69db77c83 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -23,6 +23,7 @@ use rstd::{prelude::*, result}; use substrate_primitives::u32_trait::Value as U32; use primitives::traits::{Hash, EnsureOrigin}; +use primitives::weights::SimpleDispatchInfo; use srml_support::{ dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure @@ -118,6 +119,9 @@ decl_event!( } ); +// Note: this module is not benchmarked. The weights are obtained based on the similarity fo the +// executed logic with other democracy function. Note that councillor operations are assigned to the +// operational class. decl_module! { pub struct Module, I: Instance=DefaultInstance> for enum Call where origin: ::Origin { fn deposit_event() = default; @@ -126,6 +130,7 @@ decl_module! { /// provide it pre-sorted. /// /// Requires root origin. + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] fn set_members(origin, new_members: Vec) { ensure_root(origin)?; @@ -168,6 +173,7 @@ decl_module! { /// Dispatch a proposal from a member using the `Member` origin. /// /// Origin must be a member of the collective. + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] fn execute(origin, proposal: Box<>::Proposal>) { let who = ensure_signed(origin)?; ensure!(Self::is_member(&who), "proposer not a member"); @@ -181,9 +187,9 @@ decl_module! { /// - Bounded storage reads and writes. /// - Argument `threshold` has bearing on weight. /// # + #[weight = SimpleDispatchInfo::FixedOperational(5_000_000)] fn propose(origin, #[compact] threshold: MemberCount, proposal: Box<>::Proposal>) { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), "proposer not a member"); let proposal_hash = T::Hashing::hash_of(&proposal); @@ -210,9 +216,9 @@ decl_module! { /// - Bounded storage read and writes. /// - Will be slightly heavier if the proposal is approved / disapproved after the vote. /// # + #[weight = SimpleDispatchInfo::FixedOperational(200_000)] fn vote(origin, proposal: T::Hash, #[compact] index: ProposalIndex, approve: bool) { let who = ensure_signed(origin)?; - ensure!(Self::is_member(&who), "voter not a member"); let mut voting = Self::voting(&proposal).ok_or("proposal must exist")?; @@ -393,7 +399,7 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::{ - traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage + Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage }; use crate as collective; @@ -401,6 +407,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -416,6 +423,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } impl Trait for Test { type Origin = Origin; @@ -554,7 +562,7 @@ mod tests { event: Event::collective_Instance1(RawEvent::Proposed( 1, 0, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 3, )), topics: vec![], @@ -622,7 +630,7 @@ mod tests { event: Event::collective_Instance1(RawEvent::Proposed( 1, 0, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 2, )), topics: vec![], @@ -631,7 +639,7 @@ mod tests { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Voted( 1, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), false, 0, 1, @@ -658,7 +666,7 @@ mod tests { RawEvent::Proposed( 1, 0, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 3, )), topics: vec![], @@ -667,7 +675,7 @@ mod tests { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Voted( 2, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), false, 1, 1, @@ -677,7 +685,7 @@ mod tests { EventRecord { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Disapproved( - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), )), topics: vec![], } @@ -700,7 +708,7 @@ mod tests { event: Event::collective_Instance1(RawEvent::Proposed( 1, 0, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), 2, )), topics: vec![], @@ -709,7 +717,7 @@ mod tests { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Voted( 2, - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), true, 2, 0, @@ -719,14 +727,14 @@ mod tests { EventRecord { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Approved( - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), )), topics: vec![], }, EventRecord { phase: Phase::Finalization, event: Event::collective_Instance1(RawEvent::Executed( - hex!["10b209e55d0f37cd45574674bba42519a29bf0ccf3c85c3c773fcbacab820bb4"].into(), + hex!["68eea8f20b542ec656c6ac2d10435ae3bd1729efc34d1354ab85af840aad2d35"].into(), false, )), topics: vec![], diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index 3af81d8d84194..db196ef7fe779 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -31,7 +31,7 @@ use runtime_io; use runtime_io::with_externalities; use runtime_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, H256}; use runtime_primitives::traits::{BlakeTwo256, Hash, IdentityLookup}; -use runtime_primitives::BuildStorage; +use runtime_primitives::{Perbill, BuildStorage}; use srml_support::{ assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, storage::child, StorageMap, StorageValue, traits::{Currency, Get}, @@ -100,6 +100,7 @@ parameter_types! { pub const MaximumBlockLength: u32 = 2 * 1024; pub const BalancesTransactionBaseFee: u64 = 0; pub const BalancesTransactionByteFee: u64 = 0; + pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { type Origin = Origin; @@ -114,6 +115,7 @@ impl system::Trait for Test { type Event = MetaEvent; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } impl balances::Trait for Test { @@ -129,6 +131,7 @@ impl balances::Trait for Test { type CreationFee = CreationFee; type TransactionBaseFee = BalancesTransactionBaseFee; type TransactionByteFee = BalancesTransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const MinimumPeriod: u64 = 1; diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 0ebf50ce16508..3fc9926942e70 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -44,6 +44,7 @@ mod tests { pub use substrate_primitives::{H256, Blake2Hasher, u32_trait::{_1, _2, _3, _4}}; pub use primitives::traits::{BlakeTwo256, IdentityLookup}; pub use primitives::testing::{Digest, DigestItem, Header}; + pub use primitives::Perbill; pub use {seats, motions}; use std::cell::RefCell; @@ -100,6 +101,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -115,6 +117,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } parameter_types! { pub const ExistentialDeposit: u64 = 0; @@ -136,6 +139,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const LaunchPeriod: u64 = 1; diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index cb7f665b30cc5..1736d8a97e58c 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -21,6 +21,7 @@ use rstd::prelude::*; use rstd::{result, convert::TryFrom}; use primitives::traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash}; +use primitives::weights::SimpleDispatchInfo; use parity_codec::{Encode, Decode, Input, Output}; use srml_support::{ decl_module, decl_storage, decl_event, ensure, @@ -359,6 +360,7 @@ decl_module! { /// - O(1). /// - Two DB changes, one DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] fn propose(origin, proposal: Box, #[compact] value: BalanceOf @@ -386,6 +388,7 @@ decl_module! { /// - O(1). /// - One DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] fn second(origin, #[compact] proposal: PropIndex) { let who = ensure_signed(origin)?; let mut deposit = Self::deposit_of(proposal) @@ -403,6 +406,7 @@ decl_module! { /// - O(1). /// - One DB change, one DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] fn vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote @@ -418,6 +422,7 @@ decl_module! { /// - O(1). /// - One DB change, one DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] fn proxy_vote(origin, #[compact] ref_index: ReferendumIndex, vote: Vote @@ -432,6 +437,7 @@ decl_module! { /// exceed `threshold` and, if approved, enacted after the given `delay`. /// /// It may be called from either the Root or the Emergency origin. + #[weight = SimpleDispatchInfo::FixedOperational(500_000)] fn emergency_propose(origin, proposal: Box, threshold: VoteThreshold, @@ -453,6 +459,7 @@ decl_module! { /// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same /// referendum. + #[weight = SimpleDispatchInfo::FixedOperational(500_000)] fn emergency_cancel(origin, ref_index: ReferendumIndex) { T::CancellationOrigin::ensure_origin(origin)?; @@ -466,6 +473,7 @@ decl_module! { /// Schedule a referendum to be tabled once it is legal to schedule an external /// referendum. + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] fn external_propose(origin, proposal: Box) { T::ExternalOrigin::ensure_origin(origin)?; ensure!(!>::exists(), "proposal already made"); @@ -478,6 +486,7 @@ decl_module! { /// Schedule a majority-carries referendum to be tabled next once it is legal to schedule /// an external referendum. + #[weight = SimpleDispatchInfo::FixedNormal(5_000_000)] fn external_propose_majority(origin, proposal: Box) { T::ExternalMajorityOrigin::ensure_origin(origin)?; ensure!(!>::exists(), "proposal already made"); @@ -496,6 +505,7 @@ decl_module! { /// - `voting_period`: The period that is allowed for voting on this proposal. /// - `delay`: The number of block after voting has ended in approval and this should be /// enacted. Increased to `EmergencyVotingPeriod` if too low. + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] fn external_push(origin, proposal_hash: T::Hash, voting_period: T::BlockNumber, @@ -514,6 +524,7 @@ decl_module! { } /// Veto and blacklist the external proposal hash. + #[weight = SimpleDispatchInfo::FixedNormal(200_000)] fn veto_external(origin, proposal_hash: T::Hash) { let who = T::VetoOrigin::ensure_origin(origin)?; @@ -538,12 +549,14 @@ decl_module! { } /// Remove a referendum. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn cancel_referendum(origin, #[compact] ref_index: ReferendumIndex) { ensure_root(origin)?; Self::clear_referendum(ref_index); } /// Cancel a proposal queued for enactment. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn cancel_queued( origin, #[compact] when: T::BlockNumber, @@ -572,6 +585,7 @@ decl_module! { /// # /// - One extra DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] fn set_proxy(origin, proxy: T::AccountId) { let who = ensure_signed(origin)?; ensure!(!>::exists(&proxy), "already a proxy"); @@ -583,6 +597,7 @@ decl_module! { /// # /// - One DB clear. /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] fn resign_proxy(origin) { let who = ensure_signed(origin)?; >::remove(who); @@ -593,6 +608,7 @@ decl_module! { /// # /// - One DB clear. /// # + #[weight = SimpleDispatchInfo::FixedNormal(100_000)] fn remove_proxy(origin, proxy: T::AccountId) { let who = ensure_signed(origin)?; ensure!(&Self::proxy(&proxy).ok_or("not a proxy")? == &who, "wrong proxy"); @@ -604,6 +620,7 @@ decl_module! { /// # /// - One extra DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] pub fn delegate(origin, to: T::AccountId, conviction: Conviction) { let who = ensure_signed(origin)?; >::insert(who.clone(), (to.clone(), conviction)); @@ -623,6 +640,7 @@ decl_module! { /// # /// - O(1). /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn undelegate(origin) { let who = ensure_signed(origin)?; ensure!(>::exists(&who), "not delegated"); @@ -974,6 +992,7 @@ mod tests { }; use substrate_primitives::{H256, Blake2Hasher}; use primitives::{traits::{BlakeTwo256, IdentityLookup, Bounded}, testing::Header}; + use primitives::Perbill; use balances::BalanceLock; use system::EnsureSignedBy; @@ -1000,6 +1019,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -1015,6 +1035,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } parameter_types! { pub const ExistentialDeposit: u64 = 0; @@ -1036,6 +1057,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const LaunchPeriod: u64 = 2; diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index 9960ef22b70ab..8a681fa1458cc 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -25,6 +25,7 @@ use rstd::prelude::*; use primitives::traits::{Zero, One, StaticLookup, Bounded, Saturating}; +use primitives::weights::SimpleDispatchInfo; use runtime_io::print; use srml_support::{ StorageValue, StorageMap, @@ -331,6 +332,7 @@ decl_module! { /// - Two extra DB entries, one DB change. /// - Argument `votes` is limited in length to number of candidates. /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] fn set_approvals(origin, votes: Vec, #[compact] index: VoteIndex, hint: SetIndex) -> Result { let who = ensure_signed(origin)?; Self::do_set_approvals(who, votes, index, hint) @@ -342,6 +344,7 @@ decl_module! { /// # /// - Same as `set_approvals` with one additional storage read. /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] fn proxy_set_approvals(origin, votes: Vec, #[compact] index: VoteIndex, @@ -363,6 +366,7 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] fn reap_inactive_voter( origin, #[compact] reporter_index: u32, @@ -436,6 +440,7 @@ decl_module! { /// - O(1). /// - Two fewer DB entries, one DB change. /// # + #[weight = SimpleDispatchInfo::FixedNormal(1_250_000)] fn retract_voter(origin, #[compact] index: u32) { let who = ensure_signed(origin)?; @@ -463,6 +468,7 @@ decl_module! { /// - Independent of input. /// - Three DB changes. /// # + #[weight = SimpleDispatchInfo::FixedNormal(2_500_000)] fn submit_candidacy(origin, #[compact] slot: u32) { let who = ensure_signed(origin)?; @@ -498,6 +504,7 @@ decl_module! { /// - O(voters) compute. /// - One DB change. /// # + #[weight = SimpleDispatchInfo::FixedNormal(10_000_000)] fn present_winner( origin, candidate: ::Source, @@ -566,6 +573,7 @@ decl_module! { /// Set the desired member count; if lower than the current count, then seats will not be up /// election when they expire. If more, then a new vote will be started if one is not /// already in progress. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_desired_seats(origin, #[compact] count: u32) { ensure_root(origin)?; DesiredSeats::put(count); @@ -575,6 +583,7 @@ decl_module! { /// /// Note: A tally should happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn remove_member(origin, who: ::Source) { ensure_root(origin)?; let who = T::Lookup::lookup(who)?; @@ -589,6 +598,7 @@ decl_module! { /// Set the presentation duration. If there is currently a vote being presented for, will /// invoke `finalize_vote`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_presentation_duration(origin, #[compact] count: T::BlockNumber) { ensure_root(origin)?; >::put(count); @@ -596,6 +606,7 @@ decl_module! { /// Set the presentation duration. If there is current a vote being presented for, will /// invoke `finalize_vote`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_term_duration(origin, #[compact] count: T::BlockNumber) { ensure_root(origin)?; >::put(count); @@ -1107,7 +1118,7 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::{ - traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage + Perbill, traits::{BlakeTwo256, IdentityLookup, Block as BlockT}, testing::Header, BuildStorage }; use crate as elections; @@ -1115,6 +1126,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -1130,6 +1142,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } parameter_types! { pub const ExistentialDeposit: u64 = 0; @@ -1151,6 +1164,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const CandidacyBond: u64 = 3; diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index a64cfc0af090e..68b52425ed007 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -510,7 +510,7 @@ mod tests { // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are requried. use sr_primitives::{ - traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, testing::Header + Perbill, traits::{BlakeTwo256, OnInitialize, OnFinalize, IdentityLookup}, testing::Header }; impl_outer_origin! { @@ -526,6 +526,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -541,6 +542,7 @@ mod tests { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } parameter_types! { pub const ExistentialDeposit: u64 = 0; @@ -562,6 +564,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } impl Trait for Test { type Event = (); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 326c3d7ab95d9..9ae794d698b55 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -108,6 +108,7 @@ mod internal { fn from(d: DispatchError) -> Self { match d { DispatchError::Payment => ApplyError::CantPay, + DispatchError::Resource => ApplyError::FullBlock, DispatchError::NoPermission => ApplyError::CantPay, DispatchError::BadState => ApplyError::CantPay, DispatchError::Stale => ApplyError::Stale, @@ -357,10 +358,12 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::generic::Era; - use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}; + use primitives::Perbill; + use primitives::weights::Weight; + use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}; use primitives::testing::{Digest, Header, Block}; use srml_support::{impl_outer_event, impl_outer_origin, parameter_types}; - use srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason, Get}; + use srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}; use system; use hex_literal::hex; @@ -382,6 +385,7 @@ mod tests { 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; @@ -396,6 +400,7 @@ mod tests { type BlockHashCount = BlockHashCount; type WeightMultiplierUpdate = (); type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } parameter_types! { @@ -418,6 +423,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; } impl ValidateUnsigned for Runtime { @@ -457,7 +463,7 @@ mod tests { fn balance_transfer_dispatch_works() { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); balances::GenesisConfig:: { - balances: vec![(1, 111)], + balances: vec![(1, 211)], vesting: vec![], }.assimilate_storage(&mut t.0, &mut t.1).unwrap(); let xt = primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer(2, 69)); @@ -473,7 +479,7 @@ mod tests { )); let r = Executive::apply_extrinsic(xt); assert_eq!(r, Ok(ApplyOutcome::Success)); - assert_eq!(>::total_balance(&1), 42 - 10 - weight); + assert_eq!(>::total_balance(&1), 142 - 10 - weight); assert_eq!(>::total_balance(&2), 69); }); } @@ -561,8 +567,8 @@ mod tests { // given: TestXt uses the encoded len as fixed Len: let xt = primitives::testing::TestXt(sign_extra(1, 0, 0), Call::transfer::(33, 0)); let encoded = xt.encode(); - let encoded_len = encoded.len() as u32; - let limit = >::get() / 4; + let encoded_len = encoded.len() as Weight; + let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get(); let num_to_exhaust_block = limit / encoded_len; with_externalities(&mut t, || { Executive::initialize_block(&Header::new( @@ -580,9 +586,9 @@ mod tests { if nonce != num_to_exhaust_block { assert_eq!(res.unwrap(), ApplyOutcome::Success); assert_eq!(>::all_extrinsics_weight(), encoded_len * (nonce + 1)); - assert_eq!(>::extrinsic_index(), Some(nonce + 1)); + assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { - assert_eq!(res, Err(ApplyError::CantPay)); + assert_eq!(res, Err(ApplyError::FullBlock)); } } }); @@ -604,7 +610,7 @@ mod tests { assert_eq!(Executive::apply_extrinsic(x2.clone()).unwrap(), ApplyOutcome::Success); // default weight for `TestXt` == encoded length. - assert_eq!( >::all_extrinsics_weight(), 3 * len); + assert_eq!(>::all_extrinsics_weight(), (3 * len).into()); assert_eq!(>::all_extrinsics_len(), 3 * len); let _ = >::finalize(); diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 38377f35006ef..d59183a166fae 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -268,6 +268,7 @@ mod tests { use substrate_primitives::H256; use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}; use primitives::testing::Header; + use primitives::Perbill; use srml_support::{assert_ok, impl_outer_origin, parameter_types}; use srml_system as system; use std::cell::RefCell; @@ -301,6 +302,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -315,6 +317,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } parameter_types! { diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index 60947e68eb007..8a4e47180c3f1 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -1058,6 +1058,7 @@ impl system::Trait for ElevatedTrait { type Event = (); type MaximumBlockWeight = T::MaximumBlockWeight; type MaximumBlockLength = T::MaximumBlockLength; + type AvailableBlockRatio = T::AvailableBlockRatio; type WeightMultiplierUpdate = (); type BlockHashCount = T::BlockHashCount; } diff --git a/srml/generic-asset/src/mock.rs b/srml/generic-asset/src/mock.rs index fb7fc04caa682..9437b06d203cf 100644 --- a/srml/generic-asset/src/mock.rs +++ b/srml/generic-asset/src/mock.rs @@ -20,10 +20,7 @@ #![cfg(test)] -use primitives::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; +use primitives::{Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}}; use substrate_primitives::{Blake2Hasher, H256}; use support::{parameter_types, impl_outer_event, impl_outer_origin}; @@ -42,6 +39,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 Test { type Origin = Origin; @@ -53,9 +51,10 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; + type WeightMultiplierUpdate = (); type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; - type WeightMultiplierUpdate = (); + type AvailableBlockRatio = AvailableBlockRatio; type BlockHashCount = BlockHashCount; } diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index 87845a7a4d05f..9abb12b15ba23 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -18,7 +18,7 @@ #![cfg(test)] -use primitives::{DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; +use primitives::{Perbill, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; use runtime_io; use srml_support::{impl_outer_origin, impl_outer_event, parameter_types}; use substrate_primitives::{H256, Blake2Hasher}; @@ -45,6 +45,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 Test { type Origin = Origin; @@ -60,6 +61,7 @@ impl system::Trait for Test { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } mod grandpa { diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs index 151a5186f79b6..d1ce8dbe2a087 100644 --- a/srml/indices/src/mock.rs +++ b/srml/indices/src/mock.rs @@ -21,6 +21,7 @@ use std::collections::HashSet; use ref_thread_local::{ref_thread_local, RefThreadLocal}; use primitives::testing::Header; +use primitives::Perbill; use substrate_primitives::{H256, Blake2Hasher}; use srml_support::{impl_outer_origin, parameter_types}; use {runtime_io, system}; @@ -68,6 +69,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; @@ -83,6 +85,7 @@ impl system::Trait for Runtime { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } impl Trait for Runtime { type AccountIndex = u64; diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index d425c44e2eb50..8589f92006d88 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -122,6 +122,7 @@ use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; use parity_codec::Decode; use primitives::KeyTypeId; +use primitives::weights::SimpleDispatchInfo; use primitives::traits::{Convert, Zero, Member, OpaqueKeys, TypedKey}; use srml_support::{ dispatch::Result, ConsensusEngineId, StorageValue, StorageDoubleMap, for_each_tuple, @@ -378,6 +379,7 @@ decl_module! { /// - O(log n) in number of accounts. /// - One extra DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(150_000)] fn set_keys(origin, keys: T::Keys, proof: Vec) -> Result { let who = ensure_signed(origin)?; diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs index b5cb7e4278fc7..5c2711e971ac1 100644 --- a/srml/session/src/mock.rs +++ b/srml/session/src/mock.rs @@ -21,6 +21,7 @@ use std::cell::RefCell; use srml_support::{impl_outer_origin, parameter_types}; use substrate_primitives::H256; use primitives::{ + Perbill, traits::{BlakeTwo256, IdentityLookup, ConvertInto}, testing::{Header, UintAuthorityId} }; @@ -116,6 +117,7 @@ parameter_types! { pub const MaximumBlockWeight: u32 = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const MinimumPeriod: u64 = 5; + pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { type Origin = Origin; @@ -130,6 +132,7 @@ impl system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } impl timestamp::Trait for Test { diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index cd3c8d7862f40..dbf32ca5bd750 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -294,6 +294,7 @@ use srml_support::{ }; use session::{historical::OnSessionEnding, SelectInitialValidators, SessionIndex}; use primitives::Perbill; +use primitives::weights::SimpleDispatchInfo; use primitives::traits::{ Convert, Zero, One, StaticLookup, CheckedSub, CheckedShl, Saturating, Bounded, SaturatedConversion, SimpleArithmetic @@ -696,6 +697,7 @@ decl_module! { /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned unless /// the `origin` falls below _existential deposit_ and gets removed as dust. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn bond(origin, controller: ::Source, #[compact] value: BalanceOf, @@ -743,6 +745,7 @@ decl_module! { /// - O(1). /// - One DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn bond_extra(origin, #[compact] max_additional: BalanceOf) { let stash = ensure_signed(origin)?; @@ -782,6 +785,7 @@ decl_module! { /// The only way to clean the aforementioned storage item is also user-controlled via `withdraw_unbonded`. /// - One DB entry. /// + #[weight = SimpleDispatchInfo::FixedNormal(400_000)] fn unbond(origin, #[compact] value: BalanceOf) { let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -823,6 +827,7 @@ decl_module! { /// - Contains a limited number of reads, yet the size of which could be large based on `ledger`. /// - Writes are limited to the `origin` account key. /// # + #[weight = SimpleDispatchInfo::FixedNormal(400_000)] fn withdraw_unbonded(origin) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -854,6 +859,7 @@ decl_module! { /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] fn validate(origin, prefs: ValidatorPrefs>) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -877,6 +883,7 @@ decl_module! { /// which is capped at `MAX_NOMINATIONS`. /// - Both the reads and writes follow a similar pattern. /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] fn nominate(origin, targets: Vec<::Source>) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -902,6 +909,7 @@ decl_module! { /// - Contains one read. /// - Writes are limited to the `origin` account key. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn chill(origin) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -921,6 +929,7 @@ decl_module! { /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn set_payee(origin, payee: RewardDestination) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or("not a controller")?; @@ -939,6 +948,7 @@ decl_module! { /// - Contains a limited number of reads. /// - Writes are limited to the `origin` account key. /// # + #[weight = SimpleDispatchInfo::FixedNormal(750_000)] fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or("not a stash")?; @@ -955,6 +965,7 @@ decl_module! { } /// The ideal number of validators. + #[weight = SimpleDispatchInfo::FixedOperational(150_000)] fn set_validator_count(origin, #[compact] new: u32) { ensure_root(origin)?; ValidatorCount::put(new); @@ -970,18 +981,21 @@ decl_module! { /// - Triggers the Phragmen election. Expensive but not user-controlled. /// - Depends on state: `O(|edges| * |validators|)`. /// # + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn force_new_era(origin) { ensure_root(origin)?; Self::apply_force_new_era() } /// Set the offline slash grace period. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_offline_slash_grace(origin, #[compact] new: u32) { ensure_root(origin)?; OfflineSlashGrace::put(new); } /// Set the validators who cannot be slashed (if any). + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_invulnerables(origin, validators: Vec) { ensure_root(origin)?; >::put(validators); diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index a1548a00807d6..426ba680a9e1e 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -104,6 +104,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 Test { type Origin = Origin; @@ -118,6 +119,7 @@ impl system::Trait for Test { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } parameter_types! { @@ -139,6 +141,7 @@ impl balances::Trait for Test { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const Period: BlockNumber = 1; diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index a421bdae68a52..65a15b4abfb03 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -88,6 +88,7 @@ use sr_std::prelude::*; use sr_primitives::traits::StaticLookup; +use sr_primitives::weights::SimpleDispatchInfo; use srml_support::{ StorageValue, Parameter, Dispatchable, decl_module, decl_event, decl_storage, ensure @@ -116,6 +117,7 @@ decl_module! { /// - Limited storage reads. /// - No DB writes. /// # + #[weight = SimpleDispatchInfo::FixedOperational(1_000_000)] fn sudo(origin, proposal: Box) { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 7afbd11cd1d0d..1e0556731e1a2 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -1622,7 +1622,7 @@ mod tests { fn aux_0(_origin) -> Result { unreachable!() } fn aux_1(_origin, #[compact] _data: u32) -> Result { unreachable!() } fn aux_2(_origin, _data: i32, _data2: String) -> Result { unreachable!() } - #[weight = SimpleDispatchInfo::FixedNormal(10)] + #[weight = SimpleDispatchInfo::FixedNormal(3)] fn aux_3(_origin) -> Result { unreachable!() } fn aux_4(_origin, _data: i32) -> Result { unreachable!() } fn aux_5(_origin, _data: i32, #[compact] _data2: u32) -> Result { unreachable!() } @@ -1772,7 +1772,7 @@ mod tests { #[test] fn weight_should_attach_to_call_enum() { - // max weight. not dependent on input. + // operational. assert_eq!( Call::::operational().get_dispatch_info(), DispatchInfo { weight: 5, class: DispatchClass::Operational }, @@ -1780,12 +1780,12 @@ mod tests { // default weight. assert_eq!( Call::::aux_0().get_dispatch_info(), - DispatchInfo { weight: 100, class: DispatchClass::Normal }, + DispatchInfo { weight: 10_000, class: DispatchClass::Normal }, ); // custom basic assert_eq!( Call::::aux_3().get_dispatch_info(), - DispatchInfo { weight: 10, class: DispatchClass::Normal }, + DispatchInfo { weight: 3, class: DispatchClass::Normal }, ); } } diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 96101c44d7f9e..e504726703d32 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -223,6 +223,37 @@ macro_rules! __assert_eq_uvec { } } +/// Checks that `$x` is equal to `$y` with an error rate of `$error`. +/// +/// # Example +/// +/// ```rust +/// # fn main() { +/// srml_support::assert_eq_error_rate!(10, 10, 0); +/// srml_support::assert_eq_error_rate!(10, 11, 1); +/// srml_support::assert_eq_error_rate!(12, 10, 2); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// # fn main() { +/// srml_support::assert_eq_error_rate!(12, 10, 1); +/// # } +/// ``` +#[macro_export] +#[cfg(feature = "std")] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + /// The void type - it cannot exist. // Oh rust, you crack me up... #[derive(Clone, Eq, PartialEq)] diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs index 5ff63baa1cdb4..071446ea355f7 100644 --- a/srml/system/benches/bench.rs +++ b/srml/system/benches/bench.rs @@ -19,10 +19,7 @@ use srml_system as system; use srml_support::{decl_module, decl_event, impl_outer_origin, impl_outer_event}; use runtime_io::{with_externalities, Blake2Hasher}; use substrate_primitives::H256; -use primitives::{ - traits::{BlakeTwo256, IdentityLookup}, - testing::Header, -}; +use primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; mod module { use super::*; @@ -58,6 +55,7 @@ srml_support::parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: u32 = 4 * 1024 * 1024; pub const MaximumBlockLength: u32 = 4 * 1024 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } #[derive(Clone, Eq, PartialEq)] pub struct Runtime; @@ -75,6 +73,7 @@ impl system::Trait for Runtime { type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; } impl module::Trait for Runtime { diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index bd1f76299e49c..e98c53bf1d533 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -78,7 +78,8 @@ use rstd::prelude::*; use rstd::map; use rstd::marker::PhantomData; use primitives::generic::{self, Era}; -use primitives::weights::{Weight, DispatchInfo, DispatchClass, WeightMultiplier}; +use primitives::Perbill; +use primitives::weights::{Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo}; use primitives::transaction_validity::{ValidTransaction, TransactionPriority, TransactionLongevity}; use primitives::traits::{self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash, @@ -203,6 +204,12 @@ pub trait Trait: 'static + Eq + Clone { /// The maximum length of a block (in bytes). type MaximumBlockLength: Get; + + /// The portion of the block that is available to normal transaction. The rest can only be used + /// by operational transactions. This can be applied to any resource limit managed by the system + /// module, including weight and length. + type AvailableBlockRatio: Get; + } pub type DigestOf = generic::Digest<::Hash>; @@ -218,24 +225,35 @@ decl_module! { Self::deposit_event_indexed(&[], event); } + /// A big dispatch that will disallow any other transaction to be included. + // TODO: this must be preferable available for testing really (not possible at the moment). + #[weight = SimpleDispatchInfo::MaxOperational] + fn fill_block(origin) { + ensure_root(origin)?; + } + /// Make some on-chain remark. + #[weight = SimpleDispatchInfo::FixedNormal(1_000_000)] fn remark(origin, _remark: Vec) { ensure_signed(origin)?; } /// Set the number of pages in the WebAssembly environment's heap. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_heap_pages(origin, pages: u64) { ensure_root(origin)?; storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); } /// Set the new code. + #[weight = SimpleDispatchInfo::FixedOperational(200_000)] pub fn set_code(origin, new: Vec) { ensure_root(origin)?; storage::unhashed::put_raw(well_known_keys::CODE, &new); } /// Set some items of storage. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set_storage(origin, items: Vec) { ensure_root(origin)?; for i in &items { @@ -244,6 +262,7 @@ decl_module! { } /// Kill some items from storage. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn kill_storage(origin, keys: Vec) { ensure_root(origin)?; for key in &keys { @@ -792,26 +811,28 @@ pub struct CheckWeight(PhantomData); impl CheckWeight { - /// Get the quota divisor of each dispatch class type. This indicates that all operational + /// Get the quota ratio of each dispatch class type. This indicates that all operational /// dispatches can use the full capacity of any resource, while user-triggered ones can consume - /// a quarter. - fn get_dispatch_limit_divisor(class: DispatchClass) -> Weight { + /// a portion. + fn get_dispatch_limit_ratio(class: DispatchClass) -> Perbill { match class { - DispatchClass::Operational => 1, - DispatchClass::Normal => 4, + DispatchClass::Operational => Perbill::one(), + // TODO: this must be some sort of a constant. + DispatchClass::Normal => T::AvailableBlockRatio::get(), } } + /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. fn check_weight(info: DispatchInfo) -> Result { let current_weight = Module::::all_extrinsics_weight(); let maximum_weight = T::MaximumBlockWeight::get(); - let limit = maximum_weight / Self::get_dispatch_limit_divisor(info.class); + let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; let added_weight = info.weight.min(limit); let next_weight = current_weight.saturating_add(added_weight); if next_weight > limit { - return Err(DispatchError::BadState) + return Err(DispatchError::Resource) } Ok(next_weight) } @@ -822,11 +843,11 @@ impl CheckWeight { fn check_block_length(info: DispatchInfo, len: usize) -> Result { let current_len = Module::::all_extrinsics_len(); let maximum_len = T::MaximumBlockLength::get(); - let limit = maximum_len / Self::get_dispatch_limit_divisor(info.class); + let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; let added_len = len as u32; let next_len = current_len.saturating_add(added_len); if next_len > limit { - return Err(DispatchError::BadState) + return Err(DispatchError::Resource) } Ok(next_len) } @@ -872,8 +893,8 @@ impl SignedExtension for CheckWeight { len: usize, ) -> Result { // There is no point in writing to storage here since changes are discarded. This basically - // discards any transaction which is bigger than the length or weight limit alone, which is - // a guarantee that it will fail in the pre-dispatch phase. + // discards any transaction which is bigger than the length or weight limit **alone**,which + // is a guarantee that it will fail in the pre-dispatch phase. let _ = Self::check_block_length(info, len)?; let _ = Self::check_weight(info)?; Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) @@ -1035,7 +1056,8 @@ mod tests { parameter_types! { pub const BlockHashCount: u64 = 10; pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 1024; } impl Trait for Test { @@ -1051,6 +1073,7 @@ mod tests { type Event = u16; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } @@ -1069,6 +1092,14 @@ mod tests { GenesisConfig::default().build_storage::().unwrap().0.into() } + fn normal_weight_limit() -> Weight { + ::AvailableBlockRatio::get() * ::MaximumBlockWeight::get() + } + + fn normal_length_limit() -> u32 { + ::AvailableBlockRatio::get() * ::MaximumBlockLength::get() + } + #[test] fn origin_works() { let o = Origin::from(RawOrigin::::Signed(1u64)); @@ -1222,15 +1253,16 @@ mod tests { } #[test] - fn signed_ext_check_weight_works_user_tx() { + fn signed_ext_check_weight_works_normal_tx() { with_externalities(&mut new_test_ext(), || { + let normal_limit = normal_weight_limit(); let small = DispatchInfo { weight: 100, ..Default::default() }; let medium = DispatchInfo { - weight: >::get() / 4 - 1, + weight: normal_limit - 1, ..Default::default() }; let big = DispatchInfo { - weight: >::get() / 4 + 1, + weight: normal_limit + 1, ..Default::default() }; let len = 0_usize; @@ -1265,11 +1297,12 @@ mod tests { with_externalities(&mut new_test_ext(), || { let max = DispatchInfo { weight: Weight::max_value(), ..Default::default() }; let len = 0_usize; + let normal_limit = normal_weight_limit(); assert_eq!(System::all_extrinsics_weight(), 0); let r = CheckWeight::(PhantomData).pre_dispatch(&1, max, len); assert!(r.is_ok()); - assert_eq!(System::all_extrinsics_weight(), >::get() / 4); + assert_eq!(System::all_extrinsics_weight(), normal_limit); }) } @@ -1279,9 +1312,10 @@ mod tests { let normal = DispatchInfo { weight: 100, ..Default::default() }; let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; let len = 0_usize; + let normal_limit = normal_weight_limit(); // given almost full block - AllExtrinsicsWeight::put(>::get() / 4); + AllExtrinsicsWeight::put(normal_limit); // will not fit. assert!(CheckWeight::(PhantomData).pre_dispatch(&1, normal, len).is_err()); // will fit. @@ -1289,7 +1323,7 @@ mod tests { // likewise for length limit. let len = 100_usize; - AllExtrinsicsLen::put(>::get() / 4); + AllExtrinsicsLen::put(normal_length_limit()); assert!(CheckWeight::(PhantomData).pre_dispatch(&1, normal, len).is_err()); assert!(CheckWeight::(PhantomData).pre_dispatch(&1, op, len).is_ok()); }) @@ -1316,17 +1350,24 @@ mod tests { #[test] fn signed_ext_check_weight_block_size_works() { with_externalities(&mut new_test_ext(), || { - let tx = DispatchInfo::default(); - - let reset_check_weight = |s, f| { + let normal = DispatchInfo::default(); + let normal_limit = normal_weight_limit() as usize; + let reset_check_weight = |tx, s, f| { AllExtrinsicsLen::put(0); let r = CheckWeight::(PhantomData).pre_dispatch(&1, tx, s); if f { assert!(r.is_err()) } else { assert!(r.is_ok()) } }; - reset_check_weight(128, false); - reset_check_weight(512, false); - reset_check_weight(513, true); + reset_check_weight(normal, normal_limit - 1, false); + reset_check_weight(normal, normal_limit, false); + reset_check_weight(normal, normal_limit + 1, true); + + // Operational ones don't have this limit. + let op = DispatchInfo { weight: 0, class: DispatchClass::Operational }; + reset_check_weight(op, normal_limit, false); + reset_check_weight(op, normal_limit + 100, false); + reset_check_weight(op, 1024, false); + reset_check_weight(op, 1025, true); }) } diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index ca7245664e034..030f825dbab87 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -99,6 +99,7 @@ use inherents::ProvideInherentData; use srml_support::{StorageValue, Parameter, decl_storage, decl_module, for_each_tuple}; use srml_support::traits::{Time, Get}; use runtime_primitives::traits::{SimpleArithmetic, Zero, SaturatedConversion}; +use runtime_primitives::weights::SimpleDispatchInfo; use system::ensure_none; use inherents::{RuntimeString, InherentIdentifier, ProvideInherent, IsFatalError, InherentData}; @@ -236,6 +237,7 @@ decl_module! { /// `MinimumPeriod`. /// /// The dispatch origin for this call must be `Inherent`. + #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn set(origin, #[compact] now: T::Moment) { ensure_none(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); @@ -338,7 +340,7 @@ mod tests { use srml_support::{impl_outer_origin, assert_ok, parameter_types}; use runtime_io::{with_externalities, TestExternalities}; use substrate_primitives::H256; - use runtime_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + use runtime_primitives::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; impl_outer_origin! { pub enum Origin for Test {} @@ -350,6 +352,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -364,6 +367,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } parameter_types! { diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index c8cf84355aca0..f86a8271a24ba 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -79,6 +79,7 @@ use runtime_primitives::{Permill, ModuleId}; use runtime_primitives::traits::{ Zero, EnsureOrigin, StaticLookup, CheckedSub, CheckedMul, AccountIdConversion }; +use runtime_primitives::weights::SimpleDispatchInfo; use parity_codec::{Encode, Decode}; use system::ensure_signed; @@ -153,6 +154,7 @@ decl_module! { /// - Limited storage reads. /// - One DB change, one extra DB entry. /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn propose_spend( origin, #[compact] value: BalanceOf, @@ -179,6 +181,7 @@ decl_module! { /// - Limited storage reads. /// - One DB clear. /// # + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] fn reject_proposal(origin, #[compact] proposal_id: ProposalIndex) { T::RejectOrigin::ensure_origin(origin)?; let proposal = >::take(proposal_id).ok_or("No proposal at that index")?; @@ -196,6 +199,7 @@ decl_module! { /// - Limited storage reads. /// - One DB change. /// # + #[weight = SimpleDispatchInfo::FixedOperational(100_000)] fn approve_proposal(origin, #[compact] proposal_id: ProposalIndex) { T::ApproveOrigin::ensure_origin(origin)?; @@ -360,7 +364,7 @@ mod tests { use runtime_io::with_externalities; use srml_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types}; use substrate_primitives::{H256, Blake2Hasher}; - use runtime_primitives::{traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header}; + use runtime_primitives::{Perbill, traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header}; impl_outer_origin! { pub enum Origin for Test {} @@ -372,6 +376,7 @@ mod tests { 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 Test { type Origin = Origin; @@ -386,6 +391,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; + type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; } parameter_types! { @@ -408,6 +414,7 @@ mod tests { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; + type WeightToFee = (); } parameter_types! { pub const ProposalBond: Permill = Permill::from_percent(5); diff --git a/subkey/src/main.rs b/subkey/src/main.rs index f9432b42c12b3..16abc8723aba7 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -26,10 +26,10 @@ use substrate_primitives::{ ed25519, sr25519, hexdisplay::HexDisplay, Pair, Public, blake2_256, crypto::{Ss58Codec, set_default_ss58_version, Ss58AddressFormat} }; -use parity_codec::{Encode, Decode, Compact}; +use parity_codec::{Encode, Decode}; use sr_primitives::generic::Era; use node_primitives::{Balance, Index, Hash}; -use node_runtime::{Call, UncheckedExtrinsic, /*CheckNonce, TakeFees, */BalancesCall}; +use node_runtime::{Call, UncheckedExtrinsic, BalancesCall, Runtime}; mod vanity; @@ -90,14 +90,14 @@ fn execute(matches: clap::ArgMatches) where <::Pair as Pair>::Signature: AsRef<[u8]> + AsMut<[u8]> + Default, <::Pair as Pair>::Public: Sized + AsRef<[u8]> + Ss58Codec + AsRef<<::Pair as Pair>::Public>, { - // let extra = |i: Index, f: Balance| { - // ( - // system::CheckEra::::from(Era::Immortal), - // system::CheckNonce::::from(i), - // system::CheckWeight::::from(), - // balances::TakeFees::::from(f), - // ) - // }; + let extra = |i: Index, f: Balance| { + ( + system::CheckEra::::from(Era::Immortal), + system::CheckNonce::::from(i), + system::CheckWeight::::from(), + balances::TakeFees::::from(f), + ) + }; let password = matches.value_of("password"); let maybe_network = matches.value_of("network"); if let Some(network) = maybe_network { @@ -138,7 +138,7 @@ fn execute(matches: clap::ArgMatches) where let sig = pair.sign(&message); println!("{}", hex::encode(&sig)); } - /*("transfer", Some(matches)) => { + ("transfer", Some(matches)) => { let signer = matches.value_of("from") .expect("parameter is required; thus it can't be None; qed"); let signer = Sr25519::pair_from_suri(signer, password); @@ -225,7 +225,7 @@ fn execute(matches: clap::ArgMatches) where ); println!("0x{}", hex::encode(&extrinsic.encode())); - }*/ + } ("verify", Some(matches)) => { let sig_data = matches.value_of("sig") .expect("signature parameter is required; thus it can't be None; qed");