-
Notifications
You must be signed in to change notification settings - Fork 184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transaction Weights #62
Merged
Merged
Changes from 10 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
85cf808
Brainstorm compiles.
JoshOrndorff 0f0d0f8
Module fleshed out completely.
JoshOrndorff 177bf96
Merge branch 'master' into joshy-transaction-weights
JoshOrndorff 03b8c31
Merge branch 'master' into joshy-transaction-weights
JoshOrndorff 7e2a8d3
Runtime demonstrating WeightToFee
JoshOrndorff fa31aa3
One more weight example.
JoshOrndorff ecaa66f
line width to 100.
JoshOrndorff 61758f3
Put some text in recipes. Will be nicer after https://github.com/subs…
JoshOrndorff 673a7ff
Complete links to devhub.
JoshOrndorff 3f4c197
Revert accidental change to weight module which broke compile.
JoshOrndorff 8a8efa6
Update kitchen/modules/weights/src/lib.rs
JoshOrndorff f69d1f1
Update src/design/econsecurity.md
JoshOrndorff e9928be
Correct example WeightToFee = ConvertInto.
JoshOrndorff 1a88d7a
Merge branch 'joshy-transaction-weights' of github.com:substrate-deve…
JoshOrndorff 589f5d9
Update src/design/econsecurity.md
JoshOrndorff 6ade2c5
Add Kian's suggested warning.
JoshOrndorff 78fb551
cleanup formatting characters
JoshOrndorff e6fc0e9
Add Amar's suggested warning.
JoshOrndorff File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
[package] | ||
name = "weights" | ||
version = "0.1.0" | ||
authors = ["Anonymous"] | ||
edition = "2018" | ||
|
||
[features] | ||
default = ['std'] | ||
std = [ | ||
'parity-scale-codec/std', | ||
'support/std', | ||
'system/std', | ||
'balances/std', | ||
'runtime-primitives/std', | ||
] | ||
|
||
[dependencies.parity-scale-codec] | ||
default-features = false | ||
features = ['derive'] | ||
version = '1.0.6' | ||
|
||
[dependencies.support] | ||
default_features = false | ||
git = 'https://github.com/paritytech/substrate.git' | ||
package = 'srml-support' | ||
branch = 'master' | ||
|
||
[dependencies.system] | ||
default_features = false | ||
git = 'https://github.com/paritytech/substrate.git' | ||
package = 'srml-system' | ||
branch = 'master' | ||
|
||
[dependencies.balances] | ||
default_features = false | ||
git = 'https://github.com/paritytech/substrate.git' | ||
package = 'srml-balances' | ||
branch = 'master' | ||
|
||
[dependencies.runtime-primitives] | ||
default_features = false | ||
git = 'https://github.com/paritytech/substrate.git' | ||
package = 'sr-primitives' | ||
branch = 'master' | ||
|
||
[dev-dependencies.primitives] | ||
default_features = false | ||
git = 'https://github.com/paritytech/substrate.git' | ||
package = 'substrate-primitives' | ||
branch = 'master' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
// Transaction Weight Examples | ||
// https://crates.parity.io/sr_primitives/weights/index.html | ||
use support::{ensure, decl_module, decl_storage, dispatch::{Result, WeighData}}; | ||
use runtime_primitives::weights::{ DispatchClass, Weight, ClassifyDispatch, SimpleDispatchInfo }; | ||
|
||
pub trait Trait: system::Trait {} | ||
|
||
decl_storage! { | ||
trait Store for Module<T: Trait> as SimpleMap { | ||
StoredValue get(stored_value): u32; | ||
JoshOrndorff marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
// A "scale" to weigh transactions. This scale can be used with any transactions that take a | ||
// single argument of type u32. The ultimate weight of the transaction is the / product of the | ||
// transaction parameter and the field of this struct. | ||
pub struct Linear(u32); | ||
|
||
// The actual weight calculation happens in the | ||
// impl WeighData block | ||
impl WeighData<(&u32,)> for Linear { | ||
fn weigh_data(&self, (x,): (&u32,)) -> Weight { | ||
|
||
// Use saturation so that an extremely large parameter value | ||
4meta5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Does not cause overflow. | ||
4meta5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
x.saturating_mul(self.0) | ||
} | ||
} | ||
|
||
// Any struct that is used to weigh data must also implement ClassifyDispatchInfo. Here we calssify | ||
JoshOrndorff marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// the transaction as Normal (as opposed to operational.) | ||
impl<T> ClassifyDispatch<T> for Linear { | ||
fn classify_dispatch(&self, _: T) -> DispatchClass { | ||
// Classify all calls as Normal (which is the default) | ||
Default::default() | ||
} | ||
} | ||
|
||
// Another scale to weight transactions. This one is more complex. / It computes weight according | ||
// to the formula a*x^2 + b*y + c where / a, b, and c are fields in the struct, and x and y are | ||
// transaction / parameters. | ||
pub struct Quadratic(u32, u32, u32); | ||
|
||
impl WeighData<(&u32, &u32)> for Quadratic { | ||
fn weigh_data(&self, (x, y): (&u32, &u32)) -> Weight { | ||
|
||
let ax2 = x.saturating_mul(*x).saturating_mul(self.0); | ||
let by = y.saturating_mul(self.1); | ||
let c = self.2; | ||
|
||
ax2.saturating_add(by).saturating_add(c) | ||
} | ||
} | ||
|
||
impl<T> ClassifyDispatch<T> for Quadratic { | ||
fn classify_dispatch(&self, _: T) -> DispatchClass { | ||
// Classify all calls as Normal (which is the default) | ||
Default::default() | ||
} | ||
} | ||
|
||
// A final scale to weight transactions. This one weighs / transactions where the first parameter | ||
// is bool. If / the bool is true, then the weight is linear in the / second parameter. Otherwise | ||
// the weight is constant. | ||
pub struct Conditional(u32); | ||
|
||
impl WeighData<(&bool, &u32)> for Conditional { | ||
fn weigh_data(&self, (switch, val): (&bool, &u32)) -> Weight { | ||
|
||
if *switch { | ||
val.saturating_mul(self.0) | ||
} | ||
else { | ||
self.0 | ||
} | ||
} | ||
} | ||
|
||
impl<T> ClassifyDispatch<T> for Conditional { | ||
fn classify_dispatch(&self, _: T) -> DispatchClass { | ||
// Classify all calls as Normal (which is the default) | ||
Default::default() | ||
} | ||
} | ||
|
||
decl_module! { | ||
pub struct Module<T: Trait> for enum Call where origin: T::Origin { | ||
|
||
// Store value does not loop at all so a fixed weight is appropriate. Fixed weights can | ||
// be assigned using types available in the Substrate framework. No custom coding is | ||
// necessary. | ||
#[weight = SimpleDispatchInfo::FixedNormal(100)] | ||
fn store_value(_origin, entry: u32) -> Result { | ||
|
||
StoredValue::put(entry); | ||
|
||
Ok(()) | ||
} | ||
|
||
// add_n sets the storage value n times, so it should cost n times as much as | ||
// store_value. Because it performs both a read and a write, the multiplier is set to 200 | ||
4meta5 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// instead of 100 as before. | ||
#[weight = Linear(200)] | ||
fn add_n(_origin, n: u32) -> Result { | ||
JoshOrndorff marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let mut old : u32; | ||
for _i in 1..=n { | ||
old = StoredValue::get(); | ||
StoredValue::put(old + 1); | ||
} | ||
Ok(()) | ||
} | ||
|
||
// The actual expense of `double` is proportional to a storage value. Dispatch | ||
// weightings can't use storage values directly, because the weight should be computable | ||
// ahead of time. Instead we have the caller pass in the expected storage value and we | ||
// ensure it is correct. | ||
#[weight = Linear(200)] | ||
fn double(_origin, initial_value: u32) -> Result { | ||
|
||
// Ensure the value passed by the caller actually matches storage If this condition | ||
// were not true, the caller would be able to avoid paying appropriate fees. | ||
let initial = StoredValue::get(); | ||
ensure!(initial == initial_value, "Storage value did not match parameter"); | ||
|
||
for _i in 1..=initial { | ||
let old = StoredValue::get(); | ||
StoredValue::put(old + 1); | ||
} | ||
Ok(()) | ||
} | ||
|
||
// This one is quadratic in the first argument plus linear in the second plus a constant. | ||
// This calculation is not meant to do something really useful or common other than | ||
// demonstrate that weights should grow by the same order as the compute required by the | ||
// transaction. | ||
#[weight = Quadratic(200, 30, 100)] | ||
fn complex_calculations(_origin, x: u32, y: u32) -> Result { | ||
// This first part performs a relatively cheap (hence 30) | ||
// in-memory calculations. | ||
let mut part1 = 0; | ||
for _i in 1..=y { | ||
part1 += 2 | ||
} | ||
|
||
// The second part performs x^2 storage read-writes (hence 200) | ||
for _j in 1..=x { | ||
for _k in 1..=x { | ||
StoredValue::put(StoredValue::get() + 1); | ||
} | ||
} | ||
|
||
// One final storage write (hence 100) | ||
StoredValue::put(part1); | ||
|
||
Ok(()) | ||
} | ||
|
||
// Here the first parameter, a boolean has a significant effect on the computational | ||
// intensity of the call. | ||
#[weight = Conditional(200)] | ||
fn add_or_set(_origin, add_flag: bool, val: u32) -> Result { | ||
if add_flag { | ||
StoredValue::put(&val); | ||
} | ||
else { | ||
for _i in 1..=val { | ||
StoredValue::put(StoredValue::get()); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = 'weight-fee-genesis' | ||
version = "2.0.0" | ||
authors = ["Anonymous"] | ||
edition = "2018" | ||
|
||
[dependencies.runtime] | ||
package = 'weight-fee-runtime' | ||
path = '../weight-fee-runtime' | ||
|
||
[dependencies] | ||
babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", branch = "master" } | ||
grandpa-primitives = { package = "substrate-finality-grandpa-primitives", git = "https://github.com/paritytech/substrate", branch = "master" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use runtime::{ | ||
AccountId, BabeConfig, BalancesConfig, GenesisConfig, GrandpaConfig, | ||
SudoConfig, IndicesConfig, SystemConfig, WASM_BINARY, | ||
}; | ||
use babe_primitives::{AuthorityId as BabeId}; | ||
use grandpa_primitives::{AuthorityId as GrandpaId}; | ||
|
||
pub fn testnet_genesis(initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId)>, | ||
root_key: AccountId, | ||
endowed_accounts: Vec<AccountId>, | ||
_enable_println: bool) -> GenesisConfig { | ||
GenesisConfig { | ||
system: Some(SystemConfig { | ||
code: WASM_BINARY.to_vec(), | ||
changes_trie_config: Default::default(), | ||
}), | ||
indices: Some(IndicesConfig { | ||
ids: endowed_accounts.clone(), | ||
}), | ||
balances: Some(BalancesConfig { | ||
balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), | ||
vesting: vec![], | ||
}), | ||
sudo: Some(SudoConfig { | ||
key: root_key, | ||
}), | ||
babe: Some(BabeConfig { | ||
authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), | ||
}), | ||
grandpa: Some(GrandpaConfig { | ||
authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(), | ||
}), | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we use headers here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to know more about headers. Do you have a link to read?
I do know if I remove this line, the build fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean license headers. Probably @shawntabrizi should decide.