Extensible transactions (and tips) (#3102)

* Make extrinsics extensible.

Also Remove old extrinsic types.

* Rest of mockup. Add tips.

* Fix some build issues

* Runtiem builds :)

* Substrate builds.

* Fix a doc test

* Compact encoding

* Extract out the era logic into an extension

* Weight Check signed extension. (#3115)

* Weight signed extension.

* Revert a bit + test for check era.

* Update Cargo.toml

* Update node/cli/src/factory_impl.rs

* Update node/executor/src/lib.rs

* Update node/executor/src/lib.rs

* Don't use len for weight - use data.

* Operational Transaction; second attempt (#3138)

* working poc added.

* some fixes.

* Update doc.

* Fix all tests + final logic.

* more refactoring.

* nits.

* System block limit in bytes.

* Silent the storage macro warnings.

* More logic more tests.

* Fix import.

* Refactor names.

* Fix build.

* Update srml/balances/src/lib.rs

* Final refactor.

* Bump transaction version

* Fix weight mult test.

* Fix more tests and improve doc.

* Bump.

* Make some tests work again.

* Fix subkey.

* Remove todos + bump.

* Ignore expensive test.

* Bump.
This commit is contained in:
Gavin Wood
2019-07-23 01:06:49 +08:00
committed by Kian Peymani
parent 4f5654b67d
commit 78bc5edc14
55 changed files with 1965 additions and 1646 deletions
+57 -30
View File
@@ -25,25 +25,18 @@ pub use srml_metadata::{
FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata,
ModuleConstantMetadata, DefaultByte, DefaultByteGetter,
};
pub use sr_primitives::weights::{TransactionWeight, Weighable, Weight};
pub use sr_primitives::weights::{SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData,
ClassifyDispatch,
TransactionPriority
};
pub use sr_primitives::traits::{Dispatchable, DispatchResult};
/// A type that cannot be instantiated.
pub enum Never {}
/// Result of a module function call; either nothing (functions are only called for "side effects")
/// or an error message.
pub type Result = result::Result<(), &'static str>;
/// A lazy call (module function and argument values) that can be executed via its `dispatch`
/// method.
pub trait Dispatchable {
/// Every function call from your runtime has an origin, which specifies where the extrinsic was
/// generated from. In the case of a signed extrinsic (transaction), the origin contains an
/// identifier for the caller. The origin can be empty in the case of an inherent extrinsic.
type Origin;
type Trait;
fn dispatch(self, origin: Self::Origin) -> Result;
}
pub type Result = DispatchResult;
/// Serializable version of Dispatchable.
/// This value can be used as a "function" in an extrinsic.
@@ -593,7 +586,7 @@ macro_rules! decl_module {
{ $( $constants )* }
[ $( $dispatchables )* ]
$(#[doc = $doc_attr])*
#[weight = $crate::dispatch::TransactionWeight::default()]
#[weight = $crate::dispatch::SimpleDispatchInfo::default()]
$fn_vis fn $fn_name(
$from $(, $(#[$codec_attr])* $param_name : $param )*
) $( -> $result )* { $( $impl )* }
@@ -1117,14 +1110,38 @@ macro_rules! decl_module {
}
// Implement weight calculation function for Call
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Weighable
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::GetDispatchInfo
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
{
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.") },
}
fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
$(
if let $call_type::$fn_name($( ref $param_name ),*) = self {
let weight = <dyn $crate::dispatch::WeighData<( $( & $param, )* )>>::weigh_data(
&$weight,
($( $param_name, )*)
);
let class = <dyn $crate::dispatch::ClassifyDispatch<( $( & $param, )* )>>::classify_dispatch(
&$weight,
($( $param_name, )*)
);
return $crate::dispatch::DispatchInfo { weight, class };
}
if let $call_type::__PhantomItem(_, _) = self { unreachable!("__PhantomItem should never be used.") }
)*
// Defensive only: this function must have already returned at this point.
// all dispatchable function will have a weight which has the `::default`
// implementation of `SimpleDispatchInfo`. Nonetheless, we create one if it does
// not exist.
let weight = <dyn $crate::dispatch::WeighData<_>>::weigh_data(
&$crate::dispatch::SimpleDispatchInfo::default(),
()
);
let class = <dyn $crate::dispatch::ClassifyDispatch<_>>::classify_dispatch(
&$crate::dispatch::SimpleDispatchInfo::default(),
()
);
$crate::dispatch::DispatchInfo { weight, class }
}
}
@@ -1269,10 +1286,10 @@ macro_rules! impl_outer_dispatch {
$camelcase ( $crate::dispatch::CallableCallFor<$camelcase, $runtime> )
,)*
}
impl $crate::dispatch::Weighable for $call_type {
fn weight(&self, len: usize) -> $crate::dispatch::Weight {
impl $crate::dispatch::GetDispatchInfo for $call_type {
fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
match self {
$( $call_type::$camelcase(call) => call.weight(len), )*
$( $call_type::$camelcase(call) => call.get_dispatch_info(), )*
}
}
}
@@ -1579,6 +1596,7 @@ macro_rules! __check_reserved_fn_name {
mod tests {
use super::*;
use crate::runtime_primitives::traits::{OnInitialize, OnFinalize};
use sr_primitives::weights::{DispatchInfo, DispatchClass};
pub trait Trait: system::Trait + Sized where Self::AccountId: From<u32> {
type Origin;
@@ -1604,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 = TransactionWeight::Basic(10, 100)]
#[weight = SimpleDispatchInfo::FixedNormal(10)]
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!() }
@@ -1613,8 +1631,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 = SimpleDispatchInfo::FixedOperational(5)]
fn operational(_origin) { unreachable!() }
}
}
@@ -1680,7 +1698,7 @@ mod tests {
documentation: DecodeDifferent::Encode(&[]),
},
FunctionMetadata {
name: DecodeDifferent::Encode("weighted"),
name: DecodeDifferent::Encode("operational"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
},
@@ -1755,10 +1773,19 @@ 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);
assert_eq!(
Call::<TraitImpl>::operational().get_dispatch_info(),
DispatchInfo { weight: 5, class: DispatchClass::Operational },
);
// default weight.
assert_eq!(Call::<TraitImpl>::aux_0().weight(5), 5 /*tx-len*/);
assert_eq!(
Call::<TraitImpl>::aux_0().get_dispatch_info(),
DispatchInfo { weight: 100, class: DispatchClass::Normal },
);
// custom basic
assert_eq!(Call::<TraitImpl>::aux_3().weight(5), 10 + 100 * 5 );
assert_eq!(
Call::<TraitImpl>::aux_3().get_dispatch_info(),
DispatchInfo { weight: 10, class: DispatchClass::Normal },
);
}
}
-14
View File
@@ -23,7 +23,6 @@ use crate::codec::{Codec, Encode, Decode};
use substrate_primitives::u32_trait::Value as U32;
use crate::runtime_primitives::traits::{MaybeSerializeDebug, SimpleArithmetic, Saturating};
use crate::runtime_primitives::ConsensusEngineId;
use crate::runtime_primitives::weights::Weight;
use super::for_each_tuple;
@@ -90,19 +89,6 @@ pub enum UpdateBalanceOutcome {
AccountKilled,
}
/// Simple trait designed for hooking into a transaction payment.
///
/// It operates over a single generic `AccountId` type.
pub trait MakePayment<AccountId> {
/// Make transaction payment from `who` for an extrinsic of encoded length
/// `encoded_len` bytes. Return `Ok` iff the payment was successful.
fn make_payment(who: &AccountId, weight: Weight) -> Result<(), &'static str>;
}
impl<T> MakePayment<T> for () {
fn make_payment(_: &T, _: Weight) -> Result<(), &'static str> { Ok(()) }
}
/// A trait for finding the author of a block header based on the `PreRuntime` digests contained
/// within it.
pub trait FindAuthor<Author> {