Per-transaction weight for srml (#2799)

* debug checkpoint.

* new

* Worked.

* Worked and weight propagated to executive.

* Works with some tests.

* Cleanup debug prints.

* More cleanup.

* Undo more logs.

* Undo a few more.

* Fix build.

* Allow len to be used in weight calculation.

* Remove noop function from dispath.

* Cleanup.

* Unify traits.

* Update docs and nits.

* line width

* Update core/sr-primitives/src/weights.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/sr-primitives/src/weights.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/sr-primitives/src/weights.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/sr-primitives/src/weights.rs

Co-Authored-By: Amar Singh <asinghchrony@protonmail.com>

* Update srml/example/src/lib.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Final cleanup.

* Fix build.
This commit is contained in:
Kian Peymani
2019-06-12 14:38:30 +02:00
committed by GitHub
parent e53e9e9bda
commit 3496f11404
15 changed files with 288 additions and 54 deletions
+111 -16
View File
@@ -23,6 +23,7 @@ pub use std::fmt;
pub use crate::rstd::result;
pub use crate::codec::{Codec, Decode, Encode, Input, Output, HasCompact, EncodeAsRef};
pub use srml_metadata::{FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata};
pub use sr_primitives::weights::{TransactionWeight, Weighable, Weight};
/// A type that cannot be instantiated.
pub enum Never {}
@@ -200,8 +201,7 @@ impl<T> Parameter for T where T: Codec + Clone + Eq {}
/// [`OffchainWorker`](../sr_primitives/traits/trait.OffchainWorker.html) trait.
#[macro_export]
macro_rules! decl_module {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
// Entry point #1.
(
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -221,6 +221,7 @@ macro_rules! decl_module {
$($t)*
);
};
// Entry point #2.
(
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -241,6 +242,7 @@ macro_rules! decl_module {
);
};
// Normalization expansions. Fills the defaults.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -402,9 +404,13 @@ macro_rules! decl_module {
$($rest)*
);
};
// This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
pub struct $mod_type:ident<
$trait_instance:ident:
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialize:tt )* }
@@ -412,6 +418,7 @@ macro_rules! decl_module {
{ $( $offchain:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
#[weight = $weight:expr]
$fn_vis:vis fn $fn_name:ident(
$origin:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
@@ -419,7 +426,9 @@ macro_rules! decl_module {
) => {
$crate::decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?>
pub struct $mod_type<
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ $( $on_initialize )* }
@@ -428,6 +437,7 @@ macro_rules! decl_module {
[
$($t)*
$(#[doc = $doc_attr])*
#[weight = $weight]
$fn_vis fn $fn_name(
$origin $( , $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
@@ -436,6 +446,45 @@ macro_rules! decl_module {
$($rest)*
);
};
// Add #[weight] if none is defined.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<
$trait_instance:ident:
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
>
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
{ $( $deposit_event:tt )* }
{ $( $on_initialize:tt )* }
{ $( $on_finalize:tt )* }
{ $( $offchain:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$fn_vis:vis fn $fn_name:ident(
$from:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
$($rest:tt)*
) => {
$crate::decl_module!(@normalize
$(#[$attr])*
pub struct $mod_type<
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
>
for enum $call_type where origin: $origin_type, system = $system
{ $( $deposit_event )* }
{ $( $on_initialize )* }
{ $( $on_finalize )* }
{ $( $offchain )* }
[ $($t)* ]
$(#[doc = $doc_attr])*
#[weight = $crate::dispatch::TransactionWeight::default()]
$fn_vis fn $fn_name(
$from $(, $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
$($rest)*
);
};
// Ignore any ident which is not `origin` with type `T::Origin`.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -446,6 +495,7 @@ macro_rules! decl_module {
{ $( $offchain:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$(#[weight = $weight:expr])?
$fn_vis:vis fn $fn_name:ident(
$origin:ident : T::Origin $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
@@ -457,6 +507,7 @@ macro_rules! decl_module {
not use the `T::Origin` type.)"
)
};
// Ignore any ident which is `origin` but has a type, regardless of the type token itself.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -467,6 +518,7 @@ macro_rules! decl_module {
{ $( $offchain:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$(#[weight = $weight:expr])?
$fn_vis:vis fn $fn_name:ident(
origin : $origin:ty $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
@@ -478,6 +530,7 @@ macro_rules! decl_module {
not use the `T::Origin` type.)"
)
};
// Add root if no origin is defined.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -488,6 +541,7 @@ macro_rules! decl_module {
{ $( $offchain:tt )* }
[ $($t:tt)* ]
$(#[doc = $doc_attr:tt])*
$(#[weight = $weight:expr])?
$fn_vis:vis fn $fn_name:ident(
$( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),*
) $( -> $result:ty )* { $( $impl:tt )* }
@@ -501,17 +555,18 @@ macro_rules! decl_module {
{ $( $on_initialize )* }
{ $( $on_finalize )* }
{ $( $offchain )* }
[
$($t)*
$(#[doc = $doc_attr])*
$fn_vis fn $fn_name(
root $( , $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
{ $($instance: $instantiable)? }
]
[ $($t)* ]
$(#[doc = $doc_attr])*
$(#[weight = $weight])?
$fn_vis fn $fn_name(
root $( , $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
$($rest)*
);
};
// Last normalize step. Triggers `@imp` expansion which is the real expansion.
(@normalize
$(#[$attr:meta])*
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
@@ -686,6 +741,7 @@ macro_rules! decl_module {
{}
};
// Expansion for root dispatch functions with no specified result type.
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
@@ -700,6 +756,7 @@ macro_rules! decl_module {
}
};
// Expansion for root dispatch functions with explicit return types.
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
@@ -715,6 +772,7 @@ macro_rules! decl_module {
}
};
// Expansion for _origin_ dispatch functions with no return type.
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
@@ -733,6 +791,7 @@ macro_rules! decl_module {
}
};
// Expansion for _origin_ dispatch functions with explicit return type.
(@impl_function
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
$origin_ty:ty;
@@ -868,6 +927,7 @@ macro_rules! decl_module {
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {
$(
$(#[doc = $doc_attr:tt])*
#[weight = $weight:expr]
$fn_vis:vis fn $fn_name:ident(
$from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
) $( -> $result:ty )* { $( $impl:tt )* }
@@ -908,7 +968,6 @@ macro_rules! decl_module {
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
$( $offchain )*
}
$crate::decl_module! {
@impl_deposit_event
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
@@ -951,6 +1010,18 @@ macro_rules! decl_module {
)*
}
// Implement weight calculation function for Call
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Weighable
for $call_type<$trait_instance $(, $instance)?>
{
fn weight(&self, _len: usize) -> $crate::dispatch::Weight {
match self {
$( $call_type::$fn_name(..) => $crate::dispatch::Weighable::weight(&$weight, _len), )*
$call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") },
}
}
}
// manual implementation of clone/eq/partialeq because using derive erroneously requires
// clone/eq/partialeq from T.
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Clone
@@ -1072,14 +1143,19 @@ macro_rules! impl_outer_dispatch {
$camelcase ( $crate::dispatch::CallableCallFor<$camelcase> )
,)*
}
impl $crate::dispatch::Weighable for $call_type {
fn weight(&self, len: usize) -> $crate::dispatch::Weight {
match self {
$( $call_type::$camelcase(call) => call.weight(len), )*
}
}
}
impl $crate::dispatch::Dispatchable for $call_type {
type Origin = $origin;
type Trait = $call_type;
fn dispatch(self, origin: $origin) -> $crate::dispatch::Result {
match self {
$(
$call_type::$camelcase(call) => call.dispatch(origin),
)*
$( $call_type::$camelcase(call) => call.dispatch(origin), )*
}
}
}
@@ -1271,6 +1347,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 = TransactionWeight::Basic(10, 100)]
fn aux_3() -> Result { unreachable!() }
fn aux_4(_data: i32) -> Result { unreachable!() }
fn aux_5(_origin, _data: i32, #[compact] _data2: u32) -> Result { unreachable!() }
@@ -1278,6 +1355,9 @@ mod tests {
fn on_initialize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_initialize") } }
fn on_finalize(n: T::BlockNumber) { if n.into() == 42 { panic!("on_finalize") } }
fn offchain_worker() {}
#[weight = TransactionWeight::Max]
fn weighted() { unreachable!() }
}
}
@@ -1342,6 +1422,11 @@ mod tests {
]),
documentation: DecodeDifferent::Encode(&[]),
},
FunctionMetadata {
name: DecodeDifferent::Encode("weighted"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
},
];
struct TraitImpl {}
@@ -1396,4 +1481,14 @@ mod tests {
fn on_finalize_should_work() {
<Module<TraitImpl> as OnFinalize<u32>>::on_finalize(42);
}
#[test]
fn weight_should_attach_to_call_enum() {
// max weight. not dependent on input.
assert_eq!(Call::<TraitImpl>::weighted().weight(100), 3 * 1024 * 1024);
// 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 );
}
}