-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Operational Transaction. #3106
Operational Transaction. #3106
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -24,10 +24,15 @@ | |||||
| //! Note that the decl_module macro _cannot_ enforce this and will simply fail | ||||||
| //! if an invalid struct is passed in. | ||||||
|
|
||||||
| use crate::transaction_validity::TransactionPriority; | ||||||
|
|
||||||
| /// The final type that each `#[weight = $x:expr]`'s | ||||||
| /// expression must evaluate to. | ||||||
| pub type Weight = u32; | ||||||
|
|
||||||
| /// The maximum possible weight of a block. | ||||||
| pub const MAX_TRANSACTIONS_WEIGHT: u32 = 4 * 1024 * 1024; | ||||||
|
|
||||||
| /// A `Call` enum (aka transaction) that can be weighted using the custom weight attribute of | ||||||
| /// its dispatchable functions. Is implemented by default in the `decl_module!`. | ||||||
| /// | ||||||
|
|
@@ -37,6 +42,13 @@ pub trait Weighable { | |||||
| /// Return the weight of this call. | ||||||
| /// The `len` argument is the encoded length of the transaction/call. | ||||||
| fn weight(&self, len: usize) -> Weight; | ||||||
|
|
||||||
| /// Return the priority of this transaction. | ||||||
| fn priority(&self, len: usize) -> TransactionPriority; | ||||||
|
|
||||||
| /// Determine, given the current transaction weight and sum of weights in the current block, if | ||||||
| /// the block is now full or not. | ||||||
| fn is_block_full(&self, block_weight: Weight, len: usize) -> bool; | ||||||
| } | ||||||
|
|
||||||
| /// Default type used as the weight representative in a `#[weight = x]` attribute. | ||||||
|
|
@@ -46,22 +58,35 @@ pub trait Weighable { | |||||
| pub enum TransactionWeight { | ||||||
| /// Basic weight (base, byte). | ||||||
| /// The values contained are the base weight and byte weight respectively. | ||||||
| /// | ||||||
| /// The priority of this transaction will be proportional to its computed weight. | ||||||
| Basic(Weight, Weight), | ||||||
| /// Maximum fee. This implies that this transaction _might_ get included but | ||||||
| /// no more transaction can be added. This can be done by setting the | ||||||
| /// implementation to _maximum block weight_. | ||||||
| Max, | ||||||
| /// Free. The transaction does not increase the total weight | ||||||
| /// (i.e. is not included in weight calculation). | ||||||
| Free, | ||||||
| /// Operational transaction. These are typically root transactions for operational updates, | ||||||
| /// runtime code changes or consensus reports through inherents. These transactions are still | ||||||
| /// subject to the same (base, byte) fee but will have maximum priority and will not affect | ||||||
| /// block fullness at all. | ||||||
| Operational(Weight, Weight), | ||||||
| } | ||||||
|
|
||||||
| impl Weighable for TransactionWeight { | ||||||
| fn weight(&self, len: usize) -> Weight { | ||||||
| match self { | ||||||
| TransactionWeight::Basic(base, byte) => base + byte * len as Weight, | ||||||
| TransactionWeight::Max => 3 * 1024 * 1024, | ||||||
| TransactionWeight::Free => 0, | ||||||
| TransactionWeight::Operational(_, _) => 0, | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| fn priority(&self, len: usize) -> TransactionPriority { | ||||||
| match self { | ||||||
| TransactionWeight::Basic(_, _) => self.weight(len) as TransactionPriority, | ||||||
| TransactionWeight::Operational(_, _) => TransactionPriority::max_value(), | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| fn is_block_full(&self, block_weight: Weight, len: usize) -> bool { | ||||||
| match self { | ||||||
| TransactionWeight::Basic(_, _) => self.weight(len) + block_weight > MAX_TRANSACTIONS_WEIGHT, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| TransactionWeight::Operational(_, _) => false | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -70,7 +70,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { | |||||
| // implementation changes and behavior does not, then leave spec_version as | ||||||
| // is and increment impl_version. | ||||||
| spec_version: 109, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| impl_version: 110, | ||||||
| impl_version: 111, | ||||||
| apis: RUNTIME_API_VERSIONS, | ||||||
| }; | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -26,6 +26,7 @@ pub use srml_metadata::{ | |||||||
| ModuleConstantMetadata, DefaultByte, DefaultByteGetter, | ||||||||
| }; | ||||||||
| pub use sr_primitives::weights::{TransactionWeight, Weighable, Weight}; | ||||||||
| pub use sr_primitives::transaction_validity::TransactionPriority; | ||||||||
|
|
||||||||
| /// A type that cannot be instantiated. | ||||||||
| pub enum Never {} | ||||||||
|
|
@@ -1126,6 +1127,22 @@ macro_rules! decl_module { | |||||||
| $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") }, | ||||||||
| } | ||||||||
| } | ||||||||
| fn priority(&self, _len: usize) -> $crate::dispatch::TransactionPriority { | ||||||||
| match self { | ||||||||
| $( $call_type::$fn_name(..) => $crate::dispatch::Weighable::priority(&$weight, _len), )* | ||||||||
| $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") }, | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be ensured at compile-time. For example,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bkchr this pattern can be replaced probably everywhere in storage macros? I borrowed the |
||||||||
| } | ||||||||
| } | ||||||||
| fn is_block_full(&self, _block_weight: $crate::dispatch::Weight, _len: usize) -> bool { | ||||||||
| match self { | ||||||||
| $( $call_type::$fn_name(..) => $crate::dispatch::Weighable::is_block_full( | ||||||||
| &$weight, | ||||||||
| _block_weight, | ||||||||
| _len, | ||||||||
| ), )* | ||||||||
| $call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") }, | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| // manual implementation of clone/eq/partialeq because using derive erroneously requires | ||||||||
|
|
@@ -1275,6 +1292,17 @@ macro_rules! impl_outer_dispatch { | |||||||
| $( $call_type::$camelcase(call) => call.weight(len), )* | ||||||||
| } | ||||||||
| } | ||||||||
| fn priority(&self, len: usize) -> $crate::dispatch::TransactionPriority { | ||||||||
| match self { | ||||||||
| $( $call_type::$camelcase(call) => call.priority(len), )* | ||||||||
| } | ||||||||
| } | ||||||||
| fn is_block_full(&self, block_weight: $crate::dispatch::Weight, len: usize) -> bool { | ||||||||
| match self { | ||||||||
|
|
||||||||
| $( $call_type::$camelcase(call) => call.is_block_full(block_weight, len), )* | ||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
| impl $crate::dispatch::Dispatchable for $call_type { | ||||||||
| type Origin = $origin; | ||||||||
|
|
@@ -1613,8 +1641,8 @@ mod tests { | |||||||
| fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } } | ||||||||
| fn offchain_worker() {} | ||||||||
|
|
||||||||
| #[weight = TransactionWeight::Max] | ||||||||
| fn weighted(_origin) { unreachable!() } | ||||||||
| #[weight = TransactionWeight::Operational(0, 1)] | ||||||||
| fn security_tx(_origin) { unreachable!() } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
|
|
@@ -1680,7 +1708,8 @@ mod tests { | |||||||
| documentation: DecodeDifferent::Encode(&[]), | ||||||||
| }, | ||||||||
| FunctionMetadata { | ||||||||
| name: DecodeDifferent::Encode("weighted"), | ||||||||
|
|
||||||||
| name: DecodeDifferent::Encode("security_tx"), | ||||||||
| arguments: DecodeDifferent::Encode(&[]), | ||||||||
| documentation: DecodeDifferent::Encode(&[]), | ||||||||
| }, | ||||||||
|
|
@@ -1754,10 +1783,15 @@ mod tests { | |||||||
|
|
||||||||
| #[test] | ||||||||
| fn weight_should_attach_to_call_enum() { | ||||||||
| // max weight. not dependent on input. | ||||||||
| assert_eq!(Call::<TraitImpl>::weighted().weight(100), 3 * 1024 * 1024); | ||||||||
| // Operational tx. | ||||||||
| assert_eq!(Call::<TraitImpl>::security_tx().weight(100), 0); | ||||||||
| assert_eq!(Call::<TraitImpl>::security_tx().priority(100), u64::max_value()); | ||||||||
| // one simply does not return false of the transaction type is operational!. | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough. I am personally pretty much okay with having some humor/informal statements as long as it is in test code :p |
||||||||
| assert_eq!(Call::<TraitImpl>::security_tx().is_block_full(u32::max_value(), usize::max_value()), false); | ||||||||
|
|
||||||||
| // default weight. | ||||||||
| assert_eq!(Call::<TraitImpl>::aux_0().weight(5), 5 /*tx-len*/); | ||||||||
|
|
||||||||
| // custom basic | ||||||||
| assert_eq!(Call::<TraitImpl>::aux_3().weight(5), 10 + 100 * 5 ); | ||||||||
| } | ||||||||
|
|
||||||||
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.
okay this is not a great name since it is misleading. Should be something along the lines of
xt.will_cause_full_block() -> bool