-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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, | ||||||
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, | ||||||
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.") }, | ||||||||
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, 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.") }, | ||||||||
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!. | ||||||||
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
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