From ba48a0a4c27dd4a1a89faf3fef60597b632930a0 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Mon, 17 Jun 2019 21:46:13 +1200 Subject: [PATCH 01/80] srml-system checks --- .../client/src/block_builder/block_builder.rs | 6 +- .../src/generic/unchecked_extrinsic.rs | 8 +- .../unchecked_mortal_compact_extrinsic.rs | 10 +- .../src/generic/unchecked_mortal_extrinsic.rs | 10 +- core/sr-primitives/src/lib.rs | 63 ++++----- core/sr-primitives/src/testing.rs | 1 + core/sr-primitives/src/traits.rs | 36 ++++- core/test-runtime/src/system.rs | 8 +- node/executor/src/lib.rs | 4 +- srml/balances/src/lib.rs | 1 + srml/executive/src/lib.rs | 6 +- srml/support/src/dispatch.rs | 123 +++++++++++++++++- srml/support/src/error.rs | 62 +++++++++ srml/support/src/lib.rs | 2 + srml/support/src/runtime.rs | 8 ++ srml/system/src/lib.rs | 60 +++++++-- 16 files changed, 329 insertions(+), 79 deletions(-) create mode 100644 srml/support/src/error.rs diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 4564c29aae419..3deaebfc3720c 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -17,7 +17,7 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use parity_codec::Encode; -use runtime_primitives::ApplyOutcome; +use runtime_primitives::ApplyResult; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, @@ -104,11 +104,11 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail) => { + ApplyResult::Success | ApplyResult::ModuleError { .. } => { extrinsics.push(xt); Ok(()) } - Err(e) => { + ApplyResult::ApplyError(e) => { Err(error::Error::ApplyExtrinsicFailed(e)) } } diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index d6e0d60e2c218..6db08297a5caa 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -22,6 +22,7 @@ use std::fmt; use rstd::prelude::*; use crate::codec::{Decode, Encode, Codec, Input, HasCompact}; use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup, Extrinsic}; +use crate::Error; use super::CheckedExtrinsic; #[derive(PartialEq, Eq, Clone, Encode, Decode)] @@ -83,17 +84,18 @@ where Call: Encode + Member, Signature: Member + traits::Verify + Codec, AccountId: Member + MaybeDisplay, - Context: Lookup, + Context: Lookup, { type Checked = CheckedExtrinsic; + type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some(SignatureContent{signed, signature, index}) => { let payload = (index, self.function); let signed = context.lookup(signed)?; if !crate::verify_encoded_lazy(&signature, &payload, &signed) { - return Err(crate::BAD_SIGNATURE) + return Err(Error::BadSignature) } CheckedExtrinsic { signed: Some((signed, payload.0)), diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 36e17fc277cde..7d9beec941a66 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -24,6 +24,7 @@ use runtime_io::blake2_256; use crate::codec::{Decode, Encode, Input, Compact}; use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, Checkable, Extrinsic, SaturatedConversion}; +use crate::Error; use super::{CheckedExtrinsic, Era}; const TRANSACTION_VERSION: u8 = 1; @@ -75,18 +76,19 @@ where AccountId: Member + MaybeDisplay, BlockNumber: SimpleArithmetic, Hash: Encode, - Context: Lookup + Context: Lookup + CurrentHeight + BlockNumberToHash, { type Checked = CheckedExtrinsic; + type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or("transaction birth block ancient")?; + .ok_or(Error::Unknown("transaction birth block ancient"))?; let signed = context.lookup(signed)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { @@ -96,7 +98,7 @@ where signature.verify(payload, &signed) } }) { - return Err(crate::BAD_SIGNATURE) + return Err(Error::BadSignature) } CheckedExtrinsic { signed: Some((signed, (raw_payload.0).0)), diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index 7f92b20edd0c3..dfe7a44b2493e 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -26,6 +26,7 @@ use crate::traits::{ self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, Checkable, Extrinsic, SaturatedConversion }; +use crate::Error; use super::{CheckedExtrinsic, Era}; const TRANSACTION_VERSION: u8 = 1; @@ -76,18 +77,19 @@ where AccountId: Member + MaybeDisplay, BlockNumber: SimpleArithmetic, Hash: Encode, - Context: Lookup + Context: Lookup + CurrentHeight + BlockNumberToHash, { type Checked = CheckedExtrinsic; + type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or("transaction birth block ancient")?; + .ok_or(Error::Unknown("transaction birth block ancient"))?; let signed = context.lookup(signed)?; let raw_payload = (index, self.function, era, h); @@ -98,7 +100,7 @@ where signature.verify(payload, &signed) } }) { - return Err(crate::BAD_SIGNATURE) + return Err(Error::BadSignature) } CheckedExtrinsic { signed: Some((signed, raw_payload.0)), diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 1ef8bc227578c..986a94c006a84 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -48,18 +48,23 @@ pub mod transaction_validity; /// Re-export these since they're only "kind of" generic. pub use generic::{DigestItem, Digest}; -/// A message indicating an invalid signature in extrinsic. -pub const BAD_SIGNATURE: &str = "bad signature in extrinsic"; - -/// Full block error message. -/// -/// This allows modules to indicate that given transaction is potentially valid -/// in the future, but can't be executed in the current state. -/// Note this error should be returned early in the execution to prevent DoS, -/// cause the fees are not being paid if this error is returned. -/// -/// Example: block gas limit is reached (the transaction can be retried in the next block though). -pub const BLOCK_FULL: &str = "block size limit is reached"; +/// Error type +pub enum Error { + /// Unknown error + /// This exists only to make implementation easier. Should be avoid as much as possible. + Unknown(&'static str), + /// Indicating an invalid signature in extrinsic. + BadSignature, + /// Full block error. + /// + /// This allows modules to indicate that given transaction is potentially valid + /// in the future, but can't be executed in the current state. + /// Note this error should be returned early in the execution to prevent DoS, + /// cause the fees are not being paid if this error is returned. + /// + /// Example: block gas limit is reached (the transaction can be retried in the next block though). + BlockFull +} /// Justification type. pub type Justification = Vec; @@ -486,23 +491,6 @@ impl From for AnySignature { } } -#[derive(Eq, PartialEq, Clone, Copy, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[repr(u8)] -/// Outcome of a valid extrinsic application. Capable of being sliced. -pub enum ApplyOutcome { - /// Successful application (extrinsic reported no issue). - Success = 0, - /// Failed application (extrinsic was probably a no-op other than fees). - Fail = 1, -} - -impl codec::Encode for ApplyOutcome { - fn using_encoded R>(&self, f: F) -> R { - f(&[*self as u8]) - } -} - #[derive(Eq, PartialEq, Clone, Copy, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[repr(u8)] @@ -526,8 +514,23 @@ impl codec::Encode for ApplyError { } } +// TODO: custom implement Encode & Decode to make it a two byte value +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] /// Result from attempt to apply an extrinsic. -pub type ApplyResult = Result; +pub enum ApplyResult { + /// Successful application (extrinsic reported no issue). + Success, + /// Failed application (extrinsic was probably a no-op other than fees). + ModuleError { + /// Module index, matching the metadata module index + module: i8, // use i8 instead of u8 because u8 is not supported by parity-codec + /// Module specific error value + error: i8, + }, + /// Invalid extrinsic application. + ApplyError(ApplyError), +} /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 35f3ec476f6d5..af2e2735b5bb4 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -200,6 +200,7 @@ impl Debug for TestXt { impl Checkable for TestXt { type Checked = Self; + type Error = &'static str; fn check(self, _: &Context) -> Result { Ok(self) } } impl traits::Extrinsic for TestXt { diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index b2bb7ab80511d..30db09461dfd4 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -69,26 +69,40 @@ impl Verify for substrate_primitives::sr25519::Signature { } } +/// EnsureOrigin Error type +pub trait EnsureOriginError { + /// Indicates invalid origin + fn invalid_origin() -> Self; +} + /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { /// A return type. type Success; + /// Error type + type Error: EnsureOriginError; /// Perform the origin check. - fn ensure_origin(o: OuterOrigin) -> result::Result { - Self::try_origin(o).map_err(|_| "Invalid origin") + fn ensure_origin(o: OuterOrigin) -> result::Result { + Self::try_origin(o).map_err(|_| Self::Error::invalid_origin()) } /// Perform the origin check. fn try_origin(o: OuterOrigin) -> result::Result; } +impl EnsureOriginError for () { + fn invalid_origin() -> () { } +} + /// Means of changing one type into another in a manner dependent on the source type. pub trait Lookup { /// Type to lookup from. type Source; /// Type to lookup into. type Target; + /// Error type + type Error; /// Attempt a lookup. - fn lookup(&self, s: Self::Source) -> result::Result; + fn lookup(&self, s: Self::Source) -> result::Result; } /// Means of changing one type into another in a manner dependent on the source type. @@ -99,8 +113,10 @@ pub trait StaticLookup { type Source: Codec + Clone + PartialEq + MaybeDebug; /// Type to lookup into. type Target; + /// Error type + type Error; /// Attempt a lookup. - fn lookup(s: Self::Source) -> result::Result; + fn lookup(s: Self::Source) -> result::Result; /// Convert from Target back to Source. fn unlookup(t: Self::Target) -> Self::Source; } @@ -111,13 +127,15 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(x: T) -> result::Result { Ok(x) } + type Error = (); + fn lookup(x: T) -> result::Result { Ok(x) } fn unlookup(x: T) -> T { x } } impl Lookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(&self, x: T) -> result::Result { Ok(x) } + type Error = (); + fn lookup(&self, x: T) -> result::Result { Ok(x) } } /// Get the "current" block number. @@ -701,9 +719,11 @@ pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; pub trait Checkable: Sized { /// Returned if `check` succeeds. type Checked; + /// Indicates why `check` failed + type Error; /// Check self, given an instance of Context. - fn check(self, c: &Context) -> Result; + fn check(self, c: &Context) -> Result; } /// A "checkable" piece of information, used by the standard Substrate Executive in order to @@ -721,6 +741,8 @@ pub trait BlindCheckable: Sized { // Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. impl Checkable for T { type Checked = ::Checked; + type Error = &'static str; + fn check(self, _c: &Context) -> Result { BlindCheckable::check(self) } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index d150a573e86fe..7ebc7fa16775f 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -23,7 +23,7 @@ use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _}; use runtime_primitives::generic; -use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; +use runtime_primitives::{ApplyError, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; use super::{ AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId @@ -237,7 +237,7 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { match utx { Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success), + Extrinsic::IncludeData(_) => ApplyResult::Success, } } @@ -264,13 +264,13 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); - Ok(ApplyOutcome::Success) + ApplyResult::Success } fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { let new_authorities: Vec = new_authorities.iter().cloned().collect(); ::put(new_authorities); - Ok(ApplyOutcome::Success) + ApplyResult::Success } #[cfg(feature = "std")] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 4f0c38d88482a..46527e665882d 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -38,7 +38,7 @@ mod tests { NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; - use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; + use runtime_primitives::{generic::Era, ApplyError, ApplyResult, Perbill}; use {balances, indices, system, staking, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; @@ -912,7 +912,7 @@ mod tests { let r = WasmExecutor::new() .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Ok(ApplyOutcome::Success)); + assert_eq!(r, ApplyResult::Success); runtime_io::with_externalities(&mut t, || { assert_eq!(Balances::total_balance(&alice()), 42); diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 72ec997206550..3095d92527612 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -697,6 +697,7 @@ impl, I: Instance> system::Trait for ElevatedTrait { type Lookup = T::Lookup; type Header = T::Header; type Event = (); + type Error = (); } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index f4299abe47630..eecaa2447a6dd 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -85,7 +85,7 @@ use primitives::{generic::Digest, traits::{ use srml_support::{Dispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; use system::{extrinsics_root, DigestOf}; -use primitives::{ApplyOutcome, ApplyError}; +use primitives::{ApplyResult, ApplyError}; use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity}; use primitives::weights::Weighable; @@ -100,9 +100,9 @@ mod internal { FullBlock, } - pub enum ApplyOutcome { + pub enum ApplyOutcome { Success, - Fail(&'static str), + Fail(Error), } } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 37e40058252dd..ecbfc88178647 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -30,7 +30,7 @@ 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>; +pub type Result = result::Result<(), Error>; /// A lazy call (module function and argument values) that can be executed via its `dispatch` /// method. @@ -40,7 +40,8 @@ pub trait Dispatchable { /// 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; + type Error; + fn dispatch(self, origin: Self::Origin) -> Result; } /// Serializable version of Dispatchable. @@ -217,6 +218,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -237,6 +239,7 @@ macro_rules! decl_module { {} {} {} + {} [] $($t)* ); @@ -251,6 +254,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* () = default; @@ -264,6 +268,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $($rest)* ); @@ -276,6 +281,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $vis:vis fn deposit_event $(<$dpeg:ident $(, $dpeg_instance:ident)?>)* ( @@ -291,6 +297,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $($rest)* ); @@ -303,6 +310,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } {} { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* fn on_finalize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } @@ -316,6 +324,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* } } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $($rest)* ); @@ -328,6 +337,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } {} { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* fn on_finalise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } @@ -345,6 +355,7 @@ macro_rules! decl_module { {} { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* fn on_initialize($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } @@ -358,6 +369,7 @@ macro_rules! decl_module { { fn on_initialize( $( $param_name : $param ),* ) { $( $impl )* } } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $($rest)* ); @@ -370,6 +382,7 @@ macro_rules! decl_module { {} { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* fn on_initialise($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } @@ -387,6 +400,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* fn offchain_worker($($param_name:ident : $param:ty),* ) { $( $impl:tt )* } @@ -399,11 +413,39 @@ macro_rules! decl_module { { $( $deposit_event )* } { $( $on_initialize )* } { $( $on_finalize )* } + { $( $error_type )* } { fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } } [ $($t)* ] $($rest)* ); }; + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + 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])* + type Error = $error_type:ty; + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name> + for enum $call_type where origin: $origin_type, system = $system + { $( $deposit_event )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } + { $error_type } + [ $($t)* ] + $($rest)* + ); + }; // This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse. (@normalize $(#[$attr:meta])* @@ -416,6 +458,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $error_type:ty } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* #[weight = $weight:expr] @@ -434,6 +477,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $error_type } [ $($t)* $(#[doc = $doc_attr])* @@ -458,6 +502,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $fn_vis:vis fn $fn_name:ident( @@ -475,6 +520,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $(#[doc = $doc_attr])* #[weight = $crate::dispatch::TransactionWeight::default()] @@ -484,6 +530,36 @@ macro_rules! decl_module { $($rest)* ); }; + // Add default Error if none supplied + (@normalize + $(#[$attr:meta])* + pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + 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)* ] + $($rest:tt)* + ) => { + $crate::decl_module!(@normalize + $(#[$attr])* + pub struct $mod_type<$trait_instance: $trait_name> + for enum $call_type where origin: $origin_type, system = $system + { $( $deposit_event )* } + { $( $on_initialize )* } + { $( $on_finalize )* } + { $( $offchain )* } + { Error } + [ $($t)* ] + $($rest)* + ); + $crate::decl_error! { + pub enum Error { + } + } + }; // Ignore any ident which is not `origin` with type `T::Origin`. (@normalize $(#[$attr:meta])* @@ -493,6 +569,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -516,6 +593,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -539,6 +617,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* $(#[weight = $weight:expr])? @@ -555,6 +634,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } [ $($t)* ] $(#[doc = $doc_attr])* @@ -575,6 +655,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $( $error_type:tt )* } [ $($t:tt)* ] ) => { $crate::decl_module!(@imp @@ -587,6 +668,7 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } + { $( $error_type )* } ); }; @@ -745,13 +827,14 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; root; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( root $(, $param:ident : $param_ty:ty )* ) { $( $impl:tt )* } ) => { $(#[doc = $doc_attr])* #[allow(unreachable_code)] - $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result { + $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result<$error_type> { { $( $impl )* } Ok(()) } @@ -761,6 +844,7 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; root; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( @@ -777,6 +861,7 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; $ignore:ident; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( @@ -786,7 +871,7 @@ macro_rules! decl_module { $(#[doc = $doc_attr])* $vis fn $name( $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::Result { + ) -> $crate::dispatch::Result<$error_type> { { $( $impl )* } Ok(()) } @@ -796,6 +881,7 @@ macro_rules! decl_module { (@impl_function $module:ident<$trait_instance:ident: $trait_name:ident$(, $instance:ident: $instantiable:path)?>; $origin_ty:ty; + $error_type:ty; $ignore:ident; $(#[doc = $doc_attr:tt])* $vis:vis fn $name:ident ( @@ -939,6 +1025,7 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } + { $error_type:ty } ) => { $crate::__check_reserved_fn_name! { $($fn_name)* @@ -985,6 +1072,7 @@ macro_rules! decl_module { @impl_function $mod_type<$trait_instance: $trait_name $(, $fn_instance: $fn_instantiable)?>; $origin_type; + $error_type; $from; $(#[doc = $doc_attr])* $fn_vis fn $fn_name ( @@ -1087,7 +1175,8 @@ macro_rules! decl_module { { type Trait = $trait_instance; type Origin = $origin_type; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::Result { + type Error = $error_type; + fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::Result { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1110,7 +1199,7 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { #[doc(hidden)] - pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { + pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { d.dispatch(origin) } } @@ -1135,6 +1224,25 @@ macro_rules! impl_outer_dispatch { $module:ident::$camelcase:ident, )* } + ) => { + $crate::impl_outer_dispatch! { + $(#[$attr])* + pub enum $call_type for $runtime where origin: $origin { + type Error = &'static str; + $( + $module::$camelcase, + )* + } + } + }; + ( + $(#[$attr:meta])* + pub enum $call_type:ident for $runtime:ident where origin: $origin:ty { + type Error = $error_type:ty; + $( + $module:ident::$camelcase:ident, + )* + } ) => { $(#[$attr])* #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] @@ -1154,7 +1262,8 @@ macro_rules! impl_outer_dispatch { impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; - fn dispatch(self, origin: $origin) -> $crate::dispatch::Result { + type Error = $error_type; + fn dispatch(self, origin: $origin) -> $crate::dispatch::Result { match self { $( $call_type::$camelcase(call) => call.dispatch(origin), )* } diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs new file mode 100644 index 0000000000000..5f16571589c64 --- /dev/null +++ b/srml/support/src/error.rs @@ -0,0 +1,62 @@ +#[macro_export] +macro_rules! impl_outer_error { + ( + $(#[$attr:meta])* + pub enum $name:ident { + $( $modules:tt , )* + } + ) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] + #[cfg_attr(feature = "std", derive(Debug, $crate::Serialize, $crate::Deserialize))] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum $name { + $( + $modules( $modules::Error ), + )* + } + } +} + + +#[macro_export] +macro_rules! decl_error { + ( + $(#[$attr:meta])* + pub enum Error { + $( + $errors:tt + )* + } + ) => { + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode)] + #[cfg_attr(feature = "std", derive(Debug))] + $(#[$attr])* + #[allow(non_camel_case_types)] + pub enum Error { + Unknown(&'static str), + $( + $errors + )* + } + impl From for () { + fn from(_: Error) -> () { () } + } + impl Into for Error { + fn into(self) -> u8 { + match self { + Error::Unknown(_) => 0, + _ => $crate::codec::Encode::using_encoded(&self, |s| s[0]), + } + } + } + + impl From<&'static str> for Error { + fn from(val: &'static str) -> Error { + Error::Unknown(val) + } + } + } +} diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index ae825397a6ae4..cf09f0f634adc 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -54,6 +54,8 @@ mod runtime; pub mod inherent; #[macro_use] pub mod unsigned; +#[macro_use] +pub mod error; mod double_map; pub mod traits; diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index 6bccac0d4eff0..11085b2a55f47 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -238,6 +238,12 @@ macro_rules! construct_runtime { $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } ),* ); + $crate::__decl_outer_error!( + $runtime; + $( + $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } + ),* + ); $crate::__decl_all_modules!( $runtime; ; @@ -444,6 +450,7 @@ macro_rules! __create_decl_macro { __create_decl_macro!(__decl_outer_event, impl_outer_event, Event, $); __create_decl_macro!(__decl_outer_origin, impl_outer_origin, Origin, $); +__create_decl_macro!(__decl_outer_error, impl_outer_error, Error, $); /// A macro that defines all modules as an associated types of the Runtime type. #[macro_export] @@ -593,6 +600,7 @@ macro_rules! __decl_outer_dispatch { ) => { $crate::impl_outer_dispatch!( pub enum Call for $runtime where origin: Origin { + type Error = Error; $( $parsed_modules::$parsed_name, )* } ); diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 73f8c942091e3..1256808d50498 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -76,15 +76,19 @@ use serde::Serialize; use rstd::prelude::*; #[cfg(any(feature = "std", test))] use rstd::map; -use primitives::{generic, traits::{self, CheckEqual, SimpleArithmetic, - SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash, - MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, Lookup, -}}; +use primitives::{ + generic, Error as PrimitiveError, + traits::{ + self, CheckEqual, SimpleArithmetic, + SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash, + MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, Lookup, + } +}; #[cfg(any(feature = "std", test))] use primitives::traits::Zero; use substrate_primitives::storage::well_known_keys; use srml_support::{ - storage, decl_module, decl_event, decl_storage, StorageDoubleMap, StorageValue, + storage, decl_module, decl_event, decl_storage, decl_error, StorageDoubleMap, StorageValue, StorageMap, Parameter, for_each_tuple, traits::Contains }; use safe_mix::TripletMix; @@ -184,6 +188,9 @@ pub trait Trait: 'static + Eq + Clone { /// The aggregated event type of the runtime. type Event: Parameter + Member + From; + + /// The aggregated error type of the runtime. + type Error: Parameter + Member + From; } pub type DigestOf = generic::Digest<::Hash>; @@ -194,6 +201,8 @@ pub type KeyValue = (Vec, Vec); decl_module! { pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + /// Deposits an event into this block's event record. pub fn deposit_event(event: T::Event) { Self::deposit_event_indexed(&[], event); @@ -262,6 +271,27 @@ decl_event!( } ); +decl_error! { + /// Error for the System module + pub enum Error { + BadSignature, + BlockFull, + RequireSignedOrigin, + RequireRootOrigin, + RequireNoOrigin, + } +} + +impl From for Error { + fn from(err: PrimitiveError) -> Error { + match err { + PrimitiveError::Unknown(err) => Error::Unknown(err), + PrimitiveError::BadSignature => Error::BadSignature, + PrimitiveError::BlockFull => Error::BlockFull, + } + } +} + /// Origin for the System module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] @@ -378,6 +408,7 @@ impl< AccountId, > EnsureOrigin for EnsureRoot { type Success = (); + type Error = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Root => Ok(()), @@ -392,6 +423,7 @@ impl< AccountId, > EnsureOrigin for EnsureSigned { type Success = AccountId; + type Error = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(who) => Ok(who), @@ -407,6 +439,7 @@ impl< AccountId: PartialEq + Clone, > EnsureOrigin for EnsureSignedBy { type Success = AccountId; + type Error = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(ref who) if Who::contains(who) => Ok(who.clone()), @@ -421,6 +454,7 @@ impl< AccountId, > EnsureOrigin for EnsureNone { type Success = (); + type Error = (); fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::None => Ok(()), @@ -432,6 +466,7 @@ impl< pub struct EnsureNever(::rstd::marker::PhantomData); impl EnsureOrigin for EnsureNever { type Success = T; + type Error = (); fn try_origin(o: O) -> Result { Err(o) } @@ -439,32 +474,32 @@ impl EnsureOrigin for EnsureNever { /// Ensure that the origin `o` represents a signed extrinsic (i.e. transaction). /// Returns `Ok` with the account that signed the extrinsic or an `Err` otherwise. -pub fn ensure_signed(o: OuterOrigin) -> Result +pub fn ensure_signed(o: OuterOrigin) -> Result where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::Signed(t)) => Ok(t), - _ => Err("bad origin: expected to be a signed origin"), + _ => Err(Error::RequireSignedOrigin), } } /// Ensure that the origin `o` represents the root. Returns `Ok` or an `Err` otherwise. -pub fn ensure_root(o: OuterOrigin) -> Result<(), &'static str> +pub fn ensure_root(o: OuterOrigin) -> Result<(), Error> where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::Root) => Ok(()), - _ => Err("bad origin: expected to be a root origin"), + _ => Err(Error::RequireRootOrigin), } } /// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. -pub fn ensure_none(o: OuterOrigin) -> Result<(), &'static str> +pub fn ensure_none(o: OuterOrigin) -> Result<(), Error> where OuterOrigin: Into, OuterOrigin>> { match o.into() { Ok(RawOrigin::None) => Ok(()), - _ => Err("bad origin: expected to be no origin"), + _ => Err(Error::RequireNoOrigin), } } @@ -741,7 +776,8 @@ impl Default for ChainContext { impl Lookup for ChainContext { type Source = ::Source; type Target = ::Target; - fn lookup(&self, s: Self::Source) -> rstd::result::Result { + type Error = ::Error; + fn lookup(&self, s: Self::Source) -> rstd::result::Result { ::lookup(s) } } From 52c6b90a86c911d705e900bb87137ae0f772056e Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Tue, 18 Jun 2019 20:24:15 +1200 Subject: [PATCH 02/80] wip --- .../client/src/block_builder/block_builder.rs | 2 +- core/sr-primitives/src/lib.rs | 31 +++- core/sr-primitives/src/traits.rs | 12 +- srml/balances/src/lib.rs | 4 +- srml/contract/src/gas.rs | 4 +- srml/executive/src/lib.rs | 173 +++++++++--------- srml/indices/src/lib.rs | 2 + srml/support/src/dispatch.rs | 33 ++-- srml/support/src/error.rs | 134 +++++++++++++- srml/system/src/lib.rs | 26 ++- 10 files changed, 297 insertions(+), 124 deletions(-) diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 3deaebfc3720c..48ef76c480660 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -104,7 +104,7 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - ApplyResult::Success | ApplyResult::ModuleError { .. } => { + ApplyResult::Success | ApplyResult::DispatchError(_) => { extrinsics.push(xt); Ok(()) } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 986a94c006a84..ca095aaa01494 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -66,6 +66,17 @@ pub enum Error { BlockFull } +// Exists for for backward compatibility purpose. +impl From for &str { + fn from(err: Error) -> &'static str { + match err { + Error::Unknown(val) => val, + Error::BadSignature => "bad signature in extrinsic", + Error::BlockFull => "block size limit is reached", + } + } +} + /// Justification type. pub type Justification = Vec; @@ -514,6 +525,19 @@ impl codec::Encode for ApplyError { } } +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +/// Reason why a dispatch call failed +pub struct DispatchError { + /// Module index, matching the metadata module index + pub module: i8, // use i8 instead of u8 because u8 is not supported by parity-codec + /// Module specific error value + pub error: i8, + /// Optional error message + #[codec(skip)] + pub message: Option<&'static str>, +} + // TODO: custom implement Encode & Decode to make it a two byte value #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] @@ -522,12 +546,7 @@ pub enum ApplyResult { /// Successful application (extrinsic reported no issue). Success, /// Failed application (extrinsic was probably a no-op other than fees). - ModuleError { - /// Module index, matching the metadata module index - module: i8, // use i8 instead of u8 because u8 is not supported by parity-codec - /// Module specific error value - error: i8, - }, + DispatchError(DispatchError), /// Invalid extrinsic application. ApplyError(ApplyError), } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 30db09461dfd4..2885b7ce51f90 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -113,8 +113,8 @@ pub trait StaticLookup { type Source: Codec + Clone + PartialEq + MaybeDebug; /// Type to lookup into. type Target; - /// Error type - type Error; + /// Error type. + type Error: Into<&'static str>; // Into<&'static str> for backward compatibility purpose. /// Attempt a lookup. fn lookup(s: Self::Source) -> result::Result; /// Convert from Target back to Source. @@ -127,15 +127,15 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - type Error = (); - fn lookup(x: T) -> result::Result { Ok(x) } + type Error = &'static str; + fn lookup(x: T) -> result::Result { Ok(x) } fn unlookup(x: T) -> T { x } } impl Lookup for IdentityLookup { type Source = T; type Target = T; - type Error = (); - fn lookup(&self, x: T) -> result::Result { Ok(x) } + type Error = &'static str; + fn lookup(&self, x: T) -> result::Result { Ok(x) } } /// Get the "current" block number. diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 3095d92527612..97bc4976b1d9f 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -371,7 +371,7 @@ decl_module! { #[compact] value: T::Balance ) { let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; + let dest = T::Lookup::lookup(dest).map_err(Into::into)?; >::transfer(&transactor, &dest, value)?; } @@ -393,7 +393,7 @@ decl_module! { #[compact] new_free: T::Balance, #[compact] new_reserved: T::Balance ) { - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).map_err(Into::into)?; let current_free = >::get(&who); if new_free > current_free { diff --git a/srml/contract/src/gas.rs b/srml/contract/src/gas.rs index 1ea519634463c..c8519cdc4d558 100644 --- a/srml/contract/src/gas.rs +++ b/srml/contract/src/gas.rs @@ -15,7 +15,7 @@ // along with Substrate. If not, see . use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; -use runtime_primitives::BLOCK_FULL; +use runtime_primitives::Error as PrimitiveError; use runtime_primitives::traits::{CheckedMul, CheckedSub, Zero, SaturatedConversion}; use srml_support::{StorageValue, traits::{OnUnbalanced, ExistenceRequirement, WithdrawReason, Currency, Imbalance}}; @@ -207,7 +207,7 @@ pub fn buy_gas( let gas_available = >::block_gas_limit() - >::gas_spent(); if gas_limit > gas_available { // gas limit reached, revert the transaction and retry again in the future - return Err(BLOCK_FULL); + return Err(PrimitiveError::BlockFull.into()); } // Buy the specified amount of gas. diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index eecaa2447a6dd..4bfb115880edb 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -76,34 +76,23 @@ use rstd::prelude::*; use rstd::marker::PhantomData; -use rstd::result; -use primitives::{generic::Digest, traits::{ - self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, - OnInitialize, NumberFor, Block as BlockT, OffchainWorker, - ValidateUnsigned, -}}; +use rstd::convert::TryInto; +use primitives::{ + generic::Digest, ApplyResult, ApplyError, DispatchError, + traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, + OnInitialize, NumberFor, Block as BlockT, OffchainWorker, + ValidateUnsigned, + } +}; use srml_support::{Dispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; use system::{extrinsics_root, DigestOf}; -use primitives::{ApplyResult, ApplyError}; use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity}; use primitives::weights::Weighable; mod internal { pub const MAX_TRANSACTIONS_WEIGHT: u32 = 4 * 1024 * 1024; - - pub enum ApplyError { - BadSignature(&'static str), - Stale, - Future, - CantPay, - FullBlock, - } - - pub enum ApplyOutcome { - Success, - Fail(Error), - } } /// Trait that can be used to execute a block. @@ -127,11 +116,12 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, + Error: Into + TryInto, > ExecuteBlock for Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -147,11 +137,12 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, + Error: Into + TryInto, > Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, + CallOf: Dispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -228,30 +219,30 @@ where /// Apply extrinsic outside of the block execution function. /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt /// hashes. - pub fn apply_extrinsic(uxt: Block::Extrinsic) -> result::Result { + pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyResult { let encoded = uxt.encode(); let encoded_len = encoded.len(); - match Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) { - Ok(internal::ApplyOutcome::Success) => Ok(ApplyOutcome::Success), - Ok(internal::ApplyOutcome::Fail(_)) => Ok(ApplyOutcome::Fail), - Err(internal::ApplyError::CantPay) => Err(ApplyError::CantPay), - Err(internal::ApplyError::BadSignature(_)) => Err(ApplyError::BadSignature), - Err(internal::ApplyError::Stale) => Err(ApplyError::Stale), - Err(internal::ApplyError::Future) => Err(ApplyError::Future), - Err(internal::ApplyError::FullBlock) => Err(ApplyError::FullBlock), - } + Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded)) } /// Apply an extrinsic inside the block execution function. fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { let l = uxt.encode().len(); match Self::apply_extrinsic_with_len(uxt, l, None) { - Ok(internal::ApplyOutcome::Success) => (), - Ok(internal::ApplyOutcome::Fail(e)) => runtime_io::print(e), - Err(internal::ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), - Err(internal::ApplyError::BadSignature(_)) => panic!("All extrinsics should be properly signed"), - Err(internal::ApplyError::Stale) | Err(internal::ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), - Err(internal::ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), + ApplyResult::Success => (), + ApplyResult::DispatchError(e) => { + runtime_io::print("Error:"); + // as u8 first to ensure not using sign-extend + runtime_io::print(e.module as u8 as u64); + runtime_io::print(e.error as u8 as u64); + if let Some(msg) = e.message { + runtime_io::print(msg); + } + }, + ApplyResult::ApplyError(ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), + ApplyResult::ApplyError(ApplyError::BadSignature) => panic!("All extrinsics should be properly signed"), + ApplyResult::ApplyError(ApplyError::Stale) | ApplyResult::ApplyError(ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), + ApplyResult::ApplyError(ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), } } @@ -260,47 +251,58 @@ where uxt: Block::Extrinsic, encoded_len: usize, to_note: Option>, - ) -> result::Result { + ) -> ApplyResult { // Verify that the signature is good. - let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?; - - // Check the weight of the block if that extrinsic is applied. - let weight = xt.weight(encoded_len); - if >::all_extrinsics_weight() + weight > internal::MAX_TRANSACTIONS_WEIGHT { - return Err(internal::ApplyError::FullBlock); - } + match uxt.check(&Default::default()) { + Err(_) => ApplyResult::ApplyError(ApplyError::BadSignature), + Ok(xt) => { + // Check the weight of the block if that extrinsic is applied. + let weight = xt.weight(encoded_len); + if >::all_extrinsics_weight() + weight > internal::MAX_TRANSACTIONS_WEIGHT { + return ApplyResult::ApplyError(ApplyError::FullBlock); + } - if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { - // check index - let expected_index = >::account_nonce(sender); - if index != &expected_index { return Err( - if index < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future } - ) } - // pay any fees - Payment::make_payment(sender, encoded_len).map_err(|_| internal::ApplyError::CantPay)?; - - // AUDIT: Under no circumstances may this function panic from here onwards. - // FIXME: ensure this at compile-time (such as by not defining a panic function, forcing - // a linker error unless the compiler can prove it cannot be called). - // increment nonce in storage - >::inc_account_nonce(sender); - } + if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { + // check index + let expected_index = >::account_nonce(sender); + if index != &expected_index { + return if index < &expected_index { + ApplyResult::ApplyError(ApplyError::Stale) + } else { + ApplyResult::ApplyError(ApplyError::Future) + } + } + // pay any fees + // TODO: propagate why can't pay + match Payment::make_payment(sender, encoded_len) { + Err(_) => return ApplyResult::ApplyError(ApplyError::CantPay), + Ok(_) => () + }; + + // AUDIT: Under no circumstances may this function panic from here onwards. + // FIXME: ensure this at compile-time (such as by not defining a panic function, forcing + // a linker error unless the compiler can prove it cannot be called). + // increment nonce in storage + >::inc_account_nonce(sender); + } - // Make sure to `note_extrinsic` only after we know it's going to be executed - // to prevent it from leaking in storage. - if let Some(encoded) = to_note { - >::note_extrinsic(encoded); - } + // Make sure to `note_extrinsic` only after we know it's going to be executed + // to prevent it from leaking in storage. + if let Some(encoded) = to_note { + >::note_extrinsic(encoded); + } - // Decode parameters and dispatch - let (f, s) = xt.deconstruct(); - let r = f.dispatch(s.into()); - >::note_applied_extrinsic(&r, encoded_len as u32); + // Decode parameters and dispatch + let (f, s) = xt.deconstruct(); + let r = f.dispatch(s.into()); + >::note_applied_extrinsic(r.is_ok(), encoded_len as u32); - r.map(|_| internal::ApplyOutcome::Success).or_else(|e| match e { - primitives::BLOCK_FULL => Err(internal::ApplyError::FullBlock), - e => Ok(internal::ApplyOutcome::Fail(e)) - }) + match r { + Ok(_) => ApplyResult::Success, + Err(e) => ApplyResult::DispatchError(e.into()), + } + } + } } fn final_checks(header: &System::Header) { @@ -340,12 +342,19 @@ where let xt = match uxt.check(&Default::default()) { // Checks out. Carry on. Ok(xt) => xt, - // An unknown account index implies that the transaction may yet become valid. - Err("invalid account index") => return TransactionValidity::Unknown(INVALID_INDEX), - // Technically a bad signature could also imply an out-of-date account index, but - // that's more of an edge case. - Err(primitives::BAD_SIGNATURE) => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), - Err(_) => return TransactionValidity::Invalid(UNKNOWN_ERROR), + Err(err) => { + match err.try_into() { + // An unknown account index implies that the transaction may yet become valid. + // TODO: avoid hardcoded error string here + Ok(system::Error::Unknown("invalid account index")) => + return TransactionValidity::Unknown(INVALID_INDEX), + // Technically a bad signature could also imply an out-of-date account index, but + // that's more of an edge case. + Ok(system::Error::BadSignature) => + return TransactionValidity::Invalid(ApplyError::BadSignature as i8), + _ => return TransactionValidity::Invalid(UNKNOWN_ERROR), + } + } }; match (xt.sender(), xt.index()) { diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs index 45487e3b51cd1..cbb2079fc824f 100644 --- a/srml/indices/src/lib.rs +++ b/srml/indices/src/lib.rs @@ -224,6 +224,8 @@ impl OnNewAccount for Module { impl StaticLookup for Module { type Source = address::Address; type Target = T::AccountId; + type Error = &'static str; + fn lookup(a: Self::Source) -> result::Result { Self::lookup_address(a).ok_or("invalid account index") } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index ecbfc88178647..2ab241b250006 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -29,8 +29,11 @@ pub use sr_primitives::weights::{TransactionWeight, Weighable, Weight}; 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<(), Error>; +/// or an error. +pub type DispatchResult = result::Result<(), Error>; + +/// Result with string error message. This exists for backward compatibility purpose. +pub type Result = DispatchResult<&'static str>; /// A lazy call (module function and argument values) that can be executed via its `dispatch` /// method. @@ -41,7 +44,7 @@ pub trait Dispatchable { type Origin; type Trait; type Error; - fn dispatch(self, origin: Self::Origin) -> Result; + fn dispatch(self, origin: Self::Origin) -> DispatchResult; } /// Serializable version of Dispatchable. @@ -533,7 +536,10 @@ macro_rules! decl_module { // Add default Error if none supplied (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident< + $trait_instance:ident: + $trait_name:ident$(, $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 )* } @@ -545,7 +551,9 @@ macro_rules! decl_module { ) => { $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type< + $trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)? + > for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } { $( $on_initialize )* } @@ -555,10 +563,7 @@ macro_rules! decl_module { [ $($t)* ] $($rest)* ); - $crate::decl_error! { - pub enum Error { - } - } + pub type Error = &'static str; }; // Ignore any ident which is not `origin` with type `T::Origin`. (@normalize @@ -834,7 +839,7 @@ macro_rules! decl_module { ) => { $(#[doc = $doc_attr])* #[allow(unreachable_code)] - $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::Result<$error_type> { + $vis fn $name($( $param: $param_ty ),* ) -> $crate::dispatch::DispatchResult<$error_type> { { $( $impl )* } Ok(()) } @@ -871,7 +876,7 @@ macro_rules! decl_module { $(#[doc = $doc_attr])* $vis fn $name( $origin: $origin_ty $(, $param: $param_ty )* - ) -> $crate::dispatch::Result<$error_type> { + ) -> $crate::dispatch::DispatchResult<$error_type> { { $( $impl )* } Ok(()) } @@ -1176,7 +1181,7 @@ macro_rules! decl_module { type Trait = $trait_instance; type Origin = $origin_type; type Error = $error_type; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::Result { + fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResult { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1199,7 +1204,7 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { #[doc(hidden)] - pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::Result { + pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::DispatchResult { d.dispatch(origin) } } @@ -1263,7 +1268,7 @@ macro_rules! impl_outer_dispatch { type Origin = $origin; type Trait = $call_type; type Error = $error_type; - fn dispatch(self, origin: $origin) -> $crate::dispatch::Result { + fn dispatch(self, origin: $origin) -> $crate::dispatch::DispatchResult { match self { $( $call_type::$camelcase(call) => call.dispatch(origin), )* } diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 5f16571589c64..3b943b953cb2a 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -2,20 +2,144 @@ macro_rules! impl_outer_error { ( $(#[$attr:meta])* - pub enum $name:ident { - $( $modules:tt , )* + pub enum $name:ident for $runtime:ident { + $( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)? } + ) => { + $crate::impl_outer_error! { + $(#[$attr])* + pub enum $name for $runtime where system = system { + $( $module $( <$generic $(, $instance )? > )?, )* + } + } + }; + ( + $(#[$attr:meta])* + pub enum $name:ident for $runtime:ident where system = $system:ident { + $( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)? + } + ) => { + $crate::impl_outer_error!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $module $( <$generic $(, $instance )? > )*, )* }; + ); + }; + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { + $module:ident $( )?, + $( $rest_module:tt )* + }; + $( $parsed:tt )* + ) => { + $crate::impl_outer_error!( + $( #[$attr] )*; + $name; + $runtime; + $system; + Modules { $( $rest_module )* }; + $( $parsed )* $module $( <$runtime $(, $instance )? > )?, + ); + }; + + // The main macro expansion that actually renders the Error enum. + + ( + $(#[$attr:meta])*; + $name:ident; + $runtime:ident; + $system:ident; + Modules { }; + $( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)* ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] - #[cfg_attr(feature = "std", derive(Debug, $crate::Serialize, $crate::Deserialize))] + #[derive(Clone, PartialEq, Eq, $crate::codec::Encode)] + #[cfg_attr(feature = "std", derive(Debug))] $(#[$attr])* #[allow(non_camel_case_types)] pub enum $name { + system($system::Error), $( - $modules( $modules::Error ), + $module($module::Error), )* } + + impl From<$system::Error> for $name { + fn from(err: $system::Error) -> Self { + $name::system(err) + } + } + + impl TryInto<$system::Error> for $name { + type Error = Self; + fn try_into(self) -> $crate::dispatch::result::Result<$modules::Error, Self::Error> { + if let $name::system(err) = self { + Ok(err) + } else { + Err(self) + } + } + } + + impl Into<$crate::runtime_primitives::DispatchError> for $name { + fn into(self) -> $crate::runtime_primitives::DispatchError { + match self { + system(err) => match err { + $system::Error::Unknown(msg) => + $crate::runtime_primitives::DispatchError { + module: 0, + error: 0, + message: msg, + } + _ => $crate::runtime_primitives::DispatchError { + module: 0, + error: err.into(), + message: None, + } + }, + $( + $modules(err) => match err { + $modules::Error::Unknown(msg) => + $crate::runtime_primitives::DispatchError { + module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), + error: 0, + message: msg, + } + _ => $crate::runtime_primitives::DispatchError { + module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), + error: err.into(), + message: None, + } + } + )* + } + } + } + + $( + impl From<$modules::Error> for $name { + fn from(err: $system::Error) -> Self { + $name::$modules(err) + } + } + + impl TryInto<$modules::Error> for $name { + type Error = Self; + fn try_into(self) -> $crate::dispatch::result::Result<$modules::Error, Self::Error> { + if let $name::$modules(err) = self { + Ok(err) + } else { + Err(self) + } + } + } + )* } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 1256808d50498..2f5ece98efe55 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -292,6 +292,20 @@ impl From for Error { } } +// Exists for for backward compatibility purpose. +impl From for &str { + fn from(err: Error) -> &'static str { + match err { + Error::Unknown(val) => val, + Error::BadSignature => "bad signature in extrinsic", + Error::BlockFull => "block size limit is reached", + Error::RequireSignedOrigin => "bad origin: expected to be a signed origin", + Error::RequireRootOrigin => "bad origin: expected to be a root origin", + Error::RequireNoOrigin => "bad origin: expected to be no origin", + } + } +} + /// Origin for the System module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] @@ -738,10 +752,10 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &Result<(), &'static str>, encoded_len: u32) { - Self::deposit_event(match r { - Ok(_) => Event::ExtrinsicSuccess, - Err(_) => Event::ExtrinsicFailed, + pub fn note_applied_extrinsic(success: bool, encoded_len: u32) { + Self::deposit_event(match success { + true => Event::ExtrinsicSuccess, + false => Event::ExtrinsicFailed, }.into()); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; @@ -867,8 +881,8 @@ mod tests { System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(()), 0); - System::note_applied_extrinsic(&Err(""), 0); + System::note_applied_extrinsic(true, 0); + System::note_applied_extrinsic(false, 0); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalize(); From bd7228fd06388229bcceac16ab6df1b3c5c69d81 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Tue, 18 Jun 2019 23:51:55 +1200 Subject: [PATCH 03/80] more modules compiles --- core/sr-primitives/src/traits.rs | 4 ++++ srml/contract/src/lib.rs | 2 +- srml/council/src/motions.rs | 14 +++++++++----- srml/council/src/seats.rs | 6 +++--- srml/democracy/src/lib.rs | 10 +++++----- srml/staking/src/lib.rs | 7 ++++--- srml/sudo/src/lib.rs | 7 ++++--- srml/support/src/error.rs | 30 +++++++++++++++--------------- srml/treasury/src/lib.rs | 6 +++--- 9 files changed, 48 insertions(+), 38 deletions(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 2885b7ce51f90..67b05cfe3102c 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -93,6 +93,10 @@ impl EnsureOriginError for () { fn invalid_origin() -> () { } } +impl EnsureOriginError for &'static str { + fn invalid_origin() -> &'static str { "Invalid origin" } +} + /// Means of changing one type into another in a manner dependent on the source type. pub trait Lookup { /// Type to lookup from. diff --git a/srml/contract/src/lib.rs b/srml/contract/src/lib.rs index b9c8976cc04be..04c63fb4ee027 100644 --- a/srml/contract/src/lib.rs +++ b/srml/contract/src/lib.rs @@ -397,7 +397,7 @@ decl_module! { data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; + let dest = T::Lookup::lookup(dest).map_err(Into::into)?; // Pay for the gas upfront. // diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index a53752d71f905..c7b0eb51c2439 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -18,7 +18,7 @@ use rstd::{prelude::*, result}; use substrate_primitives::u32_trait::Value as U32; -use primitives::traits::{Hash, EnsureOrigin}; +use primitives::traits::{Hash, EnsureOrigin, EnsureOriginError}; use srml_support::{ dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure @@ -259,10 +259,11 @@ pub fn ensure_council_members(o: OuterOrigin, n: MemberC pub struct EnsureMember(::rstd::marker::PhantomData); impl< - O: Into, O>> + From>, + O: Into, O>> + From> + EnsureOriginError, AccountId > EnsureOrigin for EnsureMember { type Success = AccountId; + type Error = O; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Member(id) => Ok(id), @@ -273,11 +274,12 @@ impl< pub struct EnsureMembers(::rstd::marker::PhantomData<(N, AccountId)>); impl< - O: Into, O>> + From>, + O: Into, O>> + From> + EnsureOriginError, N: U32, AccountId, > EnsureOrigin for EnsureMembers { type Success = (MemberCount, MemberCount); + type Error = O; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), @@ -290,12 +292,13 @@ pub struct EnsureProportionMoreThan( ::rstd::marker::PhantomData<(N, D, AccountId)> ); impl< - O: Into, O>> + From>, + O: Into, O>> + From> + EnsureOriginError, N: U32, D: U32, AccountId, > EnsureOrigin for EnsureProportionMoreThan { type Success = (); + type Error = O; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), @@ -308,12 +311,13 @@ pub struct EnsureProportionAtLeast( ::rstd::marker::PhantomData<(N, D, AccountId)> ); impl< - O: Into, O>> + From>, + O: Into, O>> + From> + EnsureOriginError, N: U32, D: U32, AccountId, > EnsureOrigin for EnsureProportionAtLeast { type Success = (); + type Error = O; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), diff --git a/srml/council/src/seats.rs b/srml/council/src/seats.rs index 84b6f388f29fc..7d9903868bc84 100644 --- a/srml/council/src/seats.rs +++ b/srml/council/src/seats.rs @@ -213,7 +213,7 @@ decl_module! { #[compact] assumed_vote_index: VoteIndex ) { let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).map_err(Into::into)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); @@ -352,7 +352,7 @@ decl_module! { "stake deposited to present winner and be added to leaderboard should be non-zero" ); - let candidate = T::Lookup::lookup(candidate)?; + let candidate = T::Lookup::lookup(candidate).map_err(Into::into)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; let bad_presentation_punishment = @@ -417,7 +417,7 @@ decl_module! { /// Note: A tally should happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. fn remove_member(who: ::Source) { - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).map_err(Into::into)?; let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() .into_iter() .filter(|i| i.0 != who) diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 0fead411c8796..afefa480ed615 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -191,23 +191,23 @@ pub trait Trait: system::Trait + Sized { /// Origin from which the next tabled referendum may be forced. This is a normal /// "super-majority-required" referendum. - type ExternalOrigin: EnsureOrigin; + type ExternalOrigin: EnsureOrigin; /// Origin from which the next tabled referendum may be forced; this allows for the tabling of /// a majority-carries referendum. - type ExternalMajorityOrigin: EnsureOrigin; + type ExternalMajorityOrigin: EnsureOrigin; /// Origin from which emergency referenda may be scheduled. - type EmergencyOrigin: EnsureOrigin; + type EmergencyOrigin: EnsureOrigin; /// Minimum voting period allowed for an emergency referendum. type EmergencyVotingPeriod: Get; /// Origin from which any referenda may be cancelled in an emergency. - type CancellationOrigin: EnsureOrigin; + type CancellationOrigin: EnsureOrigin; /// Origin for anyone able to veto proposals. - type VetoOrigin: EnsureOrigin; + type VetoOrigin: EnsureOrigin; /// Period in blocks where an external proposal may not be re-submitted after being vetoed. type CooloffPeriod: Get; diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 086f78bd53379..2241d3c02f7ab 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -637,7 +637,7 @@ decl_module! { return Err("stash already bonded") } - let controller = T::Lookup::lookup(controller)?; + let controller = T::Lookup::lookup(controller).map_err(Into::into)?; if >::exists(&controller) { return Err("controller already paired") @@ -795,7 +795,8 @@ decl_module! { let targets = targets.into_iter() .take(MAX_NOMINATIONS) .map(T::Lookup::lookup) - .collect::, &'static str>>()?; + .collect::, _>>() + .map_err(Into::into)?; >::remove(stash); >::insert(stash, targets); @@ -852,7 +853,7 @@ decl_module! { fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or("not a stash")?; - let controller = T::Lookup::lookup(controller)?; + let controller = T::Lookup::lookup(controller).map_err(Into::into)?; if >::exists(&controller) { return Err("controller already paired") } diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index a421bdae68a52..fc29547228301 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -123,8 +123,9 @@ decl_module! { let res = match proposal.dispatch(system::RawOrigin::Root.into()) { Ok(_) => true, - Err(e) => { - sr_io::print(e); + Err(_e) => { + // TODO: not sure how to deal with this + // sr_io::print(e); false } }; @@ -145,7 +146,7 @@ decl_module! { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; ensure!(sender == Self::key(), "only the current sudo key can change the sudo key"); - let new = T::Lookup::lookup(new)?; + let new = T::Lookup::lookup(new).map_err(Into::into)?; Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 3b943b953cb2a..8528497c5f490 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -76,9 +76,9 @@ macro_rules! impl_outer_error { } } - impl TryInto<$system::Error> for $name { + impl $crate::rstd::convert::TryInto<$system::Error> for $name { type Error = Self; - fn try_into(self) -> $crate::dispatch::result::Result<$modules::Error, Self::Error> { + fn try_into(self) -> $crate::dispatch::result::Result<$system::Error, Self::Error> { if let $name::system(err) = self { Ok(err) } else { @@ -90,49 +90,49 @@ macro_rules! impl_outer_error { impl Into<$crate::runtime_primitives::DispatchError> for $name { fn into(self) -> $crate::runtime_primitives::DispatchError { match self { - system(err) => match err { + $name::system(err) => match err { $system::Error::Unknown(msg) => $crate::runtime_primitives::DispatchError { module: 0, error: 0, message: msg, - } + }, _ => $crate::runtime_primitives::DispatchError { module: 0, error: err.into(), message: None, - } + }, }, $( - $modules(err) => match err { - $modules::Error::Unknown(msg) => + $name::$module(err) => match err { + $module::Error::Unknown(msg) => $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), error: 0, message: msg, - } + }, _ => $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), error: err.into(), message: None, - } - } + }, + }, )* } } } $( - impl From<$modules::Error> for $name { + impl From<$module::Error> for $name { fn from(err: $system::Error) -> Self { - $name::$modules(err) + $name::$module(err) } } - impl TryInto<$modules::Error> for $name { + impl $crate::rstd::convert::TryInto<$module::Error> for $name { type Error = Self; - fn try_into(self) -> $crate::dispatch::result::Result<$modules::Error, Self::Error> { - if let $name::$modules(err) = self { + fn try_into(self) -> $crate::dispatch::result::Result<$module::Error, Self::Error> { + if let $name::$module(err) = self { Ok(err) } else { Err(self) diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 95fa90f88ff5f..cae0d77d8f138 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -87,10 +87,10 @@ pub trait Trait: system::Trait { type Currency: Currency + ReservableCurrency; /// Origin from which approvals must come. - type ApproveOrigin: EnsureOrigin; + type ApproveOrigin: EnsureOrigin; /// Origin from which rejections must come. - type RejectOrigin: EnsureOrigin; + type RejectOrigin: EnsureOrigin; /// The overarching event type. type Event: From> + Into<::Event>; @@ -122,7 +122,7 @@ decl_module! { beneficiary: ::Source ) { let proposer = ensure_signed(origin)?; - let beneficiary = T::Lookup::lookup(beneficiary)?; + let beneficiary = T::Lookup::lookup(beneficiary).map_err(Into::into)?; let bond = Self::calculate_bond(value); T::Currency::reserve(&proposer, bond) From c0cece1c76f0230dd5695834d4ba4e330a765b40 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 19 Jun 2019 11:41:31 +1200 Subject: [PATCH 04/80] node-runtime checks --- .../src/generic/unchecked_extrinsic.rs | 4 ++-- .../unchecked_mortal_compact_extrinsic.rs | 4 ++-- .../src/generic/unchecked_mortal_extrinsic.rs | 4 ++-- core/sr-primitives/src/lib.rs | 6 ++++++ node/runtime/src/lib.rs | 1 + srml/council/src/motions.rs | 18 +++++++++--------- srml/executive/src/lib.rs | 14 ++++++++------ srml/support/src/dispatch.rs | 2 +- srml/support/src/error.rs | 14 ++++++++++---- srml/system/src/lib.rs | 2 +- 10 files changed, 42 insertions(+), 27 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 6db08297a5caa..fcee4242c5e8a 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -84,7 +84,7 @@ where Call: Encode + Member, Signature: Member + traits::Verify + Codec, AccountId: Member + MaybeDisplay, - Context: Lookup, + Context: Lookup { type Checked = CheckedExtrinsic; type Error = Error; @@ -93,7 +93,7 @@ where Ok(match self.signature { Some(SignatureContent{signed, signature, index}) => { let payload = (index, self.function); - let signed = context.lookup(signed)?; + let signed = context.lookup(signed).map_err(Into::into)?; if !crate::verify_encoded_lazy(&signature, &payload, &signed) { return Err(Error::BadSignature) } diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 7d9beec941a66..6fa642d8e28ff 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -76,7 +76,7 @@ where AccountId: Member + MaybeDisplay, BlockNumber: SimpleArithmetic, Hash: Encode, - Context: Lookup + Context: Lookup + CurrentHeight + BlockNumberToHash, { @@ -89,7 +89,7 @@ where let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) .ok_or(Error::Unknown("transaction birth block ancient"))?; - let signed = context.lookup(signed)?; + let signed = context.lookup(signed).map_err(Into::into)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { if payload.len() > 256 { diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index dfe7a44b2493e..20d5df30bb795 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -77,7 +77,7 @@ where AccountId: Member + MaybeDisplay, BlockNumber: SimpleArithmetic, Hash: Encode, - Context: Lookup + Context: Lookup + CurrentHeight + BlockNumberToHash, { @@ -90,7 +90,7 @@ where let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) .ok_or(Error::Unknown("transaction birth block ancient"))?; - let signed = context.lookup(signed)?; + let signed = context.lookup(signed).map_err(Into::into)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index ca095aaa01494..89013117e4111 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -77,6 +77,12 @@ impl From for &str { } } +impl Into for &'static str { + fn into(self) -> Error { + Error::Unknown(self) + } +} + /// Justification type. pub type Justification = Vec; diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 67a5b450a95bb..6f39946f9115b 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -96,6 +96,7 @@ impl system::Trait for Runtime { type Lookup = Indices; type Header = generic::Header; type Event = Event; + type Error = Error; } impl aura::Trait for Runtime { diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index c7b0eb51c2439..d3e69c935225e 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -18,7 +18,7 @@ use rstd::{prelude::*, result}; use substrate_primitives::u32_trait::Value as U32; -use primitives::traits::{Hash, EnsureOrigin, EnsureOriginError}; +use primitives::traits::{Hash, EnsureOrigin}; use srml_support::{ dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure @@ -259,11 +259,11 @@ pub fn ensure_council_members(o: OuterOrigin, n: MemberC pub struct EnsureMember(::rstd::marker::PhantomData); impl< - O: Into, O>> + From> + EnsureOriginError, + O: Into, O>> + From>, AccountId > EnsureOrigin for EnsureMember { type Success = AccountId; - type Error = O; + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Member(id) => Ok(id), @@ -274,12 +274,12 @@ impl< pub struct EnsureMembers(::rstd::marker::PhantomData<(N, AccountId)>); impl< - O: Into, O>> + From> + EnsureOriginError, + O: Into, O>> + From>, N: U32, AccountId, > EnsureOrigin for EnsureMembers { type Success = (MemberCount, MemberCount); - type Error = O; + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), @@ -292,13 +292,13 @@ pub struct EnsureProportionMoreThan( ::rstd::marker::PhantomData<(N, D, AccountId)> ); impl< - O: Into, O>> + From> + EnsureOriginError, + O: Into, O>> + From>, N: U32, D: U32, AccountId, > EnsureOrigin for EnsureProportionMoreThan { type Success = (); - type Error = O; + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), @@ -311,13 +311,13 @@ pub struct EnsureProportionAtLeast( ::rstd::marker::PhantomData<(N, D, AccountId)> ); impl< - O: Into, O>> + From> + EnsureOriginError, + O: Into, O>> + From>, N: U32, D: U32, AccountId, > EnsureOrigin for EnsureProportionAtLeast { type Success = (); - type Error = O; + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 4bfb115880edb..5cdcf1c7441cc 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -78,7 +78,7 @@ use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::convert::TryInto; use primitives::{ - generic::Digest, ApplyResult, ApplyError, DispatchError, + generic::Digest, ApplyResult, ApplyError, DispatchError, Error as PrimitiveError, traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, NumberFor, Block as BlockT, OffchainWorker, @@ -116,10 +116,11 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, + CheckableError: Into, Error: Into + TryInto, > ExecuteBlock for Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + Weighable, CallOf: Dispatchable, OriginOf: From>, @@ -137,10 +138,11 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, + CheckableError: Into, Error: Into + TryInto, > Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + Weighable, CallOf: Dispatchable, OriginOf: From>, @@ -343,14 +345,14 @@ where // Checks out. Carry on. Ok(xt) => xt, Err(err) => { - match err.try_into() { + match err.into() { // An unknown account index implies that the transaction may yet become valid. // TODO: avoid hardcoded error string here - Ok(system::Error::Unknown("invalid account index")) => + PrimitiveError::Unknown("invalid account index") => return TransactionValidity::Unknown(INVALID_INDEX), // Technically a bad signature could also imply an out-of-date account index, but // that's more of an edge case. - Ok(system::Error::BadSignature) => + PrimitiveError::BadSignature => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), _ => return TransactionValidity::Invalid(UNKNOWN_ERROR), } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 2ab241b250006..cd31f70f66c77 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -1270,7 +1270,7 @@ macro_rules! impl_outer_dispatch { type Error = $error_type; fn dispatch(self, origin: $origin) -> $crate::dispatch::DispatchResult { match self { - $( $call_type::$camelcase(call) => call.dispatch(origin), )* + $( $call_type::$camelcase(call) => call.dispatch(origin).map_err(Into::into), )* } } } diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 8528497c5f490..4cb02e594c5cb 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -76,6 +76,12 @@ macro_rules! impl_outer_error { } } + impl From<&'static str> for $name { + fn from(err: &'static str) -> Self { + $name::system($system::Error::Unknown(err)) + } + } + impl $crate::rstd::convert::TryInto<$system::Error> for $name { type Error = Self; fn try_into(self) -> $crate::dispatch::result::Result<$system::Error, Self::Error> { @@ -95,11 +101,11 @@ macro_rules! impl_outer_error { $crate::runtime_primitives::DispatchError { module: 0, error: 0, - message: msg, + message: Some(msg), }, _ => $crate::runtime_primitives::DispatchError { module: 0, - error: err.into(), + error: Into::::into(err) as i8, message: None, }, }, @@ -109,11 +115,11 @@ macro_rules! impl_outer_error { $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), error: 0, - message: msg, + message: Some(msg), }, _ => $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), - error: err.into(), + error: Into::::into(err) as i8, message: None, }, }, diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 2f5ece98efe55..02e4a8c44bfa8 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -190,7 +190,7 @@ pub trait Trait: 'static + Eq + Clone { type Event: Parameter + Member + From; /// The aggregated error type of the runtime. - type Error: Parameter + Member + From; + type Error: Member + From; } pub type DigestOf = generic::Digest<::Hash>; From a93fedd419e1b16b24cb1c42def6a155a99c0d42 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 19 Jun 2019 13:27:17 +1200 Subject: [PATCH 05/80] build.sh passes --- core/sr-primitives/src/traits.rs | 8 +++++--- core/test-runtime/src/lib.rs | 8 +++++--- core/test-runtime/src/system.rs | 21 +++++++++++++-------- node-template/runtime/src/lib.rs | 2 ++ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 67b05cfe3102c..e238cc7887d21 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -737,17 +737,19 @@ pub trait Checkable: Sized { pub trait BlindCheckable: Sized { /// Returned if `check` succeeds. type Checked; + /// Returned if `check` failed. + type Error; /// Check self. - fn check(self) -> Result; + fn check(self) -> Result; } // Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. impl Checkable for T { type Checked = ::Checked; - type Error = &'static str; + type Error = ::Error; - fn check(self, _c: &Context) -> Result { + fn check(self, _c: &Context) -> Result { BlindCheckable::check(self) } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index ce9758da4e9ae..e54af5c7a4d49 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -37,6 +37,7 @@ use runtime_primitives::{ ApplyResult, create_runtime_str, transaction_validity::TransactionValidity, + Error, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, Verify @@ -117,18 +118,19 @@ impl serde::Serialize for Extrinsic { impl BlindCheckable for Extrinsic { type Checked = Self; + type Error = Error; - fn check(self) -> Result { + fn check(self) -> Result { match self { Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), Extrinsic::Transfer(transfer, signature) => { if runtime_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer(transfer, signature)) } else { - Err(runtime_primitives::BAD_SIGNATURE) + Err(Error::BadSignature) } }, - Extrinsic::IncludeData(_) => Err(runtime_primitives::BAD_SIGNATURE), + Extrinsic::IncludeData(_) => Err(Error::BadSignature), } } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 7ebc7fa16775f..51529336eb42f 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -106,7 +106,10 @@ fn execute_block_with_state_root_handler( // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); + match execute_transaction_backend(e) { + ApplyResult::Success => (), + _ => panic!("Invalid transaction"), + }; storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); @@ -233,11 +236,13 @@ fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { - check_signature(utx)?; - match utx { - Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), - Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => ApplyResult::Success, + match check_signature(utx) { + Ok(_) => match utx { + Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), + Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), + Extrinsic::IncludeData(_) => ApplyResult::Success, + }, + Err(err) => ApplyResult::ApplyError(err) } } @@ -246,7 +251,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if !(tx.nonce == expected_nonce) { - return Err(ApplyError::Stale) + return ApplyResult::ApplyError(ApplyError::Stale) } // increment nonce in storage @@ -258,7 +263,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // enact transfer if !(tx.amount <= from_balance) { - return Err(ApplyError::CantPay) + return ApplyResult::ApplyError(ApplyError::CantPay) } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 9b99e7f08f495..26c046b2787a5 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -126,6 +126,8 @@ impl system::Trait for Runtime { type Event = Event; /// The ubiquitous origin type. type Origin = Origin; + /// The ubiquitous error type. + type Error = Error; } impl aura::Trait for Runtime { From 3039e7ce1e04536ccfa5365d589f899ffb868339 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 19 Jun 2019 16:25:51 +1200 Subject: [PATCH 06/80] include dispatch error in failed event --- srml/executive/src/lib.rs | 6 +++--- srml/system/src/lib.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 5cdcf1c7441cc..e010b0db7da47 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -296,12 +296,12 @@ where // Decode parameters and dispatch let (f, s) = xt.deconstruct(); - let r = f.dispatch(s.into()); - >::note_applied_extrinsic(r.is_ok(), encoded_len as u32); + let r = f.dispatch(s.into()).map_err(Into::::into); + >::note_applied_extrinsic(&r, encoded_len as u32); match r { Ok(_) => ApplyResult::Success, - Err(e) => ApplyResult::DispatchError(e.into()), + Err(e) => ApplyResult::DispatchError(e), } } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 02e4a8c44bfa8..883e4e8a517a3 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -77,7 +77,7 @@ use rstd::prelude::*; #[cfg(any(feature = "std", test))] use rstd::map; use primitives::{ - generic, Error as PrimitiveError, + generic, Error as PrimitiveError, DispatchError, traits::{ self, CheckEqual, SimpleArithmetic, SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash, @@ -267,7 +267,7 @@ decl_event!( /// An extrinsic completed successfully. ExtrinsicSuccess, /// An extrinsic failed. - ExtrinsicFailed, + ExtrinsicFailed(DispatchError), } ); @@ -752,10 +752,10 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(success: bool, encoded_len: u32) { - Self::deposit_event(match success { - true => Event::ExtrinsicSuccess, - false => Event::ExtrinsicFailed, + pub fn note_applied_extrinsic(r: &Result<(), DispatchError>, encoded_len: u32) { + Self::deposit_event(match r { + Ok(_) => Event::ExtrinsicSuccess, + Err(err) => Event::ExtrinsicFailed(err.clone()), }.into()); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; From c5c2e5afa44c546964c6f5c894022b910bdedd92 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 19 Jun 2019 23:30:37 +1200 Subject: [PATCH 07/80] revert some unnecessary changes --- .../client/src/block_builder/block_builder.rs | 5 +- core/sr-primitives/src/lib.rs | 20 ++-- core/test-runtime/src/system.rs | 27 +++--- node/executor/src/lib.rs | 4 +- srml/executive/src/lib.rs | 97 +++++++++---------- 5 files changed, 70 insertions(+), 83 deletions(-) diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 48ef76c480660..72b0d5f5838db 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -17,7 +17,6 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use parity_codec::Encode; -use runtime_primitives::ApplyResult; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, @@ -104,11 +103,11 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - ApplyResult::Success | ApplyResult::DispatchError(_) => { + Ok(_) => { extrinsics.push(xt); Ok(()) } - ApplyResult::ApplyError(e) => { + Err(e) => { Err(error::Error::ApplyExtrinsicFailed(e)) } } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 89013117e4111..a25b94c30cb69 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -544,18 +544,18 @@ pub struct DispatchError { pub message: Option<&'static str>, } -// TODO: custom implement Encode & Decode to make it a two byte value #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] + #[cfg_attr(feature = "std", derive(Debug, Serialize))] + /// Outcome of a valid extrinsic application. Capable of being sliced. + pub enum ApplyOutcome { + /// Successful application (extrinsic reported no issue). + Success, + /// Failed application (extrinsic was probably a no-op other than fees). + Fail(DispatchError), + } + /// Result from attempt to apply an extrinsic. -pub enum ApplyResult { - /// Successful application (extrinsic reported no issue). - Success, - /// Failed application (extrinsic was probably a no-op other than fees). - DispatchError(DispatchError), - /// Invalid extrinsic application. - ApplyError(ApplyError), -} +pub type ApplyResult = Result; /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 51529336eb42f..d150a573e86fe 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -23,7 +23,7 @@ use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; use runtime_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _}; use runtime_primitives::generic; -use runtime_primitives::{ApplyError, ApplyResult, transaction_validity::TransactionValidity}; +use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; use super::{ AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId @@ -106,10 +106,7 @@ fn execute_block_with_state_root_handler( // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - match execute_transaction_backend(e) { - ApplyResult::Success => (), - _ => panic!("Invalid transaction"), - }; + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); @@ -236,13 +233,11 @@ fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { - match check_signature(utx) { - Ok(_) => match utx { - Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), - Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => ApplyResult::Success, - }, - Err(err) => ApplyResult::ApplyError(err) + check_signature(utx)?; + match utx { + Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), + Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), + Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success), } } @@ -251,7 +246,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if !(tx.nonce == expected_nonce) { - return ApplyResult::ApplyError(ApplyError::Stale) + return Err(ApplyError::Stale) } // increment nonce in storage @@ -263,19 +258,19 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // enact transfer if !(tx.amount <= from_balance) { - return ApplyResult::ApplyError(ApplyError::CantPay) + return Err(ApplyError::CantPay) } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); - ApplyResult::Success + Ok(ApplyOutcome::Success) } fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { let new_authorities: Vec = new_authorities.iter().cloned().collect(); ::put(new_authorities); - ApplyResult::Success + Ok(ApplyOutcome::Success) } #[cfg(feature = "std")] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 46527e665882d..4f0c38d88482a 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -38,7 +38,7 @@ mod tests { NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; - use runtime_primitives::{generic::Era, ApplyError, ApplyResult, Perbill}; + use runtime_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; use {balances, indices, system, staking, timestamp, treasury, contract}; use contract::ContractAddressFor; use system::{EventRecord, Phase}; @@ -912,7 +912,7 @@ mod tests { let r = WasmExecutor::new() .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, ApplyResult::Success); + assert_eq!(r, Ok(ApplyOutcome::Success)); runtime_io::with_externalities(&mut t, || { assert_eq!(Balances::total_balance(&alice()), 42); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index e010b0db7da47..af9756e554ac7 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -78,7 +78,7 @@ use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::convert::TryInto; use primitives::{ - generic::Digest, ApplyResult, ApplyError, DispatchError, Error as PrimitiveError, + generic::Digest, ApplyResult, ApplyOutcome, ApplyError, DispatchError, Error as PrimitiveError, traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, NumberFor, Block as BlockT, OffchainWorker, @@ -231,8 +231,8 @@ where fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { let l = uxt.encode().len(); match Self::apply_extrinsic_with_len(uxt, l, None) { - ApplyResult::Success => (), - ApplyResult::DispatchError(e) => { + Ok(ApplyOutcome::Success) => (), + Ok(ApplyOutcome::Fail(e)) => { runtime_io::print("Error:"); // as u8 first to ensure not using sign-extend runtime_io::print(e.module as u8 as u64); @@ -241,10 +241,10 @@ where runtime_io::print(msg); } }, - ApplyResult::ApplyError(ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), - ApplyResult::ApplyError(ApplyError::BadSignature) => panic!("All extrinsics should be properly signed"), - ApplyResult::ApplyError(ApplyError::Stale) | ApplyResult::ApplyError(ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), - ApplyResult::ApplyError(ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), + Err(ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), + Err(ApplyError::BadSignature) => panic!("All extrinsics should be properly signed"), + Err(ApplyError::Stale) | Err(ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), + Err(ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), } } @@ -255,56 +255,49 @@ where to_note: Option>, ) -> ApplyResult { // Verify that the signature is good. - match uxt.check(&Default::default()) { - Err(_) => ApplyResult::ApplyError(ApplyError::BadSignature), - Ok(xt) => { - // Check the weight of the block if that extrinsic is applied. - let weight = xt.weight(encoded_len); - if >::all_extrinsics_weight() + weight > internal::MAX_TRANSACTIONS_WEIGHT { - return ApplyResult::ApplyError(ApplyError::FullBlock); - } + let xt = uxt.check(&Default::default()).map_err(|_| ApplyError::BadSignature)?; + // Check the weight of the block if that extrinsic is applied. + let weight = xt.weight(encoded_len); + if >::all_extrinsics_weight() + weight > internal::MAX_TRANSACTIONS_WEIGHT { + return Err(ApplyError::FullBlock); + } - if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { - // check index - let expected_index = >::account_nonce(sender); - if index != &expected_index { - return if index < &expected_index { - ApplyResult::ApplyError(ApplyError::Stale) - } else { - ApplyResult::ApplyError(ApplyError::Future) - } - } - // pay any fees - // TODO: propagate why can't pay - match Payment::make_payment(sender, encoded_len) { - Err(_) => return ApplyResult::ApplyError(ApplyError::CantPay), - Ok(_) => () - }; - - // AUDIT: Under no circumstances may this function panic from here onwards. - // FIXME: ensure this at compile-time (such as by not defining a panic function, forcing - // a linker error unless the compiler can prove it cannot be called). - // increment nonce in storage - >::inc_account_nonce(sender); + if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { + // check index + let expected_index = >::account_nonce(sender); + if index != &expected_index { + return if index < &expected_index { + Err(ApplyError::Stale) + } else { + Err(ApplyError::Future) } + } + // pay any fees + // TODO: propagate why can't pay + Payment::make_payment(sender, encoded_len).map_err(|_| ApplyError::CantPay)?; + + // AUDIT: Under no circumstances may this function panic from here onwards. + // FIXME: ensure this at compile-time (such as by not defining a panic function, forcing + // a linker error unless the compiler can prove it cannot be called). + // increment nonce in storage + >::inc_account_nonce(sender); + } - // Make sure to `note_extrinsic` only after we know it's going to be executed - // to prevent it from leaking in storage. - if let Some(encoded) = to_note { - >::note_extrinsic(encoded); - } + // Make sure to `note_extrinsic` only after we know it's going to be executed + // to prevent it from leaking in storage. + if let Some(encoded) = to_note { + >::note_extrinsic(encoded); + } - // Decode parameters and dispatch - let (f, s) = xt.deconstruct(); - let r = f.dispatch(s.into()).map_err(Into::::into); - >::note_applied_extrinsic(&r, encoded_len as u32); + // Decode parameters and dispatch + let (f, s) = xt.deconstruct(); + let r = f.dispatch(s.into()).map_err(Into::::into); + >::note_applied_extrinsic(&r, encoded_len as u32); - match r { - Ok(_) => ApplyResult::Success, - Err(e) => ApplyResult::DispatchError(e), - } - } - } + Ok(match r { + Ok(_) => ApplyOutcome::Success, + Err(e) => ApplyOutcome::Fail(e), + }) } fn final_checks(header: &System::Header) { From 1198fb75af677f17ac1a7288802f5f05a0514059 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Thu, 20 Jun 2019 11:34:48 +1200 Subject: [PATCH 08/80] refactor based on comments --- .../src/generic/unchecked_mortal_compact_extrinsic.rs | 2 +- .../sr-primitives/src/generic/unchecked_mortal_extrinsic.rs | 2 +- core/sr-primitives/src/lib.rs | 6 +++--- srml/executive/src/lib.rs | 6 +++--- srml/system/src/lib.rs | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 6fa642d8e28ff..2193b7b06f2f9 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -88,7 +88,7 @@ where Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or(Error::Unknown("transaction birth block ancient"))?; + .ok_or("transaction birth block ancient".into())?; let signed = context.lookup(signed).map_err(Into::into)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index 20d5df30bb795..c84fde6c45810 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -89,7 +89,7 @@ where Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or(Error::Unknown("transaction birth block ancient"))?; + .ok_or("transaction birth block ancient".into())?; let signed = context.lookup(signed).map_err(Into::into)?; let raw_payload = (index, self.function, era, h); diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index a25b94c30cb69..a37eb43cbbde7 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -67,9 +67,9 @@ pub enum Error { } // Exists for for backward compatibility purpose. -impl From for &str { - fn from(err: Error) -> &'static str { - match err { +impl Into<&'static str> for Error{ + fn into(self) -> &'static str { + match self { Error::Unknown(val) => val, Error::BadSignature => "bad signature in extrinsic", Error::BlockFull => "block size limit is reached", diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index af9756e554ac7..0d493986c2c79 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -116,11 +116,11 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, - CheckableError: Into, Error: Into + TryInto, > ExecuteBlock for Executive where Block::Extrinsic: Checkable + Codec, + >::Error: Into, CheckedOf: Applyable + Weighable, CallOf: Dispatchable, OriginOf: From>, @@ -138,11 +138,11 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, - CheckableError: Into, Error: Into + TryInto, > Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, + >::Error: Into, CheckedOf: Applyable + Weighable, CallOf: Dispatchable, OriginOf: From>, diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 883e4e8a517a3..6b0811d011e8a 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -293,9 +293,9 @@ impl From for Error { } // Exists for for backward compatibility purpose. -impl From for &str { - fn from(err: Error) -> &'static str { - match err { +impl Into<&'static str> for Error { + fn into(self) -> &'static str { + match self { Error::Unknown(val) => val, Error::BadSignature => "bad signature in extrinsic", Error::BlockFull => "block size limit is reached", From 1f964d1e402df28037d23d023ed7ddcfd6735d0a Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Thu, 20 Jun 2019 16:49:01 +1200 Subject: [PATCH 09/80] more compile error fixes --- .../unchecked_mortal_compact_extrinsic.rs | 7 ++++--- .../src/generic/unchecked_mortal_extrinsic.rs | 7 ++++--- core/sr-primitives/src/lib.rs | 1 + srml/executive/src/lib.rs | 2 +- srml/system/src/lib.rs | 17 +++++++++++------ 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 2193b7b06f2f9..4b01cf51b2b0a 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -200,6 +200,7 @@ mod tests { impl Lookup for TestContext { type Source = u64; type Target = u64; + type Error = &'static str; fn lookup(&self, s: u64) -> Result { Ok(s) } } impl CurrentHeight for TestContext { @@ -258,7 +259,7 @@ mod tests { fn badly_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] @@ -286,14 +287,14 @@ mod tests { fn too_late_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] fn too_early_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index c84fde6c45810..d0dacbe98585c 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -201,6 +201,7 @@ mod tests { impl Lookup for TestContext { type Source = u64; type Target = u64; + type Error = &'static str; fn lookup(&self, s: u64) -> Result { Ok(s) } } impl CurrentHeight for TestContext { @@ -259,7 +260,7 @@ mod tests { fn badly_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] @@ -287,14 +288,14 @@ mod tests { fn too_late_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] fn too_early_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); } #[test] diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index a37eb43cbbde7..824612719b279 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -48,6 +48,7 @@ pub mod transaction_validity; /// Re-export these since they're only "kind of" generic. pub use generic::{DigestItem, Digest}; +#[cfg_attr(test, derive(PartialEq, Debug))] /// Error type pub enum Error { /// Unknown error diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 0d493986c2c79..72853ddc165bb 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -119,7 +119,7 @@ impl< Error: Into + TryInto, > ExecuteBlock for Executive where - Block::Extrinsic: Checkable + Codec, + Block::Extrinsic: Checkable + Codec, >::Error: Into, CheckedOf: Applyable + Weighable, CallOf: Dispatchable, diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 6b0811d011e8a..dce2b7b36d317 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -190,7 +190,7 @@ pub trait Trait: 'static + Eq + Clone { type Event: Parameter + Member + From; /// The aggregated error type of the runtime. - type Error: Member + From; + type Error: Member + From + From<&'static str>; } pub type DigestOf = generic::Digest<::Hash>; @@ -819,12 +819,16 @@ mod tests { use primitives::BuildStorage; use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::Header; - use srml_support::impl_outer_origin; + use srml_support::{impl_outer_origin, impl_outer_error}; - impl_outer_origin!{ + impl_outer_origin! { pub enum Origin for Test where system = super {} } + impl_outer_error! { + pub enum Error for Test where system = super {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl Trait for Test { @@ -837,13 +841,14 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = u16; + type Error = Error; } impl From for u16 { fn from(e: Event) -> u16 { match e { Event::ExtrinsicSuccess => 100, - Event::ExtrinsicFailed => 101, + Event::ExtrinsicFailed(err) => Encode::using_encoded(&err, |s| (s[0] as u16) | ((s[1] as u16) << 8)), } } } @@ -881,8 +886,8 @@ mod tests { System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); - System::note_applied_extrinsic(true, 0); - System::note_applied_extrinsic(false, 0); + System::note_applied_extrinsic(&Ok(()), 0); + System::note_applied_extrinsic(&Err(DispatchError { module: 1, error: 2, message: None }), 0); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalize(); From 83975c007061b6b2789c93b70c45c86ce8c2904d Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Thu, 20 Jun 2019 22:58:01 +1200 Subject: [PATCH 10/80] avoid unnecessary into --- core/sr-primitives/src/generic/unchecked_extrinsic.rs | 2 +- .../src/generic/unchecked_mortal_compact_extrinsic.rs | 4 ++-- .../src/generic/unchecked_mortal_extrinsic.rs | 4 ++-- core/sr-primitives/src/lib.rs | 6 +++--- core/sr-primitives/src/traits.rs | 2 +- srml/balances/src/lib.rs | 6 +++--- srml/contracts/src/lib.rs | 2 +- srml/council/src/seats.rs | 6 +++--- srml/staking/src/lib.rs | 6 +++--- srml/sudo/src/lib.rs | 2 +- srml/system/src/lib.rs | 9 +++++---- srml/treasury/src/lib.rs | 2 +- 12 files changed, 26 insertions(+), 25 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index fcee4242c5e8a..0b8cc42bd137a 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -93,7 +93,7 @@ where Ok(match self.signature { Some(SignatureContent{signed, signature, index}) => { let payload = (index, self.function); - let signed = context.lookup(signed).map_err(Into::into)?; + let signed = context.lookup(signed)?; if !crate::verify_encoded_lazy(&signature, &payload, &signed) { return Err(Error::BadSignature) } diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 4b01cf51b2b0a..44003fc0d302c 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -88,8 +88,8 @@ where Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or("transaction birth block ancient".into())?; - let signed = context.lookup(signed).map_err(Into::into)?; + .ok_or("transaction birth block ancient")?; + let signed = context.lookup(signed)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { if payload.len() > 256 { diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index d0dacbe98585c..080bfa0d0531a 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -89,8 +89,8 @@ where Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); let h = context.block_number_to_hash(era.birth(current_u64).saturated_into()) - .ok_or("transaction birth block ancient".into())?; - let signed = context.lookup(signed).map_err(Into::into)?; + .ok_or("transaction birth block ancient")?; + let signed = context.lookup(signed)?; let raw_payload = (index, self.function, era, h); if !raw_payload.using_encoded(|payload| { diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 824612719b279..53f4743a78c81 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -78,9 +78,9 @@ impl Into<&'static str> for Error{ } } -impl Into for &'static str { - fn into(self) -> Error { - Error::Unknown(self) +impl From<&'static str> for Error { + fn from(val: &'static str) -> Error { + Error::Unknown(val) } } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index e238cc7887d21..03f6dc4dc65cd 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -118,7 +118,7 @@ pub trait StaticLookup { /// Type to lookup into. type Target; /// Error type. - type Error: Into<&'static str>; // Into<&'static str> for backward compatibility purpose. + type Error; /// Attempt a lookup. fn lookup(s: Self::Source) -> result::Result; /// Convert from Target back to Source. diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 97bc4976b1d9f..811e3d7cdc92a 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -371,7 +371,7 @@ decl_module! { #[compact] value: T::Balance ) { let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest).map_err(Into::into)?; + let dest = T::Lookup::lookup(dest)?; >::transfer(&transactor, &dest, value)?; } @@ -393,7 +393,7 @@ decl_module! { #[compact] new_free: T::Balance, #[compact] new_reserved: T::Balance ) { - let who = T::Lookup::lookup(who).map_err(Into::into)?; + let who = T::Lookup::lookup(who)?; let current_free = >::get(&who); if new_free > current_free { @@ -697,7 +697,7 @@ impl, I: Instance> system::Trait for ElevatedTrait { type Lookup = T::Lookup; type Header = T::Header; type Event = (); - type Error = (); + type Error = &'static str; } impl, I: Instance> Trait for ElevatedTrait { type Balance = T::Balance; diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 04c63fb4ee027..b9c8976cc04be 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -397,7 +397,7 @@ decl_module! { data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest).map_err(Into::into)?; + let dest = T::Lookup::lookup(dest)?; // Pay for the gas upfront. // diff --git a/srml/council/src/seats.rs b/srml/council/src/seats.rs index 7d9903868bc84..84b6f388f29fc 100644 --- a/srml/council/src/seats.rs +++ b/srml/council/src/seats.rs @@ -213,7 +213,7 @@ decl_module! { #[compact] assumed_vote_index: VoteIndex ) { let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who).map_err(Into::into)?; + let who = T::Lookup::lookup(who)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); @@ -352,7 +352,7 @@ decl_module! { "stake deposited to present winner and be added to leaderboard should be non-zero" ); - let candidate = T::Lookup::lookup(candidate).map_err(Into::into)?; + let candidate = T::Lookup::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; let bad_presentation_punishment = @@ -417,7 +417,7 @@ decl_module! { /// Note: A tally should happen instantly (if not already in a presentation /// period) to fill the seat if removal means that the desired members are not met. fn remove_member(who: ::Source) { - let who = T::Lookup::lookup(who).map_err(Into::into)?; + let who = T::Lookup::lookup(who)?; let new_council: Vec<(T::AccountId, T::BlockNumber)> = Self::active_council() .into_iter() .filter(|i| i.0 != who) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 2241d3c02f7ab..d0cd98d307105 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -637,7 +637,7 @@ decl_module! { return Err("stash already bonded") } - let controller = T::Lookup::lookup(controller).map_err(Into::into)?; + let controller = T::Lookup::lookup(controller)?; if >::exists(&controller) { return Err("controller already paired") @@ -796,7 +796,7 @@ decl_module! { .take(MAX_NOMINATIONS) .map(T::Lookup::lookup) .collect::, _>>() - .map_err(Into::into)?; + ?; >::remove(stash); >::insert(stash, targets); @@ -853,7 +853,7 @@ decl_module! { fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or("not a stash")?; - let controller = T::Lookup::lookup(controller).map_err(Into::into)?; + let controller = T::Lookup::lookup(controller)?; if >::exists(&controller) { return Err("controller already paired") } diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index fc29547228301..73b311b1d77cd 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -146,7 +146,7 @@ decl_module! { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; ensure!(sender == Self::key(), "only the current sudo key can change the sudo key"); - let new = T::Lookup::lookup(new).map_err(Into::into)?; + let new = T::Lookup::lookup(new)?; Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index dce2b7b36d317..f0b9a5ada9f10 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -178,7 +178,8 @@ pub trait Trait: 'static + Eq + Clone { /// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly /// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules /// (e.g. Indices module) may provide more functional/efficient alternatives. - type Lookup: StaticLookup; + // TODO: avoid &'static str error type + type Lookup: StaticLookup; /// The block header. type Header: Parameter + traits::Header< @@ -293,9 +294,9 @@ impl From for Error { } // Exists for for backward compatibility purpose. -impl Into<&'static str> for Error { - fn into(self) -> &'static str { - match self { +impl From for &'static str { + fn from(err: Error) -> &'static str { + match err { Error::Unknown(val) => val, Error::BadSignature => "bad signature in extrinsic", Error::BlockFull => "block size limit is reached", diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index cae0d77d8f138..6d7eecf7d1f60 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -122,7 +122,7 @@ decl_module! { beneficiary: ::Source ) { let proposer = ensure_signed(origin)?; - let beneficiary = T::Lookup::lookup(beneficiary).map_err(Into::into)?; + let beneficiary = T::Lookup::lookup(beneficiary)?; let bond = Self::calculate_bond(value); T::Currency::reserve(&proposer, bond) From e03db0c1148e846a345e3db43fb19f9169b41837 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Thu, 20 Jun 2019 22:59:53 +1200 Subject: [PATCH 11/80] reorder code --- core/sr-primitives/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 53f4743a78c81..ac798fd44bdb5 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -509,6 +509,16 @@ impl From for AnySignature { } } +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] + #[cfg_attr(feature = "std", derive(Debug, Serialize))] + /// Outcome of a valid extrinsic application. Capable of being sliced. + pub enum ApplyOutcome { + /// Successful application (extrinsic reported no issue). + Success, + /// Failed application (extrinsic was probably a no-op other than fees). + Fail(DispatchError), + } + #[derive(Eq, PartialEq, Clone, Copy, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[repr(u8)] @@ -545,16 +555,6 @@ pub struct DispatchError { pub message: Option<&'static str>, } -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] - #[cfg_attr(feature = "std", derive(Debug, Serialize))] - /// Outcome of a valid extrinsic application. Capable of being sliced. - pub enum ApplyOutcome { - /// Successful application (extrinsic reported no issue). - Success, - /// Failed application (extrinsic was probably a no-op other than fees). - Fail(DispatchError), - } - /// Result from attempt to apply an extrinsic. pub type ApplyResult = Result; From 7e01497074cc9d7ac8e63a92b4ee472d57028e51 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Fri, 21 Jun 2019 12:04:44 +1200 Subject: [PATCH 12/80] fixes some tests --- core/sr-primitives/src/testing.rs | 5 +++-- node-template/runtime/src/template.rs | 6 ++++++ srml/assets/src/lib.rs | 7 ++++++- srml/aura/src/mock.rs | 6 ++++++ srml/balances/src/mock.rs | 7 ++++++- srml/contracts/src/tests.rs | 7 ++++++- srml/council/src/lib.rs | 7 ++++++- srml/democracy/src/lib.rs | 7 ++++++- srml/example/src/lib.rs | 7 ++++++- srml/executive/src/lib.rs | 15 ++++++++++----- srml/finality-tracker/src/lib.rs | 7 ++++++- srml/grandpa/src/mock.rs | 10 ++++++++-- srml/indices/src/mock.rs | 7 ++++++- srml/session/src/lib.rs | 7 ++++++- srml/staking/src/mock.rs | 7 ++++++- srml/support/src/dispatch.rs | 5 ++--- srml/support/test/tests/instance.rs | 6 ++++++ srml/system/benches/bench.rs | 6 ++++++ srml/system/src/lib.rs | 10 +++++----- srml/timestamp/src/lib.rs | 7 ++++++- srml/treasury/src/lib.rs | 7 ++++++- 21 files changed, 124 insertions(+), 29 deletions(-) diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index af2e2735b5bb4..3fb276632097c 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -22,6 +22,7 @@ use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys}; use crate::generic; use crate::weights::{Weighable, Weight}; +use crate::Error; pub use substrate_primitives::H256; use substrate_primitives::U256; use substrate_primitives::ed25519::{Public as AuthorityId}; @@ -200,8 +201,8 @@ impl Debug for TestXt { impl Checkable for TestXt { type Checked = Self; - type Error = &'static str; - fn check(self, _: &Context) -> Result { Ok(self) } + type Error = Error; + fn check(self, _: &Context) -> Result { Ok(self) } } impl traits::Extrinsic for TestXt { fn is_signed(&self) -> Option { diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index c8b75f43f5f5b..dcd50f5c1a709 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -82,6 +82,11 @@ mod tests { pub enum Origin for Test {} } + #[allow(non_camel_case_types)] + pub enum Error { + system(system::Error) + } + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -97,6 +102,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Test { type Event = (); diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index d563db3b14146..a65a9296cd0a9 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -240,7 +240,7 @@ mod tests { use super::*; use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, assert_ok, assert_noop}; + use srml_support::{impl_outer_origin, impl_outer_error, assert_ok, assert_noop}; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. @@ -254,6 +254,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Test {} + } + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -269,6 +273,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Test { type Event = (); diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index e9c43850f6e01..386938f92069d 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -32,6 +32,11 @@ impl_outer_origin!{ #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; +#[allow(non_camel_case_types)] +pub enum Error { + system(system::Error) +} + impl system::Trait for Test { type Origin = Origin; type Index = u64; @@ -42,6 +47,7 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl timestamp::Trait for Test { diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index ac5208ab90c2a..d97ae38dcc042 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -22,13 +22,17 @@ use primitives::BuildStorage; use primitives::{traits::{IdentityLookup}, testing::Header}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use srml_support::impl_outer_origin; +use srml_support::{impl_outer_origin, impl_outer_error}; use crate::{GenesisConfig, Module, Trait}; impl_outer_origin!{ pub enum Origin for Runtime {} } +impl_outer_error! { + pub enum Error for Runtime {} +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Runtime; @@ -42,6 +46,7 @@ impl system::Trait for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Runtime { type Balance = u64; diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index 61a81a4eb683b..84097c728a1eb 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -33,7 +33,7 @@ use runtime_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, H use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; use runtime_primitives::BuildStorage; use srml_support::{ - assert_ok, impl_outer_dispatch, impl_outer_event, impl_outer_origin, storage::child, + assert_ok, impl_outer_dispatch, impl_outer_event, impl_outer_origin, impl_outer_error, storage::child, traits::Currency, StorageMap, StorageValue }; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -64,6 +64,10 @@ impl_outer_dispatch! { } } +impl_outer_error! { + pub enum Error for Test {} +} + #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; impl system::Trait for Test { @@ -76,6 +80,7 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; + type Error = Error; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 681bc731be895..3b61ef89fc223 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -38,7 +38,7 @@ mod tests { // These re-exports are here for a reason, edit with care pub use super::*; pub use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch, parameter_types}; + use srml_support::{impl_outer_origin, impl_outer_error, impl_outer_event, impl_outer_dispatch, parameter_types}; pub use substrate_primitives::{H256, Blake2Hasher, u32_trait::{_1, _2, _3, _4}}; pub use primitives::{ BuildStorage, traits::{BlakeTwo256, IdentityLookup}, testing::{Digest, DigestItem, Header} @@ -64,6 +64,10 @@ mod tests { } } + impl_outer_error! { + pub enum Error for Test {} + } + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; @@ -77,6 +81,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; + type Error = Error; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index afefa480ed615..695c16fadf4d5 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -913,7 +913,7 @@ mod tests { use super::*; use runtime_io::with_externalities; use srml_support::{ - impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, + impl_outer_origin, impl_outer_error, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, traits::Contains }; use substrate_primitives::{H256, Blake2Hasher}; @@ -939,6 +939,10 @@ mod tests { } } + impl_outer_error! { + pub enum Error for Test {} + } + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; @@ -952,6 +956,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index dd14b7198acd3..a15e9d5f2bf5d 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -504,7 +504,7 @@ impl Module { mod tests { use super::*; - use srml_support::{impl_outer_origin, assert_ok}; + use srml_support::{impl_outer_origin, impl_outer_error, assert_ok}; use sr_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures @@ -518,6 +518,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Test {} + } + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -533,6 +537,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 72853ddc165bb..d335e7c5dd029 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -116,13 +116,13 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, - Error: Into + TryInto, > ExecuteBlock for Executive where Block::Extrinsic: Checkable + Codec, >::Error: Into, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, + CallOf: Dispatchable, + as Dispatchable>::Error: Into + TryInto, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -138,13 +138,13 @@ impl< Payment: MakePayment, UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, - Error: Into + TryInto, > Executive where Block::Extrinsic: Checkable + Codec, >::Error: Into, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, + CallOf: Dispatchable, + as Dispatchable>::Error: Into + TryInto, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -402,7 +402,7 @@ mod tests { use primitives::BuildStorage; use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, Header, Block}; - use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event}; + use srml_support::{traits::Currency, impl_outer_origin, impl_outer_event, impl_outer_error}; use system; use hex_literal::hex; @@ -417,6 +417,10 @@ mod tests { } } + impl_outer_error! { + pub enum Error for Runtime {} + } + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq)] pub struct Runtime; @@ -430,6 +434,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; + type Error = Error; } impl balances::Trait for Runtime { type Balance = u64; diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 6442fee543ab4..a10954ead17d5 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -264,7 +264,7 @@ mod tests { use primitives::BuildStorage; use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}; use primitives::testing::Header; - use srml_support::impl_outer_origin; + use srml_support::{impl_outer_origin, impl_outer_error}; use srml_system as system; use lazy_static::lazy_static; use parking_lot::Mutex; @@ -284,6 +284,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Test {} + } + impl system::Trait for Test { type Origin = Origin; type Index = u64; @@ -294,6 +298,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } type System = system::Module; diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index 80c99b9a3cfaa..06ce9a3bb6e65 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -22,7 +22,7 @@ use primitives::{ BuildStorage, DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId} }; use runtime_io; -use srml_support::{impl_outer_origin, impl_outer_event}; +use srml_support::{impl_outer_origin, impl_outer_error, impl_outer_event}; use substrate_primitives::{H256, Blake2Hasher}; use parity_codec::{Encode, Decode}; use crate::{AuthorityId, GenesisConfig, Trait, Module, Signal}; @@ -32,6 +32,10 @@ impl_outer_origin!{ pub enum Origin for Test {} } +impl_outer_error! { + pub enum Error for Test {} +} + impl From> for DigestItem { fn from(log: Signal) -> DigestItem { DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) @@ -41,10 +45,11 @@ impl From> for DigestItem { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug, Decode, Encode)] pub struct Test; + impl Trait for Test { type Event = TestEvent; - } + impl system::Trait for Test { type Origin = Origin; type Index = u64; @@ -55,6 +60,7 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; + type Error = Error; } mod grandpa { diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs index e2ea51e89d958..8159a2f4bffcc 100644 --- a/srml/indices/src/mock.rs +++ b/srml/indices/src/mock.rs @@ -23,7 +23,7 @@ use ref_thread_local::{ref_thread_local, RefThreadLocal}; use primitives::BuildStorage; use primitives::testing::Header; use substrate_primitives::{H256, Blake2Hasher}; -use srml_support::impl_outer_origin; +use srml_support::{impl_outer_origin, impl_outer_error}; use {runtime_io, system}; use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint}; @@ -31,6 +31,10 @@ impl_outer_origin!{ pub enum Origin for Runtime {} } +impl_outer_error! { + pub enum Error for Runtime {} +} + ref_thread_local! { static managed ALIVE: HashSet = HashSet::new(); } @@ -75,6 +79,7 @@ impl system::Trait for Runtime { type Lookup = Indices; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Runtime { type AccountIndex = u64; diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 3ae7c9801299b..f39d1f2f38d6b 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -381,7 +381,7 @@ impl OnFreeBalanceZero for Module { mod tests { use super::*; use std::cell::RefCell; - use srml_support::{impl_outer_origin, assert_ok}; + use srml_support::{impl_outer_origin, impl_outer_error, assert_ok}; use runtime_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; use primitives::BuildStorage; @@ -392,6 +392,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Test {} + } + thread_local!{ static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); static AUTHORITIES: RefCell> = @@ -449,6 +453,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl timestamp::Trait for Test { type Moment = u64; diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index ea4fcbd8f9f01..2e6a8731d051a 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -22,7 +22,7 @@ use primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize}; use primitives::testing::{Header, UintAuthorityId}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use srml_support::{impl_outer_origin, parameter_types, assert_ok, traits::Currency}; +use srml_support::{impl_outer_origin, impl_outer_error, parameter_types, assert_ok, traits::Currency}; use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination}; /// The AccountId alias in this test module. @@ -70,6 +70,10 @@ impl_outer_origin!{ pub enum Origin for Test {} } +impl_outer_error! { + pub enum Error for Test {} +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; @@ -83,6 +87,7 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl balances::Trait for Test { type Balance = u64; diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index cd31f70f66c77..d8bb4ea030f74 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -416,8 +416,8 @@ macro_rules! decl_module { { $( $deposit_event )* } { $( $on_initialize )* } { $( $on_finalize )* } - { $( $error_type )* } { fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } } + { $( $error_type )* } [ $($t)* ] $($rest)* ); @@ -559,11 +559,10 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } - { Error } + { &'static str } [ $($t)* ] $($rest)* ); - pub type Error = &'static str; }; // Ignore any ident which is not `origin` with type `T::Origin`. (@normalize diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs index f7b4a4bd3a251..2201a92573b0c 100644 --- a/srml/support/test/tests/instance.rs +++ b/srml/support/test/tests/instance.rs @@ -48,6 +48,7 @@ mod system { srml_support::decl_module! { pub struct Module for enum Call where origin: T::Origin { + type Error = Error; pub fn deposit_event(_event: T::Event) { } } @@ -90,6 +91,11 @@ mod system { { o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin") } + + srml_support::decl_error! { + pub enum Error { + } + } } // Test for: diff --git a/srml/system/benches/bench.rs b/srml/system/benches/bench.rs index ee4ebf711ab31..a3068463e7fde 100644 --- a/srml/system/benches/bench.rs +++ b/srml/system/benches/bench.rs @@ -54,6 +54,11 @@ impl_outer_event! { } } +#[allow(non_camel_case_types)] +pub enum Error { + system(system::Error) +} + #[derive(Clone, Eq, PartialEq)] pub struct Runtime; impl system::Trait for Runtime { @@ -66,6 +71,7 @@ impl system::Trait for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = Event; + type Error = Error; } impl module::Trait for Runtime { diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index f0b9a5ada9f10..a487da0238d90 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -423,7 +423,7 @@ impl< AccountId, > EnsureOrigin for EnsureRoot { type Success = (); - type Error = (); + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Root => Ok(()), @@ -438,7 +438,7 @@ impl< AccountId, > EnsureOrigin for EnsureSigned { type Success = AccountId; - type Error = (); + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(who) => Ok(who), @@ -454,7 +454,7 @@ impl< AccountId: PartialEq + Clone, > EnsureOrigin for EnsureSignedBy { type Success = AccountId; - type Error = (); + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(ref who) if Who::contains(who) => Ok(who.clone()), @@ -469,7 +469,7 @@ impl< AccountId, > EnsureOrigin for EnsureNone { type Success = (); - type Error = (); + type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::None => Ok(()), @@ -481,7 +481,7 @@ impl< pub struct EnsureNever(::rstd::marker::PhantomData); impl EnsureOrigin for EnsureNever { type Success = T; - type Error = (); + type Error = &'static str; fn try_origin(o: O) -> Result { Err(o) } diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index e9c0d85a20a05..34e6024f2a685 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -330,7 +330,7 @@ impl ProvideInherent for Module { mod tests { use super::*; - use srml_support::{impl_outer_origin, assert_ok}; + use srml_support::{impl_outer_origin, impl_outer_error, assert_ok}; use runtime_io::{with_externalities, TestExternalities}; use substrate_primitives::H256; use runtime_primitives::BuildStorage; @@ -341,6 +341,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Runtime {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { @@ -353,6 +357,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Test { type Moment = u64; diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 6d7eecf7d1f60..972d51231a1c9 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -334,7 +334,7 @@ mod tests { use super::*; use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, assert_ok, assert_noop}; + use srml_support::{impl_outer_origin, impl_outer_error, assert_ok, assert_noop}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_primitives::BuildStorage; use runtime_primitives::traits::{BlakeTwo256, OnFinalize, IdentityLookup}; @@ -344,6 +344,10 @@ mod tests { pub enum Origin for Test {} } + impl_outer_error! { + pub enum Error for Test where system = system {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; impl system::Trait for Test { @@ -356,6 +360,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl balances::Trait for Test { type Balance = u64; From a6c989bb3090817af5a1a73828c9bb1e0b12896a Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Fri, 21 Jun 2019 12:33:47 +1200 Subject: [PATCH 13/80] manually implement encode & decode to avoid i8 workaround --- core/sr-primitives/src/lib.rs | 27 +++++++++++++++++++++------ srml/executive/src/lib.rs | 5 ++--- srml/support/src/error.rs | 4 ++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index ac798fd44bdb5..c9754b861de13 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -536,25 +536,40 @@ pub enum ApplyError { FullBlock = 255, } -impl codec::Encode for ApplyError { +impl Encode for ApplyError { fn using_encoded R>(&self, f: F) -> R { f(&[*self as u8]) } } -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] +#[derive(Eq, PartialEq, Clone, Copy)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] /// Reason why a dispatch call failed pub struct DispatchError { /// Module index, matching the metadata module index - pub module: i8, // use i8 instead of u8 because u8 is not supported by parity-codec + pub module: u8, /// Module specific error value - pub error: i8, - /// Optional error message - #[codec(skip)] + pub error: u8, + /// Optional error message. pub message: Option<&'static str>, } +impl Encode for DispatchError { + fn using_encoded R>(&self, f: F) -> R { + f(&[self.module, self.error]) + } +} + +impl Decode for DispatchError { + fn decode(input: &mut R) -> Option { + Some(DispatchError { + module: input.read_byte()?, + error: input.read_byte()?, + message: None, + }) + } +} + /// Result from attempt to apply an extrinsic. pub type ApplyResult = Result; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index d335e7c5dd029..049b99f1a4b78 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -234,9 +234,8 @@ where Ok(ApplyOutcome::Success) => (), Ok(ApplyOutcome::Fail(e)) => { runtime_io::print("Error:"); - // as u8 first to ensure not using sign-extend - runtime_io::print(e.module as u8 as u64); - runtime_io::print(e.error as u8 as u64); + runtime_io::print(e.module as u64); + runtime_io::print(e.error as u64); if let Some(msg) = e.message { runtime_io::print(msg); } diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 4cb02e594c5cb..d65965f11de63 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -105,7 +105,7 @@ macro_rules! impl_outer_error { }, _ => $crate::runtime_primitives::DispatchError { module: 0, - error: Into::::into(err) as i8, + error: Into::::into(err), message: None, }, }, @@ -119,7 +119,7 @@ macro_rules! impl_outer_error { }, _ => $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), - error: Into::::into(err) as i8, + error: Into::::into(err), message: None, }, }, From 9d2dbbb63fe6a2f559c6de528f7e24f84d545d54 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Fri, 21 Jun 2019 20:53:40 +1200 Subject: [PATCH 14/80] more test fixes --- srml/aura/src/mock.rs | 11 +++--- srml/balances/src/lib.rs | 23 +++++++++++- srml/balances/src/mock.rs | 9 ++++- srml/balances/src/tests.rs | 13 ++++--- srml/support/src/dispatch.rs | 69 +++++++++++++++++++----------------- srml/support/src/error.rs | 19 +++++----- srml/system/src/lib.rs | 2 +- 7 files changed, 91 insertions(+), 55 deletions(-) diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index 386938f92069d..9b6e3e6573fec 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -19,7 +19,7 @@ #![cfg(test)] use primitives::{BuildStorage, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; -use srml_support::impl_outer_origin; +use srml_support::{impl_outer_origin, impl_outer_error}; use runtime_io; use substrate_primitives::{H256, Blake2Hasher}; use crate::{Trait, Module, GenesisConfig}; @@ -28,15 +28,14 @@ impl_outer_origin!{ pub enum Origin for Test {} } +impl_outer_error! { + pub enum Error for Runtime {} +} + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; -#[allow(non_camel_case_types)] -pub enum Error { - system(system::Error) -} - impl system::Trait for Test { type Origin = Origin; type Index = u64; diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 811e3d7cdc92a..88f746f9ffaf3 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -152,7 +152,7 @@ use rstd::prelude::*; use rstd::{cmp, result, mem}; use parity_codec::{Codec, Encode, Decode}; -use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module, decl_error}; use srml_support::traits::{ UpdateBalanceOutcome, Currency, OnFreeBalanceZero, MakePayment, OnUnbalanced, WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, @@ -170,6 +170,8 @@ mod tests; pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; +pub type DispatchResult = srml_support::dispatch::DispatchResult<>::Error>; + pub trait Subtrait: system::Trait { /// The balance of an account. type Balance: Parameter + Member + SimpleArithmetic + Codec + Default + Copy + @@ -211,6 +213,9 @@ pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; + + /// The overarching error type. + type Error: From + From + From<&'static str>; } impl, I: Instance> Subtrait for T { @@ -233,6 +238,19 @@ decl_event!( } ); +decl_error! { + pub enum Error { + } +} + +impl From for &'static str { + fn from(err: Error) -> &'static str { + match err { + Error::Unknown(msg) => msg, + } + } +} + /// Struct to encode the vesting schedule of an individual account. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] @@ -340,6 +358,8 @@ decl_storage! { decl_module! { pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + type Error = >::Error; + fn deposit_event() = default; /// Transfer some liquid free balance to another account. @@ -707,6 +727,7 @@ impl, I: Instance> Trait for ElevatedTrait { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = &'static str; } impl, I: Instance> Currency for Module diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index d97ae38dcc042..b5681f31c3c40 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -29,8 +29,14 @@ impl_outer_origin!{ pub enum Origin for Runtime {} } +mod balances { + pub use crate::Error; +} + impl_outer_error! { - pub enum Error for Runtime {} + pub enum Error for Runtime { + balances, + } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -56,6 +62,7 @@ impl Trait for Runtime { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); + type Error = Error; } pub struct ExtBuilder { diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 0a5a4b5bb70a6..2d85af274e143 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -208,7 +208,7 @@ fn default_indexing_on_new_accounts_should_not_work2() { // account 1 has 256 * 10 = 2560, account 5 is not exist, ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( Balances::transfer(Some(1).into(), 5, 9), - "value too low to create account" + mock::Error::balances(Error::Unknown("value too low to create account")) ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 100); @@ -347,7 +347,10 @@ fn balance_transfer_when_reserved_should_not_work() { with_externalities(&mut ExtBuilder::default().build(), || { let _ = Balances::deposit_creating(&1, 111); assert_ok!(Balances::reserve(&1, 69)); - assert_noop!(Balances::transfer(Some(1).into(), 2, 69), "balance too low to send value"); + assert_noop!( + Balances::transfer(Some(1).into(), 2, 69), + mock::Error::balances(Error::Unknown("balance too low to send value")) + ); }); } @@ -475,7 +478,7 @@ fn transferring_too_high_value_should_not_panic() { assert_err!( Balances::transfer(Some(1).into(), 2, u64::max_value()), - "destination balance too high to receive value" + mock::Error::balances(Error::Unknown("destination balance too high to receive value")) ); assert_eq!(Balances::free_balance(&1), u64::max_value()); @@ -553,7 +556,7 @@ fn transfer_overflow_isnt_exploitable() { assert_err!( Balances::transfer(Some(1).into(), 5, evil_value), - "got overflow after adding a fee to value" + mock::Error::balances(Error::Unknown("got overflow after adding a fee to value")) ); } ); @@ -617,7 +620,7 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has only 10 units vested at block 1 assert_noop!( Balances::transfer(Some(1).into(), 2, 11), - "vesting balance too high to send value" + mock::Error::balances(Error::Unknown("vesting balance too high to send value")) ); // Account 1 cannot send more than vested amount } ); diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index d8bb4ea030f74..c01180c94f693 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -424,7 +424,10 @@ macro_rules! decl_module { }; (@normalize $(#[$attr:meta])* - pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident> + pub struct $mod_type:ident< + $trait_instance:ident: + $trait_name:ident$(, $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 )* } @@ -438,7 +441,9 @@ macro_rules! decl_module { ) => { $crate::decl_module!(@normalize $(#[$attr])* - pub struct $mod_type<$trait_instance: $trait_name> + pub struct $mod_type< + $trait_instance: $trait_name$(, $instance: $instantiable $(= $module_default_instance)?)? + > for enum $call_type where origin: $origin_type, system = $system { $( $deposit_event )* } { $( $on_initialize )* } @@ -449,7 +454,7 @@ macro_rules! decl_module { $($rest)* ); }; - // This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse. + // Add default Error if none supplied (@normalize $(#[$attr:meta])* pub struct $mod_type:ident< @@ -461,13 +466,8 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } - { $error_type:ty } + { } [ $($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 )* } $($rest:tt)* ) => { $crate::decl_module!(@normalize @@ -480,20 +480,12 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } - { $error_type } - [ - $($t)* - $(#[doc = $doc_attr])* - #[weight = $weight] - $fn_vis fn $fn_name( - $origin $( , $(#[$codec_attr])* $param_name : $param )* - ) $( -> $result )* { $( $impl )* } - { $($instance: $instantiable)? } - ] + { &'static str } + [ $($t)* ] $($rest)* ); }; - // Add #[weight] if none is defined. + // This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident< @@ -505,11 +497,12 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } - { $( $error_type:tt )* } + { $error_type:ty } [ $($t:tt)* ] $(#[doc = $doc_attr:tt])* + #[weight = $weight:expr] $fn_vis:vis fn $fn_name:ident( - $from:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* + $origin:ident $(, $(#[$codec_attr:ident])* $param_name:ident : $param:ty)* ) $( -> $result:ty )* { $( $impl:tt )* } $($rest:tt)* ) => { @@ -523,17 +516,20 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } - { $( $error_type )* } - [ $($t)* ] - $(#[doc = $doc_attr])* - #[weight = $crate::dispatch::TransactionWeight::default()] - $fn_vis fn $fn_name( - $from $(, $(#[$codec_attr])* $param_name : $param )* - ) $( -> $result )* { $( $impl )* } + { $error_type } + [ + $($t)* + $(#[doc = $doc_attr])* + #[weight = $weight] + $fn_vis fn $fn_name( + $origin $( , $(#[$codec_attr])* $param_name : $param )* + ) $( -> $result )* { $( $impl )* } + { $($instance: $instantiable)? } + ] $($rest)* ); }; - // Add default Error if none supplied + // Add #[weight] if none is defined. (@normalize $(#[$attr:meta])* pub struct $mod_type:ident< @@ -545,8 +541,12 @@ macro_rules! decl_module { { $( $on_initialize:tt )* } { $( $on_finalize:tt )* } { $( $offchain:tt )* } - { } + { $( $error_type: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 @@ -559,8 +559,13 @@ macro_rules! decl_module { { $( $on_initialize )* } { $( $on_finalize )* } { $( $offchain )* } - { &'static str } + { $( $error_type )* } [ $($t)* ] + $(#[doc = $doc_attr])* + #[weight = $crate::dispatch::TransactionWeight::default()] + $fn_vis fn $fn_name( + $from $(, $(#[$codec_attr])* $param_name : $param )* + ) $( -> $result )* { $( $impl )* } $($rest)* ); }; diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index d65965f11de63..c4b83e796b8f1 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -96,7 +96,7 @@ macro_rules! impl_outer_error { impl Into<$crate::runtime_primitives::DispatchError> for $name { fn into(self) -> $crate::runtime_primitives::DispatchError { match self { - $name::system(err) => match err { + $name::system(ref err) => match err { $system::Error::Unknown(msg) => $crate::runtime_primitives::DispatchError { module: 0, @@ -110,15 +110,15 @@ macro_rules! impl_outer_error { }, }, $( - $name::$module(err) => match err { + $name::$module(ref err) => match err { $module::Error::Unknown(msg) => $crate::runtime_primitives::DispatchError { - module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), + module: $crate::codec::Encode::using_encoded(&self, |s| s[0]), error: 0, message: Some(msg), }, _ => $crate::runtime_primitives::DispatchError { - module: $crate::codec::Encode.using_encoded(&self, |s| s[0]), + module: $crate::codec::Encode::using_encoded(&self, |s| s[0]), error: Into::::into(err), message: None, }, @@ -130,7 +130,7 @@ macro_rules! impl_outer_error { $( impl From<$module::Error> for $name { - fn from(err: $system::Error) -> Self { + fn from(err: $module::Error) -> Self { $name::$module(err) } } @@ -174,11 +174,12 @@ macro_rules! decl_error { impl From for () { fn from(_: Error) -> () { () } } - impl Into for Error { - fn into(self) -> u8 { - match self { + + impl From<&Error> for u8 { + fn from(err: &Error) -> u8 { + match err { Error::Unknown(_) => 0, - _ => $crate::codec::Encode::using_encoded(&self, |s| s[0]), + _ => $crate::codec::Encode::using_encoded(err, |s| s[0]), } } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index a487da0238d90..ab9c82a249a39 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -202,7 +202,7 @@ pub type KeyValue = (Vec, Vec); decl_module! { pub struct Module for enum Call where origin: T::Origin { - type Error = Error; + type Error = T::Error; /// Deposits an event into this block's event record. pub fn deposit_event(event: T::Event) { From 31c9c845f0928f33f2681f6b7d536462b080f664 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Fri, 21 Jun 2019 22:01:51 +1200 Subject: [PATCH 15/80] more fixes --- node-template/runtime/src/lib.rs | 2 ++ node-template/runtime/src/template.rs | 5 ++--- node/runtime/src/lib.rs | 1 + srml/contracts/src/tests.rs | 5 ++++- srml/council/src/lib.rs | 5 ++++- srml/democracy/src/lib.rs | 5 ++++- srml/example/src/lib.rs | 5 ++++- srml/executive/src/lib.rs | 7 +++++-- srml/staking/src/mock.rs | 5 ++++- srml/treasury/src/lib.rs | 5 ++++- 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 26c046b2787a5..0d783d69f6136 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -162,6 +162,8 @@ impl balances::Trait for Runtime { type OnNewAccount = Indices; /// The ubiquitous event type. type Event = Event; + /// The ubiquitous event type. + type Error = Error; type TransactionPayment = (); type DustRemoval = (); diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index dcd50f5c1a709..3124b67f7deb2 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -82,9 +82,8 @@ mod tests { pub enum Origin for Test {} } - #[allow(non_camel_case_types)] - pub enum Error { - system(system::Error) + impl_outer_error! { + pub enum Error for Test {} } // For testing the module, we construct most of a mock runtime. This means diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index f43b27b92e6fc..ff4632690cedc 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -119,6 +119,7 @@ impl balances::Trait for Runtime { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); + type Error = Error; } impl timestamp::Trait for Runtime { diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index 84097c728a1eb..c416379c60847 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -65,7 +65,9 @@ impl_outer_dispatch! { } impl_outer_error! { - pub enum Error for Test {} + pub enum Error for Test { + balances + } } #[derive(Clone, Eq, PartialEq, Debug)] @@ -90,6 +92,7 @@ impl balances::Trait for Test { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); + type Error = Error; } impl timestamp::Trait for Test { type Moment = u64; diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 3b61ef89fc223..76599d5f100dd 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -65,7 +65,9 @@ mod tests { } impl_outer_error! { - pub enum Error for Test {} + pub enum Error for Test { + balances + } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -91,6 +93,7 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = Error; } parameter_types! { pub const LaunchPeriod: u64 = 1; diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 695c16fadf4d5..ca60292452ae7 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -940,7 +940,9 @@ mod tests { } impl_outer_error! { - pub enum Error for Test {} + pub enum Error for Test { + balances + } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -966,6 +968,7 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = Error; } parameter_types! { pub const LaunchPeriod: u64 = 2; diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index a15e9d5f2bf5d..74eef11fcdfe3 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -519,7 +519,9 @@ mod tests { } impl_outer_error! { - pub enum Error for Test {} + pub enum Error for Test { + balances + } } // For testing the module, we construct most of a mock runtime. This means @@ -547,6 +549,7 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = Error; } impl Trait for Test { type Event = (); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 049b99f1a4b78..91948a2ecd40b 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -417,7 +417,9 @@ mod tests { } impl_outer_error! { - pub enum Error for Runtime {} + pub enum Error for Runtime { + balances + } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -443,6 +445,7 @@ mod tests { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); + type Error = Error; } impl ValidateUnsigned for Runtime { @@ -639,7 +642,7 @@ mod tests { with_externalities(&mut t, || { assert_eq!(Executive::validate_transaction(xt.clone()), valid); - assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail)); + assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 0, message: None }))); }); } } diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 2e6a8731d051a..7dc368cc52319 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -71,7 +71,9 @@ impl_outer_origin!{ } impl_outer_error! { - pub enum Error for Test {} + pub enum Error for Test { + balances + } } // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -97,6 +99,7 @@ impl balances::Trait for Test { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = Error; } parameter_types! { pub const Period: BlockNumber = 1; diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 972d51231a1c9..690c24f3f5716 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -345,7 +345,9 @@ mod tests { } impl_outer_error! { - pub enum Error for Test where system = system {} + pub enum Error for Test { + balances + } } #[derive(Clone, Eq, PartialEq)] @@ -370,6 +372,7 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); + type Error = Error; } impl Trait for Test { type Currency = balances::Module; From 6cad33a73b76aaabed1c004a21a8b6d30ae47f95 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 16:30:16 +1200 Subject: [PATCH 16/80] more error fixes --- node-template/runtime/src/lib.rs | 2 +- node-template/runtime/src/template.rs | 2 +- node/runtime/src/lib.rs | 2 +- srml/contracts/src/tests.rs | 2 ++ srml/council/src/lib.rs | 2 ++ srml/democracy/src/lib.rs | 4 +++- srml/staking/src/tests.rs | 10 ++++++++-- 7 files changed, 18 insertions(+), 6 deletions(-) diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 0d783d69f6136..b685201800126 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -191,7 +191,7 @@ construct_runtime!( Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, Aura: aura::{Module, Config, Inherent(Timestamp)}, Indices: indices::{default, Config}, - Balances: balances, + Balances: balances::{default, Error}, Sudo: sudo, // Used for the module template in `./template.rs` TemplateModule: template::{Module, Call, Storage, Event}, diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index 3124b67f7deb2..eb138b032c7fd 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -71,7 +71,7 @@ mod tests { use runtime_io::with_externalities; use primitives::{H256, Blake2Hasher}; - use support::{impl_outer_origin, assert_ok}; + use support::{impl_outer_origin, impl_outer_error, assert_ok}; use runtime_primitives::{ BuildStorage, traits::{BlakeTwo256, IdentityLookup}, diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index ff4632690cedc..e4677aeb49f8e 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -253,7 +253,7 @@ construct_runtime!( Aura: aura::{Module, Config, Inherent(Timestamp)}, Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, Indices: indices, - Balances: balances, + Balances: balances::{default, Error}, Session: session::{Module, Call, Storage, Event, Config}, Staking: staking::{default, OfflineWorker}, Democracy: democracy, diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index c416379c60847..b18b9bf26163d 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -59,6 +59,8 @@ impl_outer_origin! { } impl_outer_dispatch! { pub enum Call for Test where origin: Origin { + type Error = Error; + balances::Balances, contract::Contract, } diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 76599d5f100dd..b21cb145adc24 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -59,6 +59,8 @@ mod tests { impl_outer_dispatch! { pub enum Call for Test where origin: Origin { + type Error = Error; + balances::Balances, democracy::Democracy, } diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index ca60292452ae7..4823d650a0885 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -934,6 +934,8 @@ mod tests { impl_outer_dispatch! { pub enum Call for Test where origin: Origin { + type Error = Error; + balances::Balances, democracy::Democracy, } @@ -941,7 +943,7 @@ mod tests { impl_outer_error! { pub enum Error for Test { - balances + balances, } } diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index 180ce130ae414..0bdd4d5abadca 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -818,7 +818,10 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 (via controller 10) is totally staked assert_eq!(Staking::stakers(&11).total, 1000); // Confirm account 11 cannot transfer as a result - assert_noop!(Balances::transfer(Origin::signed(11), 20, 1), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + Balances::transfer(Origin::signed(11), 20, 1), + mock::Error::system(system::Error::Unknown("account liquidity restrictions prevent withdrawal")) + ); // Give account 11 extra free balance let _ = Balances::make_free_balance_be(&11, 10000); @@ -844,7 +847,10 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 (via controller 20) is totally staked assert_eq!(Staking::stakers(&21).total, 1000); // Confirm account 21 can transfer at most 1000 - assert_noop!(Balances::transfer(Origin::signed(21), 20, 1001), "account liquidity restrictions prevent withdrawal"); + assert_noop!( + Balances::transfer(Origin::signed(21), 20, 1001), + mock::Error::system(system::Error::Unknown("account liquidity restrictions prevent withdrawal")) + ); assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); }); } From ba42e6a0f8417194e54ddc468f44753a287c62c4 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Sat, 22 Jun 2019 17:59:47 +1200 Subject: [PATCH 17/80] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tomasz Drwięga --- core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index 080bfa0d0531a..bdf96e15298d6 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -84,7 +84,7 @@ where type Checked = CheckedExtrinsic; type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); @@ -202,7 +202,7 @@ mod tests { type Source = u64; type Target = u64; type Error = &'static str; - fn lookup(&self, s: u64) -> Result { Ok(s) } + fn lookup(&self, s: u64) -> Result { Ok(s) } } impl CurrentHeight for TestContext { type BlockNumber = u64; From 0f01cc48625c0bfeaad848e2c3a89c17a4d196bf Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 18:00:11 +1200 Subject: [PATCH 18/80] address comments --- core/client/src/block_builder/block_builder.rs | 3 ++- srml/executive/src/lib.rs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 72b0d5f5838db..882791f95a79a 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -17,6 +17,7 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use parity_codec::Encode; +use runtime_primitives::ApplyOutcome; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, @@ -103,7 +104,7 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - Ok(_) => { + Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail(_)) => { extrinsics.push(xt); Ok(()) } diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 91948a2ecd40b..2e2e50fa27522 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -337,16 +337,16 @@ where // Checks out. Carry on. Ok(xt) => xt, Err(err) => { - match err.into() { + return match err.into() { // An unknown account index implies that the transaction may yet become valid. // TODO: avoid hardcoded error string here PrimitiveError::Unknown("invalid account index") => - return TransactionValidity::Unknown(INVALID_INDEX), + TransactionValidity::Unknown(INVALID_INDEX), // Technically a bad signature could also imply an out-of-date account index, but // that's more of an edge case. PrimitiveError::BadSignature => - return TransactionValidity::Invalid(ApplyError::BadSignature as i8), - _ => return TransactionValidity::Invalid(UNKNOWN_ERROR), + TransactionValidity::Invalid(ApplyError::BadSignature as i8), + _ => TransactionValidity::Invalid(UNKNOWN_ERROR), } } }; From c7ae1b177f57e11ddc43b74ce3f998f1de4f8bd8 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 18:17:15 +1200 Subject: [PATCH 19/80] test for DispatchError encoding --- core/sr-primitives/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index c9754b861de13..aee62937f2331 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -688,6 +688,7 @@ impl traits::Extrinsic for OpaqueExtrinsic { #[cfg(test)] mod tests { + use super::DispatchError; use crate::codec::{Encode, Decode}; macro_rules! per_thing_mul_upper_test { @@ -786,4 +787,21 @@ mod tests { ((Into::::into(std::u128::MAX) * 999_999u32) / 1_000_000u32).as_u128() ); } + + #[test] + fn dispatch_error_encoding() { + let error = DispatchError { + module: 1, + error: 2, + message: Some("error message"), + }; + let encoded = error.encode(); + let decoded = DispatchError::decode(&mut &*encoded).unwrap(); + assert_eq!(encoded, vec![1, 2]); + assert_eq!(decoded, DispatchError { + module: 1, + error: 2, + message: None, + }); + } } From 0e424c1b450895dce08480a0e2cd3201df4f95c8 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 18:18:57 +1200 Subject: [PATCH 20/80] tyep alias for democracy --- srml/democracy/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 4823d650a0885..f43e5d7c993fb 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -164,6 +164,7 @@ impl Decode for Vote { } type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type Error = &'static str; pub trait Trait: system::Trait + Sized { type Proposal: Parameter + Dispatchable + IsSubType>; @@ -191,23 +192,23 @@ pub trait Trait: system::Trait + Sized { /// Origin from which the next tabled referendum may be forced. This is a normal /// "super-majority-required" referendum. - type ExternalOrigin: EnsureOrigin; + type ExternalOrigin: EnsureOrigin; /// Origin from which the next tabled referendum may be forced; this allows for the tabling of /// a majority-carries referendum. - type ExternalMajorityOrigin: EnsureOrigin; + type ExternalMajorityOrigin: EnsureOrigin; /// Origin from which emergency referenda may be scheduled. - type EmergencyOrigin: EnsureOrigin; + type EmergencyOrigin: EnsureOrigin; /// Minimum voting period allowed for an emergency referendum. type EmergencyVotingPeriod: Get; /// Origin from which any referenda may be cancelled in an emergency. - type CancellationOrigin: EnsureOrigin; + type CancellationOrigin: EnsureOrigin; /// Origin for anyone able to veto proposals. - type VetoOrigin: EnsureOrigin; + type VetoOrigin: EnsureOrigin; /// Period in blocks where an external proposal may not be re-submitted after being vetoed. type CooloffPeriod: Get; From a145f271c44281e7c3c9e2765c1535c9a8095b13 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 18:30:45 +1200 Subject: [PATCH 21/80] make error printable --- srml/sudo/src/lib.rs | 7 +++---- srml/support/src/error.rs | 12 ++++++++++++ srml/support/src/lib.rs | 2 +- srml/system/src/lib.rs | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 73b311b1d77cd..90fedc2fe6f89 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -99,7 +99,7 @@ pub trait Trait: system::Trait { type Event: From> + Into<::Event>; /// A sudo-able call. - type Proposal: Parameter + Dispatchable; + type Proposal: Parameter + Dispatchable::Error>; } decl_module! { @@ -123,9 +123,8 @@ decl_module! { let res = match proposal.dispatch(system::RawOrigin::Root.into()) { Ok(_) => true, - Err(_e) => { - // TODO: not sure how to deal with this - // sr_io::print(e); + Err(e) => { + sr_io::print(e); false } }; diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index c4b83e796b8f1..fa990880bb8cc 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -82,6 +82,18 @@ macro_rules! impl_outer_error { } } + impl $crate::Printable for $name { + fn print(self) { + $crate::print("Error:"); + let err = Into::<$crate::runtime_primitives::DispatchError>::into(self); + $crate::print(err.module as u64); + $crate::print(err.error as u64); + if let Some(msg) = err.message { + $crate::print(msg); + } + } + } + impl $crate::rstd::convert::TryInto<$system::Error> for $name { type Error = Self; fn try_into(self) -> $crate::dispatch::result::Result<$system::Error, Self::Error> { diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index cf09f0f634adc..a6cef4b0bdfb7 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -65,7 +65,7 @@ pub use self::storage::{ pub use self::hashable::Hashable; pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; pub use self::double_map::StorageDoubleMapWithHasher; -pub use runtime_io::{print, storage_root}; +pub use runtime_io::{print, storage_root, Printable}; /// Macro for easily creating a new implementation of the `Get` trait. Use similarly to /// how you would declare a `const`: diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index ab9c82a249a39..2b2289262a85f 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -191,7 +191,7 @@ pub trait Trait: 'static + Eq + Clone { type Event: Parameter + Member + From; /// The aggregated error type of the runtime. - type Error: Member + From + From<&'static str>; + type Error: Member + From + From<&'static str> + runtime_io::Printable; } pub type DigestOf = generic::Digest<::Hash>; From ef4eecdc3fc855407ab64efc59a02539a578bc87 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 18:35:53 +1200 Subject: [PATCH 22/80] line width --- srml/executive/src/lib.rs | 5 ++++- srml/support/src/dispatch.rs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 2e2e50fa27522..6670a6dfae3a5 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -642,7 +642,10 @@ mod tests { with_externalities(&mut t, || { assert_eq!(Executive::validate_transaction(xt.clone()), valid); - assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 0, message: None }))); + assert_eq!( + Executive::apply_extrinsic(xt), + Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 0, message: None })) + ); }); } } diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index c01180c94f693..e6018579537dc 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -1208,7 +1208,10 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> { #[doc(hidden)] - pub fn dispatch>(d: D, origin: D::Origin) -> $crate::dispatch::DispatchResult { + pub fn dispatch>( + d: D, + origin: D::Origin + ) -> $crate::dispatch::DispatchResult { d.dispatch(origin) } } From 33668d85856ba2a4af678183c893cfafcb5623e7 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 19:04:00 +1200 Subject: [PATCH 23/80] fix balances tests --- srml/balances/src/tests.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 2d85af274e143..39fdc4ae26198 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -208,7 +208,7 @@ fn default_indexing_on_new_accounts_should_not_work2() { // account 1 has 256 * 10 = 2560, account 5 is not exist, ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( Balances::transfer(Some(1).into(), 5, 9), - mock::Error::balances(Error::Unknown("value too low to create account")) + mock::Error::system(system::Error::Unknown("value too low to create account")) ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 100); @@ -349,7 +349,7 @@ fn balance_transfer_when_reserved_should_not_work() { assert_ok!(Balances::reserve(&1, 69)); assert_noop!( Balances::transfer(Some(1).into(), 2, 69), - mock::Error::balances(Error::Unknown("balance too low to send value")) + mock::Error::system(system::Error::Unknown("balance too low to send value")) ); }); } @@ -478,7 +478,7 @@ fn transferring_too_high_value_should_not_panic() { assert_err!( Balances::transfer(Some(1).into(), 2, u64::max_value()), - mock::Error::balances(Error::Unknown("destination balance too high to receive value")) + mock::Error::system(system::Error::Unknown("destination balance too high to receive value")) ); assert_eq!(Balances::free_balance(&1), u64::max_value()); @@ -556,7 +556,7 @@ fn transfer_overflow_isnt_exploitable() { assert_err!( Balances::transfer(Some(1).into(), 5, evil_value), - mock::Error::balances(Error::Unknown("got overflow after adding a fee to value")) + mock::Error::system(system::Error::Unknown("got overflow after adding a fee to value")) ); } ); @@ -620,7 +620,7 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has only 10 units vested at block 1 assert_noop!( Balances::transfer(Some(1).into(), 2, 11), - mock::Error::balances(Error::Unknown("vesting balance too high to send value")) + mock::Error::system(system::Error::Unknown("vesting balance too high to send value")) ); // Account 1 cannot send more than vested amount } ); From d128a1af462f06e02519f4bca212f792179ee0be Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 22:15:34 +1200 Subject: [PATCH 24/80] fix executive test --- srml/executive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 6670a6dfae3a5..41e239fe2a462 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -644,7 +644,7 @@ mod tests { assert_eq!(Executive::validate_transaction(xt.clone()), valid); assert_eq!( Executive::apply_extrinsic(xt), - Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 0, message: None })) + Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 4 /*RequireNoOrigin*/ , message: None })) ); }); } From a4a8cdc8588b1e8b3829e79f5c27092b62dc794f Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 22:58:51 +1200 Subject: [PATCH 25/80] fix system tests --- srml/system/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 2b2289262a85f..ad13a311e3a2d 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -895,7 +895,7 @@ mod tests { assert_eq!(System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(1), event: 0x0201u16, topics: vec![] }, EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } ]); }); From f4387fbb8623bc763fc02dcc40578009001fa693 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 23:29:42 +1200 Subject: [PATCH 26/80] bump version --- node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 70a03ab5faacb..6b74f8499389c 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 97, - impl_version: 98, + spec_version: 99, + impl_version: 99, apis: RUNTIME_API_VERSIONS, }; From ef2eaa6fb0633709a9852b5d46eafba9b396986c Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 22 Jun 2019 23:36:51 +1200 Subject: [PATCH 27/80] ensure consistent method signature --- core/sr-primitives/src/generic/unchecked_extrinsic.rs | 2 +- .../src/generic/unchecked_mortal_compact_extrinsic.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 0b8cc42bd137a..5706e8d428b3f 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -89,7 +89,7 @@ where type Checked = CheckedExtrinsic; type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some(SignatureContent{signed, signature, index}) => { let payload = (index, self.function); diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 44003fc0d302c..80e07da1ea0b2 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -83,7 +83,7 @@ where type Checked = CheckedExtrinsic; type Error = Error; - fn check(self, context: &Context) -> Result { + fn check(self, context: &Context) -> Result { Ok(match self.signature { Some((signed, signature, index, era)) => { let current_u64 = context.current_height().saturated_into::(); From 31c998f736bd904f60164727f30f06be98e9a47e Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 26 Jun 2019 13:33:43 +1200 Subject: [PATCH 28/80] Apply suggestions from code review Co-Authored-By: Gavin Wood --- core/sr-primitives/src/lib.rs | 4 ++-- core/sr-primitives/src/traits.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index aee62937f2331..43eea029b18c2 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -64,11 +64,11 @@ pub enum Error { /// cause the fees are not being paid if this error is returned. /// /// Example: block gas limit is reached (the transaction can be retried in the next block though). - BlockFull + BlockFull, } // Exists for for backward compatibility purpose. -impl Into<&'static str> for Error{ +impl Into<&'static str> for Error { fn into(self) -> &'static str { match self { Error::Unknown(val) => val, diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 03f6dc4dc65cd..270d9fe84a0b4 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -90,7 +90,7 @@ pub trait EnsureOrigin { } impl EnsureOriginError for () { - fn invalid_origin() -> () { } + fn invalid_origin() -> () {} } impl EnsureOriginError for &'static str { From 51ec6283ff1fb3a1fd9e1844d83229e40e387a63 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 26 Jun 2019 14:03:41 +1200 Subject: [PATCH 29/80] changes based on review --- node/runtime/src/lib.rs | 14 +++++++------- srml/council/src/lib.rs | 10 +++++----- srml/council/src/motions.rs | 38 +++++++++++++++++++++---------------- srml/executive/src/lib.rs | 22 ++++++++++----------- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 6b74f8499389c..5906b4c4cc0a2 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -187,11 +187,11 @@ impl democracy::Trait for Runtime { type VotingPeriod = VotingPeriod; type EmergencyVotingPeriod = EmergencyVotingPeriod; type MinimumDeposit = MinimumDeposit; - type ExternalOrigin = council_motions::EnsureProportionAtLeast<_1, _2, AccountId>; - type ExternalMajorityOrigin = council_motions::EnsureProportionAtLeast<_2, _3, AccountId>; - type EmergencyOrigin = council_motions::EnsureProportionAtLeast<_1, _1, AccountId>; - type CancellationOrigin = council_motions::EnsureProportionAtLeast<_2, _3, AccountId>; - type VetoOrigin = council_motions::EnsureMember; + type ExternalOrigin = council_motions::EnsureProportionAtLeast<_1, _2, AccountId, &'static str>; + type ExternalMajorityOrigin = council_motions::EnsureProportionAtLeast<_2, _3, AccountId, &'static str>; + type EmergencyOrigin = council_motions::EnsureProportionAtLeast<_1, _1, AccountId, &'static str>; + type CancellationOrigin = council_motions::EnsureProportionAtLeast<_2, _3, AccountId, &'static str>; + type VetoOrigin = council_motions::EnsureMember; type CooloffPeriod = CooloffPeriod; } @@ -212,8 +212,8 @@ impl council::motions::Trait for Runtime { impl treasury::Trait for Runtime { type Currency = Balances; - type ApproveOrigin = council_motions::EnsureMembers<_4, AccountId>; - type RejectOrigin = council_motions::EnsureMembers<_2, AccountId>; + type ApproveOrigin = council_motions::EnsureMembers<_4, AccountId, &'static str>; + type RejectOrigin = council_motions::EnsureMembers<_2, AccountId, &'static str>; type Event = Event; type MintedForSpending = (); type ProposalRejection = (); diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index b21cb145adc24..7bead543a9049 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -113,11 +113,11 @@ mod tests { type EmergencyVotingPeriod = VotingPeriod; type VotingPeriod = VotingPeriod; type MinimumDeposit = MinimumDeposit; - type ExternalOrigin = motions::EnsureProportionAtLeast<_1, _2, u64>; - type ExternalMajorityOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; - type EmergencyOrigin = motions::EnsureProportionAtLeast<_1, _1, u64>; - type CancellationOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; - type VetoOrigin = motions::EnsureMember; + type ExternalOrigin = motions::EnsureProportionAtLeast<_1, _2, u64, &'static str>; + type ExternalMajorityOrigin = motions::EnsureProportionAtLeast<_2, _3, u64, &'static str>; + type EmergencyOrigin = motions::EnsureProportionAtLeast<_1, _1, u64, &'static str>; + type CancellationOrigin = motions::EnsureProportionAtLeast<_2, _3, u64, &'static str>; + type VetoOrigin = motions::EnsureMember; type CooloffPeriod = CooloffPeriod; } impl seats::Trait for Test { diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index d3e69c935225e..3d2ee1506d5ab 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -18,7 +18,7 @@ use rstd::{prelude::*, result}; use substrate_primitives::u32_trait::Value as U32; -use primitives::traits::{Hash, EnsureOrigin}; +use primitives::traits::{Hash, EnsureOrigin, EnsureOriginError}; use srml_support::{ dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure @@ -257,13 +257,14 @@ pub fn ensure_council_members(o: OuterOrigin, n: MemberC } } -pub struct EnsureMember(::rstd::marker::PhantomData); +pub struct EnsureMember(::rstd::marker::PhantomData<(AccountId, Error)>); impl< O: Into, O>> + From>, - AccountId -> EnsureOrigin for EnsureMember { + AccountId, + Error: EnsureOriginError, +> EnsureOrigin for EnsureMember { type Success = AccountId; - type Error = &'static str; + type Error = Error; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Member(id) => Ok(id), @@ -272,14 +273,17 @@ impl< } } -pub struct EnsureMembers(::rstd::marker::PhantomData<(N, AccountId)>); +pub struct EnsureMembers( + ::rstd::marker::PhantomData<(N, AccountId, Error)> +); impl< O: Into, O>> + From>, N: U32, AccountId, -> EnsureOrigin for EnsureMembers { + Error: EnsureOriginError, +> EnsureOrigin for EnsureMembers { type Success = (MemberCount, MemberCount); - type Error = &'static str; + type Error = Error; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), @@ -288,17 +292,18 @@ impl< } } -pub struct EnsureProportionMoreThan( - ::rstd::marker::PhantomData<(N, D, AccountId)> +pub struct EnsureProportionMoreThan( + ::rstd::marker::PhantomData<(N, D, AccountId, Error)> ); impl< O: Into, O>> + From>, N: U32, D: U32, AccountId, -> EnsureOrigin for EnsureProportionMoreThan { + Error: EnsureOriginError, +> EnsureOrigin for EnsureProportionMoreThan { type Success = (); - type Error = &'static str; + type Error = Error; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), @@ -307,17 +312,18 @@ impl< } } -pub struct EnsureProportionAtLeast( - ::rstd::marker::PhantomData<(N, D, AccountId)> +pub struct EnsureProportionAtLeast( + ::rstd::marker::PhantomData<(N, D, AccountId, Error)> ); impl< O: Into, O>> + From>, N: U32, D: U32, AccountId, -> EnsureOrigin for EnsureProportionAtLeast { + Error: EnsureOriginError, +> EnsureOrigin for EnsureProportionAtLeast { type Success = (); - type Error = &'static str; + type Error = Error; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 41e239fe2a462..43e62b8d302f6 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -336,18 +336,16 @@ where let xt = match uxt.check(&Default::default()) { // Checks out. Carry on. Ok(xt) => xt, - Err(err) => { - return match err.into() { - // An unknown account index implies that the transaction may yet become valid. - // TODO: avoid hardcoded error string here - PrimitiveError::Unknown("invalid account index") => - TransactionValidity::Unknown(INVALID_INDEX), - // Technically a bad signature could also imply an out-of-date account index, but - // that's more of an edge case. - PrimitiveError::BadSignature => - TransactionValidity::Invalid(ApplyError::BadSignature as i8), - _ => TransactionValidity::Invalid(UNKNOWN_ERROR), - } + Err(err) => return match err.into() { + // An unknown account index implies that the transaction may yet become valid. + // TODO: avoid hardcoded error string here + PrimitiveError::Unknown("invalid account index") => + TransactionValidity::Unknown(INVALID_INDEX), + // Technically a bad signature could also imply an out-of-date account index, but + // that's more of an edge case. + PrimitiveError::BadSignature => + TransactionValidity::Invalid(ApplyError::BadSignature as i8), + _ => TransactionValidity::Invalid(UNKNOWN_ERROR), } }; From 88887ee77fc791e6cc156ca159ab2fcc4eea4521 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 26 Jun 2019 14:13:31 +1200 Subject: [PATCH 30/80] Add issue number for TODOs --- srml/executive/src/lib.rs | 4 ++-- srml/system/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 43e62b8d302f6..2c057bc976d4d 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -272,7 +272,7 @@ where } } // pay any fees - // TODO: propagate why can't pay + // TODO: propagate why can't pay #2952 Payment::make_payment(sender, encoded_len).map_err(|_| ApplyError::CantPay)?; // AUDIT: Under no circumstances may this function panic from here onwards. @@ -338,7 +338,7 @@ where Ok(xt) => xt, Err(err) => return match err.into() { // An unknown account index implies that the transaction may yet become valid. - // TODO: avoid hardcoded error string here + // TODO: avoid hardcoded error string here #2953 PrimitiveError::Unknown("invalid account index") => TransactionValidity::Unknown(INVALID_INDEX), // Technically a bad signature could also imply an out-of-date account index, but diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index ad13a311e3a2d..f8dcb4407f0fe 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -178,7 +178,7 @@ pub trait Trait: 'static + Eq + Clone { /// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly /// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules /// (e.g. Indices module) may provide more functional/efficient alternatives. - // TODO: avoid &'static str error type + // TODO: avoid &'static str error type #2953 type Lookup: StaticLookup; /// The block header. From c147a8e7ad29e177f005f39030233990f1934e8a Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 29 Jun 2019 15:16:54 +1200 Subject: [PATCH 31/80] fix --- srml/support/src/runtime.rs | 4 +++- srml/support/test/tests/instance.rs | 1 + srml/support/test/tests/issue2219.rs | 3 ++- srml/support/test/tests/system.rs | 8 +++++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index c162704a2f664..b5006714ca577 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -219,7 +219,9 @@ macro_rules! construct_runtime { $crate::__decl_outer_error!( $runtime; $( - $name: $module:: $( < $module_instance >:: )? { $( $modules $( <$modules_generic $(, $modules_instance)?> )* ),* } + $name: $module:: $( < $module_instance >:: )? { + $( $modules $( <$modules_generic> )* ),* + } ),* ); $crate::__decl_all_modules!( diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs index 28636573d3b55..00cace355a16e 100644 --- a/srml/support/test/tests/instance.rs +++ b/srml/support/test/tests/instance.rs @@ -209,6 +209,7 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; + type Error = Error; } srml_support::construct_runtime!( diff --git a/srml/support/test/tests/issue2219.rs b/srml/support/test/tests/issue2219.rs index 185b5e24807a9..0fba65bd750a7 100644 --- a/srml/support/test/tests/issue2219.rs +++ b/srml/support/test/tests/issue2219.rs @@ -160,6 +160,7 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; + type Error = Error; } impl module::Trait for Runtime {} @@ -183,4 +184,4 @@ fn create_genesis_config() { enable_storage_role: true, }) }; -} \ No newline at end of file +} diff --git a/srml/support/test/tests/system.rs b/srml/support/test/tests/system.rs index 6483161211afc..5f04021106a59 100644 --- a/srml/support/test/tests/system.rs +++ b/srml/support/test/tests/system.rs @@ -8,6 +8,7 @@ pub trait Trait: 'static + Eq + Clone { type Hash; type AccountId: Encode + Decode; type Event: From; + type Error: From + From<&'static str>; } srml_support::decl_module! { @@ -24,6 +25,11 @@ srml_support::decl_event!( } ); +srml_support::decl_error! { + pub enum Error { + } +} + /// Origin for the system module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] @@ -49,4 +55,4 @@ pub fn ensure_root(o: OuterOrigin) -> Result<(), &'stati where OuterOrigin: Into, OuterOrigin>> { o.into().map(|_| ()).map_err(|_| "bad origin: expected to be a root origin") -} \ No newline at end of file +} From 633a482723dae72bdc003bd2ce32fb6fc2aaaee3 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 29 Jun 2019 15:20:51 +1200 Subject: [PATCH 32/80] line width --- srml/staking/src/mock.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index ee87012e8035b..d9afd1659affa 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -22,7 +22,9 @@ use primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize}; use primitives::testing::{Header, UintAuthorityId}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use srml_support::{impl_outer_origin, impl_outer_error, parameter_types, assert_ok, traits::Currency, EnumerableStorageMap}; +use srml_support::{ + impl_outer_origin, impl_outer_error, parameter_types, assert_ok, traits::Currency, EnumerableStorageMap +}; use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, Nominators }; From b61e13758c95e7d21de2e56b376252d09eb80245 Mon Sep 17 00:00:00 2001 From: Bryan Chen Date: Sat, 29 Jun 2019 15:53:37 +1200 Subject: [PATCH 33/80] fix test --- srml/authorship/src/lib.rs | 7 ++++++- srml/finality-tracker/src/lib.rs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/srml/authorship/src/lib.rs b/srml/authorship/src/lib.rs index 8add05bb5930d..ffe7f974492f7 100644 --- a/srml/authorship/src/lib.rs +++ b/srml/authorship/src/lib.rs @@ -315,12 +315,16 @@ mod tests { use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::Header; use primitives::generic::DigestItem; - use srml_support::{parameter_types, impl_outer_origin, ConsensusEngineId}; + use srml_support::{parameter_types, impl_outer_origin, impl_outer_error, ConsensusEngineId}; impl_outer_origin!{ pub enum Origin for Test {} } + impl_outer_error!{ + pub enum Error for Test {} + } + #[derive(Clone, Eq, PartialEq)] pub struct Test; @@ -334,6 +338,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } impl Trait for Test { diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 46e4492fd16b1..ed7509b2244fb 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -294,6 +294,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); + type Error = Error; } type System = system::Module; From 3d2c850a7074b31499b0a4bc8d70f6f9874d5f5c Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 15:35:59 +1200 Subject: [PATCH 34/80] Update core/sr-primitives/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- core/sr-primitives/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 2f08bdc479395..f5c4abd53be40 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -56,7 +56,7 @@ pub use generic::{DigestItem, Digest}; pub enum Error { /// Unknown error /// This exists only to make implementation easier. Should be avoid as much as possible. - Unknown(&'static str), + Other(&'static str), /// Indicating an invalid signature in extrinsic. BadSignature, /// Full block error. From 8330acfb97b0892d3c62d2ccedb1254942645d25 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 15:36:22 +1200 Subject: [PATCH 35/80] Update core/sr-primitives/src/traits.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- core/sr-primitives/src/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 40b2e1ebb483e..bfe68d22088ed 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -131,7 +131,7 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - type Error = &'static str; + type Error = (); fn lookup(x: T) -> result::Result { Ok(x) } fn unlookup(x: T) -> T { x } } From d41955a7facc0a78906e647c40d28d3006c71480 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 15:40:55 +1200 Subject: [PATCH 36/80] Update srml/council/src/motions.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- srml/council/src/motions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index 91fdbd1565b66..fe9da639538f5 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -313,7 +313,7 @@ impl< } pub struct EnsureProportionAtLeast( - ::rstd::marker::PhantomData<(N, D, AccountId, Error)> + rstd::marker::PhantomData<(N, D, AccountId, Error)> ); impl< O: Into, O>> + From>, From 66187b3c00e489b79cdd6600a6aaf0145046c178 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 15:41:10 +1200 Subject: [PATCH 37/80] Update srml/council/src/motions.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- srml/council/src/motions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/council/src/motions.rs b/srml/council/src/motions.rs index fe9da639538f5..a44377a10833e 100644 --- a/srml/council/src/motions.rs +++ b/srml/council/src/motions.rs @@ -274,7 +274,7 @@ impl< } pub struct EnsureMembers( - ::rstd::marker::PhantomData<(N, AccountId, Error)> + rstd::marker::PhantomData<(N, AccountId, Error)> ); impl< O: Into, O>> + From>, From 7489d3a7defe7878229709cbc89073c1ae06ae9e Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 17:02:22 +1200 Subject: [PATCH 38/80] update based on review --- .../src/generic/unchecked_extrinsic.rs | 6 ++-- .../unchecked_mortal_compact_extrinsic.rs | 12 +++---- .../src/generic/unchecked_mortal_extrinsic.rs | 12 +++---- core/sr-primitives/src/lib.rs | 34 +++++++++---------- core/sr-primitives/src/testing.rs | 4 +-- core/sr-primitives/src/traits.rs | 2 +- core/test-runtime/src/lib.rs | 10 +++--- srml/balances/src/lib.rs | 2 +- srml/balances/src/tests.rs | 10 +++--- srml/contracts/src/gas.rs | 2 +- srml/executive/src/lib.rs | 14 ++++---- srml/staking/src/tests.rs | 4 +-- srml/support/src/error.rs | 15 ++++---- srml/system/src/lib.rs | 6 ++-- 14 files changed, 64 insertions(+), 69 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 5706e8d428b3f..d11561a415836 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -22,7 +22,7 @@ use std::fmt; use rstd::prelude::*; use crate::codec::{Decode, Encode, Codec, Input, HasCompact}; use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, Lookup, Extrinsic}; -use crate::Error; +use crate::PrimitiveError; use super::CheckedExtrinsic; #[derive(PartialEq, Eq, Clone, Encode, Decode)] @@ -87,7 +87,7 @@ where Context: Lookup { type Checked = CheckedExtrinsic; - type Error = Error; + type Error = PrimitiveError; fn check(self, context: &Context) -> Result { Ok(match self.signature { @@ -95,7 +95,7 @@ where let payload = (index, self.function); let signed = context.lookup(signed)?; if !crate::verify_encoded_lazy(&signature, &payload, &signed) { - return Err(Error::BadSignature) + return Err(PrimitiveError::BadSignature) } CheckedExtrinsic { signed: Some((signed, payload.0)), diff --git a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs index 80e07da1ea0b2..2cd52b386662a 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_compact_extrinsic.rs @@ -24,7 +24,7 @@ use runtime_io::blake2_256; use crate::codec::{Decode, Encode, Input, Compact}; use crate::traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, Checkable, Extrinsic, SaturatedConversion}; -use crate::Error; +use crate::PrimitiveError; use super::{CheckedExtrinsic, Era}; const TRANSACTION_VERSION: u8 = 1; @@ -81,7 +81,7 @@ where + BlockNumberToHash, { type Checked = CheckedExtrinsic; - type Error = Error; + type Error = PrimitiveError; fn check(self, context: &Context) -> Result { Ok(match self.signature { @@ -98,7 +98,7 @@ where signature.verify(payload, &signed) } }) { - return Err(Error::BadSignature) + return Err(PrimitiveError::BadSignature) } CheckedExtrinsic { signed: Some((signed, (raw_payload.0).0)), @@ -259,7 +259,7 @@ mod tests { fn badly_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] @@ -287,14 +287,14 @@ mod tests { fn too_late_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] fn too_early_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] diff --git a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index bdf96e15298d6..38f88b65a1cfe 100644 --- a/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -26,7 +26,7 @@ use crate::traits::{ self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, Checkable, Extrinsic, SaturatedConversion }; -use crate::Error; +use crate::PrimitiveError; use super::{CheckedExtrinsic, Era}; const TRANSACTION_VERSION: u8 = 1; @@ -82,7 +82,7 @@ where + BlockNumberToHash, { type Checked = CheckedExtrinsic; - type Error = Error; + type Error = PrimitiveError; fn check(self, context: &Context) -> Result { Ok(match self.signature { @@ -100,7 +100,7 @@ where signature.verify(payload, &signed) } }) { - return Err(Error::BadSignature) + return Err(PrimitiveError::BadSignature) } CheckedExtrinsic { signed: Some((signed, raw_payload.0)), @@ -260,7 +260,7 @@ mod tests { fn badly_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] @@ -288,14 +288,14 @@ mod tests { fn too_late_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] fn too_early_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, vec![0u8;0], DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, vec![0u8;0], Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(Error::BadSignature)); + assert_eq!(>::check(ux, &TestContext), Err(PrimitiveError::BadSignature)); } #[test] diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index f5c4abd53be40..e197885ca82f9 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -52,8 +52,8 @@ pub mod transaction_validity; pub use generic::{DigestItem, Digest}; #[cfg_attr(test, derive(PartialEq, Debug))] -/// Error type -pub enum Error { +/// Primitive Error type +pub enum PrimitiveError { /// Unknown error /// This exists only to make implementation easier. Should be avoid as much as possible. Other(&'static str), @@ -71,19 +71,19 @@ pub enum Error { } // Exists for for backward compatibility purpose. -impl Into<&'static str> for Error { +impl Into<&'static str> for PrimitiveError { fn into(self) -> &'static str { match self { - Error::Unknown(val) => val, - Error::BadSignature => "bad signature in extrinsic", - Error::BlockFull => "block size limit is reached", + PrimitiveError::Other(val) => val, + PrimitiveError::BadSignature => "bad signature in extrinsic", + PrimitiveError::BlockFull => "block size limit is reached", } } } -impl From<&'static str> for Error { - fn from(val: &'static str) -> Error { - Error::Unknown(val) +impl From<&'static str> for PrimitiveError { + fn from(val: &'static str) -> PrimitiveError { + PrimitiveError::Other(val) } } @@ -565,14 +565,14 @@ impl From for AnySignature { } #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] - #[cfg_attr(feature = "std", derive(Debug, Serialize))] - /// Outcome of a valid extrinsic application. Capable of being sliced. - pub enum ApplyOutcome { - /// Successful application (extrinsic reported no issue). - Success, - /// Failed application (extrinsic was probably a no-op other than fees). - Fail(DispatchError), - } +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +/// Outcome of a valid extrinsic application. Capable of being sliced. +pub enum ApplyOutcome { + /// Successful application (extrinsic reported no issue). + Success, + /// Failed application (extrinsic was probably a no-op other than fees). + Fail(DispatchError), +} #[derive(Eq, PartialEq, Clone, Copy, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 3fb276632097c..ed779156dd21d 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -22,7 +22,7 @@ use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Checkable, Applyable, BlakeTwo256, OpaqueKeys}; use crate::generic; use crate::weights::{Weighable, Weight}; -use crate::Error; +use crate::PrimitiveError; pub use substrate_primitives::H256; use substrate_primitives::U256; use substrate_primitives::ed25519::{Public as AuthorityId}; @@ -201,7 +201,7 @@ impl Debug for TestXt { impl Checkable for TestXt { type Checked = Self; - type Error = Error; + type Error = PrimitiveError; fn check(self, _: &Context) -> Result { Ok(self) } } impl traits::Extrinsic for TestXt { diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index bfe68d22088ed..40b2e1ebb483e 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -131,7 +131,7 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - type Error = (); + type Error = &'static str; fn lookup(x: T) -> result::Result { Ok(x) } fn unlookup(x: T) -> T { x } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index a47be8fb2e715..edd192407eb5f 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -37,7 +37,7 @@ use runtime_primitives::{ ApplyResult, create_runtime_str, transaction_validity::TransactionValidity, - Error, + PrimitiveError, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, Verify @@ -123,19 +123,19 @@ impl serde::Serialize for Extrinsic { impl BlindCheckable for Extrinsic { type Checked = Self; - type Error = Error; + type Error = PrimitiveError; - fn check(self) -> Result { + fn check(self) -> Result { match self { Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), Extrinsic::Transfer(transfer, signature) => { if runtime_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer(transfer, signature)) } else { - Err(Error::BadSignature) + Err(PrimitiveError::BadSignature) } }, - Extrinsic::IncludeData(_) => Err(Error::BadSignature), + Extrinsic::IncludeData(_) => Err(PrimitiveError::BadSignature), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), } } diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index e479bbfecb69b..99273f0618d5a 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -287,7 +287,7 @@ decl_error! { impl From for &'static str { fn from(err: Error) -> &'static str { match err { - Error::Unknown(msg) => msg, + Error::Other(msg) => msg, } } } diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 39fdc4ae26198..8989a4bab99fb 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -208,7 +208,7 @@ fn default_indexing_on_new_accounts_should_not_work2() { // account 1 has 256 * 10 = 2560, account 5 is not exist, ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( Balances::transfer(Some(1).into(), 5, 9), - mock::Error::system(system::Error::Unknown("value too low to create account")) + mock::Error::system(system::Error::Other("value too low to create account")) ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 100); @@ -349,7 +349,7 @@ fn balance_transfer_when_reserved_should_not_work() { assert_ok!(Balances::reserve(&1, 69)); assert_noop!( Balances::transfer(Some(1).into(), 2, 69), - mock::Error::system(system::Error::Unknown("balance too low to send value")) + mock::Error::system(system::Error::Other("balance too low to send value")) ); }); } @@ -478,7 +478,7 @@ fn transferring_too_high_value_should_not_panic() { assert_err!( Balances::transfer(Some(1).into(), 2, u64::max_value()), - mock::Error::system(system::Error::Unknown("destination balance too high to receive value")) + mock::Error::system(system::Error::Other("destination balance too high to receive value")) ); assert_eq!(Balances::free_balance(&1), u64::max_value()); @@ -556,7 +556,7 @@ fn transfer_overflow_isnt_exploitable() { assert_err!( Balances::transfer(Some(1).into(), 5, evil_value), - mock::Error::system(system::Error::Unknown("got overflow after adding a fee to value")) + mock::Error::system(system::Error::Other("got overflow after adding a fee to value")) ); } ); @@ -620,7 +620,7 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 90); // Account 1 has only 10 units vested at block 1 assert_noop!( Balances::transfer(Some(1).into(), 2, 11), - mock::Error::system(system::Error::Unknown("vesting balance too high to send value")) + mock::Error::system(system::Error::Other("vesting balance too high to send value")) ); // Account 1 cannot send more than vested amount } ); diff --git a/srml/contracts/src/gas.rs b/srml/contracts/src/gas.rs index da13c0fea2f53..cf0aa2ebd7ebf 100644 --- a/srml/contracts/src/gas.rs +++ b/srml/contracts/src/gas.rs @@ -16,7 +16,7 @@ use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; use rstd::convert::TryFrom; -use runtime_primitives::Error as PrimitiveError; +use runtime_primitives::PrimitiveError; use runtime_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto}; use srml_support::StorageValue; use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReason}; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 8aafeac448fe9..90ea8448a768b 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -78,7 +78,7 @@ use rstd::prelude::*; use rstd::marker::PhantomData; use rstd::convert::TryInto; use primitives::{ - generic::Digest, ApplyResult, ApplyOutcome, ApplyError, DispatchError, Error as PrimitiveError, + generic::Digest, ApplyResult, ApplyOutcome, ApplyError, DispatchError, PrimitiveError, traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, NumberFor, Block as BlockT, OffchainWorker, @@ -264,12 +264,10 @@ where if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { // check index let expected_index = >::account_nonce(sender); - if index != &expected_index { - return if index < &expected_index { - Err(ApplyError::Stale) - } else { - Err(ApplyError::Future) - } + if index < &expected_index { + return Err(ApplyError::Stale) + } else if index > &expected_index { + return Err(ApplyError::Future) } // pay any fees // TODO: propagate why can't pay #2952 @@ -339,7 +337,7 @@ where Err(err) => return match err.into() { // An unknown account index implies that the transaction may yet become valid. // TODO: avoid hardcoded error string here #2953 - PrimitiveError::Unknown("invalid account index") => + PrimitiveError::Other("invalid account index") => TransactionValidity::Unknown(INVALID_INDEX), // Technically a bad signature could also imply an out-of-date account index, but // that's more of an edge case. diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index f70813d7bc661..b3863a3a2ca07 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -887,7 +887,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), - mock::Error::system(system::Error::Unknown("account liquidity restrictions prevent withdrawal")) + mock::Error::system(system::Error::Other("account liquidity restrictions prevent withdrawal")) ); // Give account 11 extra free balance @@ -916,7 +916,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), - mock::Error::system(system::Error::Unknown("account liquidity restrictions prevent withdrawal")) + mock::Error::system(system::Error::Other("account liquidity restrictions prevent withdrawal")) ); assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); }); diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index fa990880bb8cc..d39e43271768f 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -78,7 +78,7 @@ macro_rules! impl_outer_error { impl From<&'static str> for $name { fn from(err: &'static str) -> Self { - $name::system($system::Error::Unknown(err)) + $name::system($system::Error::Other(err)) } } @@ -109,7 +109,7 @@ macro_rules! impl_outer_error { fn into(self) -> $crate::runtime_primitives::DispatchError { match self { $name::system(ref err) => match err { - $system::Error::Unknown(msg) => + $system::Error::Other(msg) => $crate::runtime_primitives::DispatchError { module: 0, error: 0, @@ -123,7 +123,7 @@ macro_rules! impl_outer_error { }, $( $name::$module(ref err) => match err { - $module::Error::Unknown(msg) => + $module::Error::Other(msg) => $crate::runtime_primitives::DispatchError { module: $crate::codec::Encode::using_encoded(&self, |s| s[0]), error: 0, @@ -178,19 +178,16 @@ macro_rules! decl_error { $(#[$attr])* #[allow(non_camel_case_types)] pub enum Error { - Unknown(&'static str), + Other(&'static str), $( $errors )* } - impl From for () { - fn from(_: Error) -> () { () } - } impl From<&Error> for u8 { fn from(err: &Error) -> u8 { match err { - Error::Unknown(_) => 0, + Error::Other(_) => 0, _ => $crate::codec::Encode::using_encoded(err, |s| s[0]), } } @@ -198,7 +195,7 @@ macro_rules! decl_error { impl From<&'static str> for Error { fn from(val: &'static str) -> Error { - Error::Unknown(val) + Error::Other(val) } } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 005c3975ed53f..b4668d2cdfeb6 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -77,7 +77,7 @@ use rstd::prelude::*; #[cfg(any(feature = "std", test))] use rstd::map; use primitives::{ - generic, Error as PrimitiveError, DispatchError, + generic, PrimitiveError, DispatchError, traits::{ self, CheckEqual, SimpleArithmetic, SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, CurrentHeight, BlockNumberToHash, @@ -286,7 +286,7 @@ decl_error! { impl From for Error { fn from(err: PrimitiveError) -> Error { match err { - PrimitiveError::Unknown(err) => Error::Unknown(err), + PrimitiveError::Other(err) => Error::Other(err), PrimitiveError::BadSignature => Error::BadSignature, PrimitiveError::BlockFull => Error::BlockFull, } @@ -297,7 +297,7 @@ impl From for Error { impl From for &'static str { fn from(err: Error) -> &'static str { match err { - Error::Unknown(val) => val, + Error::Other(val) => val, Error::BadSignature => "bad signature in extrinsic", Error::BlockFull => "block size limit is reached", Error::RequireSignedOrigin => "bad origin: expected to be a signed origin", From 6e5c3ce89c5ff9d11b6fbf687937f7bf5d8fbb13 Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Wed, 10 Jul 2019 18:16:50 +1200 Subject: [PATCH 39/80] More concrete macro matching --- srml/support/src/error.rs | 11 +++++++---- srml/support/test/tests/system.rs | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index d39e43271768f..e0041dd41f2ef 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -168,8 +168,10 @@ macro_rules! decl_error { $(#[$attr:meta])* pub enum Error { $( - $errors:tt - )* + $(#[$variant_attr:meta])* + $name:ident + ),* + $(,)? } ) => { // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. @@ -180,8 +182,9 @@ macro_rules! decl_error { pub enum Error { Other(&'static str), $( - $errors - )* + $(#[$variant_attr])* + $name + ),* } impl From<&Error> for u8 { diff --git a/srml/support/test/tests/system.rs b/srml/support/test/tests/system.rs index 5f04021106a59..9ae9c4a4bf060 100644 --- a/srml/support/test/tests/system.rs +++ b/srml/support/test/tests/system.rs @@ -27,6 +27,8 @@ srml_support::decl_event!( srml_support::decl_error! { pub enum Error { + TestError, + AnotherError } } From efe953a3f105da29a7bf9f5c587e22b65fa998df Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Thu, 18 Jul 2019 14:16:16 +1200 Subject: [PATCH 40/80] fix test build issue --- srml/balances/src/tests.rs | 2 +- srml/collective/src/lib.rs | 1 + srml/elections/src/lib.rs | 4 +++- srml/executive/src/lib.rs | 6 +++++- srml/generic-asset/src/lib.rs | 1 + srml/generic-asset/src/mock.rs | 7 ++++++- 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 9dacdfd595140..cf2b5831055ab 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -652,7 +652,7 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 45); assert_noop!( Balances::transfer(Some(1).into(), 2, 56), - mock::Error::system(system::Error::Other("vesting balance too high to send value") + mock::Error::system(system::Error::Other("vesting balance too high to send value")) ); // Account 1 cannot send more than vested amount } ); diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index 60652f6af07f6..914bdbb253062 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -414,6 +414,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; + type Error = Error; type BlockHashCount = BlockHashCount; } impl Trait for Test { diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index 80324ecefbdaf..92ccc3c3374b8 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -1119,6 +1119,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; + type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -1133,6 +1134,7 @@ mod tests { type OnNewAccount = (); type OnFreeBalanceZero = (); type Event = Event; + type Error = Error; type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); @@ -1220,7 +1222,7 @@ mod tests { UncheckedExtrinsic = UncheckedExtrinsic { System: system::{Module, Call, Event}, - Balances: balances::{Module, Call, Event, Config}, + Balances: balances::{Module, Call, Event, Config, Error}, Elections: elections::{Module, Call, Event, Config}, } ); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index d98e1e1d378a8..970d65b6dfdd5 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -682,7 +682,11 @@ mod tests { )); if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { - assert_eq!(Executive::apply_extrinsic(xt).unwrap(), ApplyOutcome::Fail); + assert_eq!(Executive::apply_extrinsic(xt).unwrap(), ApplyOutcome::Fail(DispatchError { + module: 0, + error: 0, + message: Some("account liquidity restrictions prevent withdrawal") + })); // but tx fee has been deducted. the transaction failed on transfer, not on fee. assert_eq!(>::total_balance(&1), 111 - 10); } else { diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index 60370600a69a6..6cab7c4935033 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -1056,6 +1056,7 @@ impl system::Trait for ElevatedTrait { type Lookup = T::Lookup; type Header = T::Header; type Event = (); + type Error = &'static str; type BlockHashCount = T::BlockHashCount; } impl Trait for ElevatedTrait { diff --git a/srml/generic-asset/src/mock.rs b/srml/generic-asset/src/mock.rs index 02e18fc335839..70d6273fddfa8 100644 --- a/srml/generic-asset/src/mock.rs +++ b/srml/generic-asset/src/mock.rs @@ -25,7 +25,7 @@ use primitives::{ traits::{BlakeTwo256, IdentityLookup}, }; use substrate_primitives::{Blake2Hasher, H256}; -use support::{parameter_types, impl_outer_event, impl_outer_origin}; +use support::{parameter_types, impl_outer_event, impl_outer_origin, impl_outer_error}; use super::*; @@ -33,6 +33,10 @@ impl_outer_origin! { pub enum Origin for Test {} } +impl_outer_error! { + pub enum Error for Test {} +} + // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -51,6 +55,7 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; + type Error = Error; type BlockHashCount = BlockHashCount; } From bec79261ca2ee9c165ff585af3e1141ffcb5d238 Mon Sep 17 00:00:00 2001 From: Kian Peymani Date: Thu, 18 Jul 2019 11:28:55 +0200 Subject: [PATCH 41/80] Update hex-literal dependency version. (#3141) * Update hex-literal dep version. * Update lock file. --- Cargo.lock | 38 ++------------------------------------ core/client/Cargo.toml | 2 +- srml/babe/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fcd6982e0115..4a985f432f872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1176,15 +1176,6 @@ name = "hex" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "hex-literal" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hex-literal" version = "0.2.0" @@ -1194,14 +1185,6 @@ dependencies = [ "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hex-literal-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "hex-literal-impl" version = "0.2.0" @@ -2832,14 +2815,6 @@ dependencies = [ "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro-hack" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro-hack" version = "0.5.8" @@ -2850,11 +2825,6 @@ dependencies = [ "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro-hack-impl" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "proc-macro2" version = "0.4.30" @@ -3690,7 +3660,7 @@ dependencies = [ name = "srml-babe" version = "2.0.0" dependencies = [ - "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4235,7 +4205,7 @@ dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.17 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -6046,9 +6016,7 @@ dependencies = [ "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc2928beef125e519d69ae1baa8c37ea2e0d3848545217f6db0179c5eb1d639" "checksum hex-literal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3da68162fdd2147e66682e78e729bd77f93b4c99656db058c5782d8c6b6225a" -"checksum hex-literal-impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "520870c3213943eb8d7803e80180d12a6c7ceb4ae74602544529d1643dc4ddda" "checksum hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06095d08c7c05760f11a071b3e1d4c5b723761c01bd8d7201c30a9536668a612" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" "checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" @@ -6184,9 +6152,7 @@ dependencies = [ "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum primitive-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "366ef730e56c11fd21ab3e518866cf7feb0fdf7f7c16ddc68485579e9d802787" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -"checksum proc-macro-hack 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c725b36c99df7af7bf9324e9c999b9e37d92c8f8caf106d82e1d7953218d2d8" "checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" -"checksum proc-macro-hack-impl 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2b753ad9ed99dd8efeaa7d2fb8453c8f6bc3e54b97966d35f1bc77ca6865254a" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum protobuf 2.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f00e4a3cb64ecfeac2c0a73c74c68ae3439d7a6bead3870be56ad5dd2620a6f" "checksum pwasm-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "efb0dcbddbb600f47a7098d33762a00552c671992171637f5bb310b37fe1f0e4" diff --git a/core/client/Cargo.toml b/core/client/Cargo.toml index 29951b5c48492..f140b2f343f74 100644 --- a/core/client/Cargo.toml +++ b/core/client/Cargo.toml @@ -9,7 +9,7 @@ derive_more = { version = "0.14.0", optional = true } fnv = { version = "1.0", optional = true } log = { version = "0.4", optional = true } parking_lot = { version = "0.8.0", optional = true } -hex = { package = "hex-literal", version = "0.1", optional = true } +hex = { package = "hex-literal", version = "0.2", optional = true } futures-preview = { version = "0.3.0-alpha.17", optional = true } consensus = { package = "substrate-consensus-common", path = "../consensus/common", optional = true } executor = { package = "substrate-executor", path = "../executor", optional = true } diff --git a/srml/babe/Cargo.toml b/srml/babe/Cargo.toml index afa46370cd0c7..e8dc183b54de4 100644 --- a/srml/babe/Cargo.toml +++ b/srml/babe/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -hex-literal = "0.1.4" +hex-literal = "0.2" parity-codec = { version = "4.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.93", optional = true } inherents = { package = "substrate-inherents", path = "../../core/inherents", default-features = false } From 9a68a71f40eaef16842a46828d9d6b89d19fd98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 7 Aug 2019 13:44:31 +0200 Subject: [PATCH 42/80] Start to rework the new error handling --- core/sr-io/src/lib.rs | 8 ++- core/sr-io/with_std.rs | 8 +-- core/sr-io/without_std.rs | 7 +- core/sr-primitives/src/lib.rs | 22 +++++++ srml/balances/src/lib.rs | 24 +------ srml/staking/src/mock.rs | 11 +--- srml/staking/src/tests.rs | 4 +- srml/support/src/dispatch.rs | 119 +++++++++++++++++++++++++--------- srml/support/src/error.rs | 71 +++++++++++++++----- srml/support/src/lib.rs | 9 ++- srml/system/src/lib.rs | 7 +- 11 files changed, 194 insertions(+), 96 deletions(-) diff --git a/core/sr-io/src/lib.rs b/core/sr-io/src/lib.rs index f340f0a99b008..826b6964ca65f 100644 --- a/core/sr-io/src/lib.rs +++ b/core/sr-io/src/lib.rs @@ -55,7 +55,13 @@ pub mod offchain; /// Trait for things which can be printed. pub trait Printable { /// Print the object. - fn print(self); + fn print(&self); +} + +impl Printable for u8 { + fn print(&self) { + u64::from(*self).print() + } } /// Converts a public trait definition into a private trait and set of public functions diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index 9475aa07151bf..8e6c9b533c132 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -465,19 +465,19 @@ pub fn with_storage_and_children R>( } impl<'a> Printable for &'a [u8] { - fn print(self) { - println!("Runtime: {}", HexDisplay::from(&self)); + fn print(&self) { + println!("Runtime: {}", HexDisplay::from(self)); } } impl<'a> Printable for &'a str { - fn print(self) { + fn print(&self) { println!("Runtime: {}", self); } } impl Printable for u64 { - fn print(self) { + fn print(&self) { println!("Runtime: {}", self); } } diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index 5565f9ab3802c..9a0cd6c9964cf 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -1172,7 +1172,7 @@ unsafe fn from_raw_parts(ptr: *mut u8, len: u32) -> Option> { impl Api for () {} impl<'a> Printable for &'a [u8] { - fn print(self) { + fn print(&self) { unsafe { ext_print_hex.get()(self.as_ptr(), self.len() as u32); } @@ -1180,7 +1180,7 @@ impl<'a> Printable for &'a [u8] { } impl<'a> Printable for &'a str { - fn print(self) { + fn print(&self) { unsafe { ext_print_utf8.get()(self.as_ptr() as *const u8, self.len() as u32); } @@ -1188,7 +1188,8 @@ impl<'a> Printable for &'a str { } impl Printable for u64 { - fn print(self) { + fn print(&self) { unsafe { ext_print_num.get()(self); } } } + diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 8bca8eb7bbd74..c4d5b9e305d5e 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -612,6 +612,17 @@ pub struct DispatchError { pub message: Option<&'static str>, } +impl DispatchError { + /// Create a new instance of `DispatchError`. + pub fn new(module: u8, error: u8, message: Option<&'static str>) -> Self { + Self { + module, + error, + message, + } + } +} + impl Encode for DispatchError { fn using_encoded R>(&self, f: F) -> R { f(&[self.module, self.error]) @@ -628,6 +639,17 @@ impl Decode for DispatchError { } } +impl runtime_io::Printable for DispatchError { + fn print(&self) { + "DispatchError".print(); + self.module.print(); + self.error.print(); + if let Some(msg) = self.message { + msg.print(); + } + } +} + /// Result from attempt to apply an extrinsic. pub type ApplyResult = Result; diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index bb1ccf1d7d8d0..30fb2a48e935c 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -152,7 +152,7 @@ use rstd::prelude::*; use rstd::{cmp, result, mem}; use parity_codec::{Codec, Encode, Decode}; -use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module, decl_error}; +use srml_support::{StorageValue, StorageMap, Parameter, decl_event, decl_storage, decl_module}; use srml_support::traits::{ UpdateBalanceOutcome, Currency, OnFreeBalanceZero, MakePayment, OnUnbalanced, WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, @@ -170,8 +170,6 @@ mod tests; pub use self::imbalances::{PositiveImbalance, NegativeImbalance}; -pub type DispatchResult = srml_support::dispatch::DispatchResult<>::Error>; - pub const DEFAULT_EXISTENTIAL_DEPOSIT: u32 = 0; pub const DEFAULT_TRANSFER_FEE: u32 = 0; pub const DEFAULT_CREATION_FEE: u32 = 0; @@ -235,9 +233,6 @@ pub trait Trait: system::Trait { /// The overarching event type. type Event: From> + Into<::Event>; - /// The overarching error type. - type Error: From + From + From<&'static str>; - /// The minimum amount required to keep an account open. type ExistentialDeposit: Get; @@ -279,19 +274,6 @@ decl_event!( } ); -decl_error! { - pub enum Error { - } -} - -impl From for &'static str { - fn from(err: Error) -> &'static str { - match err { - Error::Other(msg) => msg, - } - } -} - /// Struct to encode the vesting schedule of an individual account. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] @@ -404,8 +386,6 @@ decl_storage! { decl_module! { pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { - type Error = >::Error; - /// The minimum amount required to keep an account open. const ExistentialDeposit: T::Balance = T::ExistentialDeposit::get(); @@ -780,7 +760,6 @@ impl, I: Instance> system::Trait for ElevatedTrait { type Lookup = T::Lookup; type Header = T::Header; type Event = (); - type Error = &'static str; type BlockHashCount = T::BlockHashCount; } impl, I: Instance> Trait for ElevatedTrait { @@ -791,7 +770,6 @@ impl, I: Instance> Trait for ElevatedTrait { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); - type Error = &'static str; type ExistentialDeposit = T::ExistentialDeposit; type TransferFee = T::TransferFee; type CreationFee = T::CreationFee; diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 7d84cf4b4286a..23648e88eb039 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -22,7 +22,7 @@ use primitives::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize}; use primitives::testing::{Header, UintAuthorityId}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use srml_support::{assert_ok, impl_outer_origin, impl_outer_error, parameter_types, EnumerableStorageMap}; +use srml_support::{assert_ok, impl_outer_origin, parameter_types, EnumerableStorageMap}; use srml_support::traits::{Currency, Get}; use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, Nominators @@ -30,7 +30,6 @@ use crate::{EraIndex, GenesisConfig, Module, Trait, StakerStatus, /// The AccountId alias in this test module. pub type AccountId = u64; -pub type BlockNumber = u64; pub type Balance = u64; /// Simple structure that exposes how u64 currency can be represented as... u64. @@ -82,12 +81,6 @@ impl_outer_origin!{ pub enum Origin for Test {} } -impl_outer_error! { - pub enum Error for Test { - balances - } -} - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; @@ -104,7 +97,6 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -121,7 +113,6 @@ impl balances::Trait for Test { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index 0f39b560e51ba..ee9c55f17376a 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -891,7 +891,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), - mock::Error::system(system::Error::Other("account liquidity restrictions prevent withdrawal")) + "account liquidity restrictions prevent withdrawal", ); // Give account 11 extra free balance @@ -920,7 +920,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), - mock::Error::system(system::Error::Other("account liquidity restrictions prevent withdrawal")) + "account liquidity restrictions prevent withdrawal", ); assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); }); diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index ac07ab51d49ef..10031f50a9d91 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -25,7 +25,7 @@ pub use srml_metadata::{ FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata, ModuleConstantMetadata, DefaultByte, DefaultByteGetter, }; -pub use sr_primitives::weights::{TransactionWeight, Weighable, Weight}; +pub use sr_primitives::{DispatchError, weights::{TransactionWeight, Weighable, Weight}}; /// A type that cannot be instantiated. pub enum Never {} @@ -37,22 +37,54 @@ pub type DispatchResult = result::Result<(), Error>; /// Result with string error message. This exists for backward compatibility purpose. pub type Result = DispatchResult<&'static str>; -/// A lazy call (module function and argument values) that can be executed via its `dispatch` +/// A lazy module call (module function and argument values) that can be executed via its `dispatch` /// method. -pub trait Dispatchable { +pub trait ModuleDispatchable { /// 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; - type Error; + type Error: ModuleDispatchError; + fn dispatch(self, origin: Self::Origin) -> DispatchResult; } +/// A lazy runtime call that can be executed via its `dispatch` method. +pub trait RuntimeDispatchable { + /// 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) -> DispatchResult; +} + +pub trait ModuleDispatchError { + /// Convert this error to an `u8`. + /// + /// The `u8` corresponds to the index of the variant in the error enum. + fn as_u8(&self) -> u8; + + /// Convert the error to a `&'static str`. + fn as_str(&self) -> &'static str; +} + +impl ModuleDispatchError for &'static str { + fn as_u8(&self) -> u8 { + 0 + } + + fn as_str(&self) -> &'static str { + self + } +} + /// Serializable version of Dispatchable. /// This value can be used as a "function" in an extrinsic. pub trait Callable { - type Call: Dispatchable + Codec + Clone + PartialEq + Eq; + type Call: ModuleDispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue @@ -1296,7 +1328,7 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::ModuleDispatchable for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { type Trait = $trait_instance; @@ -1327,7 +1359,7 @@ macro_rules! decl_module { where $( $other_where_bounds )* { #[doc(hidden)] - pub fn dispatch>( + pub fn dispatch>( d: D, origin: D::Origin ) -> $crate::dispatch::DispatchResult { @@ -1367,25 +1399,6 @@ macro_rules! impl_outer_dispatch { $module:ident::$camelcase:ident, )* } - ) => { - $crate::impl_outer_dispatch! { - $(#[$attr])* - pub enum $call_type for $runtime where origin: $origin { - type Error = &'static str; - $( - $module::$camelcase, - )* - } - } - }; - ( - $(#[$attr:meta])* - pub enum $call_type:ident for $runtime:ident where origin: $origin:ty { - type Error = $error_type:ty; - $( - $module:ident::$camelcase:ident, - )* - } ) => { $(#[$attr])* #[derive(Clone, PartialEq, Eq, $crate::codec::Encode, $crate::codec::Decode)] @@ -1402,13 +1415,22 @@ macro_rules! impl_outer_dispatch { } } } - impl $crate::dispatch::Dispatchable for $call_type { + impl $crate::dispatch::RuntimeDispatchable for $call_type { type Origin = $origin; type Trait = $call_type; - type Error = $error_type; - fn dispatch(self, origin: $origin) -> $crate::dispatch::DispatchResult { - match self { - $( $call_type::$camelcase(call) => call.dispatch(origin).map_err(Into::into), )* + fn dispatch( + self, + origin: $origin, + ) -> $crate::dispatch::DispatchResult<$crate::dispatch::DispatchError> { + use $crate::{ModuleDispatchable, ModuleDispatchError}; + $crate::impl_outer_dispatch! { + @DISPATCH_MATCH + self + $call_type + origin + {} + 0; + $( $camelcase ),* } } } @@ -1430,6 +1452,41 @@ macro_rules! impl_outer_dispatch { } } )* + }; + (@DISPATCH_MATCH + $self:ident + $call_type:ident + $origin:ident + { $( $generated:tt )* } + $index:expr; + $name:ident + $( , $rest:ident )* + ) => { + $crate::impl_outer_dispatch! { + @DISPATCH_MATCH + $self + $call_type + $origin + { + $( $generated )* + $call_type::$name(call) => call.dispatch($origin).map_err(|e| { + $crate::dispatch::DispatchError::new($index, e.as_u8(), Some(e.as_str())) + }), + } + $index + 1; + $( $rest ),* + } + }; + (@DISPATCH_MATCH + $self:ident + $call_type:ident + $origin:ident + { $( $generated:tt )* } + $index:expr; + ) => { + match $self { + $( $generated )* + } } } diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index e0041dd41f2ef..387397b4a310a 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -161,25 +161,22 @@ macro_rules! impl_outer_error { } } - #[macro_export] macro_rules! decl_error { ( $(#[$attr:meta])* - pub enum Error { + pub enum $error:ident { $( - $(#[$variant_attr:meta])* + $( #[$variant_attr:meta] )* $name:ident ),* $(,)? } ) => { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode)] + #[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum Error { + pub enum $error { Other(&'static str), $( $(#[$variant_attr])* @@ -187,19 +184,63 @@ macro_rules! decl_error { ),* } - impl From<&Error> for u8 { - fn from(err: &Error) -> u8 { - match err { - Error::Other(_) => 0, - _ => $crate::codec::Encode::using_encoded(err, |s| s[0]), + impl $crate::ModuleDispatchError for $error { + fn as_u8(&self) -> u8 { + $crate::decl_error! { + @GENERATE_AS_U8 + self + $error + {} + 1, + $( $name ),* + } + } + + fn as_str(&self) -> &'static str { + match self { + $error::Other(err) => err, + $( + $error::$name => stringify!($name), + )* } } } - impl From<&'static str> for Error { - fn from(val: &'static str) -> Error { - Error::Other(val) + impl From<&'static str> for $error { + fn from(val: &'static str) -> $error { + $error::Other(val) + } + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + $name:ident + $( , $rest:ident )* + ) => { + $crate::decl_error! { + @GENERATE_AS_U8 + $self + $error + { + $( $generated )* + $error::$name => $index, } + $index + 1, + $( $rest ),* + } + }; + (@GENERATE_AS_U8 + $self:ident + $error:ident + { $( $generated:tt )* } + $index:expr, + ) => { + match $self { + $error::Other(_) => 0, + $( $generated )* } } } diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index a2747c2802314..2e2b9dbb898b0 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -65,7 +65,9 @@ pub use self::storage::{ StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap }; pub use self::hashable::Hashable; -pub use self::dispatch::{Parameter, Dispatchable, Callable, IsSubType}; +pub use self::dispatch::{ + Parameter, ModuleDispatchable, RuntimeDispatchable, Callable, IsSubType, ModuleDispatchError, +}; pub use self::double_map::StorageDoubleMapWithHasher; pub use runtime_io::{print, storage_root, Printable}; pub use runtime_primitives::ConsensusEngineId; @@ -144,7 +146,10 @@ macro_rules! ensure { #[macro_export] #[cfg(feature = "std")] macro_rules! assert_noop { - ( $x:expr , $y:expr ) => { + ( + $x:expr, + $y:expr $(,)? + ) => { let h = $crate::storage_root(); $crate::assert_err!($x, $y); assert_eq!(h, $crate::storage_root()); diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 773900b874176..08c46468861ee 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -70,6 +70,7 @@ //! ``` #![cfg_attr(not(feature = "std"), no_std)] +#![feature(trace_macros)] #[cfg(feature = "std")] use serde::Serialize; @@ -188,9 +189,6 @@ pub trait Trait: 'static + Eq + Clone { /// The aggregated event type of the runtime. type Event: Parameter + Member + From; - /// The aggregated error type of the runtime. - type Error: Member + From + From<&'static str> + runtime_io::Printable; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount: Get; } @@ -203,7 +201,7 @@ pub type KeyValue = (Vec, Vec); decl_module! { pub struct Module for enum Call where origin: T::Origin { - type Error = T::Error; + type Error = Error; /// Deposits an event into this block's event record. pub fn deposit_event(event: T::Event) { @@ -862,7 +860,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = u16; - type Error = Error; type BlockHashCount = BlockHashCount; } From 35f9ebc5b9ead9d5cd94e5c57bb06c847498a8a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 12 Aug 2019 19:32:54 +0200 Subject: [PATCH 43/80] More work to get it back compiling --- core/sr-io/without_std.rs | 2 +- node-template/runtime/src/lib.rs | 5 - node-template/runtime/src/template.rs | 6 +- node/runtime/src/lib.rs | 2 - srml/assets/src/lib.rs | 7 +- srml/aura/src/mock.rs | 7 +- srml/authorship/src/lib.rs | 7 +- srml/balances/src/mock.rs | 14 +-- srml/balances/src/tests.rs | 10 +- srml/collective/src/lib.rs | 5 +- srml/contracts/src/lib.rs | 4 +- srml/contracts/src/tests.rs | 12 +- srml/council/src/lib.rs | 8 +- srml/democracy/src/lib.rs | 16 +-- srml/elections/src/lib.rs | 2 - srml/example/src/lib.rs | 10 +- srml/executive/src/lib.rs | 30 +---- srml/finality-tracker/src/lib.rs | 7 +- srml/generic-asset/src/lib.rs | 1 - srml/generic-asset/src/mock.rs | 7 +- srml/grandpa/src/mock.rs | 9 +- srml/indices/src/mock.rs | 7 +- srml/session/src/mock.rs | 8 +- srml/sudo/src/lib.rs | 4 +- srml/support/src/error.rs | 171 ++------------------------ srml/support/src/lib.rs | 2 +- srml/support/src/runtime.rs | 10 -- srml/support/test/tests/instance.rs | 1 - srml/support/test/tests/issue2219.rs | 1 - srml/support/test/tests/system.rs | 4 +- srml/system/src/lib.rs | 6 +- srml/timestamp/src/lib.rs | 7 +- srml/treasury/src/lib.rs | 10 +- 33 files changed, 53 insertions(+), 349 deletions(-) diff --git a/core/sr-io/without_std.rs b/core/sr-io/without_std.rs index 9a0cd6c9964cf..58f6dcf468c6f 100644 --- a/core/sr-io/without_std.rs +++ b/core/sr-io/without_std.rs @@ -1189,7 +1189,7 @@ impl<'a> Printable for &'a str { impl Printable for u64 { fn print(&self) { - unsafe { ext_print_num.get()(self); } + unsafe { ext_print_num.get()(*self); } } } diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index 5fae7efe490ba..ada638c5eab56 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -133,8 +133,6 @@ impl system::Trait for Runtime { type Event = Event; /// The ubiquitous origin type. type Origin = Origin; - /// The ubiquitous error type. - type Error = Error; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; } @@ -183,9 +181,6 @@ impl balances::Trait for Runtime { type OnNewAccount = Indices; /// The ubiquitous event type. type Event = Event; - /// The ubiquitous event type. - type Error = Error; - type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index a3ce00e58be13..4049c09a9930d 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -71,17 +71,13 @@ mod tests { use runtime_io::with_externalities; use primitives::{H256, Blake2Hasher}; - use support::{impl_outer_origin, impl_outer_error, assert_ok, parameter_types}; + use support::{impl_outer_origin, assert_ok, parameter_types}; use runtime_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; impl_outer_origin! { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Test {} - } - // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 0667d98f150d4..f1903c006273a 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -123,7 +123,6 @@ impl system::Trait for Runtime { type Lookup = Indices; type Header = generic::Header; type Event = Event; - type Error = Error; type BlockHashCount = BlockHashCount; } @@ -160,7 +159,6 @@ impl balances::Trait for Runtime { type CreationFee = CreationFee; type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; - type Error = Error; } parameter_types! { diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index 318ba3e519074..19159bf60fba3 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -240,7 +240,7 @@ mod tests { use super::*; use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, impl_outer_error, assert_ok, assert_noop, parameter_types}; + use srml_support::{impl_outer_origin, assert_ok, assert_noop, parameter_types}; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. @@ -250,10 +250,6 @@ mod tests { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Test {} - } - // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -272,7 +268,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } impl Trait for Test { diff --git a/srml/aura/src/mock.rs b/srml/aura/src/mock.rs index da3017fd414a6..0cce522c76032 100644 --- a/srml/aura/src/mock.rs +++ b/srml/aura/src/mock.rs @@ -22,7 +22,7 @@ use primitives::{ traits::IdentityLookup, testing::{Header, UintAuthorityId}, }; -use srml_support::{impl_outer_origin, impl_outer_error, parameter_types}; +use srml_support::{impl_outer_origin, parameter_types}; use runtime_io; use substrate_primitives::{H256, Blake2Hasher}; use crate::{Trait, Module, GenesisConfig}; @@ -31,10 +31,6 @@ impl_outer_origin!{ pub enum Origin for Test {} } -impl_outer_error! { - pub enum Error for Runtime {} -} - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; @@ -54,7 +50,6 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } diff --git a/srml/authorship/src/lib.rs b/srml/authorship/src/lib.rs index 7e38bfdc81210..758eeb285e197 100644 --- a/srml/authorship/src/lib.rs +++ b/srml/authorship/src/lib.rs @@ -326,16 +326,12 @@ mod tests { use primitives::traits::{BlakeTwo256, IdentityLookup}; use primitives::testing::Header; use primitives::generic::DigestItem; - use srml_support::{parameter_types, impl_outer_origin, impl_outer_error, ConsensusEngineId}; + use srml_support::{parameter_types, impl_outer_origin, ConsensusEngineId}; impl_outer_origin!{ pub enum Origin for Test {} } - impl_outer_error!{ - pub enum Error for Test {} - } - #[derive(Clone, Eq, PartialEq)] pub struct Test; @@ -353,7 +349,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } diff --git a/srml/balances/src/mock.rs b/srml/balances/src/mock.rs index 77eec99d9ce6b..38dae9f25f6f5 100644 --- a/srml/balances/src/mock.rs +++ b/srml/balances/src/mock.rs @@ -21,7 +21,7 @@ use primitives::{traits::{IdentityLookup}, testing::Header}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_io; -use srml_support::{impl_outer_origin, impl_outer_error, parameter_types, traits::Get}; +use srml_support::{impl_outer_origin, parameter_types, traits::Get}; use std::cell::RefCell; use crate::{GenesisConfig, Module, Trait}; @@ -29,16 +29,6 @@ impl_outer_origin!{ pub enum Origin for Runtime {} } -mod balances { - pub use crate::Error; -} - -impl_outer_error! { - pub enum Error for Runtime { - balances, - } -} - thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); static TRANSFER_FEE: RefCell = RefCell::new(0); @@ -88,7 +78,6 @@ impl system::Trait for Runtime { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } impl Trait for Runtime { @@ -99,7 +88,6 @@ impl Trait for Runtime { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index cf2b5831055ab..582949fa05fd0 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -215,7 +215,7 @@ fn default_indexing_on_new_accounts_should_not_work2() { // ext_deposit is 10, value is 9, not satisfies for ext_deposit assert_noop!( Balances::transfer(Some(1).into(), 5, 9), - mock::Error::system(system::Error::Other("value too low to create account")) + "value too low to create account", ); assert_eq!(Balances::is_dead_account(&5), true); // account 5 should not exist assert_eq!(Balances::free_balance(&1), 100); @@ -360,7 +360,7 @@ fn balance_transfer_when_reserved_should_not_work() { assert_ok!(Balances::reserve(&1, 69)); assert_noop!( Balances::transfer(Some(1).into(), 2, 69), - mock::Error::system(system::Error::Other("balance too low to send value")) + "balance too low to send value", ); }); } @@ -489,7 +489,7 @@ fn transferring_too_high_value_should_not_panic() { assert_err!( Balances::transfer(Some(1).into(), 2, u64::max_value()), - mock::Error::system(system::Error::Other("destination balance too high to receive value")) + "destination balance too high to receive value", ); assert_eq!(Balances::free_balance(&1), u64::max_value()); @@ -567,7 +567,7 @@ fn transfer_overflow_isnt_exploitable() { assert_err!( Balances::transfer(Some(1).into(), 5, evil_value), - mock::Error::system(system::Error::Other("got overflow after adding a fee to value")) + "got overflow after adding a fee to value", ); } ); @@ -652,7 +652,7 @@ fn unvested_balance_should_not_transfer() { assert_eq!(Balances::vesting_balance(&1), 45); assert_noop!( Balances::transfer(Some(1).into(), 2, 56), - mock::Error::system(system::Error::Other("vesting balance too high to send value")) + "vesting balance too high to send value", ); // Account 1 cannot send more than vested amount } ); diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index 914bdbb253062..2a86adf835c97 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -24,7 +24,7 @@ use rstd::{prelude::*, result}; use substrate_primitives::u32_trait::Value as U32; use primitives::traits::{Hash, EnsureOrigin}; use srml_support::{ - dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, + dispatch::{RuntimeDispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure }; use system::{self, ensure_signed, ensure_root}; @@ -43,7 +43,7 @@ pub trait Trait: system::Trait { type Origin: From>; /// The outer call dispatch type. - type Proposal: Parameter + Dispatchable>::Origin>; + type Proposal: Parameter + RuntimeDispatchable>::Origin>; /// The outer event type. type Event: From> + Into<::Event>; @@ -414,7 +414,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type Error = Error; type BlockHashCount = BlockHashCount; } impl Trait for Test { diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index f38010a3557a9..ad277305a5e6a 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -102,7 +102,7 @@ use runtime_io::blake2_256; use runtime_primitives::traits::{ Hash, StaticLookup, Zero, MaybeSerializeDebug, Member }; -use srml_support::dispatch::{Result, Dispatchable}; +use srml_support::dispatch::{Result, RuntimeDispatchable}; use srml_support::{ Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child, parameter_types, @@ -320,7 +320,7 @@ pub trait Trait: timestamp::Trait { type Currency: Currency; /// The outer call dispatch type. - type Call: Parameter + Dispatchable::Origin>; + type Call: Parameter + RuntimeDispatchable::Origin>; /// The overarching event type. type Event: From> + Into<::Event>; diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index db005197f194e..3e63bc0defc89 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -34,7 +34,7 @@ use runtime_primitives::traits::{BlakeTwo256, Hash, IdentityLookup}; use runtime_primitives::BuildStorage; use srml_support::{ assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, - impl_outer_error, storage::child, StorageMap, StorageValue, traits::{Currency, Get}, + storage::child, StorageMap, StorageValue, traits::{Currency, Get}, }; use std::cell::RefCell; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -60,19 +60,11 @@ impl_outer_origin! { } impl_outer_dispatch! { pub enum Call for Test where origin: Origin { - type Error = Error; - balances::Balances, contract::Contract, } } -impl_outer_error! { - pub enum Error for Test { - balances - } -} - thread_local! { static EXISTENTIAL_DEPOSIT: RefCell = RefCell::new(0); static TRANSFER_FEE: RefCell = RefCell::new(0); @@ -115,7 +107,6 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -130,7 +121,6 @@ impl balances::Trait for Test { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 2fcdb22d81c02..8c7a9f00d5ad1 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -39,7 +39,7 @@ mod tests { // These re-exports are here for a reason, edit with care pub use super::*; pub use runtime_io::with_externalities; - use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch, impl_outer_error, parameter_types}; + use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_dispatch, parameter_types}; use srml_support::traits::Get; pub use substrate_primitives::{H256, Blake2Hasher, u32_trait::{_1, _2, _3, _4}}; pub use primitives::traits::{BlakeTwo256, IdentityLookup}; @@ -68,12 +68,6 @@ mod tests { } } - impl_outer_error! { - pub enum Error for Test { - balances - } - } - thread_local! { static VOTER_BOND: RefCell = RefCell::new(0); static VOTING_FEE: RefCell = RefCell::new(0); diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index c856f34ff2f6f..98ab111402cf8 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -24,7 +24,7 @@ use primitives::traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Ha use parity_codec::{Encode, Decode, Input, Output}; use srml_support::{ decl_module, decl_storage, decl_event, ensure, - StorageValue, StorageMap, Parameter, Dispatchable, IsSubType, EnumerableStorageMap, + StorageValue, StorageMap, Parameter, RuntimeDispatchable, IsSubType, EnumerableStorageMap, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, OnFreeBalanceZero, Get @@ -174,7 +174,7 @@ pub const DEFAULT_EMERGENCY_VOTING_PERIOD: u32 = 0; pub const DEFAULT_COOLOFF_PERIOD: u32 = 0; pub trait Trait: system::Trait + Sized { - type Proposal: Parameter + Dispatchable + IsSubType, Self>; + type Proposal: Parameter + RuntimeDispatchable + IsSubType, Self>; type Event: From> + Into<::Event>; /// Currency type for this module. @@ -970,7 +970,7 @@ mod tests { use super::*; use runtime_io::with_externalities; use srml_support::{ - impl_outer_origin, impl_outer_error, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, + impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types, traits::Contains }; use substrate_primitives::{H256, Blake2Hasher}; @@ -989,19 +989,11 @@ mod tests { impl_outer_dispatch! { pub enum Call for Test where origin: Origin { - type Error = Error; - balances::Balances, democracy::Democracy, } } - impl_outer_error! { - pub enum Error for Test { - balances, - } - } - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq, Debug)] pub struct Test; @@ -1018,7 +1010,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -1036,7 +1027,6 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index 92ccc3c3374b8..70321132e6ae9 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -1119,7 +1119,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = Event; - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -1134,7 +1133,6 @@ mod tests { type OnNewAccount = (); type OnFreeBalanceZero = (); type Event = Event; - type Error = Error; type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 2f840657c3397..20ee1c6ba114f 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -505,7 +505,7 @@ impl Module { mod tests { use super::*; - use srml_support::{assert_ok, impl_outer_origin, impl_outer_error, parameter_types}; + use srml_support::{assert_ok, impl_outer_origin, parameter_types}; use sr_io::with_externalities; use substrate_primitives::{H256, Blake2Hasher}; // The testing primitives are very useful for avoiding having to work with signatures @@ -518,12 +518,6 @@ mod tests { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Test { - balances - } - } - // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -542,7 +536,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -560,7 +553,6 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 970d65b6dfdd5..354ed8b429905 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -76,7 +76,6 @@ use rstd::prelude::*; use rstd::marker::PhantomData; -use rstd::convert::TryInto; use primitives::{ generic::Digest, ApplyResult, ApplyOutcome, ApplyError, DispatchError, PrimitiveError, traits::{ @@ -85,7 +84,7 @@ use primitives::{ ValidateUnsigned, } }; -use srml_support::{Dispatchable, traits::MakePayment}; +use srml_support::{RuntimeDispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; use system::{extrinsics_root, DigestOf}; use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity}; @@ -103,7 +102,7 @@ pub trait ExecuteBlock { pub type CheckedOf = >::Checked; pub type CallOf = as Applyable>::Call; -pub type OriginOf = as Dispatchable>::Origin; +pub type OriginOf = as RuntimeDispatchable>::Origin; pub struct Executive( PhantomData<(System, Block, Context, Payment, UnsignedValidator, AllModules)> @@ -121,8 +120,7 @@ where Block::Extrinsic: Checkable + Codec, >::Error: Into, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, - as Dispatchable>::Error: Into + TryInto, + CallOf: RuntimeDispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -143,8 +141,7 @@ where Block::Extrinsic: Checkable + Codec, >::Error: Into, CheckedOf: Applyable + Weighable, - CallOf: Dispatchable, - as Dispatchable>::Error: Into + TryInto, + CallOf: RuntimeDispatchable, OriginOf: From>, UnsignedValidator: ValidateUnsigned>, { @@ -232,14 +229,7 @@ where let l = uxt.encode().len(); match Self::apply_extrinsic_with_len(uxt, l, None) { Ok(ApplyOutcome::Success) => (), - Ok(ApplyOutcome::Fail(e)) => { - runtime_io::print("Error:"); - runtime_io::print(e.module as u64); - runtime_io::print(e.error as u64); - if let Some(msg) = e.message { - runtime_io::print(msg); - } - }, + Ok(ApplyOutcome::Fail(e)) => runtime_io::print(e), Err(ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), Err(ApplyError::BadSignature) => panic!("All extrinsics should be properly signed"), Err(ApplyError::Stale) | Err(ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), @@ -396,7 +386,7 @@ mod tests { use substrate_primitives::{H256, Blake2Hasher}; use primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup}; use primitives::testing::{Digest, Header, Block}; - use srml_support::{impl_outer_event, impl_outer_origin, impl_outer_error, parameter_types}; + use srml_support::{impl_outer_event, impl_outer_origin, parameter_types}; use srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}; use system; use hex_literal::hex; @@ -412,12 +402,6 @@ mod tests { } } - impl_outer_error! { - pub enum Error for Runtime { - balances - } - } - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. #[derive(Clone, Eq, PartialEq)] pub struct Runtime; @@ -434,7 +418,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = MetaEvent; - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -452,7 +435,6 @@ mod tests { type TransactionPayment = (); type DustRemoval = (); type TransferPayment = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; diff --git a/srml/finality-tracker/src/lib.rs b/srml/finality-tracker/src/lib.rs index 465734f9c0d9d..f9ccc36346222 100644 --- a/srml/finality-tracker/src/lib.rs +++ b/srml/finality-tracker/src/lib.rs @@ -268,7 +268,7 @@ mod tests { use substrate_primitives::H256; use primitives::traits::{BlakeTwo256, IdentityLookup, OnFinalize, Header as HeaderT}; use primitives::testing::Header; - use srml_support::{assert_ok, impl_outer_origin, impl_outer_error, parameter_types}; + use srml_support::{assert_ok, impl_outer_origin, parameter_types}; use srml_system as system; use std::cell::RefCell; @@ -285,10 +285,6 @@ mod tests { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Test {} - } - thread_local! { static NOTIFICATIONS: RefCell> = Default::default(); } @@ -314,7 +310,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index 6cab7c4935033..60370600a69a6 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -1056,7 +1056,6 @@ impl system::Trait for ElevatedTrait { type Lookup = T::Lookup; type Header = T::Header; type Event = (); - type Error = &'static str; type BlockHashCount = T::BlockHashCount; } impl Trait for ElevatedTrait { diff --git a/srml/generic-asset/src/mock.rs b/srml/generic-asset/src/mock.rs index 70d6273fddfa8..02e18fc335839 100644 --- a/srml/generic-asset/src/mock.rs +++ b/srml/generic-asset/src/mock.rs @@ -25,7 +25,7 @@ use primitives::{ traits::{BlakeTwo256, IdentityLookup}, }; use substrate_primitives::{Blake2Hasher, H256}; -use support::{parameter_types, impl_outer_event, impl_outer_origin, impl_outer_error}; +use support::{parameter_types, impl_outer_event, impl_outer_origin}; use super::*; @@ -33,10 +33,6 @@ impl_outer_origin! { pub enum Origin for Test {} } -impl_outer_error! { - pub enum Error for Test {} -} - // For testing the module, we construct most of a mock runtime. This means // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of modules we want to use. @@ -55,7 +51,6 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; - type Error = Error; type BlockHashCount = BlockHashCount; } diff --git a/srml/grandpa/src/mock.rs b/srml/grandpa/src/mock.rs index 30b34da75451c..a7a4d3e2c49d6 100644 --- a/srml/grandpa/src/mock.rs +++ b/srml/grandpa/src/mock.rs @@ -20,7 +20,7 @@ use primitives::{DigestItem, traits::IdentityLookup, testing::{Header, UintAuthorityId}}; use runtime_io; -use srml_support::{impl_outer_origin, impl_outer_event, impl_outer_error, parameter_types}; +use srml_support::{impl_outer_origin, impl_outer_event, parameter_types}; use substrate_primitives::{H256, Blake2Hasher}; use parity_codec::{Encode, Decode}; use crate::{AuthorityId, GenesisConfig, Trait, Module, ConsensusLog}; @@ -30,10 +30,6 @@ impl_outer_origin!{ pub enum Origin for Test {} } -impl_outer_error! { - pub enum Error for Test {} -} - pub fn grandpa_log(log: ConsensusLog) -> DigestItem { DigestItem::Consensus(GRANDPA_ENGINE_ID, log.encode()) } @@ -53,12 +49,11 @@ impl system::Trait for Test { type Index = u64; type BlockNumber = u64; type Hash = H256; - type Hashing = ::primitives::traits::BlakeTwo256; + type Hashing = primitives::traits::BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; type Header = Header; type Event = TestEvent; - type Error = Error; type BlockHashCount = BlockHashCount; } diff --git a/srml/indices/src/mock.rs b/srml/indices/src/mock.rs index 5f61cec5481fc..53e8f314c94bb 100644 --- a/srml/indices/src/mock.rs +++ b/srml/indices/src/mock.rs @@ -22,7 +22,7 @@ use std::collections::HashSet; use ref_thread_local::{ref_thread_local, RefThreadLocal}; use primitives::testing::Header; use substrate_primitives::{H256, Blake2Hasher}; -use srml_support::{impl_outer_origin, impl_outer_error, parameter_types}; +use srml_support::{impl_outer_origin, parameter_types}; use {runtime_io, system}; use crate::{GenesisConfig, Module, Trait, IsDeadAccount, OnNewAccount, ResolveHint}; @@ -30,10 +30,6 @@ impl_outer_origin!{ pub enum Origin for Runtime {} } -impl_outer_error! { - pub enum Error for Runtime {} -} - ref_thread_local! { static managed ALIVE: HashSet = HashSet::new(); } @@ -81,7 +77,6 @@ impl system::Trait for Runtime { type Lookup = Indices; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } impl Trait for Runtime { diff --git a/srml/session/src/mock.rs b/srml/session/src/mock.rs index 39f44346cd68d..ed7a6bf631359 100644 --- a/srml/session/src/mock.rs +++ b/srml/session/src/mock.rs @@ -18,22 +18,17 @@ use super::*; use std::cell::RefCell; -use srml_support::{impl_outer_origin, impl_outer_error, parameter_types}; +use srml_support::{impl_outer_origin, parameter_types}; use substrate_primitives::H256; use primitives::{ traits::{BlakeTwo256, IdentityLookup, ConvertInto}, testing::{Header, UintAuthorityId} }; - impl_outer_origin! { pub enum Origin for Test {} } -impl_outer_error! { - pub enum Error for Test {} -} - thread_local! { pub static NEXT_VALIDATORS: RefCell> = RefCell::new(vec![1, 2, 3]); pub static AUTHORITIES: RefCell> = @@ -125,7 +120,6 @@ impl system::Trait for Test { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } impl timestamp::Trait for Test { diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 90fedc2fe6f89..f2665102f7eb5 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -89,7 +89,7 @@ use sr_std::prelude::*; use sr_primitives::traits::StaticLookup; use srml_support::{ - StorageValue, Parameter, Dispatchable, decl_module, decl_event, + StorageValue, Parameter, RuntimeDispatchable, decl_module, decl_event, decl_storage, ensure }; use system::ensure_signed; @@ -99,7 +99,7 @@ pub trait Trait: system::Trait { type Event: From> + Into<::Event>; /// A sudo-able call. - type Proposal: Parameter + Dispatchable::Error>; + type Proposal: Parameter + RuntimeDispatchable; } decl_module! { diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 387397b4a310a..cd561a4542897 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -1,165 +1,20 @@ -#[macro_export] -macro_rules! impl_outer_error { - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident { - $( $module:ident $( <$generic:ident $(, $instance:path )? > )? ),* $(,)? - } - ) => { - $crate::impl_outer_error! { - $(#[$attr])* - pub enum $name for $runtime where system = system { - $( $module $( <$generic $(, $instance )? > )?, )* - } - } - }; - ( - $(#[$attr:meta])* - pub enum $name:ident for $runtime:ident where system = $system:ident { - $( $module:ident $( <$generic:ident $(, $instance:path )?> )? ),* $(,)? - } - ) => { - $crate::impl_outer_error!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $module $( <$generic $(, $instance )? > )*, )* }; - ); - }; - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { - $module:ident $( )?, - $( $rest_module:tt )* - }; - $( $parsed:tt )* - ) => { - $crate::impl_outer_error!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_module )* }; - $( $parsed )* $module $( <$runtime $(, $instance )? > )?, - ); - }; +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. - // The main macro expansion that actually renders the Error enum. +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. - ( - $(#[$attr:meta])*; - $name:ident; - $runtime:ident; - $system:ident; - Modules { }; - $( $module:ident $( <$generic_param:ident $(, $generic_instance:path )? > )* ,)* - ) => { - // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. - #[derive(Clone, PartialEq, Eq, $crate::codec::Encode)] - #[cfg_attr(feature = "std", derive(Debug))] - $(#[$attr])* - #[allow(non_camel_case_types)] - pub enum $name { - system($system::Error), - $( - $module($module::Error), - )* - } +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. - impl From<$system::Error> for $name { - fn from(err: $system::Error) -> Self { - $name::system(err) - } - } +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . - impl From<&'static str> for $name { - fn from(err: &'static str) -> Self { - $name::system($system::Error::Other(err)) - } - } - - impl $crate::Printable for $name { - fn print(self) { - $crate::print("Error:"); - let err = Into::<$crate::runtime_primitives::DispatchError>::into(self); - $crate::print(err.module as u64); - $crate::print(err.error as u64); - if let Some(msg) = err.message { - $crate::print(msg); - } - } - } - - impl $crate::rstd::convert::TryInto<$system::Error> for $name { - type Error = Self; - fn try_into(self) -> $crate::dispatch::result::Result<$system::Error, Self::Error> { - if let $name::system(err) = self { - Ok(err) - } else { - Err(self) - } - } - } - - impl Into<$crate::runtime_primitives::DispatchError> for $name { - fn into(self) -> $crate::runtime_primitives::DispatchError { - match self { - $name::system(ref err) => match err { - $system::Error::Other(msg) => - $crate::runtime_primitives::DispatchError { - module: 0, - error: 0, - message: Some(msg), - }, - _ => $crate::runtime_primitives::DispatchError { - module: 0, - error: Into::::into(err), - message: None, - }, - }, - $( - $name::$module(ref err) => match err { - $module::Error::Other(msg) => - $crate::runtime_primitives::DispatchError { - module: $crate::codec::Encode::using_encoded(&self, |s| s[0]), - error: 0, - message: Some(msg), - }, - _ => $crate::runtime_primitives::DispatchError { - module: $crate::codec::Encode::using_encoded(&self, |s| s[0]), - error: Into::::into(err), - message: None, - }, - }, - )* - } - } - } - - $( - impl From<$module::Error> for $name { - fn from(err: $module::Error) -> Self { - $name::$module(err) - } - } - - impl $crate::rstd::convert::TryInto<$module::Error> for $name { - type Error = Self; - fn try_into(self) -> $crate::dispatch::result::Result<$module::Error, Self::Error> { - if let $name::$module(err) = self { - Ok(err) - } else { - Err(self) - } - } - } - )* - } -} +//! Macro for declaring a module error. #[macro_export] macro_rules! decl_error { diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 2e2b9dbb898b0..7a29b880cb2e6 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -166,7 +166,7 @@ macro_rules! assert_noop { #[macro_export] #[cfg(feature = "std")] macro_rules! assert_err { - ( $x:expr , $y:expr ) => { + ( $x:expr , $y:expr $(,)? ) => { assert_eq!($x, Err($y)); } } diff --git a/srml/support/src/runtime.rs b/srml/support/src/runtime.rs index b5006714ca577..4461e37518698 100644 --- a/srml/support/src/runtime.rs +++ b/srml/support/src/runtime.rs @@ -216,14 +216,6 @@ macro_rules! construct_runtime { } ),* ); - $crate::__decl_outer_error!( - $runtime; - $( - $name: $module:: $( < $module_instance >:: )? { - $( $modules $( <$modules_generic> )* ),* - } - ),* - ); $crate::__decl_all_modules!( $runtime; ; @@ -411,7 +403,6 @@ macro_rules! __create_decl_macro { __create_decl_macro!(__decl_outer_event, impl_outer_event, Event, $); __create_decl_macro!(__decl_outer_origin, impl_outer_origin, Origin, $); -__create_decl_macro!(__decl_outer_error, impl_outer_error, Error, $); /// A macro that defines all modules as an associated types of the Runtime type. #[macro_export] @@ -561,7 +552,6 @@ macro_rules! __decl_outer_dispatch { ) => { $crate::impl_outer_dispatch!( pub enum Call for $runtime where origin: Origin { - type Error = Error; $( $parsed_modules::$parsed_name, )* } ); diff --git a/srml/support/test/tests/instance.rs b/srml/support/test/tests/instance.rs index ffa082f69a09b..9c42298d460fe 100644 --- a/srml/support/test/tests/instance.rs +++ b/srml/support/test/tests/instance.rs @@ -238,7 +238,6 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; - type Error = Error; } srml_support::construct_runtime!( diff --git a/srml/support/test/tests/issue2219.rs b/srml/support/test/tests/issue2219.rs index 0fba65bd750a7..e057f2c7c79f9 100644 --- a/srml/support/test/tests/issue2219.rs +++ b/srml/support/test/tests/issue2219.rs @@ -160,7 +160,6 @@ impl system::Trait for Runtime { type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; - type Error = Error; } impl module::Trait for Runtime {} diff --git a/srml/support/test/tests/system.rs b/srml/support/test/tests/system.rs index 9ae9c4a4bf060..02a89dbac9548 100644 --- a/srml/support/test/tests/system.rs +++ b/srml/support/test/tests/system.rs @@ -8,13 +8,11 @@ pub trait Trait: 'static + Eq + Clone { type Hash; type AccountId: Encode + Decode; type Event: From; - type Error: From + From<&'static str>; } srml_support::decl_module! { pub struct Module for enum Call where origin: T::Origin { - pub fn deposit_event(_event: T::Event) { - } + pub fn deposit_event(_event: T::Event) {} } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 08c46468861ee..85e69277ef1c0 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -833,16 +833,12 @@ mod tests { use runtime_io::with_externalities; use substrate_primitives::H256; use primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; - use srml_support::{impl_outer_origin, impl_outer_error, parameter_types}; + use srml_support::{impl_outer_origin, parameter_types}; impl_outer_origin! { pub enum Origin for Test where system = super {} } - impl_outer_error! { - pub enum Error for Test where system = super {} - } - #[derive(Clone, Eq, PartialEq)] pub struct Test; diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index edd4ce264e55c..48a0d04c32198 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -325,7 +325,7 @@ impl ProvideInherent for Module { mod tests { use super::*; - use srml_support::{impl_outer_origin, impl_outer_error, assert_ok, parameter_types}; + use srml_support::{impl_outer_origin, assert_ok, parameter_types}; use runtime_io::{with_externalities, TestExternalities}; use substrate_primitives::H256; use runtime_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -334,10 +334,6 @@ mod tests { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Runtime {} - } - #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -353,7 +349,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 39bbf35cc403b..268233c37e419 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -358,7 +358,7 @@ mod tests { use super::*; use runtime_io::with_externalities; - use srml_support::{assert_noop, assert_ok, impl_outer_origin, impl_outer_error, parameter_types}; + use srml_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types}; use substrate_primitives::{H256, Blake2Hasher}; use runtime_primitives::{traits::{BlakeTwo256, OnFinalize, IdentityLookup}, testing::Header}; @@ -366,12 +366,6 @@ mod tests { pub enum Origin for Test {} } - impl_outer_error! { - pub enum Error for Test { - balances - } - } - #[derive(Clone, Eq, PartialEq)] pub struct Test; parameter_types! { @@ -387,7 +381,6 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; } parameter_types! { @@ -405,7 +398,6 @@ mod tests { type TransactionPayment = (); type TransferPayment = (); type DustRemoval = (); - type Error = Error; type ExistentialDeposit = ExistentialDeposit; type TransferFee = TransferFee; type CreationFee = CreationFee; From a3b5693665b6b40d1941f5b506ef265df35a79b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 13 Aug 2019 15:30:20 +0200 Subject: [PATCH 44/80] Start to fix after master merge --- .../src/generic/unchecked_extrinsic.rs | 11 ++++++---- core/sr-primitives/src/lib.rs | 21 ++----------------- core/sr-primitives/src/testing.rs | 2 +- core/sr-primitives/src/traits.rs | 4 +--- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index f570548969c36..0498152b0d966 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -21,9 +21,11 @@ use std::fmt; use rstd::prelude::*; use runtime_io::blake2_256; -use crate::codec::{Decode, Encode, Input, Error}; -use crate::traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}; -use super::CheckedExtrinsic; +use codec::{Decode, Encode, Input, Error}; +use crate::{ + traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}, + PrimitiveError, generic::CheckedExtrinsic, +}; const TRANSACTION_VERSION: u8 = 3; @@ -91,7 +93,8 @@ where Signature: Member + traits::Verify, Extra: SignedExtension, AccountId: Member + MaybeDisplay, - Lookup: traits::Lookup + Lookup: traits::Lookup, + PrimitiveError: From, { type Checked = CheckedExtrinsic; type Error = PrimitiveError; diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 0bdfad52fb73b..f7272701a1fb8 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -657,8 +657,6 @@ pub enum ApplyOutcome { Fail(DispatchError), } -impl codec::EncodeLike for ApplyOutcome {} - #[derive(Eq, PartialEq, Clone, Copy, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] #[repr(u8)] @@ -684,7 +682,7 @@ impl Encode for ApplyError { impl codec::EncodeLike for ApplyError {} -#[derive(Eq, PartialEq, Clone, Copy)] +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] /// Reason why a dispatch call failed pub struct DispatchError { @@ -693,6 +691,7 @@ pub struct DispatchError { /// Module specific error value pub error: u8, /// Optional error message. + #[codec(skip)] pub message: Option<&'static str>, } @@ -707,22 +706,6 @@ impl DispatchError { } } -impl Encode for DispatchError { - fn using_encoded R>(&self, f: F) -> R { - f(&[self.module, self.error]) - } -} - -impl Decode for DispatchError { - fn decode(input: &mut R) -> Option { - Some(DispatchError { - module: input.read_byte()?, - error: input.read_byte()?, - message: None, - }) - } -} - impl runtime_io::Printable for DispatchError { fn print(&self) { "DispatchError".print(); diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 7b6f179017519..6a19ccd2592bb 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -23,7 +23,7 @@ use crate::traits::{ self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, DispatchError, DispatchResult, ValidateUnsigned, SignedExtension, Dispatchable, }; -use crate::{generic, KeyTypeId}; +use crate::{generic, KeyTypeId, PrimitiveError}; use crate::weights::{GetDispatchInfo, DispatchInfo}; pub use primitives::H256; use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 5830a0ee90dcc..f0f8fd859eda2 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -881,9 +881,7 @@ pub trait Dispatchable { /// Means by which a transaction may be extended. This type embodies both the data and the logic /// that should be additionally associated with the transaction. It should be plain old data. -pub trait SignedExtension: - Codec + MaybeDebug + Sync + Send + Clone + Eq + PartialEq -{ +pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + PartialEq { /// The type which encodes the sender identity. type AccountId; From 6784605960d4bf1cfb89e17822c9560d3b7b2f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 15 Aug 2019 15:10:07 +0200 Subject: [PATCH 45/80] The great transaction error handling refactoring --- .../src/generic/checked_extrinsic.rs | 27 ++- .../src/generic/unchecked_extrinsic.rs | 12 +- core/sr-primitives/src/lib.rs | 116 ++++++------- core/sr-primitives/src/testing.rs | 25 +-- core/sr-primitives/src/traits.rs | 142 +++++++--------- .../sr-primitives/src/transaction_validity.rs | 157 ++++++++++++++---- srml/executive/src/lib.rs | 1 - srml/staking/src/mock.rs | 1 + srml/support/src/dispatch.rs | 64 +------ srml/support/src/error.rs | 9 +- srml/support/src/lib.rs | 4 +- srml/support/src/unsigned.rs | 7 +- srml/system/src/lib.rs | 113 ++++++------- 13 files changed, 337 insertions(+), 341 deletions(-) diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 08d7b10386721..720005097a4a2 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -17,10 +17,8 @@ //! Generic implementation of an extrinsic that has passed the verification //! stage. -use rstd::result::Result; use crate::traits::{ - self, Member, MaybeDisplay, SignedExtension, DispatchError, Dispatchable, DispatchResult, - ValidateUnsigned + self, Member, MaybeDisplay, SignedExtension, Dispatchable, ValidateUnsigned, }; use crate::weights::{GetDispatchInfo, DispatchInfo}; use crate::transaction_validity::TransactionValidity; @@ -55,28 +53,25 @@ where self.signed.as_ref().map(|x| &x.0) } - fn validate>(&self, + fn validate>( + &self, info: DispatchInfo, len: usize, ) -> TransactionValidity { if let Some((ref id, ref extra)) = self.signed { - Extra::validate(extra, id, &self.function, info, len).into() + Extra::validate(extra, id, &self.function, info, len) } else { - match Extra::validate_unsigned(&self.function, info, len) { - Ok(extra) => match U::validate_unsigned(&self.function) { - TransactionValidity::Valid(v) => - TransactionValidity::Valid(v.combine_with(extra)), - x => x, - }, - x => x.into(), - } + Extra::validate_unsigned(&self.function, info, len).combine_with( + || U::validate_unsigned(&self.function) + ) } } - fn dispatch(self, + fn apply( + self, info: DispatchInfo, len: usize, - ) -> Result { + ) -> crate::ApplyResult { let (maybe_who, pre) = if let Some((id, extra)) = self.signed { let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?; (Some(id), pre) @@ -86,7 +81,7 @@ where }; let res = self.function.dispatch(Origin::from(maybe_who)); Extra::post_dispatch(pre, info, len); - Ok(res) + res.map_err(|e| crate::DispatchError::from(e.into()).into()) } } diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 0498152b0d966..53206e19049ff 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -24,7 +24,8 @@ use runtime_io::blake2_256; use codec::{Decode, Encode, Input, Error}; use crate::{ traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}, - PrimitiveError, generic::CheckedExtrinsic, + generic::CheckedExtrinsic, + transaction_validity::{TransactionValidityError, InvalidTransactionValidity}, }; const TRANSACTION_VERSION: u8 = 3; @@ -94,15 +95,14 @@ where Extra: SignedExtension, AccountId: Member + MaybeDisplay, Lookup: traits::Lookup, - PrimitiveError: From, + TransactionValidityError: From, { type Checked = CheckedExtrinsic; - type Error = PrimitiveError; - fn check(self, lookup: &Lookup) -> Result { + fn check(self, lookup: &Lookup) -> Result { Ok(match self.signature { Some((signed, signature, extra)) => { - let additional_signed = extra.additional_signed()?; + let additional_signed = extra.additional_signed(); let raw_payload = (self.function, extra, additional_signed); let signed = lookup.lookup(signed)?; if !raw_payload.using_encoded(|payload| { @@ -112,7 +112,7 @@ where signature.verify(payload, &signed) } }) { - return Err(PrimitiveError::BadSignature) + return Err(InvalidTransactionValidity::BadProof.into()) } CheckedExtrinsic { signed: Some((signed, raw_payload.1)), diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index f7272701a1fb8..30726baef1989 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -58,42 +58,6 @@ pub use generic::{DigestItem, Digest}; pub use primitives::crypto::{key_types, KeyTypeId, CryptoType}; pub use app_crypto::AppKey; -#[cfg_attr(test, derive(PartialEq, Debug))] -/// Primitive Error type -pub enum PrimitiveError { - /// Unknown error - /// This exists only to make implementation easier. Should be avoid as much as possible. - Other(&'static str), - /// Indicating an invalid signature in extrinsic. - BadSignature, - /// Full block error message. - /// - /// This allows modules to indicate that given transaction is potentially valid - /// in the future, but can't be executed in the current state. - /// Note this error should be returned early in the execution to prevent DoS, - /// cause the fees are not being paid if this error is returned. - /// - /// Example: block gas limit is reached (the transaction can be retried in the next block though). - BlockFull, -} - -// Exists for for backward compatibility purpose. -impl Into<&'static str> for PrimitiveError { - fn into(self) -> &'static str { - match self { - PrimitiveError::Other(val) => val, - PrimitiveError::BadSignature => "bad signature in extrinsic", - PrimitiveError::BlockFull => "block size limit is reached", - } - } -} - -impl From<&'static str> for PrimitiveError { - fn from(val: &'static str) -> PrimitiveError { - PrimitiveError::Other(val) - } -} - /// Justification type. pub type Justification = Vec; @@ -647,47 +611,50 @@ impl From for AnySignature { } } -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -/// Outcome of a valid extrinsic application. Capable of being sliced. -pub enum ApplyOutcome { - /// Successful application (extrinsic reported no issue). - Success, - /// Failed application (extrinsic was probably a no-op other than fees). - Fail(DispatchError), -} - -#[derive(Eq, PartialEq, Clone, Copy, Decode)] +#[derive(Eq, PartialEq, Clone, Copy, Decode, Encode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] -#[repr(u8)] /// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). pub enum ApplyError { - /// Bad signature. - BadSignature = 0, - /// Nonce too low. - Stale = 1, - /// Nonce too high. - Future = 2, - /// Sending account had too low a balance. - CantPay = 3, - /// Block is full, no more extrinsics can be applied. - FullBlock = 255, + /// General error to do with the inability to pay some fees (e.g. account balance too low). + Payment, + + /// General error to do with the permissions of the sender. + NoPermission, + + /// General error to do with the state of the system in general. + BadState, + + /// General error to do with the exhaustion of block resources. + Exhausted, + + /// Any error that occurred in a module while dispatching the transaction. + Module(DispatchError), + + /// Any error to do with the transaction validity. + Validity(transaction_validity::TransactionValidityError), +} + +impl From for ApplyError { + fn from(err: DispatchError) -> Self { + ApplyError::Module(err) + } } -impl Encode for ApplyError { - fn using_encoded R>(&self, f: F) -> R { - f(&[*self as u8]) +impl From for ApplyError { + fn from(err: transaction_validity::TransactionValidityError) -> Self { + ApplyError::Validity(err) } } -impl codec::EncodeLike for ApplyError {} +/// Result from attempt to apply an extrinsic. +pub type ApplyResult = Result<(), ApplyError>; #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] /// Reason why a dispatch call failed pub struct DispatchError { /// Module index, matching the metadata module index - pub module: u8, + pub module: Option, /// Module specific error value pub error: u8, /// Optional error message. @@ -697,7 +664,7 @@ pub struct DispatchError { impl DispatchError { /// Create a new instance of `DispatchError`. - pub fn new(module: u8, error: u8, message: Option<&'static str>) -> Self { + pub fn new(module: Option, error: u8, message: Option<&'static str>) -> Self { Self { module, error, @@ -709,7 +676,9 @@ impl DispatchError { impl runtime_io::Printable for DispatchError { fn print(&self) { "DispatchError".print(); - self.module.print(); + if let Some(module) = self.module { + module.print(); + } self.error.print(); if let Some(msg) = self.message { msg.print(); @@ -717,8 +686,21 @@ impl runtime_io::Printable for DispatchError { } } -/// Result from attempt to apply an extrinsic. -pub type ApplyResult = Result; +impl traits::ModuleDispatchError for &'static str { + fn as_u8(&self) -> u8 { + 0 + } + + fn as_str(&self) -> &'static str { + self + } +} + +impl From<&'static str> for DispatchError { + fn from(err: &'static str) -> DispatchError { + DispatchError::new(None, 0, Some(err)) + } +} /// Verify a signature on an encoded value in a lazy manner. This can be /// an optimization if the signature scheme has an "unsigned" escape hash. diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 6a19ccd2592bb..fb37d7512c3e6 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -20,14 +20,14 @@ use serde::{Serialize, Serializer, Deserialize, de::Error as DeError, Deserializ use std::{fmt::Debug, ops::Deref, fmt}; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{ - self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, DispatchError, DispatchResult, - ValidateUnsigned, SignedExtension, Dispatchable, + self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, ValidateUnsigned, + SignedExtension, Dispatchable, }; -use crate::{generic, KeyTypeId, PrimitiveError}; +use crate::{generic, KeyTypeId, ApplyResult, DispatchError}; use crate::weights::{GetDispatchInfo, DispatchInfo}; pub use primitives::H256; use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; -use crate::transaction_validity::TransactionValidity; +use crate::transaction_validity::{TransactionValidity, TransactionValidityError}; /// Authority Id #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize)] @@ -270,8 +270,7 @@ impl Debug for TestXt { impl Checkable for TestXt { type Checked = Self; - type Error = PrimitiveError; - fn check(self, _: &Context) -> Result { Ok(self) } + fn check(self, _: &Context) -> Result { Ok(self) } } impl traits::Extrinsic for TestXt { type Call = Call; @@ -288,7 +287,7 @@ impl traits::Extrinsic for TestXt impl Applyable for TestXt where Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable, Extra: SignedExtension, - Origin: From> + Origin: From>, { type AccountId = u64; type Call = Call; @@ -296,7 +295,8 @@ impl Applyable for TestXt where fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) } /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>(&self, + fn validate>( + &self, _info: DispatchInfo, _len: usize, ) -> TransactionValidity { @@ -305,10 +305,11 @@ impl Applyable for TestXt where /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, /// index and sender. - fn dispatch(self, + fn apply( + self, info: DispatchInfo, len: usize, - ) -> Result { + ) -> ApplyResult { let maybe_who = if let Some((who, extra)) = self.0 { Extra::pre_dispatch(extra, &who, &self.1, info, len)?; Some(who) @@ -316,7 +317,7 @@ impl Applyable for TestXt where Extra::pre_dispatch_unsigned(&self.1, info, len)?; None }; - Ok(self.1.dispatch(maybe_who.into())) + self.1.dispatch(maybe_who.into()).map_err(|e| DispatchError::from(e.into()).into()) } } @@ -328,4 +329,4 @@ impl GetDispatchInfo for TestXt { ..Default::default() } } -} +} \ No newline at end of file diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index f0f8fd859eda2..4dc2a605c2f37 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -23,7 +23,7 @@ use runtime_io; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use primitives::{self, Hasher, Blake2Hasher}; use crate::codec::{Codec, Encode, Decode, HasCompact}; -use crate::transaction_validity::{ValidTransaction, TransactionValidity}; +use crate::transaction_validity::{ValidTransaction, TransactionValidity, TransactionValidityError}; use crate::generic::{Digest, DigestItem}; use crate::weights::DispatchInfo; pub use integer_sqrt::IntegerSquareRoot; @@ -790,11 +790,9 @@ pub type DigestItemFor = DigestItem<<::Header as Header>::Hash>; pub trait Checkable: Sized { /// Returned if `check` succeeds. type Checked; - /// Indicates why `check` failed - type Error; /// Check self, given an instance of Context. - fn check(self, c: &Context) -> Result; + fn check(self, c: &Context) -> Result; } /// A "checkable" piece of information, used by the standard Substrate Executive in order to @@ -804,67 +802,23 @@ pub trait Checkable: Sized { pub trait BlindCheckable: Sized { /// Returned if `check` succeeds. type Checked; - /// Returned if `check` failed. - type Error; /// Check self. - fn check(self) -> Result; + fn check(self) -> Result; } // Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`. impl Checkable for T { type Checked = ::Checked; - type Error = ::Error; - fn check(self, _c: &Context) -> Result { + fn check(self, _c: &Context) -> Result { BlindCheckable::check(self) } } -/// An abstract error concerning an attempt to verify, check or dispatch the transaction. This -/// cannot be more concrete because it's designed to work reasonably well over a broad range of -/// possible transaction types. -#[cfg_attr(feature = "std", derive(Debug))] -pub enum DispatchError { - /// General error to do with the inability to pay some fees (e.g. account balance too low). - Payment, - - /// General error to do with the exhaustion of block resources. - Exhausted, - - /// General error to do with the permissions of the sender. - NoPermission, - - /// General error to do with the state of the system in general. - BadState, - - /// General error to do with the transaction being outdated (e.g. nonce too low). - Stale, - - /// General error to do with the transaction not yet being valid (e.g. nonce too high). - Future, - - /// General error to do with the transaction's proofs (e.g. signature). - BadProof, -} - -impl From for i8 { - fn from(e: DispatchError) -> i8 { - match e { - DispatchError::Payment => -64, - DispatchError::Exhausted => -65, - DispatchError::NoPermission => -66, - DispatchError::BadState => -67, - DispatchError::Stale => -68, - DispatchError::Future => -69, - DispatchError::BadProof => -70, - } - } -} - /// Result of a module function call; either nothing (functions are only called for "side effects") /// or an error message. -pub type DispatchResult = result::Result<(), &'static str>; +pub type DispatchResult = result::Result<(), Error>; /// A lazy call (module function and argument values) that can be executed via its `dispatch` /// method. @@ -875,8 +829,10 @@ pub trait Dispatchable { type Origin; /// ... type Trait; + /// The error type returned by this dispatchable. + type Error: Into; /// Actually dispatch this call and result the result of it. - fn dispatch(self, origin: Self::Origin) -> DispatchResult; + fn dispatch(self, origin: Self::Origin) -> DispatchResult; } /// Means by which a transaction may be extended. This type embodies both the data and the logic @@ -897,7 +853,7 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti /// Construct any additional data that should be in the signed payload of the transaction. Can /// also perform any pre-signature-verification checks and return an error if needed. - fn additional_signed(&self) -> Result; + fn additional_signed(&self) -> Result; /// Validate a signed transaction for the transaction queue. fn validate( @@ -906,8 +862,8 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result { - Ok(Default::default()) + ) -> TransactionValidity { + ValidTransaction::default().into() } /// Do any pre-flight stuff for a signed transaction. @@ -917,8 +873,11 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - self.validate(who, call, info, len).map(|_| Self::Pre::default()) + ) -> Result { + self.validate(who, call, info, len) + .into_result() + .map(|_| Self::Pre::default()) + .map_err(Into::into) } /// Validate an unsigned transaction for the transaction queue. Normally the default @@ -928,23 +887,35 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result { Ok(Default::default()) } + ) -> TransactionValidity { + ValidTransaction::default().into() + } /// Do any pre-flight stuff for a unsigned transaction. fn pre_dispatch_unsigned( call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - Self::validate_unsigned(call, info, len).map(|_| Self::Pre::default()) + ) -> Result { + Self::validate_unsigned(call, info, len) + .into_result() + .map(|_| Self::Pre::default()) + .map_err(Into::into) } /// Do any post-flight stuff for a transaction. - fn post_dispatch( - _pre: Self::Pre, - _info: DispatchInfo, - _len: usize, - ) { } + fn post_dispatch(_pre: Self::Pre, _info: DispatchInfo, _len: usize) { } +} + +/// An error that is returned by a dispatchable function of a module. +pub trait ModuleDispatchError { + /// Convert this error to an `u8`. + /// + /// The `u8` corresponds to the index of the variant in the error enum. + fn as_u8(&self) -> u8; + + /// Convert the error to a `&'static str`. + fn as_str(&self) -> &'static str; } macro_rules! tuple_impl_indexed { @@ -959,10 +930,10 @@ macro_rules! tuple_impl_indexed { > SignedExtension for ($($direct),+,) { type AccountId = AccountId; type Call = Call; - type AdditionalSigned = ($($direct::AdditionalSigned,)+); + type AdditionalSigned = ( $( $direct::AdditionalSigned, )+ ); type Pre = ($($direct::Pre,)+); - fn additional_signed(&self) -> Result { - Ok(( $(self.$index.additional_signed()?,)+ )) + fn additional_signed(&self) -> Result { + Ok(( $( self.$index.additional_signed()?, )+ )) } fn validate( &self, @@ -970,9 +941,14 @@ macro_rules! tuple_impl_indexed { call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - let aggregator = vec![$(<$direct as SignedExtension>::validate(&self.$index, who, call, info, len)?),+]; - Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a))) + ) -> TransactionValidity { + let aggregator = vec![ + $( <$direct as SignedExtension>::validate(&self.$index, who, call, info, len) ),+ + ]; + aggregator.into_iter().fold( + TransactionValidity::Valid(ValidTransaction::default()), + |acc, a| acc.combine_with(|| a) + ) } fn pre_dispatch( self, @@ -980,22 +956,26 @@ macro_rules! tuple_impl_indexed { call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { + ) -> Result { Ok(($(self.$index.pre_dispatch(who, call, info, len)?,)+)) } fn validate_unsigned( call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { - let aggregator = vec![$($direct::validate_unsigned(call, info, len)?),+]; - Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a))) + ) -> TransactionValidity { + let aggregator = vec![ $( $direct::validate_unsigned(call, info, len) ),+ ]; + + aggregator.into_iter().fold( + TransactionValidity::Valid(ValidTransaction::default()), + |acc, a| acc.combine_with(|| a) + ) } fn pre_dispatch_unsigned( call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { + ) -> Result { Ok(($($direct::pre_dispatch_unsigned(call, info, len)?,)+)) } fn post_dispatch( @@ -1032,7 +1012,7 @@ impl SignedExtension for () { type AdditionalSigned = (); type Call = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } } /// An "executable" piece of information, used by the standard Substrate Executive in order to @@ -1052,17 +1032,19 @@ pub trait Applyable: Sized + Send + Sync { fn sender(&self) -> Option<&Self::AccountId>; /// Checks to see if this is a valid *transaction*. It returns information on it if so. - fn validate>(&self, + fn validate>( + &self, info: DispatchInfo, len: usize, ) -> TransactionValidity; /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, /// index and sender. - fn dispatch(self, + fn apply( + self, info: DispatchInfo, len: usize, - ) -> Result; + ) -> crate::ApplyResult; } /// Auxiliary wrapper that holds an api instance and binds it to the given lifetime. diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 4d5d53baf199f..722926a6b85c1 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -17,8 +17,7 @@ //! Transaction validity interface. use rstd::prelude::*; -use crate::codec::{Encode, Decode, Error}; -use crate::traits::DispatchError; +use crate::codec::{Encode, Decode}; /// Priority for a transaction. Additive. Higher is better. pub type TransactionPriority = u64; @@ -30,29 +29,142 @@ pub type TransactionLongevity = u64; /// Tag for a transaction. No two transactions with the same tag should be placed on-chain. pub type TransactionTag = Vec; +/// An invalid transaction validity. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] +#[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] +pub enum InvalidTransactionValidity { + /// General error to do with the transaction not yet being valid (e.g. nonce too high). + Future, + /// General error to do with the transaction being outdated (e.g. nonce too low). + Stale, + /// General error to do with the transaction's proofs (e.g. signature). + BadProof, + /// The transaction birth block is ancient. + AncientBirthBlock, + /// The transaction **alone** would exhaust the resources of a block. + ExhaustResources, + /// Any other custom invalid validity that is not covered by this enum. + Custom(u8), +} + +/// An unknown transaction validity. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] +#[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] +pub enum UnknownTransactionValidity { + /// An invalid/unknown account index + InvalidIndex, + /// No validator found for the given unsigned transaction. + NoUnsignedValidator, + /// Any other custom unknown validity that is not covered by this enum. + Custom(u8), +} + +/// The error that can occur while checking the validity of a transaction. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] +#[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] +pub enum TransactionValidityError { + /// The transaction is invalid. + Invalid(InvalidTransactionValidity), + /// Transaction validity can't be determined. + Unknown(UnknownTransactionValidity), +} + +impl Into for InvalidTransactionValidity { + fn into(self) -> TransactionValidityError { + TransactionValidityError::Invalid(self) + } +} + +impl Into for UnknownTransactionValidity { + fn into(self) -> TransactionValidityError { + TransactionValidityError::Unknown(self) + } +} + +impl Into for InvalidTransactionValidity { + fn into(self) -> crate::ApplyError { + TransactionValidityError::from(self.into()).into() + } +} + +impl Into for UnknownTransactionValidity { + fn into(self) -> crate::ApplyError { + TransactionValidityError::from(self.into()).into() + } +} + /// Information on a transaction's validity and, if valid, on how it relates to other transactions. -#[derive(Clone, PartialEq, Eq, Encode)] +#[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum TransactionValidity { - /// Transaction is invalid. Details are described by the error code. - Invalid(i8), + /// Transaction is invalid. + Invalid(InvalidTransactionValidity), /// Transaction is valid. Valid(ValidTransaction), /// Transaction validity can't be determined. - Unknown(i8), + Unknown(UnknownTransactionValidity), } -impl From> for TransactionValidity { - fn from(r: Result) -> Self { - match r { - Ok(v) => TransactionValidity::Valid(v), - Err(e) => TransactionValidity::Invalid(e.into()), +impl Into for TransactionValidityError { + fn into(self) -> TransactionValidity { + match self { + TransactionValidityError::Invalid(invalid) => TransactionValidity::Invalid(invalid), + TransactionValidityError::Unknown(unknown) => TransactionValidity::Unknown(unknown), + } + } +} + +impl Into for InvalidTransactionValidity { + fn into(self) -> TransactionValidity { + TransactionValidity::Invalid(self) + } +} + +impl Into for UnknownTransactionValidity { + fn into(self) -> TransactionValidity { + TransactionValidity::Unknown(self) + } +} + +impl Into for ValidTransaction { + fn into(self) -> TransactionValidity { + TransactionValidity::Valid(self) + } +} + +impl TransactionValidity { + /// Combine two `TransactionValidity`s. + /// + /// If both are valid, they are combined. + /// + /// If one of them is not valid, the non-valid one is returned. If both are not valid, `self` is + /// returned. + pub fn combine_with Self>(self, other: F) -> Self { + match self { + TransactionValidity::Valid(valid) => { + match other() { + TransactionValidity::Valid(other_valid) => { + TransactionValidity::Valid(valid.combine_with(other_valid)) + }, + o => o, + } + }, + _ => self, + } + } + + /// Convert this `TransactionValidity` into a `Result`. + pub fn into_result(self) -> Result { + match self { + TransactionValidity::Valid(valid) => Ok(valid), + TransactionValidity::Invalid(invalid) => Err(invalid.into()), + TransactionValidity::Unknown(unknown) => Err(unknown.into()), } } } /// Information concerning a valid transaction. -#[derive(Clone, PartialEq, Eq, Encode)] +#[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub struct ValidTransaction { /// Priority of the transaction. @@ -112,27 +224,6 @@ impl ValidTransaction { } } -impl Decode for TransactionValidity { - fn decode(value: &mut I) -> Result { - match value.read_byte()? { - 0 => Ok(TransactionValidity::Invalid(i8::decode(value)?)), - 1 => { - let priority = TransactionPriority::decode(value)?; - let requires = Vec::decode(value)?; - let provides = Vec::decode(value)?; - let longevity = TransactionLongevity::decode(value)?; - let propagate = bool::decode(value).unwrap_or(true); - - Ok(TransactionValidity::Valid(ValidTransaction { - priority, requires, provides, longevity, propagate, - })) - }, - 2 => Ok(TransactionValidity::Unknown(i8::decode(value)?)), - _ => Err("Invalid transaction validity variant".into()), - } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 3bc2ad920df83..b6c57f4070f9d 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -254,7 +254,6 @@ where >::note_applied_extrinsic(&r, encoded_len as u32); r.map(|_| ApplyOutcome::Success).map_err(ApplyOutcome::Fail) - }) } fn final_checks(header: &System::Header) { diff --git a/srml/staking/src/mock.rs b/srml/staking/src/mock.rs index 856ee999ca5f1..d8233e5f45dfa 100644 --- a/srml/staking/src/mock.rs +++ b/srml/staking/src/mock.rs @@ -31,6 +31,7 @@ use crate::{ /// The AccountId alias in this test module. pub type AccountId = u64; +pub type BlockNumber = u64; pub type Balance = u64; /// Simple structure that exposes how u64 currency can be represented as... u64. diff --git a/srml/support/src/dispatch.rs b/srml/support/src/dispatch.rs index 31b077bbc2dac..f0acee2a3677e 100644 --- a/srml/support/src/dispatch.rs +++ b/srml/support/src/dispatch.rs @@ -29,67 +29,19 @@ pub use sr_primitives::{ weights::{ SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch, TransactionPriority - }, traits::{Dispatchable, DispatchResult}, DispatchError + }, traits::{Dispatchable, DispatchResult, ModuleDispatchError}, DispatchError }; /// 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. -pub type DispatchResult = result::Result<(), Error>; - /// Result with string error message. This exists for backward compatibility purpose. pub type Result = DispatchResult<&'static str>; -/// A lazy module call (module function and argument values) that can be executed via its `dispatch` -/// method. -pub trait ModuleDispatchable { - /// 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; - type Error: ModuleDispatchError; - - fn dispatch(self, origin: Self::Origin) -> DispatchResult; -} - -/// A lazy runtime call that can be executed via its `dispatch` method. -pub trait RuntimeDispatchable { - /// 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) -> DispatchResult; -} - -pub trait ModuleDispatchError { - /// Convert this error to an `u8`. - /// - /// The `u8` corresponds to the index of the variant in the error enum. - fn as_u8(&self) -> u8; - - /// Convert the error to a `&'static str`. - fn as_str(&self) -> &'static str; -} - -impl ModuleDispatchError for &'static str { - fn as_u8(&self) -> u8 { - 0 - } - - fn as_str(&self) -> &'static str { - self - } -} - /// Serializable version of Dispatchable. /// This value can be used as a "function" in an extrinsic. pub trait Callable { - type Call: ModuleDispatchable + Codec + Clone + PartialEq + Eq; + type Call: Dispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue @@ -1357,7 +1309,7 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::ModuleDispatchable + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { type Trait = $trait_instance; @@ -1388,7 +1340,7 @@ macro_rules! decl_module { where $( $other_where_bounds )* { #[doc(hidden)] - pub fn dispatch>( + pub fn dispatch>( d: D, origin: D::Origin ) -> $crate::dispatch::DispatchResult { @@ -1444,14 +1396,14 @@ macro_rules! impl_outer_dispatch { } } } - impl $crate::dispatch::RuntimeDispatchable for $call_type { + impl $crate::dispatch::Dispatchable for $call_type { type Origin = $origin; type Trait = $call_type; + type Error = $crate::dispatch::DispatchError; fn dispatch( self, origin: $origin, ) -> $crate::dispatch::DispatchResult<$crate::dispatch::DispatchError> { - use $crate::{ModuleDispatchable, ModuleDispatchError}; $crate::impl_outer_dispatch! { @DISPATCH_MATCH self @@ -1499,7 +1451,9 @@ macro_rules! impl_outer_dispatch { { $( $generated )* $call_type::$name(call) => call.dispatch($origin).map_err(|e| { - $crate::dispatch::DispatchError::new($index, e.as_u8(), Some(e.as_str())) + let mut error: $crate::dispatch::DispatchError = e.into(); + error.module = Some($index); + error }), } $index + 1; diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index cd561a4542897..ed6b08269d33b 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -39,7 +39,7 @@ macro_rules! decl_error { ),* } - impl $crate::ModuleDispatchError for $error { + impl $crate::dispatch::ModuleDispatchError for $error { fn as_u8(&self) -> u8 { $crate::decl_error! { @GENERATE_AS_U8 @@ -66,6 +66,13 @@ macro_rules! decl_error { $error::Other(val) } } + + impl Into<$crate::dispatch::DispatchError> for $error { + fn into(self) -> $crate::dispatch::DispatchError { + use $crate::dispatch::ModuleDispatchError; + $crate::dispatch::DispatchError::new(None, self.as_u8(), Some(self.as_str())) + } + } }; (@GENERATE_AS_U8 $self:ident diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 5f5d24d8c9d48..3624b42050b84 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -67,9 +67,7 @@ pub use self::storage::{ StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap }; pub use self::hashable::Hashable; -pub use self::dispatch::{ - Parameter, ModuleDispatchable, RuntimeDispatchable, Callable, IsSubType, ModuleDispatchError, -}; +pub use self::dispatch::{Parameter, Callable, IsSubType}; pub use self::double_map::StorageDoubleMapWithHasher; pub use runtime_io::{print, storage_root, Printable}; pub use sr_primitives::{self, ConsensusEngineId}; diff --git a/srml/support/src/unsigned.rs b/srml/support/src/unsigned.rs index 1c62dd0c58435..abe366993621c 100644 --- a/srml/support/src/unsigned.rs +++ b/srml/support/src/unsigned.rs @@ -17,7 +17,7 @@ #[doc(hidden)] pub use crate::sr_primitives::traits::ValidateUnsigned; #[doc(hidden)] -pub use crate::sr_primitives::transaction_validity::TransactionValidity; +pub use crate::sr_primitives::transaction_validity::{TransactionValidity, UnknownTransactionValidity}; #[doc(hidden)] pub use crate::sr_primitives::ApplyError; @@ -72,7 +72,7 @@ macro_rules! impl_outer_validate_unsigned { #[allow(unreachable_patterns)] match call { $( Call::$module(inner_call) => $module::validate_unsigned(inner_call), )* - _ => $crate::unsigned::TransactionValidity::Invalid($crate::unsigned::ApplyError::BadSignature as i8), + _ => $crate::unsigned::UnknownTransactionValidity::NoUnsignedValidator.into(), } } } @@ -81,8 +81,7 @@ macro_rules! impl_outer_validate_unsigned { #[cfg(test)] mod test_empty_call { - pub enum Call { - } + pub enum Call {} #[allow(unused)] pub struct Runtime; diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 67e7843470a19..d3e9b7408042c 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -78,22 +78,24 @@ use rstd::prelude::*; #[cfg(any(feature = "std", test))] use rstd::map; use rstd::marker::PhantomData; -use sr_primitives::generic::{self, Era}; -use sr_primitives::Perbill; -use sr_primitives::weights::{ - Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo +use sr_primitives::{ + generic::{self, Era}, Perbill, ApplyError, + weights::{Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo}, + transaction_validity::{ + ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, + InvalidTransactionValidity, TransactionValidity, + }, + traits::{ + self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, Lookup, + SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, SaturatedConversion, + MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, + }, }; -use sr_primitives::transaction_validity::{ - ValidTransaction, TransactionPriority, TransactionLongevity -}; -use sr_primitives::traits::{self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, - SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, DispatchError, SaturatedConversion, - MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, Lookup, -}; -use primitives::{storage::well_known_keys, DispatchError}; + +use primitives::storage::well_known_keys; use srml_support::{ storage, decl_module, decl_event, decl_storage, StorageDoubleMap, StorageValue, StorageMap, - Parameter, for_each_tuple, traits::{Contains, Get} + Parameter, for_each_tuple, traits::{Contains, Get}, decl_error, }; use safe_mix::TripletMix; use codec::{Encode, Decode}; @@ -310,7 +312,7 @@ decl_event!( /// An extrinsic completed successfully. ExtrinsicSuccess, /// An extrinsic failed. - ExtrinsicFailed(DispatchError), + ExtrinsicFailed(ApplyError), } ); @@ -325,30 +327,6 @@ decl_error! { } } -impl From for Error { - fn from(err: PrimitiveError) -> Error { - match err { - PrimitiveError::Other(err) => Error::Other(err), - PrimitiveError::BadSignature => Error::BadSignature, - PrimitiveError::BlockFull => Error::BlockFull, - } - } -} - -// Exists for for backward compatibility purpose. -impl From for &'static str { - fn from(err: Error) -> &'static str { - match err { - Error::Other(val) => val, - Error::BadSignature => "bad signature in extrinsic", - Error::BlockFull => "block size limit is reached", - Error::RequireSignedOrigin => "bad origin: expected to be a signed origin", - Error::RequireRootOrigin => "bad origin: expected to be a root origin", - Error::RequireNoOrigin => "bad origin: expected to be no origin", - } - } -} - /// Origin for the System module. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] @@ -832,7 +810,7 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &Result<(), &'static str>, _encoded_len: u32) { + pub fn note_applied_extrinsic(r: &Result<(), ApplyError>, _encoded_len: u32) { Self::deposit_event(match r { Ok(_) => Event::ExtrinsicSuccess, Err(err) => Event::ExtrinsicFailed(err.clone()), @@ -865,7 +843,6 @@ impl Module { pub struct CheckWeight(PhantomData); impl CheckWeight { - /// Get the quota ratio of each dispatch class type. This indicates that all operational /// dispatches can use the full capacity of any resource, while user-triggered ones can consume /// a portion. @@ -880,14 +857,14 @@ impl CheckWeight { /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. - fn check_weight(info: DispatchInfo) -> Result { + fn check_weight(info: DispatchInfo) -> Result { let current_weight = Module::::all_extrinsics_weight(); let maximum_weight = T::MaximumBlockWeight::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; let added_weight = info.weight.min(limit); let next_weight = current_weight.saturating_add(added_weight); if next_weight > limit { - return Err(DispatchError::Exhausted) + return Err(ApplyError::Exhausted) } Ok(next_weight) } @@ -895,14 +872,14 @@ impl CheckWeight { /// Checks if the current extrinsic can fit into the block with respect to block length limits. /// /// Upon successes, it returns the new block length as a `Result`. - fn check_block_length(info: DispatchInfo, len: usize) -> Result { + fn check_block_length(info: DispatchInfo, len: usize) -> Result { let current_len = Module::::all_extrinsics_len(); let maximum_len = T::MaximumBlockLength::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; let added_len = len as u32; let next_len = current_len.saturating_add(added_len); if next_len > limit { - return Err(DispatchError::Exhausted) + return Err(ApplyError::Exhausted) } Ok(next_len) } @@ -928,7 +905,7 @@ impl SignedExtension for CheckWeight { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn pre_dispatch( self, @@ -936,7 +913,7 @@ impl SignedExtension for CheckWeight { _call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result<(), DispatchError> { + ) -> Result<(), ApplyError> { let next_len = Self::check_block_length(info, len)?; AllExtrinsicsLen::put(next_len); let next_weight = Self::check_weight(info)?; @@ -950,13 +927,15 @@ impl SignedExtension for CheckWeight { _call: &Self::Call, info: DispatchInfo, len: usize, - ) -> Result { + ) -> TransactionValidity { // There is no point in writing to storage here since changes are discarded. This basically - // discards any transaction which is bigger than the length or weight limit **alone**,which + // discards any transaction which is bigger than the length or weight limit **alone**, which // is a guarantee that it will fail in the pre-dispatch phase. - let _ = Self::check_block_length(info, len)?; - let _ = Self::check_weight(info)?; - Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) + if Self::check_block_length(info, len).is_err() || Self::check_weight(info).is_err() { + return InvalidTransactionValidity::ExhaustResources.into(); + } + + ValidTransaction { priority: Self::get_priority(info), ..Default::default() }.into() } } @@ -992,7 +971,7 @@ impl SignedExtension for CheckNonce { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn pre_dispatch( self, @@ -1000,13 +979,18 @@ impl SignedExtension for CheckNonce { _call: &Self::Call, _info: DispatchInfo, _len: usize, - ) -> Result<(), DispatchError> { + ) -> Result<(), ApplyError> { let expected = >::get(who); if self.0 != expected { return Err( - if self.0 < expected { DispatchError::Stale } else { DispatchError::Future } + if self.0 < expected { + InvalidTransactionValidity::Stale + } else { + InvalidTransactionValidity::Future + }.into() ) } + >::insert(who, expected + T::Index::one()); Ok(()) } @@ -1017,11 +1001,11 @@ impl SignedExtension for CheckNonce { _call: &Self::Call, info: DispatchInfo, _len: usize, - ) -> Result { + ) -> TransactionValidity { // check index let expected = >::get(who); if self.0 < expected { - return Err(DispatchError::Stale) + return InvalidTransactionValidity::Stale.into() } let provides = vec![Encode::encode(&(who, self.0))]; @@ -1031,13 +1015,13 @@ impl SignedExtension for CheckNonce { vec![] }; - Ok(ValidTransaction { + ValidTransaction { priority: info.weight as TransactionPriority, requires, provides, longevity: TransactionLongevity::max_value(), propagate: true, - }) + }.into() } } @@ -1066,11 +1050,14 @@ impl SignedExtension for CheckEra { type AdditionalSigned = T::Hash; type Pre = (); - fn additional_signed(&self) -> Result { + fn additional_signed(&self) -> Result { let current_u64 = >::block_number().saturated_into::(); let n = (self.0).0.birth(current_u64).saturated_into::(); - if !>::exists(n) { Err("transaction birth block ancient")? } - Ok(>::block_hash(n)) + if !>::exists(n) { + Err(InvalidTransactionValidity::AncientBirthBlock.into()) + } else { + Ok(>::block_hash(n)) + } } } @@ -1098,7 +1085,7 @@ impl SignedExtension for CheckGenesis { type AdditionalSigned = T::Hash; type Pre = (); - fn additional_signed(&self) -> Result { + fn additional_signed(&self) -> Result { Ok(>::block_hash(T::BlockNumber::zero())) } } @@ -1124,7 +1111,7 @@ mod tests { use super::*; use runtime_io::with_externalities; use primitives::H256; - use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header}; + use sr_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header, DispatchError}; use srml_support::{impl_outer_origin, parameter_types}; impl_outer_origin! { From 7424908d2e4dac7e3b3c423223c1e6e0c12614bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 15 Aug 2019 15:15:26 +0200 Subject: [PATCH 46/80] Make `decl_error` errors convertible to `&'static str` --- srml/support/src/error.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index ed6b08269d33b..3bc0f989ccbf4 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -67,6 +67,13 @@ macro_rules! decl_error { } } + impl From<$error> for &'static str { + fn from(err: $error) -> &'static str { + use $crate::dispatch::ModuleDispatchError; + err.as_str() + } + } + impl Into<$crate::dispatch::DispatchError> for $error { fn into(self) -> $crate::dispatch::DispatchError { use $crate::dispatch::ModuleDispatchError; From cc862ef91cae36cc9a9ffd0e084627d3cd167cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 16 Aug 2019 17:00:26 +0200 Subject: [PATCH 47/80] Make srml-executive build again --- .../src/generic/checked_extrinsic.rs | 3 +- core/sr-primitives/src/lib.rs | 44 +++++-- core/sr-primitives/src/testing.rs | 4 +- .../sr-primitives/src/transaction_validity.rs | 39 ++++++ srml/balances/src/lib.rs | 28 +++-- srml/executive/src/lib.rs | 112 +++++++++--------- srml/system/src/lib.rs | 16 +-- 7 files changed, 159 insertions(+), 87 deletions(-) diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 720005097a4a2..4afb7eba3b9c2 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -22,6 +22,7 @@ use crate::traits::{ }; use crate::weights::{GetDispatchInfo, DispatchInfo}; use crate::transaction_validity::TransactionValidity; +use crate::DispatchError; /// Definition of something that the external world might want to say; its /// existence implies that it has been checked and is good, particularly with @@ -81,7 +82,7 @@ where }; let res = self.function.dispatch(Origin::from(maybe_who)); Extra::post_dispatch(pre, info, len); - res.map_err(|e| crate::DispatchError::from(e.into()).into()) + Ok(res.map_err(|e| DispatchError::from(e.into()).into()).into()) } } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 30726baef1989..533ff5947c4a5 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -615,9 +615,6 @@ impl From for AnySignature { #[cfg_attr(feature = "std", derive(Debug, Serialize))] /// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). pub enum ApplyError { - /// General error to do with the inability to pay some fees (e.g. account balance too low). - Payment, - /// General error to do with the permissions of the sender. NoPermission, @@ -627,16 +624,18 @@ pub enum ApplyError { /// General error to do with the exhaustion of block resources. Exhausted, - /// Any error that occurred in a module while dispatching the transaction. - Module(DispatchError), - /// Any error to do with the transaction validity. Validity(transaction_validity::TransactionValidityError), } -impl From for ApplyError { - fn from(err: DispatchError) -> Self { - ApplyError::Module(err) +impl Into<&'static str> for ApplyError { + fn into(self) -> &'static str { + match self { + ApplyError::NoPermission => "Transaction does not have required permissions", + ApplyError::BadState => "System in bad state", + ApplyError::Exhausted => "Transaction exhausted block limits", + ApplyError::Validity(v) => v.into(), + } } } @@ -646,8 +645,33 @@ impl From for ApplyError { } } +/// The outcome of applying a transaction. +#[derive(Eq, PartialEq, Clone, Copy, Decode, Encode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize))] +pub enum ApplyOutcome { + /// The transaction was applied successfully. + Success, + /// Any error that occurred in a module while dispatching the transaction. + Fail(DispatchError), +} + +impl From for ApplyOutcome { + fn from(err: DispatchError) -> Self { + ApplyOutcome::Fail(err) + } +} + +impl From> for ApplyOutcome { + fn from(res: Result<(), DispatchError>) -> Self { + match res { + Ok(()) => ApplyOutcome::Success, + Err(e) => e.into(), + } + } +} + /// Result from attempt to apply an extrinsic. -pub type ApplyResult = Result<(), ApplyError>; +pub type ApplyResult = Result; #[derive(Eq, PartialEq, Clone, Copy, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index fb37d7512c3e6..6ccf9bdaade0f 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -317,7 +317,9 @@ impl Applyable for TestXt where Extra::pre_dispatch_unsigned(&self.1, info, len)?; None }; - self.1.dispatch(maybe_who.into()).map_err(|e| DispatchError::from(e.into()).into()) + + let res = self.1.dispatch(maybe_who.into()); + Ok(res.map_err(|e| DispatchError::from(e.into()).into()).into()) } } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 722926a6b85c1..59f21a3cba0c6 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -33,6 +33,8 @@ pub type TransactionTag = Vec; #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum InvalidTransactionValidity { + /// General error to do with the inability to pay some fees (e.g. account balance too low). + Payment, /// General error to do with the transaction not yet being valid (e.g. nonce too high). Future, /// General error to do with the transaction being outdated (e.g. nonce too low). @@ -47,6 +49,22 @@ pub enum InvalidTransactionValidity { Custom(u8), } +impl Into<&'static str> for InvalidTransactionValidity { + fn into(self) -> &'static str { + match self { + InvalidTransactionValidity::Future => "Transaction will be valid in the future", + InvalidTransactionValidity::Stale => "Transaction is outdated", + InvalidTransactionValidity::BadProof => "Transaction has a bad signature", + InvalidTransactionValidity::AncientBirthBlock => "Transaction has an ancient birth block", + InvalidTransactionValidity::ExhaustResources => + "Transaction would exhausts the block limits", + InvalidTransactionValidity::Payment => + "Inability to pay some fees (e.g. account balance too low)", + InvalidTransactionValidity::Custom(_) => "InvalidTransactionValidity custom error", + } + } +} + /// An unknown transaction validity. #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] @@ -59,6 +77,18 @@ pub enum UnknownTransactionValidity { Custom(u8), } +impl Into<&'static str> for UnknownTransactionValidity { + fn into(self) -> &'static str { + match self { + UnknownTransactionValidity::InvalidIndex => + "Transaction used an invalid/unknown account index", + UnknownTransactionValidity::NoUnsignedValidator => + "Could not find an unsigned validator for the unsigned transaction", + UnknownTransactionValidity::Custom(_) => "UnknownTransactionValidity custom error", + } + } +} + /// The error that can occur while checking the validity of a transaction. #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] @@ -69,6 +99,15 @@ pub enum TransactionValidityError { Unknown(UnknownTransactionValidity), } +impl Into<&'static str> for TransactionValidityError { + fn into(self) -> &'static str { + match self { + TransactionValidityError::Invalid(invalid) => invalid.into(), + TransactionValidityError::Unknown(unknown) => unknown.into(), + } + } +} + impl Into for InvalidTransactionValidity { fn into(self) -> TransactionValidityError { TransactionValidityError::Invalid(self) diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 66d0ee028495f..75a348e4a8689 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -159,12 +159,17 @@ use srml_support::traits::{ Imbalance, SignedImbalance, ReservableCurrency, Get, }; use srml_support::dispatch::Result; -use sr_primitives::traits::{ - Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug, - Saturating, Bounded, SignedExtension, SaturatedConversion, DispatchError, Convert, +use sr_primitives::{ + transaction_validity::{ + TransactionPriority, ValidTransaction, InvalidTransactionValidity, TransactionValidity, + TransactionValidityError, + }, + traits::{ + Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug, + Saturating, Bounded, SignedExtension, SaturatedConversion, Convert, + }, + weights::{DispatchInfo, SimpleDispatchInfo, Weight}, }; -use sr_primitives::transaction_validity::{TransactionPriority, ValidTransaction}; -use sr_primitives::weights::{DispatchInfo, SimpleDispatchInfo, Weight}; use system::{IsDeadAccount, OnNewAccount, ensure_signed, ensure_root}; mod mock; @@ -1217,7 +1222,7 @@ impl, I: Instance + Clone + Eq> SignedExtension for TakeFees { type Call = T::Call; type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn validate( &self, @@ -1225,22 +1230,25 @@ impl, I: Instance + Clone + Eq> SignedExtension for TakeFees { _call: &Self::Call, info: DispatchInfo, len: usize, - ) -> rstd::result::Result { + ) -> TransactionValidity { // pay any fees. let fee = Self::compute_fee(len, info, self.0); - let imbalance = >::withdraw( + let imbalance = match >::withdraw( who, fee, WithdrawReason::TransactionPayment, ExistenceRequirement::KeepAlive, - ).map_err(|_| DispatchError::Payment)?; + ) { + Ok(imbalance) => imbalance, + Err(_) => return InvalidTransactionValidity::Payment.into(), + }; T::TransactionPayment::on_unbalanced(imbalance); let mut r = ValidTransaction::default(); // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which // will be a bit more than setting the priority to tip. For now, this is enough. r.priority = fee.saturated_into::(); - Ok(r) + r.into() } } diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index b6c57f4070f9d..9f5669f5d2652 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -59,13 +59,13 @@ //! # pub type Balances = u64; //! # pub type AllModules = u64; //! # pub enum Runtime {}; -//! # use sr_primitives::transaction_validity::TransactionValidity; +//! # use sr_primitives::transaction_validity::{TransactionValidity, UnknownTransactionValidity}; //! # use sr_primitives::traits::ValidateUnsigned; //! # impl ValidateUnsigned for Runtime { //! # type Call = (); //! # //! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { -//! # TransactionValidity::Invalid(0) +//! # UnknownTransactionValidity::NoUnsignedValidator.into() //! # } //! # } //! /// Executive: handles dispatch to the various modules. @@ -74,19 +74,17 @@ #![cfg_attr(not(feature = "std"), no_std)] -use rstd::prelude::*; -use rstd::marker::PhantomData; -use rstd::result; -use sr_primitives::{generic::Digest, traits::{ - self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, PrimitiveError, - OnInitialize, NumberFor, Block as BlockT, OffchainWorker, ValidateUnsigned -}}; -use srml_support::Dispatchable; +use rstd::{prelude::*, marker::PhantomData}; +use sr_primitives::{ + generic::Digest, ApplyResult, ApplyOutcome, weights::GetDispatchInfo, + traits::{ + self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, + NumberFor, Block as BlockT, OffchainWorker, ValidateUnsigned, Dispatchable + }, + transaction_validity::TransactionValidity, +}; use codec::{Codec, Encode}; use system::{extrinsics_root, DigestOf}; -use sr_primitives::{ApplyOutcome, ApplyError}; -use sr_primitives::transaction_validity::TransactionValidity; -use sr_primitives::weights::GetDispatchInfo; /// Trait that can be used to execute a block. pub trait ExecuteBlock { @@ -96,7 +94,7 @@ pub trait ExecuteBlock { pub type CheckedOf = >::Checked; pub type CallOf = as Applyable>::Call; -pub type OriginOf = as RuntimeDispatchable>::Origin; +pub type OriginOf = as Dispatchable>::Origin; pub struct Executive( PhantomData<(System, Block, Context, UnsignedValidator, AllModules)> @@ -111,7 +109,6 @@ impl< > ExecuteBlock for Executive where Block::Extrinsic: Checkable + Codec, - >::Error: Into, CheckedOf: Applyable + GetDispatchInfo, CallOf: Dispatchable, OriginOf: From>, @@ -131,7 +128,6 @@ impl< > Executive where Block::Extrinsic: Checkable + Codec, - >::Error: Into, CheckedOf: Applyable + GetDispatchInfo, CallOf: Dispatchable, OriginOf: From>, @@ -222,10 +218,7 @@ where match Self::apply_extrinsic_with_len(uxt, l, None) { Ok(ApplyOutcome::Success) => (), Ok(ApplyOutcome::Fail(e)) => runtime_io::print(e), - Err(ApplyError::CantPay) => panic!("All extrinsics should have sender able to pay their fees"), - Err(ApplyError::BadSignature) => panic!("All extrinsics should be properly signed"), - Err(ApplyError::Stale) | Err(ApplyError::Future) => panic!("All extrinsics should have the correct nonce"), - Err(ApplyError::FullBlock) => panic!("Extrinsics should not exceed block limit"), + Err(e) => { let err: &'static str = e.into(); panic!(err) }, } } @@ -236,7 +229,7 @@ where to_note: Option>, ) -> ApplyResult { // Verify that the signature is good. - let xt = uxt.check(&Default::default()).map_err(ApplyError::CantPay)?; + let xt = uxt.check(&Default::default())?; // We don't need to make sure to `note_extrinsic` only after we know it's going to be // executed to prevent it from leaking in storage since at this point, it will either @@ -249,11 +242,11 @@ where // Decode parameters and dispatch let dispatch_info = xt.get_dispatch_info(); - let r = Applyable::dispatch(xt, dispatch_info, encoded_len).map_err(DispatchError::from)?; + let r = Applyable::apply(xt, dispatch_info, encoded_len)?; >::note_applied_extrinsic(&r, encoded_len as u32); - r.map(|_| ApplyOutcome::Success).map_err(ApplyOutcome::Fail) + Ok(r) } fn final_checks(header: &System::Header) { @@ -283,25 +276,11 @@ where /// /// Changes made to storage should be discarded. pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { - // Note errors > 0 are from ApplyError - const UNKNOWN_ERROR: i8 = -127; - const INVALID_INDEX: i8 = -10; - let encoded_len = uxt.using_encoded(|d| d.len()); let xt = match uxt.check(&Default::default()) { // Checks out. Carry on. Ok(xt) => xt, - Err(err) => return match err.into() { - // An unknown account index implies that the transaction may yet become valid. - // TODO: avoid hardcoded error string here #2953 - PrimitiveError::Other("invalid account index") => - TransactionValidity::Unknown(INVALID_INDEX), - // Technically a bad signature could also imply an out-of-date account index, but - // that's more of an edge case. - PrimitiveError::BadSignature => - TransactionValidity::Invalid(ApplyError::BadSignature as i8), - _ => TransactionValidity::Invalid(UNKNOWN_ERROR), - } + Err(err) => return err.into(), }; let dispatch_info = xt.get_dispatch_info(); @@ -321,13 +300,15 @@ mod tests { use balances::Call; use runtime_io::with_externalities; use primitives::{H256, Blake2Hasher}; - use sr_primitives::generic::Era; - use sr_primitives::Perbill; - use sr_primitives::weights::Weight; - use sr_primitives::traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}; - use sr_primitives::testing::{Digest, Header, Block}; - use srml_support::{impl_outer_event, impl_outer_origin, parameter_types}; - use srml_support::traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}; + use sr_primitives::{ + generic::Era, Perbill, DispatchError, weights::Weight, testing::{Digest, Header, Block}, + traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, + transaction_validity::{UnknownTransactionValidity, InvalidTransactionValidity}, ApplyError, + }; + use srml_support::{ + impl_outer_event, impl_outer_origin, parameter_types, + traits::{Currency, LockIdentifier, LockableCurrency, WithdrawReasons, WithdrawReason}, + }; use system; use hex_literal::hex; @@ -396,7 +377,7 @@ mod tests { fn validate_unsigned(call: &Self::Call) -> TransactionValidity { match call { Call::set_balance(_, _, _) => TransactionValidity::Valid(Default::default()), - _ => TransactionValidity::Invalid(0), + _ => UnknownTransactionValidity::NoUnsignedValidator.into(), } } } @@ -442,7 +423,7 @@ mod tests { Digest::default(), )); let r = Executive::apply_extrinsic(xt); - assert_eq!(r, Ok(ApplyOutcome::Success)); + assert!(r.is_ok()); assert_eq!(>::total_balance(&1), 142 - 10 - weight); assert_eq!(>::total_balance(&2), 69); }); @@ -545,14 +526,19 @@ mod tests { assert_eq!(>::all_extrinsics_weight(), 0); for nonce in 0..=num_to_exhaust_block { - let xt = sr_primitives::testing::TestXt(sign_extra(1, nonce.into(), 0), Call::transfer::(33, 0)); + let xt = sr_primitives::testing::TestXt( + sign_extra(1, nonce.into(), 0), Call::transfer::(33, 0), + ); let res = Executive::apply_extrinsic(xt); if nonce != num_to_exhaust_block { - assert_eq!(res.unwrap(), ApplyOutcome::Success); - assert_eq!(>::all_extrinsics_weight(), encoded_len * (nonce + 1)); + assert!(res.is_ok()); + assert_eq!( + >::all_extrinsics_weight(), + encoded_len * (nonce + 1), + ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { - assert_eq!(res, Err(ApplyError::FullBlock)); + assert_eq!(res, Err(ApplyError::Exhausted)); } } }); @@ -594,7 +580,11 @@ mod tests { assert_eq!(Executive::validate_transaction(xt.clone()), valid); assert_eq!( Executive::apply_extrinsic(xt), - Ok(ApplyOutcome::Fail(DispatchError { module: 0, error: 4 /*RequireNoOrigin*/ , message: None })) + Ok( + ApplyOutcome::Fail( + DispatchError { module: None, error: 0, message: Some("RequireRootOrigin") } + ) + ) ); }); } @@ -623,15 +613,21 @@ mod tests { )); if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { - assert_eq!(Executive::apply_extrinsic(xt).unwrap(), ApplyOutcome::Fail(DispatchError { - module: 0, - error: 0, - message: Some("account liquidity restrictions prevent withdrawal") - })); + assert_eq!( + Executive::apply_extrinsic(xt).unwrap(), + ApplyOutcome::Fail(DispatchError { + module: None, + error: 0, + message: Some("account liquidity restrictions prevent withdrawal"), + }), + ); // but tx fee has been deducted. the transaction failed on transfer, not on fee. assert_eq!(>::total_balance(&1), 111 - 10 - weight); } else { - assert_eq!(Executive::apply_extrinsic(xt), Err(ApplyError::CantPay)); + assert_eq!( + Executive::apply_extrinsic(xt), + Err(ApplyError::Validity(InvalidTransactionValidity::Payment.into())), + ); assert_eq!(>::total_balance(&1), 111); } }); diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index d3e9b7408042c..3efde0f240cc4 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -79,7 +79,7 @@ use rstd::prelude::*; use rstd::map; use rstd::marker::PhantomData; use sr_primitives::{ - generic::{self, Era}, Perbill, ApplyError, + generic::{self, Era}, Perbill, ApplyError, ApplyOutcome, DispatchError, weights::{Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo}, transaction_validity::{ ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, @@ -312,7 +312,7 @@ decl_event!( /// An extrinsic completed successfully. ExtrinsicSuccess, /// An extrinsic failed. - ExtrinsicFailed(ApplyError), + ExtrinsicFailed(DispatchError), } ); @@ -810,11 +810,13 @@ impl Module { } /// To be called immediately after an extrinsic has been applied. - pub fn note_applied_extrinsic(r: &Result<(), ApplyError>, _encoded_len: u32) { - Self::deposit_event(match r { - Ok(_) => Event::ExtrinsicSuccess, - Err(err) => Event::ExtrinsicFailed(err.clone()), - }.into()); + pub fn note_applied_extrinsic(r: &ApplyOutcome, _encoded_len: u32) { + Self::deposit_event( + match r { + ApplyOutcome::Success => Event::ExtrinsicSuccess, + ApplyOutcome::Fail(err) => Event::ExtrinsicFailed(err.clone()), + }.into() + ); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; From 3b809f285d1806680f1f94eed13d54d606df6475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 16 Aug 2019 22:36:22 +0200 Subject: [PATCH 48/80] Fix `sr-primitives` tests --- .../src/generic/unchecked_extrinsic.rs | 25 ++++++---- core/sr-primitives/src/lib.rs | 19 ++++---- .../sr-primitives/src/transaction_validity.rs | 48 +++++++++++++++---- srml/collective/src/lib.rs | 4 +- srml/contracts/src/lib.rs | 4 +- srml/democracy/src/lib.rs | 1 - srml/sudo/src/lib.rs | 10 ++-- 7 files changed, 73 insertions(+), 38 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 53206e19049ff..3293d82233129 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -102,7 +102,7 @@ where fn check(self, lookup: &Lookup) -> Result { Ok(match self.signature { Some((signed, signature, extra)) => { - let additional_signed = extra.additional_signed(); + let additional_signed = extra.additional_signed()?; let raw_payload = (self.function, extra, additional_signed); let signed = lookup.lookup(signed)?; if !raw_payload.using_encoded(|payload| { @@ -200,7 +200,12 @@ where Extra: SignedExtension, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedExtrinsic({:?}, {:?})", self.signature.as_ref().map(|x| (&x.0, &x.2)), self.function) + write!( + f, + "UncheckedExtrinsic({:?}, {:?})", + self.signature.as_ref().map(|x| (&x.0, &x.2)), + self.function, + ) } } @@ -216,7 +221,8 @@ mod tests { impl Lookup for TestContext { type Source = u64; type Target = u64; - fn lookup(&self, s: u64) -> Result { Ok(s) } + type Error = TransactionValidityError; + fn lookup(&self, s: u64) -> Result { Ok(s) } } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)] @@ -242,7 +248,7 @@ mod tests { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } } type Ex = UncheckedExtrinsic; @@ -293,10 +299,13 @@ mod tests { vec![0u8; 0], TEST_ACCOUNT, TestSig(TEST_ACCOUNT, vec![0u8; 0]), - TestExtra + TestExtra, ); assert!(ux.is_signed().unwrap_or(false)); - assert_eq!(>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE)); + assert_eq!( + >::check(ux, &TestContext), + Err(InvalidTransactionValidity::BadProof.into()), + ); } #[test] @@ -305,12 +314,12 @@ mod tests { vec![0u8; 0], TEST_ACCOUNT, TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()), - TestExtra + TestExtra, ); assert!(ux.is_signed().unwrap_or(false)); assert_eq!( >::check(ux, &TestContext), - Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }) + Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }), ); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 533ff5947c4a5..2a09fc76d770f 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -1019,17 +1019,20 @@ mod tests { #[test] fn dispatch_error_encoding() { let error = DispatchError { - module: 1, + module: Some(1), error: 2, message: Some("error message"), }; let encoded = error.encode(); - let decoded = DispatchError::decode(&mut &*encoded).unwrap(); - assert_eq!(encoded, vec![1, 2]); - assert_eq!(decoded, DispatchError { - module: 1, - error: 2, - message: None, - }); + let decoded = DispatchError::decode(&mut &encoded[..]).unwrap(); + assert_eq!(encoded, vec![1, 1, 2]); + assert_eq!( + decoded, + DispatchError { + module: Some(1), + error: 2, + message: None, + }, + ); } } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 59f21a3cba0c6..9f8f79f7be547 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -133,7 +133,7 @@ impl Into for UnknownTransactionValidity { } /// Information on a transaction's validity and, if valid, on how it relates to other transactions. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum TransactionValidity { /// Transaction is invalid. @@ -202,8 +202,29 @@ impl TransactionValidity { } } +impl Decode for TransactionValidity { + fn decode(value: &mut I) -> Result { + match value.read_byte()? { + 0 => Ok(TransactionValidity::Invalid(InvalidTransactionValidity::decode(value)?)), + 1 => { + let priority = TransactionPriority::decode(value)?; + let requires = Vec::decode(value)?; + let provides = Vec::decode(value)?; + let longevity = TransactionLongevity::decode(value)?; + let propagate = bool::decode(value).unwrap_or(true); + + Ok(TransactionValidity::Valid(ValidTransaction { + priority, requires, provides, longevity, propagate, + })) + }, + 2 => Ok(TransactionValidity::Unknown(UnknownTransactionValidity::decode(value)?)), + _ => Err("Invalid transaction validity variant".into()), + } + } +} + /// Information concerning a valid transaction. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Debug))] pub struct ValidTransaction { /// Priority of the transaction. @@ -270,16 +291,23 @@ mod tests { #[test] fn should_decode_with_backward_compat() { let old_encoding = vec![ - 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0 + 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, ]; - assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Ok(TransactionValidity::Valid(ValidTransaction { - priority: 5, - requires: vec![vec![1, 2, 3, 4]], - provides: vec![vec![4, 5, 6]], - longevity: 42, - propagate: true, - }))); + assert_eq!( + TransactionValidity::decode(&mut &*old_encoding), + Ok( + TransactionValidity::Valid( + ValidTransaction { + priority: 5, + requires: vec![vec![1, 2, 3, 4]], + provides: vec![vec![4, 5, 6]], + longevity: 42, + propagate: true, + } + ), + ) + ); } #[test] diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index 13f51259c599c..5aea34d7915f7 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -28,7 +28,7 @@ use primitives::u32_trait::Value as U32; use sr_primitives::traits::{Hash, EnsureOrigin}; use sr_primitives::weights::SimpleDispatchInfo; use srml_support::{ - dispatch::{RuntimeDispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, + dispatch::{Dispatchable, Parameter}, codec::{Encode, Decode}, traits::ChangeMembers, StorageValue, StorageMap, decl_module, decl_event, decl_storage, ensure }; use system::{self, ensure_signed, ensure_root}; @@ -47,7 +47,7 @@ pub trait Trait: system::Trait { type Origin: From>; /// The outer call dispatch type. - type Proposal: Parameter + RuntimeDispatchable>::Origin>; + type Proposal: Parameter + Dispatchable>::Origin>; /// The outer event type. type Event: From> + Into<::Event>; diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 0d018e1451416..9f9fae52922bf 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -103,7 +103,7 @@ use runtime_io::blake2_256; use sr_primitives::traits::{ Hash, StaticLookup, Zero, MaybeSerializeDebug, Member }; -use srml_support::dispatch::{Result, RuntimeDispatchable}; +use srml_support::dispatch::{Result, Dispatchable}; use srml_support::{ Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child, parameter_types, @@ -321,7 +321,7 @@ pub trait Trait: timestamp::Trait { type Currency: Currency; /// The outer call dispatch type. - type Call: Parameter + RuntimeDispatchable::Origin>; + type Call: Parameter + Dispatchable::Origin>; /// The overarching event type. type Event: From> + Into<::Event>; diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 610c298367606..d459fdca139f9 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -173,7 +173,6 @@ impl Decode for Vote { } type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type Error = &'static str; pub const DEFAULT_ENACTMENT_PERIOD: u32 = 0; pub const DEFAULT_LAUNCH_PERIOD: u32 = 0; diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 983e48441b948..48e3bea42f214 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -87,12 +87,8 @@ #![cfg_attr(not(feature = "std"), no_std)] use sr_std::prelude::*; -use sr_primitives::traits::StaticLookup; -use sr_primitives::weights::SimpleDispatchInfo; -use srml_support::{ - StorageValue, Parameter, RuntimeDispatchable, decl_module, decl_event, - decl_storage, ensure -}; +use sr_primitives::{traits::{StaticLookup, Dispatchable}, weights::SimpleDispatchInfo}; +use srml_support::{StorageValue, Parameter, decl_module, decl_event, decl_storage, ensure}; use system::ensure_signed; pub trait Trait: system::Trait { @@ -100,7 +96,7 @@ pub trait Trait: system::Trait { type Event: From> + Into<::Event>; /// A sudo-able call. - type Proposal: Parameter + RuntimeDispatchable; + type Proposal: Parameter + Dispatchable; } decl_module! { From ddd630a083d7b4e14e6317e6974127aadde989c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sat, 17 Aug 2019 00:03:33 +0200 Subject: [PATCH 49/80] More fixes --- .../sr-primitives/src/transaction_validity.rs | 21 ++++++++ core/test-runtime/src/lib.rs | 13 ++--- core/transaction-pool/graph/src/error.rs | 12 +++-- srml/democracy/src/lib.rs | 8 +-- srml/sudo/src/lib.rs | 5 +- srml/system/src/lib.rs | 51 +++++++++++-------- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 9f8f79f7be547..39e4d9e117815 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -200,6 +200,27 @@ impl TransactionValidity { TransactionValidity::Unknown(unknown) => Err(unknown.into()), } } + + /// Returns if the validity `invalid` or `unknown`. + pub fn is_invalid_or_unknown(&self) -> bool { + match self { + TransactionValidity::Invalid(_) | TransactionValidity::Unknown(_) => true, + TransactionValidity::Valid(_) => false, + } + } + + /// Returns if the validity `valid`. + pub fn is_valid(&self) -> bool { + !self.is_invalid_or_unknown() + } + + /// Try to convert into `ValidTransaction`. + pub fn into_valid(self) -> Option { + match self { + TransactionValidity::Valid(valid) => Some(valid), + _ => None, + } + } } impl Decode for TransactionValidity { diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index c3be0538ba02a..9f8668e9bb932 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -37,8 +37,10 @@ use substrate_client::{ impl_runtime_apis, }; use sr_primitives::{ - ApplyResult, create_runtime_str, Perbill, impl_opaque_keys, PrimitiveError, - transaction_validity::{TransactionValidity, ValidTransaction}, + ApplyResult, create_runtime_str, Perbill, impl_opaque_keys, + transaction_validity::{ + TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransactionValidity, + }, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup, @@ -122,19 +124,18 @@ impl serde::Serialize for Extrinsic { impl BlindCheckable for Extrinsic { type Checked = Self; - type Error = PrimitiveError; - fn check(self) -> Result { + fn check(self) -> Result { match self { Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)), Extrinsic::Transfer(transfer, signature) => { if sr_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer(transfer, signature)) } else { - Err(PrimitiveError::BadSignature) + Err(InvalidTransactionValidity::BadProof.into()) } }, - Extrinsic::IncludeData(_) => Err(PrimitiveError::BadSignature), + Extrinsic::IncludeData(_) => Err(InvalidTransactionValidity::BadProof.into()), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), } } diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index 07e0324354dfa..e2acad6ae2a1a 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -16,7 +16,9 @@ //! Transaction pool errors. -use sr_primitives::transaction_validity::TransactionPriority as Priority; +use sr_primitives::transaction_validity::{ + TransactionPriority as Priority, InvalidTransactionValidity, UnknownTransactionValidity, +}; /// Transaction pool result. pub type Result = std::result::Result; @@ -25,11 +27,11 @@ pub type Result = std::result::Result; #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Transaction is not verifiable yet, but might be in the future. - #[display(fmt="Unkown Transaction Validity. Error code: {}", _0)] - UnknownTransactionValidity(i8), + #[display(fmt="Unkown Transaction Validity. Error code: {:?}", _0)] + UnknownTransactionValidity(UnknownTransactionValidity), /// Transaction is invalid. - #[display(fmt="Invalid Transaction. Error Code: {}", _0)] - InvalidTransaction(i8), + #[display(fmt="Invalid Transaction. Error Code: {:?}", _0)] + InvalidTransaction(InvalidTransactionValidity), /// The transaction is temporarily banned. #[display(fmt="Temporarily Banned")] TemporarilyBanned, diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index d459fdca139f9..ee4fee7e004fa 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -20,12 +20,14 @@ use rstd::prelude::*; use rstd::{result, convert::TryFrom}; -use sr_primitives::traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash}; -use sr_primitives::weights::SimpleDispatchInfo; +use sr_primitives::{ + traits::{Zero, Bounded, CheckedMul, CheckedDiv, EnsureOrigin, Hash, Dispatchable}, + weights::SimpleDispatchInfo, +}; use codec::{Encode, Decode, Input, Output, Error}; use srml_support::{ decl_module, decl_storage, decl_event, ensure, - StorageValue, StorageMap, Parameter, Dispatchable, EnumerableStorageMap, + StorageValue, StorageMap, Parameter, EnumerableStorageMap, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, OnFreeBalanceZero, Get diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 48e3bea42f214..60c112b79e053 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -87,7 +87,9 @@ #![cfg_attr(not(feature = "std"), no_std)] use sr_std::prelude::*; -use sr_primitives::{traits::{StaticLookup, Dispatchable}, weights::SimpleDispatchInfo}; +use sr_primitives::{ + traits::{StaticLookup, Dispatchable}, weights::SimpleDispatchInfo, DispatchError, +}; use srml_support::{StorageValue, Parameter, decl_module, decl_event, decl_storage, ensure}; use system::ensure_signed; @@ -122,6 +124,7 @@ decl_module! { let res = match proposal.dispatch(system::RawOrigin::Root.into()) { Ok(_) => true, Err(e) => { + let e: DispatchError = e.into(); sr_io::print(e); false } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 3efde0f240cc4..d1f4b3c048abd 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1200,17 +1200,23 @@ mod tests { System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); - System::note_applied_extrinsic(&Ok(()), 0); - System::note_applied_extrinsic(&Err(DispatchError { module: 1, error: 2, message: None }), 0); + System::note_applied_extrinsic(&ApplyOutcome::Success, 0); + System::note_applied_extrinsic( + &ApplyOutcome::Fail(DispatchError::new(Some(1), 2, None)), + 0, + ); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalize(); - assert_eq!(System::events(), vec![ - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 0x0201u16, topics: vec![] }, - EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } - ]); + assert_eq!( + System::events(), + vec![ + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(1), event: 257u16, topics: vec![] }, + EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } + ] + ); }); } @@ -1314,13 +1320,13 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // stale - assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_err()); + assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_invalid_or_unknown()); assert!(CheckNonce::(0).pre_dispatch(&1, CALL, info, len).is_err()); // correct - assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_ok()); + assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_valid()); assert!(CheckNonce::(1).pre_dispatch(&1, CALL, info, len).is_ok()); // future - assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_ok()); + assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_valid()); assert!(CheckNonce::(5).pre_dispatch(&1, CALL, info, len).is_err()); }) } @@ -1409,14 +1415,19 @@ mod tests { let op = DispatchInfo { weight: 100, class: DispatchClass::Operational }; let len = 0_usize; - assert_eq!( - CheckWeight::(PhantomData).validate(&1, CALL, normal, len).unwrap().priority, - 100, - ); - assert_eq!( - CheckWeight::(PhantomData).validate(&1, CALL, op, len).unwrap().priority, - Bounded::max_value(), - ); + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, normal, len) + .into_valid() + .unwrap() + .priority; + assert_eq!(priority, 100); + + let priority = CheckWeight::(PhantomData) + .validate(&1, CALL, op, len) + .into_valid() + .unwrap() + .priority; + assert_eq!(priority, Bounded::max_value()); }) } @@ -1450,7 +1461,7 @@ mod tests { // future assert_eq!( CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), - "transaction birth block ancient" + InvalidTransactionValidity::AncientBirthBlock.into(), ); // correct From f611efcb61d3007ff1d2038c9cfe788633127498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 18 Aug 2019 17:22:45 +0200 Subject: [PATCH 50/80] Last round of fix ups --- core/basic-authorship/src/basic_authorship.rs | 9 ++-- core/rpc/src/author/error.rs | 10 ++--- .../src/generic/unchecked_extrinsic.rs | 23 ++++------- core/sr-primitives/src/lib.rs | 14 +++++-- core/sr-primitives/src/traits.rs | 41 +++++++------------ .../sr-primitives/src/transaction_validity.rs | 39 ++++++++++++++---- core/test-runtime/src/system.rs | 32 +++++++-------- core/transaction-pool/graph/src/pool.rs | 11 +++-- node-template/runtime/src/template.rs | 1 - node/executor/src/lib.rs | 20 +++++---- srml/assets/src/lib.rs | 2 +- srml/balances/src/lib.rs | 4 +- srml/collective/src/lib.rs | 4 -- srml/contracts/src/gas.rs | 3 +- srml/contracts/src/lib.rs | 2 +- srml/democracy/src/lib.rs | 6 +-- srml/elections/src/lib.rs | 8 ++-- srml/executive/src/lib.rs | 2 +- srml/im-online/src/lib.rs | 20 +++++---- srml/indices/src/lib.rs | 8 ++-- srml/staking/src/lib.rs | 10 ++--- srml/sudo/src/lib.rs | 2 +- srml/support/src/lib.rs | 2 +- srml/system/src/lib.rs | 34 +++++++-------- srml/treasury/src/lib.rs | 6 +-- 25 files changed, 166 insertions(+), 147 deletions(-) diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 2030f2be5a2f9..4b7179a55c959 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -30,9 +30,10 @@ use inherents::InherentData; use log::{error, info, debug, trace}; use primitives::{H256, Blake2Hasher, ExecutionContext}; use sr_primitives::{ - traits::{Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256}, + traits::{ + Block as BlockT, Hash as HashT, Header as HeaderT, ProvideRuntimeApi, DigestFor, BlakeTwo256 + }, generic::BlockId, - ApplyError, }; use transaction_pool::txpool::{self, Pool as TransactionPool}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; @@ -170,7 +171,7 @@ impl Proposer, A> wh Ok(()) => { debug!("[{:?}] Pushed to the block.", pending.hash); } - Err(error::Error::ApplyExtrinsicFailed(ApplyError::FullBlock)) => { + Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhaust_resources() => { if is_first { debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); unqueue_invalid.push(pending.hash.clone()); @@ -178,7 +179,7 @@ impl Proposer, A> wh skipped += 1; debug!( "Block seems full, but will try {} more transactions before quitting.", - MAX_SKIPPED_TRANSACTIONS - skipped + MAX_SKIPPED_TRANSACTIONS - skipped, ); } else { debug!("Block is full, proceed with proposing."); diff --git a/core/rpc/src/author/error.rs b/core/rpc/src/author/error.rs index 2fcc8c780dfdb..15cd615e827dc 100644 --- a/core/rpc/src/author/error.rs +++ b/core/rpc/src/author/error.rs @@ -99,15 +99,15 @@ impl From for rpc::Error { message: format!("Verification Error: {}", e).into(), data: Some(format!("{:?}", e).into()), }, - Error::Pool(PoolError::InvalidTransaction(code)) => rpc::Error { + Error::Pool(PoolError::InvalidTransaction(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_INVALID_TX), message: "Invalid Transaction".into(), - data: Some(code.into()), + data: serde_json::to_value(e).ok(), }, - Error::Pool(PoolError::UnknownTransactionValidity(code)) => rpc::Error { + Error::Pool(PoolError::UnknownTransactionValidity(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), message: "Unknown Transaction Validity".into(), - data: Some(code.into()), + data: serde_json::to_value(e).ok(), }, Error::Pool(PoolError::TemporarilyBanned) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), @@ -131,7 +131,7 @@ impl From for rpc::Error { }, Error::Pool(PoolError::ImmediatelyDropped) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED), - message: "Immediately Dropped" .into(), + message: "Immediately Dropped".into(), data: Some("The transaction couldn't enter the pool because of the limit".into()), }, e => errors::internal(e), diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 3293d82233129..38a688929846e 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -25,7 +25,9 @@ use codec::{Decode, Encode, Input, Error}; use crate::{ traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}, generic::CheckedExtrinsic, - transaction_validity::{TransactionValidityError, InvalidTransactionValidity}, + transaction_validity::{ + TransactionValidityError, InvalidTransactionValidity, UnknownTransactionValidity, + }, }; const TRANSACTION_VERSION: u8 = 3; @@ -95,7 +97,6 @@ where Extra: SignedExtension, AccountId: Member + MaybeDisplay, Lookup: traits::Lookup, - TransactionValidityError: From, { type Checked = CheckedExtrinsic; @@ -104,7 +105,7 @@ where Some((signed, signature, extra)) => { let additional_signed = extra.additional_signed()?; let raw_payload = (self.function, extra, additional_signed); - let signed = lookup.lookup(signed)?; + let signed = lookup.lookup(signed).ok_or(UnknownTransactionValidity::InvalidIndex)?; if !raw_payload.using_encoded(|payload| { if payload.len() > 256 { signature.verify(&blake2_256(payload)[..], &signed) @@ -214,16 +215,10 @@ mod tests { use super::*; use runtime_io::blake2_256; use crate::codec::{Encode, Decode}; - use crate::traits::{SignedExtension, Lookup}; + use crate::traits::{SignedExtension, IdentityLookup}; use serde::{Serialize, Deserialize}; - struct TestContext; - impl Lookup for TestContext { - type Source = u64; - type Target = u64; - type Error = TransactionValidityError; - fn lookup(&self, s: u64) -> Result { Ok(s) } - } + type TestContext = IdentityLookup; #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Encode, Decode)] struct TestSig(u64, Vec); @@ -290,7 +285,7 @@ mod tests { fn unsigned_check_should_work() { let ux = Ex::new_unsigned(vec![0u8; 0]); assert!(!ux.is_signed().unwrap_or(false)); - assert!(>::check(ux, &TestContext).is_ok()); + assert!(>::check(ux, &Default::default()).is_ok()); } #[test] @@ -303,7 +298,7 @@ mod tests { ); assert!(ux.is_signed().unwrap_or(false)); assert_eq!( - >::check(ux, &TestContext), + >::check(ux, &Default::default()), Err(InvalidTransactionValidity::BadProof.into()), ); } @@ -318,7 +313,7 @@ mod tests { ); assert!(ux.is_signed().unwrap_or(false)); assert_eq!( - >::check(ux, &TestContext), + >::check(ux, &Default::default()), Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }), ); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 2a09fc76d770f..760e0ecca8eaf 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -621,19 +621,25 @@ pub enum ApplyError { /// General error to do with the state of the system in general. BadState, - /// General error to do with the exhaustion of block resources. - Exhausted, - /// Any error to do with the transaction validity. Validity(transaction_validity::TransactionValidityError), } +impl ApplyError { + /// Returns if the reason for the error was block resource exhaustion. + pub fn exhaust_resources(&self) -> bool { + match self { + Self::Validity(e) => e.exhaust_resources(), + _ => false, + } + } +} + impl Into<&'static str> for ApplyError { fn into(self) -> &'static str { match self { ApplyError::NoPermission => "Transaction does not have required permissions", ApplyError::BadState => "System in bad state", - ApplyError::Exhausted => "Transaction exhausted block limits", ApplyError::Validity(v) => v.into(), } } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 4dc2a605c2f37..cd13bd24d9308 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -93,44 +93,36 @@ impl< } } -/// EnsureOrigin Error type -pub trait EnsureOriginError { - /// Indicates invalid origin - fn invalid_origin() -> Self; +/// An error type that indicates that the origin is invalid. +#[derive(Encode, Decode)] +pub struct InvalidOrigin; + +impl From for &'static str { + fn from(_: InvalidOrigin) -> &'static str { + "Invalid origin" + } } /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { /// A return type. type Success; - /// Error type - type Error: EnsureOriginError; /// Perform the origin check. - fn ensure_origin(o: OuterOrigin) -> result::Result { - Self::try_origin(o).map_err(|_| Self::Error::invalid_origin()) + fn ensure_origin(o: OuterOrigin) -> result::Result { + Self::try_origin(o).map_err(|_| InvalidOrigin) } /// Perform the origin check. fn try_origin(o: OuterOrigin) -> result::Result; } -impl EnsureOriginError for () { - fn invalid_origin() -> () {} -} - -impl EnsureOriginError for &'static str { - fn invalid_origin() -> &'static str { "Invalid origin" } -} - /// Means of changing one type into another in a manner dependent on the source type. pub trait Lookup { /// Type to lookup from. type Source; /// Type to lookup into. type Target; - /// Error type - type Error; /// Attempt a lookup. - fn lookup(&self, s: Self::Source) -> result::Result; + fn lookup(&self, s: Self::Source) -> Option; } /// Means of changing one type into another in a manner dependent on the source type. @@ -141,10 +133,8 @@ pub trait StaticLookup { type Source: Codec + Clone + PartialEq + MaybeDebug; /// Type to lookup into. type Target; - /// Error type. - type Error; /// Attempt a lookup. - fn lookup(s: Self::Source) -> result::Result; + fn lookup(s: Self::Source) -> Option; /// Convert from Target back to Source. fn unlookup(t: Self::Target) -> Self::Source; } @@ -155,15 +145,14 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - type Error = &'static str; - fn lookup(x: T) -> result::Result { Ok(x) } + fn lookup(x: T) -> Option { Some(x) } fn unlookup(x: T) -> T { x } } + impl Lookup for IdentityLookup { type Source = T; type Target = T; - type Error = &'static str; - fn lookup(&self, x: T) -> result::Result { Ok(x) } + fn lookup(&self, x: T) -> Option { Some(x) } } /// Extensible conversion trait. Generic over both source and destination types. diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 39e4d9e117815..040367eec8c7a 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -33,6 +33,8 @@ pub type TransactionTag = Vec; #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum InvalidTransactionValidity { + /// The call of the transaction is not expected. + Call, /// General error to do with the inability to pay some fees (e.g. account balance too low). Payment, /// General error to do with the transaction not yet being valid (e.g. nonce too high). @@ -49,9 +51,20 @@ pub enum InvalidTransactionValidity { Custom(u8), } +impl InvalidTransactionValidity { + /// Returns if the reason for the invalidity was block resource exhaustion. + pub fn exhaust_resources(&self) -> bool { + match self { + Self::ExhaustResources => true, + _ => false, + } + } +} + impl Into<&'static str> for InvalidTransactionValidity { fn into(self) -> &'static str { match self { + InvalidTransactionValidity::Call => "Transaction call is not expected", InvalidTransactionValidity::Future => "Transaction will be valid in the future", InvalidTransactionValidity::Stale => "Transaction is outdated", InvalidTransactionValidity::BadProof => "Transaction has a bad signature", @@ -99,6 +112,16 @@ pub enum TransactionValidityError { Unknown(UnknownTransactionValidity), } +impl TransactionValidityError { + /// Returns if the reason for the error was block resource exhaustion. + pub fn exhaust_resources(&self) -> bool { + match self { + Self::Invalid(e) => e.exhaust_resources(), + Self::Unknown(_) => false, + } + } +} + impl Into<&'static str> for TransactionValidityError { fn into(self) -> &'static str { match self { @@ -108,27 +131,27 @@ impl Into<&'static str> for TransactionValidityError { } } -impl Into for InvalidTransactionValidity { - fn into(self) -> TransactionValidityError { - TransactionValidityError::Invalid(self) +impl From for TransactionValidityError { + fn from(err: InvalidTransactionValidity) -> Self { + TransactionValidityError::Invalid(err) } } -impl Into for UnknownTransactionValidity { - fn into(self) -> TransactionValidityError { - TransactionValidityError::Unknown(self) +impl From for TransactionValidityError { + fn from(err: UnknownTransactionValidity) -> Self { + TransactionValidityError::Unknown(err) } } impl Into for InvalidTransactionValidity { fn into(self) -> crate::ApplyError { - TransactionValidityError::from(self.into()).into() + TransactionValidityError::from(self).into() } } impl Into for UnknownTransactionValidity { fn into(self) -> crate::ApplyError { - TransactionValidityError::from(self.into()).into() + TransactionValidityError::from(self).into() } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index f3c890cf79f54..6dd48205c7edd 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -21,12 +21,13 @@ use rstd::prelude::*; use runtime_io::{storage_root, ordered_trie_root, storage_changes_root, twox_128, blake2_256}; use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; -use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Header as _}; -use sr_primitives::generic; -use sr_primitives::{ApplyError, ApplyOutcome, ApplyResult}; -use sr_primitives::transaction_validity::{TransactionValidity, ValidTransaction}; +use sr_primitives::{ + traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyOutcome, + ApplyResult, + transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransactionValidity}, +}; use codec::{KeyedVec, Encode}; -use super::{ +use crate::{ AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId }; use primitives::{Blake2Hasher, storage::well_known_keys}; @@ -146,17 +147,17 @@ impl executive::ExecuteBlock for BlockExecutor { /// This doesn't attempt to validate anything regarding the block. pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { if check_signature(&utx).is_err() { - return TransactionValidity::Invalid(ApplyError::BadSignature as i8); + return InvalidTransactionValidity::BadProof.into(); } let tx = utx.transfer(); let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if tx.nonce < expected_nonce { - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransactionValidity::Stale.into(); } if tx.nonce > expected_nonce + 64 { - return TransactionValidity::Unknown(ApplyError::Future as i8); + return InvalidTransactionValidity::Future.into(); } let hash = |from: &AccountId, nonce: u64| { @@ -232,8 +233,7 @@ pub fn finalize_block() -> Header { #[inline(always)] fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { use sr_primitives::traits::BlindCheckable; - utx.clone().check().map_err(|_| ApplyError::BadSignature)?; - Ok(()) + utx.clone().check().map_err(|_| InvalidTransactionValidity::BadProof.into()).map(|_| ()) } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { @@ -251,7 +251,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if !(tx.nonce == expected_nonce) { - return Err(ApplyError::Stale) + return Err(InvalidTransactionValidity::Stale.into()) } // increment nonce in storage @@ -263,7 +263,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // enact transfer if !(tx.amount <= from_balance) { - return Err(ApplyError::CantPay) + return Err(InvalidTransactionValidity::Payment.into()) } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); @@ -292,7 +292,7 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { println!( "Hash: given={}, expected={}", HexDisplay::from(given.as_fixed_bytes()), - HexDisplay::from(expected.as_fixed_bytes()) + HexDisplay::from(expected.as_fixed_bytes()), ); } } @@ -300,9 +300,9 @@ fn info_expect_equal_hash(given: &Hash, expected: &Hash) { #[cfg(not(feature = "std"))] fn info_expect_equal_hash(given: &Hash, expected: &Hash) { if given != expected { - ::runtime_io::print("Hash not equal"); - ::runtime_io::print(given.as_bytes()); - ::runtime_io::print(expected.as_bytes()); + runtime_io::print("Hash not equal"); + runtime_io::print(given.as_bytes()); + runtime_io::print(expected.as_bytes()); } } diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 6eec0d222f1a3..ede5d7dc24a04 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -452,7 +452,7 @@ fn fire_events( #[cfg(test)] mod tests { use super::*; - use sr_primitives::transaction_validity::ValidTransaction; + use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransactionValidity}; use futures::Stream; use codec::Encode; use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; @@ -470,8 +470,11 @@ mod tests { type Error = error::Error; /// Verify extrinsic at given block. - fn validate_transaction(&self, at: &BlockId, uxt: ExtrinsicFor) -> Result { - + fn validate_transaction( + &self, + at: &BlockId, + uxt: ExtrinsicFor, + ) -> Result { let block_number = self.block_id_to_number(at)?.unwrap(); let nonce = uxt.transfer().nonce; @@ -486,7 +489,7 @@ mod tests { } if nonce < block_number { - Ok(TransactionValidity::Invalid(0)) + Ok(InvalidTransactionValidity::Stale.into()) } else { Ok(TransactionValidity::Valid(ValidTransaction { priority: 4, diff --git a/node-template/runtime/src/template.rs b/node-template/runtime/src/template.rs index c49024b598522..aa399a8edde9c 100644 --- a/node-template/runtime/src/template.rs +++ b/node-template/runtime/src/template.rs @@ -103,7 +103,6 @@ mod tests { type Header = Header; type WeightMultiplierUpdate = (); type Event = (); - type Error = Error; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type MaximumBlockLength = MaximumBlockLength; diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index c2e442fd580b1..f090d5048a5f2 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -44,11 +44,17 @@ mod tests { use keyring::{AccountKeyring, Ed25519Keyring, Sr25519Keyring}; use runtime_support::{Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities as CoreTestExternalities}; - use primitives::{ twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, NativeOrEncoded}; + use primitives::{ + twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, + NativeOrEncoded, + }; use node_primitives::{Hash, BlockNumber, AccountId, Balance, Index}; - use sr_primitives::traits::{Header as HeaderT, Hash as HashT, Convert}; - use sr_primitives::{generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; - use sr_primitives::weights::{WeightMultiplier, GetDispatchInfo}; + use sr_primitives::{ + traits::{Header as HeaderT, Hash as HashT, Convert}, + generic::Era, ApplyOutcome, ApplyResult, Perbill, + transaction_validity::InvalidTransactionValidity, + weights::{WeightMultiplier, GetDispatchInfo}, + }; use contracts::ContractAddressFor; use system::{EventRecord, Phase}; use node_runtime::{ @@ -205,7 +211,7 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); } #[test] @@ -241,7 +247,7 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); } #[test] @@ -893,7 +899,7 @@ mod tests { let r = WasmExecutor::new() .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Err(ApplyError::CantPay)); + assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); } #[test] diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index d5ae95c559539..8698ad9d41eaa 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -174,7 +174,7 @@ decl_module! { let origin = ensure_signed(origin)?; let origin_account = (id, origin.clone()); let origin_balance = >::get(&origin_account); - let target = T::Lookup::lookup(target)?; + let target = T::Lookup::lookup(target).ok_or("could not find `target` account")?; ensure!(!amount.is_zero(), "transfer amount should be non-zero"); ensure!(origin_balance >= amount, "origin account balance must be greater than or equal to the transfer amount"); diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 75a348e4a8689..961b27a5f9eb7 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -447,7 +447,7 @@ decl_module! { #[compact] value: T::Balance ) { let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; + let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; >::transfer(&transactor, &dest, value)?; } @@ -472,7 +472,7 @@ decl_module! { #[compact] new_reserved: T::Balance ) { ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).ok_or("could not find `who` account")?; let current_free = >::get(&who); if new_free > current_free { diff --git a/srml/collective/src/lib.rs b/srml/collective/src/lib.rs index 5aea34d7915f7..9dafa6721c8d2 100644 --- a/srml/collective/src/lib.rs +++ b/srml/collective/src/lib.rs @@ -302,7 +302,6 @@ impl< I, > EnsureOrigin for EnsureMember { type Success = AccountId; - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Member(id) => Ok(id), @@ -319,7 +318,6 @@ impl< I, > EnsureOrigin for EnsureMembers { type Success = (MemberCount, MemberCount); - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n >= N::VALUE => Ok((n, m)), @@ -339,7 +337,6 @@ impl< I, > EnsureOrigin for EnsureProportionMoreThan { type Success = (); - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE > N::VALUE * m => Ok(()), @@ -359,7 +356,6 @@ impl< I, > EnsureOrigin for EnsureProportionAtLeast { type Success = (); - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Members(n, m) if n * D::VALUE >= N::VALUE * m => Ok(()), diff --git a/srml/contracts/src/gas.rs b/srml/contracts/src/gas.rs index d069d996938ab..1fbb9f22be5a9 100644 --- a/srml/contracts/src/gas.rs +++ b/srml/contracts/src/gas.rs @@ -16,7 +16,6 @@ use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; use rstd::convert::TryFrom; -use sr_primitives::PrimitiveError; use sr_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto}; use srml_support::StorageValue; use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReason}; @@ -205,7 +204,7 @@ pub fn buy_gas( let gas_available = T::BlockGasLimit::get() - >::gas_spent(); if gas_limit > gas_available { // gas limit reached, revert the transaction and retry again in the future - return Err(PrimitiveError::BlockFull.into()); + return Err("gas block limit reached"); } // Buy the specified amount of gas. diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 9f9fae52922bf..75452625f7671 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -557,7 +557,7 @@ decl_module! { data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest)?; + let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { ctx.call(dest, value, gas_meter, data) diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index ee4fee7e004fa..d4cb8402137a7 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -209,11 +209,11 @@ pub trait Trait: system::Trait + Sized { /// Origin from which the next tabled referendum may be forced. This is a normal /// "super-majority-required" referendum. - type ExternalOrigin: EnsureOrigin; + type ExternalOrigin: EnsureOrigin; /// Origin from which the next tabled referendum may be forced; this allows for the tabling of /// a majority-carries referendum. - type ExternalMajorityOrigin: EnsureOrigin; + type ExternalMajorityOrigin: EnsureOrigin; /// Origin from which the next tabled referendum may be forced; this allows for the tabling of /// a negative-turnout-bias (default-carries) referendum. @@ -231,7 +231,7 @@ pub trait Trait: system::Trait + Sized { type CancellationOrigin: EnsureOrigin; /// Origin for anyone able to veto proposals. - type VetoOrigin: EnsureOrigin; + type VetoOrigin: EnsureOrigin; /// Period in blocks where an external proposal may not be re-submitted after being vetoed. type CooloffPeriod: Get; diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index 11a1704149cfc..d12d0f44d2a70 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -375,7 +375,7 @@ decl_module! { #[compact] assumed_vote_index: VoteIndex ) { let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).ok_or("Could not find `who` account")?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); @@ -514,10 +514,10 @@ decl_module! { let who = ensure_signed(origin)?; ensure!( !total.is_zero(), - "stake deposited to present winner and be added to leaderboard should be non-zero" + "stake deposited to present winner and be added to leaderboard should be non-zero", ); - let candidate = T::Lookup::lookup(candidate)?; + let candidate = T::Lookup::lookup(candidate).ok_or("could not find `candidate` account")?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; let bad_presentation_punishment = @@ -586,7 +586,7 @@ decl_module! { #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn remove_member(origin, who: ::Source) { ensure_root(origin)?; - let who = T::Lookup::lookup(who)?; + let who = T::Lookup::lookup(who).ok_or("could not find `who` account")?; let new_set: Vec<(T::AccountId, T::BlockNumber)> = Self::members() .into_iter() .filter(|i| i.0 != who) diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 9f5669f5d2652..50ec42f48dfa5 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -538,7 +538,7 @@ mod tests { ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { - assert_eq!(res, Err(ApplyError::Exhausted)); + assert_eq!(res, Err(InvalidTransactionValidity::ExhaustResources.into())); } } }); diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index eff811d6cacf3..02364cc4ac330 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -70,8 +70,10 @@ use primitives::offchain::{OpaqueNetworkState, StorageKind}; use codec::{Encode, Decode}; use sr_primitives::{ - ApplyError, traits::{Extrinsic as ExtrinsicT}, - transaction_validity::{TransactionValidity, TransactionLongevity, ValidTransaction}, + traits::Extrinsic as ExtrinsicT, + transaction_validity::{ + TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransactionValidity, + }, }; use rstd::prelude::*; use session::SessionIndex; @@ -127,7 +129,7 @@ enum OffchainErr { } impl Printable for OffchainErr { - fn print(self) { + fn print(&self) { match self { OffchainErr::DecodeWorkerStatus => print("Offchain error: decoding WorkerStatus failed!"), OffchainErr::ExtrinsicCreation => print("Offchain error: extrinsic creation failed!"), @@ -381,24 +383,24 @@ impl session::OneSessionHandler for Module { impl srml_support::unsigned::ValidateUnsigned for Module { type Call = Call; - fn validate_unsigned(call: &Self::Call) -> srml_support::unsigned::TransactionValidity { + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { if let Call::heartbeat(heartbeat, signature) = call { if >::is_online_in_current_session(heartbeat.authority_index) { // we already received a heartbeat for this authority - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransactionValidity::Stale.into(); } // check if session index from heartbeat is recent let current_session = >::current_index(); if heartbeat.session_index != current_session { - return TransactionValidity::Invalid(ApplyError::Stale as i8); + return InvalidTransactionValidity::Stale.into(); } // verify that the incoming (unverified) pubkey is actually an authority id let keys = Keys::get(); let authority_id = match keys.get(heartbeat.authority_index as usize) { Some(id) => id, - None => return TransactionValidity::Invalid(ApplyError::BadSignature as i8), + None => return InvalidTransactionValidity::BadProof.into(), }; // check signature (this is expensive so we do it last). @@ -407,7 +409,7 @@ impl srml_support::unsigned::ValidateUnsigned for Module { }); if !signature_valid { - return TransactionValidity::Invalid(ApplyError::BadSignature as i8); + return InvalidTransactionValidity::BadProof.into(); } return TransactionValidity::Valid(ValidTransaction { @@ -419,6 +421,6 @@ impl srml_support::unsigned::ValidateUnsigned for Module { }) } - TransactionValidity::Invalid(0) + InvalidTransactionValidity::Call.into() } } diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs index 8d4dda5abe87c..dfc06b1a4db26 100644 --- a/srml/indices/src/lib.rs +++ b/srml/indices/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use rstd::{prelude::*, result, marker::PhantomData, convert::TryInto}; +use rstd::{prelude::*, marker::PhantomData, convert::TryInto}; use codec::{Encode, Codec}; use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage}; use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member}; @@ -224,11 +224,11 @@ impl OnNewAccount for Module { impl StaticLookup for Module { type Source = address::Address; type Target = T::AccountId; - type Error = &'static str; - fn lookup(a: Self::Source) -> result::Result { - Self::lookup_address(a).ok_or("invalid account index") + fn lookup(a: Self::Source) -> Option { + Self::lookup_address(a) } + fn unlookup(a: Self::Target) -> Self::Source { address::Address::Id(a) } diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 3a39689646b2c..771f6540736bc 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -740,7 +740,8 @@ decl_module! { return Err("stash already bonded") } - let controller = T::Lookup::lookup(controller)?; + let controller = T::Lookup::lookup(controller) + .ok_or("could not find `controller` account")?; if >::exists(&controller) { return Err("controller already paired") @@ -922,9 +923,8 @@ decl_module! { ensure!(!targets.is_empty(), "targets cannot be empty"); let targets = targets.into_iter() .take(MAX_NOMINATIONS) - .map(T::Lookup::lookup) - .collect::, _>>() - ?; + .map(|t| T::Lookup::lookup(t).ok_or("could not find a target account")) + .collect::, _>>()?; >::remove(stash); >::insert(stash, targets); @@ -984,7 +984,7 @@ decl_module! { fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or("not a stash")?; - let controller = T::Lookup::lookup(controller)?; + let controller = T::Lookup::lookup(controller).ok_or("could not find `controller` account")?; if >::exists(&controller) { return Err("controller already paired") } diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index 60c112b79e053..4d3c5cff74f8a 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -146,7 +146,7 @@ decl_module! { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; ensure!(sender == Self::key(), "only the current sudo key can change the sudo key"); - let new = T::Lookup::lookup(new)?; + let new = T::Lookup::lookup(new).ok_or("could not find requested account")?; Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 3624b42050b84..e2394c8e2546d 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -132,7 +132,7 @@ macro_rules! fail { /// Used as `ensure!(expression_to_ensure, expression_to_return_on_false)`. #[macro_export] macro_rules! ensure { - ( $x:expr, $y:expr ) => {{ + ( $x:expr, $y:expr $(,)? ) => {{ if !$x { $crate::fail!($y); } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index d1f4b3c048abd..9fd7665b9cb41 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -186,8 +186,7 @@ pub trait Trait: 'static + Eq + Clone { /// Used to define the type and conversion mechanism for referencing accounts in transactions. It's perfectly /// reasonable for this to be an identity conversion (with the source type being `AccountId`), but other modules /// (e.g. Indices module) may provide more functional/efficient alternatives. - // TODO: avoid &'static str error type #2953 - type Lookup: StaticLookup; + type Lookup: StaticLookup; /// Handler for updating the weight multiplier at the end of each block. /// @@ -451,7 +450,6 @@ impl< AccountId, > EnsureOrigin for EnsureRoot { type Success = (); - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Root => Ok(()), @@ -466,7 +464,6 @@ impl< AccountId, > EnsureOrigin for EnsureSigned { type Success = AccountId; - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(who) => Ok(who), @@ -482,7 +479,6 @@ impl< AccountId: PartialEq + Clone, > EnsureOrigin for EnsureSignedBy { type Success = AccountId; - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::Signed(ref who) if Who::contains(who) => Ok(who.clone()), @@ -497,7 +493,6 @@ impl< AccountId, > EnsureOrigin for EnsureNone { type Success = (); - type Error = &'static str; fn try_origin(o: O) -> Result { o.into().and_then(|o| match o { RawOrigin::None => Ok(()), @@ -509,7 +504,6 @@ impl< pub struct EnsureNever(::rstd::marker::PhantomData); impl EnsureOrigin for EnsureNever { type Success = T; - type Error = &'static str; fn try_origin(o: O) -> Result { Err(o) } @@ -859,31 +853,33 @@ impl CheckWeight { /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. - fn check_weight(info: DispatchInfo) -> Result { + fn check_weight(info: DispatchInfo) -> Result { let current_weight = Module::::all_extrinsics_weight(); let maximum_weight = T::MaximumBlockWeight::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_weight; let added_weight = info.weight.min(limit); let next_weight = current_weight.saturating_add(added_weight); if next_weight > limit { - return Err(ApplyError::Exhausted) + Err(InvalidTransactionValidity::ExhaustResources.into()) + } else { + Ok(next_weight) } - Ok(next_weight) } /// Checks if the current extrinsic can fit into the block with respect to block length limits. /// /// Upon successes, it returns the new block length as a `Result`. - fn check_block_length(info: DispatchInfo, len: usize) -> Result { + fn check_block_length(info: DispatchInfo, len: usize) -> Result { let current_len = Module::::all_extrinsics_len(); let maximum_len = T::MaximumBlockLength::get(); let limit = Self::get_dispatch_limit_ratio(info.class) * maximum_len; let added_len = len as u32; let next_len = current_len.saturating_add(added_len); if next_len > limit { - return Err(ApplyError::Exhausted) + Err(InvalidTransactionValidity::ExhaustResources.into()) + } else { + Ok(next_len) } - Ok(next_len) } /// get the priority of an extrinsic denoted by `info`. @@ -933,8 +929,12 @@ impl SignedExtension for CheckWeight { // There is no point in writing to storage here since changes are discarded. This basically // discards any transaction which is bigger than the length or weight limit **alone**, which // is a guarantee that it will fail in the pre-dispatch phase. - if Self::check_block_length(info, len).is_err() || Self::check_weight(info).is_err() { - return InvalidTransactionValidity::ExhaustResources.into(); + if let Err(e) = Self::check_block_length(info, len) { + return e.into(); + } + + if let Err(e) = Self::check_weight(info) { + return e.into(); } ValidTransaction { priority: Self::get_priority(info), ..Default::default() }.into() @@ -1102,8 +1102,8 @@ impl Default for ChainContext { impl Lookup for ChainContext { type Source = ::Source; type Target = ::Target; - type Error = ::Error; - fn lookup(&self, s: Self::Source) -> rstd::result::Result { + + fn lookup(&self, s: Self::Source) -> Option { ::lookup(s) } } diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index 25cb9ebda9d8b..9fcd67552e696 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -99,10 +99,10 @@ pub trait Trait: system::Trait { type Currency: Currency + ReservableCurrency; /// Origin from which approvals must come. - type ApproveOrigin: EnsureOrigin; + type ApproveOrigin: EnsureOrigin; /// Origin from which rejections must come. - type RejectOrigin: EnsureOrigin; + type RejectOrigin: EnsureOrigin; /// The overarching event type. type Event: From> + Into<::Event>; @@ -161,7 +161,7 @@ decl_module! { beneficiary: ::Source ) { let proposer = ensure_signed(origin)?; - let beneficiary = T::Lookup::lookup(beneficiary)?; + let beneficiary = T::Lookup::lookup(beneficiary).ok_or("could not find `beneficiary`")?; let bond = Self::calculate_bond(value); T::Currency::reserve(&proposer, bond) From 89a04a56c396aa123f4d3bfed047c0b3de4c5475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 18 Aug 2019 18:06:25 +0200 Subject: [PATCH 51/80] Fix build --- srml/im-online/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index d4abf69bb27d5..7871a9d630852 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -74,7 +74,7 @@ use rstd::prelude::*; use session::historical::IdentificationTuple; use sr_io::Printable; use sr_primitives::{ - traits::Extrinsic as ExtrinsicT, Perbill, + traits::{Extrinsic as ExtrinsicT, Convert}, Perbill, transaction_validity::{ TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransactionValidity, }, From 86ce38bca21f9a9fcc30b9bed98798d13eb10cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Sun, 18 Aug 2019 18:30:03 +0200 Subject: [PATCH 52/80] Fix build --- srml/system/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 9d6dab75c11e3..33c5869b01329 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1122,7 +1122,7 @@ impl SignedExtension for CheckVersion { type AdditionalSigned = u32; type Pre = (); - fn additional_signed(&self) -> Result { + fn additional_signed(&self) -> Result { Ok(>::runtime_version().spec_version) } } From 41a176a4907c01f203883f6c433b5db8aba04a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 26 Aug 2019 11:08:59 +0200 Subject: [PATCH 53/80] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tomasz Drwięga --- core/sr-primitives/src/transaction_validity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 040367eec8c7a..3f2fd646c713e 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -46,7 +46,7 @@ pub enum InvalidTransactionValidity { /// The transaction birth block is ancient. AncientBirthBlock, /// The transaction **alone** would exhaust the resources of a block. - ExhaustResources, + ExhaustsResources, /// Any other custom invalid validity that is not covered by this enum. Custom(u8), } From a644a6ec7ee6bc479b5894e239f1ccd9f044e42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 26 Aug 2019 13:29:02 +0200 Subject: [PATCH 54/80] Rename some stuff --- core/basic-authorship/src/basic_authorship.rs | 2 +- core/rpc/src/author/error.rs | 2 +- .../src/generic/unchecked_extrinsic.rs | 8 +-- core/sr-primitives/src/lib.rs | 4 +- .../sr-primitives/src/transaction_validity.rs | 68 +++++++++---------- core/test-runtime/src/lib.rs | 6 +- core/test-runtime/src/system.rs | 14 ++-- core/transaction-pool/graph/src/error.rs | 6 +- core/transaction-pool/graph/src/pool.rs | 6 +- node/executor/src/lib.rs | 8 +-- srml/balances/src/lib.rs | 6 +- srml/executive/src/lib.rs | 12 ++-- srml/im-online/src/lib.rs | 12 ++-- srml/support/src/unsigned.rs | 4 +- srml/system/src/lib.rs | 16 ++--- 15 files changed, 87 insertions(+), 87 deletions(-) diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index 4b7179a55c959..d90d0d728233f 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -171,7 +171,7 @@ impl Proposer, A> wh Ok(()) => { debug!("[{:?}] Pushed to the block.", pending.hash); } - Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhaust_resources() => { + Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausts_resources() => { if is_first { debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); unqueue_invalid.push(pending.hash.clone()); diff --git a/core/rpc/src/author/error.rs b/core/rpc/src/author/error.rs index 15cd615e827dc..5faca1fecd959 100644 --- a/core/rpc/src/author/error.rs +++ b/core/rpc/src/author/error.rs @@ -104,7 +104,7 @@ impl From for rpc::Error { message: "Invalid Transaction".into(), data: serde_json::to_value(e).ok(), }, - Error::Pool(PoolError::UnknownTransactionValidity(e)) => rpc::Error { + Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error { code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), message: "Unknown Transaction Validity".into(), data: serde_json::to_value(e).ok(), diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 38a688929846e..721d2df92a53a 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -26,7 +26,7 @@ use crate::{ traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}, generic::CheckedExtrinsic, transaction_validity::{ - TransactionValidityError, InvalidTransactionValidity, UnknownTransactionValidity, + TransactionValidityError, InvalidTransaction, UnknownTransaction, }, }; @@ -105,7 +105,7 @@ where Some((signed, signature, extra)) => { let additional_signed = extra.additional_signed()?; let raw_payload = (self.function, extra, additional_signed); - let signed = lookup.lookup(signed).ok_or(UnknownTransactionValidity::InvalidIndex)?; + let signed = lookup.lookup(signed).ok_or(UnknownTransaction::InvalidIndex)?; if !raw_payload.using_encoded(|payload| { if payload.len() > 256 { signature.verify(&blake2_256(payload)[..], &signed) @@ -113,7 +113,7 @@ where signature.verify(payload, &signed) } }) { - return Err(InvalidTransactionValidity::BadProof.into()) + return Err(InvalidTransaction::BadProof.into()) } CheckedExtrinsic { signed: Some((signed, raw_payload.1)), @@ -299,7 +299,7 @@ mod tests { assert!(ux.is_signed().unwrap_or(false)); assert_eq!( >::check(ux, &Default::default()), - Err(InvalidTransactionValidity::BadProof.into()), + Err(InvalidTransaction::BadProof.into()), ); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 4e69a7c45e719..7db75623c39be 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -639,9 +639,9 @@ pub enum ApplyError { impl ApplyError { /// Returns if the reason for the error was block resource exhaustion. - pub fn exhaust_resources(&self) -> bool { + pub fn exhausts_resources(&self) -> bool { match self { - Self::Validity(e) => e.exhaust_resources(), + Self::Validity(e) => e.exhausts_resources(), _ => false, } } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 3f2fd646c713e..c897a203dcc5a 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -32,7 +32,7 @@ pub type TransactionTag = Vec; /// An invalid transaction validity. #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] -pub enum InvalidTransactionValidity { +pub enum InvalidTransaction { /// The call of the transaction is not expected. Call, /// General error to do with the inability to pay some fees (e.g. account balance too low). @@ -51,29 +51,29 @@ pub enum InvalidTransactionValidity { Custom(u8), } -impl InvalidTransactionValidity { +impl InvalidTransaction { /// Returns if the reason for the invalidity was block resource exhaustion. - pub fn exhaust_resources(&self) -> bool { + pub fn exhausts_resources(&self) -> bool { match self { - Self::ExhaustResources => true, + Self::ExhaustsResources => true, _ => false, } } } -impl Into<&'static str> for InvalidTransactionValidity { +impl Into<&'static str> for InvalidTransaction { fn into(self) -> &'static str { match self { - InvalidTransactionValidity::Call => "Transaction call is not expected", - InvalidTransactionValidity::Future => "Transaction will be valid in the future", - InvalidTransactionValidity::Stale => "Transaction is outdated", - InvalidTransactionValidity::BadProof => "Transaction has a bad signature", - InvalidTransactionValidity::AncientBirthBlock => "Transaction has an ancient birth block", - InvalidTransactionValidity::ExhaustResources => + InvalidTransaction::Call => "Transaction call is not expected", + InvalidTransaction::Future => "Transaction will be valid in the future", + InvalidTransaction::Stale => "Transaction is outdated", + InvalidTransaction::BadProof => "Transaction has a bad signature", + InvalidTransaction::AncientBirthBlock => "Transaction has an ancient birth block", + InvalidTransaction::ExhaustsResources => "Transaction would exhausts the block limits", - InvalidTransactionValidity::Payment => + InvalidTransaction::Payment => "Inability to pay some fees (e.g. account balance too low)", - InvalidTransactionValidity::Custom(_) => "InvalidTransactionValidity custom error", + InvalidTransaction::Custom(_) => "InvalidTransaction custom error", } } } @@ -81,7 +81,7 @@ impl Into<&'static str> for InvalidTransactionValidity { /// An unknown transaction validity. #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] -pub enum UnknownTransactionValidity { +pub enum UnknownTransaction { /// An invalid/unknown account index InvalidIndex, /// No validator found for the given unsigned transaction. @@ -90,14 +90,14 @@ pub enum UnknownTransactionValidity { Custom(u8), } -impl Into<&'static str> for UnknownTransactionValidity { +impl Into<&'static str> for UnknownTransaction { fn into(self) -> &'static str { match self { - UnknownTransactionValidity::InvalidIndex => + UnknownTransaction::InvalidIndex => "Transaction used an invalid/unknown account index", - UnknownTransactionValidity::NoUnsignedValidator => + UnknownTransaction::NoUnsignedValidator => "Could not find an unsigned validator for the unsigned transaction", - UnknownTransactionValidity::Custom(_) => "UnknownTransactionValidity custom error", + UnknownTransaction::Custom(_) => "UnknownTransaction custom error", } } } @@ -107,16 +107,16 @@ impl Into<&'static str> for UnknownTransactionValidity { #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum TransactionValidityError { /// The transaction is invalid. - Invalid(InvalidTransactionValidity), + Invalid(InvalidTransaction), /// Transaction validity can't be determined. - Unknown(UnknownTransactionValidity), + Unknown(UnknownTransaction), } impl TransactionValidityError { /// Returns if the reason for the error was block resource exhaustion. - pub fn exhaust_resources(&self) -> bool { + pub fn exhausts_resources(&self) -> bool { match self { - Self::Invalid(e) => e.exhaust_resources(), + Self::Invalid(e) => e.exhausts_resources(), Self::Unknown(_) => false, } } @@ -131,25 +131,25 @@ impl Into<&'static str> for TransactionValidityError { } } -impl From for TransactionValidityError { - fn from(err: InvalidTransactionValidity) -> Self { +impl From for TransactionValidityError { + fn from(err: InvalidTransaction) -> Self { TransactionValidityError::Invalid(err) } } -impl From for TransactionValidityError { - fn from(err: UnknownTransactionValidity) -> Self { +impl From for TransactionValidityError { + fn from(err: UnknownTransaction) -> Self { TransactionValidityError::Unknown(err) } } -impl Into for InvalidTransactionValidity { +impl Into for InvalidTransaction { fn into(self) -> crate::ApplyError { TransactionValidityError::from(self).into() } } -impl Into for UnknownTransactionValidity { +impl Into for UnknownTransaction { fn into(self) -> crate::ApplyError { TransactionValidityError::from(self).into() } @@ -160,11 +160,11 @@ impl Into for UnknownTransactionValidity { #[cfg_attr(feature = "std", derive(Debug))] pub enum TransactionValidity { /// Transaction is invalid. - Invalid(InvalidTransactionValidity), + Invalid(InvalidTransaction), /// Transaction is valid. Valid(ValidTransaction), /// Transaction validity can't be determined. - Unknown(UnknownTransactionValidity), + Unknown(UnknownTransaction), } impl Into for TransactionValidityError { @@ -176,13 +176,13 @@ impl Into for TransactionValidityError { } } -impl Into for InvalidTransactionValidity { +impl Into for InvalidTransaction { fn into(self) -> TransactionValidity { TransactionValidity::Invalid(self) } } -impl Into for UnknownTransactionValidity { +impl Into for UnknownTransaction { fn into(self) -> TransactionValidity { TransactionValidity::Unknown(self) } @@ -249,7 +249,7 @@ impl TransactionValidity { impl Decode for TransactionValidity { fn decode(value: &mut I) -> Result { match value.read_byte()? { - 0 => Ok(TransactionValidity::Invalid(InvalidTransactionValidity::decode(value)?)), + 0 => Ok(TransactionValidity::Invalid(InvalidTransaction::decode(value)?)), 1 => { let priority = TransactionPriority::decode(value)?; let requires = Vec::decode(value)?; @@ -261,7 +261,7 @@ impl Decode for TransactionValidity { priority, requires, provides, longevity, propagate, })) }, - 2 => Ok(TransactionValidity::Unknown(UnknownTransactionValidity::decode(value)?)), + 2 => Ok(TransactionValidity::Unknown(UnknownTransaction::decode(value)?)), _ => Err("Invalid transaction validity variant".into()), } } diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 99c83a8bfc778..e6557b1556581 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -39,7 +39,7 @@ use substrate_client::{ use sr_primitives::{ ApplyResult, create_runtime_str, Perbill, impl_opaque_keys, transaction_validity::{ - TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransactionValidity, + TransactionValidity, ValidTransaction, TransactionValidityError, InvalidTransaction, }, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, @@ -132,10 +132,10 @@ impl BlindCheckable for Extrinsic { if sr_primitives::verify_encoded_lazy(&signature, &transfer, &transfer.from) { Ok(Extrinsic::Transfer(transfer, signature)) } else { - Err(InvalidTransactionValidity::BadProof.into()) + Err(InvalidTransaction::BadProof.into()) } }, - Extrinsic::IncludeData(_) => Err(InvalidTransactionValidity::BadProof.into()), + Extrinsic::IncludeData(_) => Err(InvalidTransaction::BadProof.into()), Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)), } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 6dd48205c7edd..6ed4c548c9b07 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -24,7 +24,7 @@ use runtime_support::storage_items; use sr_primitives::{ traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyOutcome, ApplyResult, - transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransactionValidity}, + transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransaction}, }; use codec::{KeyedVec, Encode}; use crate::{ @@ -147,17 +147,17 @@ impl executive::ExecuteBlock for BlockExecutor { /// This doesn't attempt to validate anything regarding the block. pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { if check_signature(&utx).is_err() { - return InvalidTransactionValidity::BadProof.into(); + return InvalidTransaction::BadProof.into(); } let tx = utx.transfer(); let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if tx.nonce < expected_nonce { - return InvalidTransactionValidity::Stale.into(); + return InvalidTransaction::Stale.into(); } if tx.nonce > expected_nonce + 64 { - return InvalidTransactionValidity::Future.into(); + return InvalidTransaction::Future.into(); } let hash = |from: &AccountId, nonce: u64| { @@ -233,7 +233,7 @@ pub fn finalize_block() -> Header { #[inline(always)] fn check_signature(utx: &Extrinsic) -> Result<(), ApplyError> { use sr_primitives::traits::BlindCheckable; - utx.clone().check().map_err(|_| InvalidTransactionValidity::BadProof.into()).map(|_| ()) + utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ()) } fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { @@ -251,7 +251,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let nonce_key = tx.from.to_keyed_vec(NONCE_OF); let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0); if !(tx.nonce == expected_nonce) { - return Err(InvalidTransactionValidity::Stale.into()) + return Err(InvalidTransaction::Stale.into()); } // increment nonce in storage @@ -263,7 +263,7 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { // enact transfer if !(tx.amount <= from_balance) { - return Err(InvalidTransactionValidity::Payment.into()) + return Err(InvalidTransaction::Payment.into()); } let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF); let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index 60dd76067aa29..a837fd6c2f86e 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -17,7 +17,7 @@ //! Transaction pool errors. use sr_primitives::transaction_validity::{ - TransactionPriority as Priority, InvalidTransactionValidity, UnknownTransactionValidity, + TransactionPriority as Priority, InvalidTransaction, UnknownTransaction, }; /// Transaction pool result. @@ -28,10 +28,10 @@ pub type Result = std::result::Result; pub enum Error { /// Transaction is not verifiable yet, but might be in the future. #[display(fmt="Unkown transaction validity: {:?}", _0)] - UnknownTransactionValidity(UnknownTransactionValidity), + UnknownTransaction(UnknownTransaction), /// Transaction is invalid. #[display(fmt="Invalid transaction validity: {:?}", _0)] - InvalidTransaction(InvalidTransactionValidity), + InvalidTransaction(InvalidTransaction), /// The transaction validity returned no "provides" tag. /// /// Such transactions are not accepted to the pool, since we use those tags diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 746060062aad5..83c9311089ee2 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -151,7 +151,7 @@ impl Pool { }, TransactionValidity::Unknown(e) => { self.listener.write().invalid(&hash); - Err(error::Error::UnknownTransactionValidity(e).into()) + Err(error::Error::UnknownTransaction(e).into()) }, } }) @@ -454,7 +454,7 @@ fn fire_events( #[cfg(test)] mod tests { use super::*; - use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransactionValidity}; + use sr_primitives::transaction_validity::{ValidTransaction, InvalidTransaction}; use codec::Encode; use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; use assert_matches::assert_matches; @@ -492,7 +492,7 @@ mod tests { } if nonce < block_number { - Ok(InvalidTransactionValidity::Stale.into()) + Ok(InvalidTransaction::Stale.into()) } else { Ok(TransactionValidity::Valid(ValidTransaction { priority: 4, diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index d9a29d2abd536..966e5942d666d 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -52,7 +52,7 @@ mod tests { use sr_primitives::{ traits::{Header as HeaderT, Hash as HashT, Convert}, generic::Era, ApplyOutcome, ApplyResult, Perbill, - transaction_validity::InvalidTransactionValidity, + transaction_validity::InvalidTransaction, weights::{WeightMultiplier, GetDispatchInfo}, }; use contracts::ContractAddressFor; @@ -211,7 +211,7 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] @@ -247,7 +247,7 @@ mod tests { None, ).0.unwrap(); let r = ApplyResult::decode(&mut &v.as_encoded()[..]).unwrap(); - assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] @@ -898,7 +898,7 @@ mod tests { let r = WasmExecutor::new() .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Err(InvalidTransactionValidity::Payment.into())); + assert_eq!(r, Err(InvalidTransaction::Payment.into())); } #[test] diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 19a44e62257b5..f83182261f4d6 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -161,8 +161,8 @@ use srml_support::traits::{ use srml_support::dispatch::Result; use sr_primitives::{ transaction_validity::{ - TransactionPriority, ValidTransaction, InvalidTransactionValidity, TransactionValidity, - TransactionValidityError, + TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, + TransactionValidity, }, traits::{ Zero, SimpleArithmetic, StaticLookup, Member, CheckedAdd, CheckedSub, MaybeSerializeDebug, @@ -1241,7 +1241,7 @@ impl, I: Instance + Clone + Eq> SignedExtension for TakeFees { ExistenceRequirement::KeepAlive, ) { Ok(imbalance) => imbalance, - Err(_) => return InvalidTransactionValidity::Payment.into(), + Err(_) => return InvalidTransaction::Payment.into(), }; T::TransactionPayment::on_unbalanced(imbalance); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 2fb4562c78405..61a1b5258f5a5 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -59,13 +59,13 @@ //! # pub type Balances = u64; //! # pub type AllModules = u64; //! # pub enum Runtime {}; -//! # use sr_primitives::transaction_validity::{TransactionValidity, UnknownTransactionValidity}; +//! # use sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; //! # use sr_primitives::traits::ValidateUnsigned; //! # impl ValidateUnsigned for Runtime { //! # type Call = (); //! # //! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { -//! # UnknownTransactionValidity::NoUnsignedValidator.into() +//! # UnknownTransaction::NoUnsignedValidator.into() //! # } //! # } //! /// Executive: handles dispatch to the various modules. @@ -303,7 +303,7 @@ mod tests { use sr_primitives::{ generic::Era, Perbill, DispatchError, weights::Weight, testing::{Digest, Header, Block}, traits::{Header as HeaderT, BlakeTwo256, IdentityLookup, ConvertInto}, - transaction_validity::{UnknownTransactionValidity, InvalidTransactionValidity}, ApplyError, + transaction_validity::{InvalidTransaction, UnknownTransaction}, ApplyError, }; use srml_support::{ impl_outer_event, impl_outer_origin, parameter_types, @@ -378,7 +378,7 @@ mod tests { fn validate_unsigned(call: &Self::Call) -> TransactionValidity { match call { Call::set_balance(_, _, _) => TransactionValidity::Valid(Default::default()), - _ => UnknownTransactionValidity::NoUnsignedValidator.into(), + _ => UnknownTransaction::NoUnsignedValidator.into(), } } } @@ -539,7 +539,7 @@ mod tests { ); assert_eq!(>::extrinsic_index(), Some(nonce as u32 + 1)); } else { - assert_eq!(res, Err(InvalidTransactionValidity::ExhaustResources.into())); + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); } } }); @@ -627,7 +627,7 @@ mod tests { } else { assert_eq!( Executive::apply_extrinsic(xt), - Err(ApplyError::Validity(InvalidTransactionValidity::Payment.into())), + Err(ApplyError::Validity(InvalidTransaction::Payment.into())), ); assert_eq!(>::total_balance(&1), 111); } diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 7871a9d630852..511dfc1528439 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -76,7 +76,7 @@ use sr_io::Printable; use sr_primitives::{ traits::{Extrinsic as ExtrinsicT, Convert}, Perbill, transaction_validity::{ - TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransactionValidity, + TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransaction, }, }; use sr_staking_primitives::{ @@ -472,20 +472,20 @@ impl srml_support::unsigned::ValidateUnsigned for Module { if let Call::heartbeat(heartbeat, signature) = call { if >::is_online_in_current_session(heartbeat.authority_index) { // we already received a heartbeat for this authority - return InvalidTransactionValidity::Stale.into(); + return InvalidTransaction::Stale.into(); } // check if session index from heartbeat is recent let current_session = >::current_index(); if heartbeat.session_index != current_session { - return InvalidTransactionValidity::Stale.into(); + return InvalidTransaction::Stale.into(); } // verify that the incoming (unverified) pubkey is actually an authority id let keys = Keys::get(); let authority_id = match keys.get(heartbeat.authority_index as usize) { Some(id) => id, - None => return InvalidTransactionValidity::BadProof.into(), + None => return InvalidTransaction::BadProof.into(), }; // check signature (this is expensive so we do it last). @@ -494,7 +494,7 @@ impl srml_support::unsigned::ValidateUnsigned for Module { }); if !signature_valid { - return InvalidTransactionValidity::BadProof.into(); + return InvalidTransaction::BadProof.into(); } return TransactionValidity::Valid(ValidTransaction { @@ -506,7 +506,7 @@ impl srml_support::unsigned::ValidateUnsigned for Module { }) } - InvalidTransactionValidity::Call.into() + InvalidTransaction::Call.into() } } diff --git a/srml/support/src/unsigned.rs b/srml/support/src/unsigned.rs index abe366993621c..4d2ceddd79f4a 100644 --- a/srml/support/src/unsigned.rs +++ b/srml/support/src/unsigned.rs @@ -17,7 +17,7 @@ #[doc(hidden)] pub use crate::sr_primitives::traits::ValidateUnsigned; #[doc(hidden)] -pub use crate::sr_primitives::transaction_validity::{TransactionValidity, UnknownTransactionValidity}; +pub use crate::sr_primitives::transaction_validity::{TransactionValidity, UnknownTransaction}; #[doc(hidden)] pub use crate::sr_primitives::ApplyError; @@ -72,7 +72,7 @@ macro_rules! impl_outer_validate_unsigned { #[allow(unreachable_patterns)] match call { $( Call::$module(inner_call) => $module::validate_unsigned(inner_call), )* - _ => $crate::unsigned::UnknownTransactionValidity::NoUnsignedValidator.into(), + _ => $crate::unsigned::UnknownTransaction::NoUnsignedValidator.into(), } } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 33c5869b01329..ae7abe5aaac0a 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -84,7 +84,7 @@ use sr_primitives::{ weights::{Weight, DispatchInfo, DispatchClass, WeightMultiplier, SimpleDispatchInfo}, transaction_validity::{ ValidTransaction, TransactionPriority, TransactionLongevity, TransactionValidityError, - InvalidTransactionValidity, TransactionValidity, + InvalidTransaction, TransactionValidity, }, traits::{ self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, Lookup, @@ -866,7 +866,7 @@ impl CheckWeight { let added_weight = info.weight.min(limit); let next_weight = current_weight.saturating_add(added_weight); if next_weight > limit { - Err(InvalidTransactionValidity::ExhaustResources.into()) + Err(InvalidTransaction::ExhaustsResources.into()) } else { Ok(next_weight) } @@ -882,7 +882,7 @@ impl CheckWeight { let added_len = len as u32; let next_len = current_len.saturating_add(added_len); if next_len > limit { - Err(InvalidTransactionValidity::ExhaustResources.into()) + Err(InvalidTransaction::ExhaustsResources.into()) } else { Ok(next_len) } @@ -992,9 +992,9 @@ impl SignedExtension for CheckNonce { if self.0 != expected { return Err( if self.0 < expected { - InvalidTransactionValidity::Stale + InvalidTransaction::Stale } else { - InvalidTransactionValidity::Future + InvalidTransaction::Future }.into() ) } @@ -1013,7 +1013,7 @@ impl SignedExtension for CheckNonce { // check index let expected = >::get(who); if self.0 < expected { - return InvalidTransactionValidity::Stale.into() + return InvalidTransaction::Stale.into() } let provides = vec![Encode::encode(&(who, self.0))]; @@ -1062,7 +1062,7 @@ impl SignedExtension for CheckEra { let current_u64 = >::block_number().saturated_into::(); let n = (self.0).0.birth(current_u64).saturated_into::(); if !>::exists(n) { - Err(InvalidTransactionValidity::AncientBirthBlock.into()) + Err(InvalidTransaction::AncientBirthBlock.into()) } else { Ok(>::block_hash(n)) } @@ -1497,7 +1497,7 @@ mod tests { // future assert_eq!( CheckEra::::from(Era::mortal(4, 2)).additional_signed().err().unwrap(), - InvalidTransactionValidity::AncientBirthBlock.into(), + InvalidTransaction::AncientBirthBlock.into(), ); // correct From 80a07b03f1a5f1d068a4191cc2cbb2be6e0ebfd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 26 Aug 2019 16:21:03 +0200 Subject: [PATCH 55/80] Fixes after master merge --- core/client/src/client.rs | 2 ++ node/executor/src/lib.rs | 15 +++++---------- srml/balances/src/lib.rs | 4 ++-- srml/example/src/lib.rs | 28 +++++++++++++++++----------- srml/scored-pool/src/lib.rs | 4 ++-- 5 files changed, 28 insertions(+), 25 deletions(-) diff --git a/core/client/src/client.rs b/core/client/src/client.rs index c6234dc8d1cca..e0fd141224f02 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1491,6 +1491,8 @@ impl CallRuntimeAt for Client where _ => None, }; + self. + self.executor.contextual_call::<_, _, fn(_,_) -> _,_,_>( || core_api.initialize_block(at, &self.prepare_environment_block(at)?), at, diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 83ea155aa795d..617d2c15c4fc1 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -44,23 +44,18 @@ mod tests { use runtime_support::{Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities as CoreTestExternalities}; use primitives::{ - twox_128, blake2_256, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, - NativeOrEncoded, + twox_128, blake2_256, Blake2Hasher, NeverNativeValue, NativeOrEncoded, map }; - use node_primitives::{Hash, BlockNumber, AccountId, Balance, Index}; + use node_primitives::{Hash, BlockNumber, Balance}; use sr_primitives::{ - traits::{Header as HeaderT, Hash as HashT, Convert}, - generic::Era, ApplyOutcome, ApplyResult, Perbill, - transaction_validity::InvalidTransaction, - weights::{WeightMultiplier, GetDispatchInfo}, + traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyOutcome, ApplyResult, + transaction_validity::InvalidTransaction, weights::{WeightMultiplier, GetDispatchInfo}, }; use contracts::ContractAddressFor; use system::{EventRecord, Phase}; - use node_primitives::{Hash, BlockNumber, Balance}; use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, - System, Event, - TransferFee, TransactionBaseFee, TransactionByteFee, + System, Event, TransferFee, TransactionBaseFee, TransactionByteFee, }; use node_runtime::constants::currency::*; use node_runtime::impls::WeightToFee; diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index ef5f13e4e0ae9..69e1c0b851da7 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -504,8 +504,8 @@ decl_module! { #[compact] value: T::Balance ) { ensure_root(origin)?; - let source = T::Lookup::lookup(source)?; - let dest = T::Lookup::lookup(dest)?; + let source = T::Lookup::lookup(source).ok_or("could not find `source` account")?; + let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; >::transfer(&source, &dest, value)?; } } diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index 3de961f5cdcf5..82366dd9ce051 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -258,9 +258,10 @@ use srml_support::{StorageValue, dispatch::Result, decl_module, decl_storage, de use system::{ensure_signed, ensure_root}; use codec::{Encode, Decode}; use sr_primitives::{ - traits::{SignedExtension, DispatchError, Bounded}, - transaction_validity::ValidTransaction, - weights::{SimpleDispatchInfo, DispatchInfo}, + traits::{SignedExtension, Bounded}, weights::{SimpleDispatchInfo, DispatchInfo}, + transaction_validity::{ + ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity, + }, }; /// Our module's configuration trait. All our types and consts go in here. If the @@ -561,7 +562,7 @@ impl SignedExtension for WatchDummy { type AdditionalSigned = (); type Pre = (); - fn additional_signed(&self) -> rstd::result::Result<(), &'static str> { Ok(()) } + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } fn validate( &self, @@ -569,9 +570,11 @@ impl SignedExtension for WatchDummy { call: &Self::Call, _info: DispatchInfo, len: usize, - ) -> rstd::result::Result { + ) -> TransactionValidity { // if the transaction is too big, just drop it. - if len > 200 { return Err(DispatchError::Exhausted) } + if len > 200 { + return InvalidTransaction::ExhaustsResources.into() + } // check for `set_dummy` match call { @@ -580,9 +583,9 @@ impl SignedExtension for WatchDummy { let mut valid_tx = ValidTransaction::default(); valid_tx.priority = Bounded::max_value(); - Ok(valid_tx) + valid_tx.into() } - _ => Ok(Default::default()) + _ => ValidTransaction::default().into(), } } } @@ -712,12 +715,15 @@ mod tests { let info = DispatchInfo::default(); assert_eq!( - WatchDummy::(PhantomData).validate(&1, &call, info, 150).unwrap().priority, - Bounded::max_value() + WatchDummy::(PhantomData).validate(&1, &call, info, 150) + .into_valid() + .unwrap() + .priority, + Bounded::max_value(), ); assert_eq!( WatchDummy::(PhantomData).validate(&1, &call, info, 250), - Err(DispatchError::Exhausted) + InvalidTransaction::ExhaustsResources.into(), ); }) } diff --git a/srml/scored-pool/src/lib.rs b/srml/scored-pool/src/lib.rs index 1348b738643a2..c0d11a8e15bbd 100644 --- a/srml/scored-pool/src/lib.rs +++ b/srml/scored-pool/src/lib.rs @@ -309,7 +309,7 @@ decl_module! { .or_else(ensure_root) .map_err(|_| "bad origin")?; - let who = T::Lookup::lookup(dest)?; + let who = T::Lookup::lookup(dest).ok_or("Could not find `dest` account")?; let pool = >::get(); Self::ensure_index(&pool, &who, index)?; @@ -335,7 +335,7 @@ decl_module! { .or_else(ensure_root) .map_err(|_| "bad origin")?; - let who = T::Lookup::lookup(dest)?; + let who = T::Lookup::lookup(dest).ok_or("Could not find `dest` account")?; let mut pool = >::get(); Self::ensure_index(&pool, &who, index)?; From 31cd0483f6b645ab68c468601e3ec1abd5155142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 26 Aug 2019 23:30:47 +0200 Subject: [PATCH 56/80] Adds `CheckBlockGasLimit` signed extension --- core/client/src/client.rs | 2 - node/cli/src/factory_impl.rs | 5 ++- node/cli/src/service.rs | 10 ++++- node/runtime/src/lib.rs | 3 +- node/testing/src/keyring.rs | 3 +- srml/contracts/src/gas.rs | 17 +++---- srml/contracts/src/lib.rs | 87 +++++++++++++++++++++++++++++++----- srml/contracts/src/tests.rs | 42 ++++++++++++----- srml/support/src/lib.rs | 2 +- subkey/src/main.rs | 1 + 10 files changed, 132 insertions(+), 40 deletions(-) diff --git a/core/client/src/client.rs b/core/client/src/client.rs index e0fd141224f02..c6234dc8d1cca 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1491,8 +1491,6 @@ impl CallRuntimeAt for Client where _ => None, }; - self. - self.executor.contextual_call::<_, _, fn(_,_) -> _,_,_>( || core_api.initialize_block(at, &self.prepare_environment_block(at)?), at, diff --git a/node/cli/src/factory_impl.rs b/node/cli/src/factory_impl.rs index e371aef8e0842..c16a8af6f8f29 100644 --- a/node/cli/src/factory_impl.rs +++ b/node/cli/src/factory_impl.rs @@ -56,7 +56,8 @@ impl FactoryState { system::CheckEra::from(Era::mortal(256, phase)), system::CheckNonce::from(index), system::CheckWeight::new(), - balances::TakeFees::from(0) + balances::TakeFees::from(0), + Default::default(), ) } } @@ -147,7 +148,7 @@ impl RuntimeAdapter for FactoryState { (*amount).into() ) ) - }, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), ())) + }, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), ())) } fn inherent_extrinsics(&self) -> InherentData { diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 7022d12d69a0f..9cfc32b456f25 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -477,7 +477,15 @@ mod tests { let check_nonce = system::CheckNonce::from(index); let check_weight = system::CheckWeight::new(); let take_fees = balances::TakeFees::from(0); - let extra = (check_version, check_genesis, check_era, check_nonce, check_weight, take_fees); + let extra = ( + check_version, + check_genesis, + check_era, + check_nonce, + check_weight, + take_fees, + Default::default(), + ); let raw_payload = (function, extra.clone(), version, genesis_hash, genesis_hash); let signature = raw_payload.using_encoded(|payload| if payload.len() > 256 { diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 0ec471e404efd..313375fe80730 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -470,7 +470,8 @@ pub type SignedExtra = ( system::CheckEra, system::CheckNonce, system::CheckWeight, - balances::TakeFees + balances::TakeFees, + contracts::CheckBlockGasLimit, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; diff --git a/node/testing/src/keyring.rs b/node/testing/src/keyring.rs index 12a3e7c2d4d43..0c6eb478cc5a0 100644 --- a/node/testing/src/keyring.rs +++ b/node/testing/src/keyring.rs @@ -72,7 +72,8 @@ pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra { system::CheckEra::from(Era::mortal(256, 0)), system::CheckNonce::from(nonce), system::CheckWeight::new(), - balances::TakeFees::from(extra_fee) + balances::TakeFees::from(extra_fee), + Default::default(), ) } diff --git a/srml/contracts/src/gas.rs b/srml/contracts/src/gas.rs index 1fbb9f22be5a9..5add9bdfbeccf 100644 --- a/srml/contracts/src/gas.rs +++ b/srml/contracts/src/gas.rs @@ -16,9 +16,12 @@ use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf}; use rstd::convert::TryFrom; -use sr_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto}; -use srml_support::StorageValue; -use srml_support::traits::{Currency, ExistenceRequirement, Get, Imbalance, OnUnbalanced, WithdrawReason}; +use sr_primitives::traits::{ + CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto, +}; +use srml_support::{ + traits::{Currency, ExistenceRequirement, Imbalance, OnUnbalanced, WithdrawReason}, StorageValue, +}; #[cfg(test)] use std::{any::Any, fmt::Debug}; @@ -199,14 +202,6 @@ pub fn buy_gas( transactor: &T::AccountId, gas_limit: Gas, ) -> Result<(GasMeter, NegativeImbalanceOf), &'static str> { - // Check if the specified amount of gas is available in the current block. - // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. - let gas_available = T::BlockGasLimit::get() - >::gas_spent(); - if gas_limit > gas_available { - // gas limit reached, revert the transaction and retry again in the future - return Err("gas block limit reached"); - } - // Buy the specified amount of gas. let gas_price = >::gas_price(); let cost = if gas_price.is_zero() { diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index f835b55be07b4..b9bda1401547f 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -100,15 +100,19 @@ use primitives::crypto::UncheckedFrom; use rstd::{prelude::*, marker::PhantomData}; use codec::{Codec, Encode, Decode}; use runtime_io::blake2_256; -use sr_primitives::traits::{ - Hash, StaticLookup, Zero, MaybeSerializeDebug, Member +use sr_primitives::{ + traits::{Hash, StaticLookup, Zero, MaybeSerializeDebug, Member, SignedExtension}, + weights::DispatchInfo, + transaction_validity::{ + ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError, + }, }; use srml_support::dispatch::{Result, Dispatchable}; use srml_support::{ Parameter, StorageMap, StorageValue, decl_module, decl_event, decl_storage, storage::child, parameter_types, }; -use srml_support::traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get}; +use srml_support::{traits::{OnFreeBalanceZero, OnUnbalanced, Currency, Get}, IsSubType}; use system::{ensure_signed, RawOrigin, ensure_root}; use primitives::storage::well_known_keys::CHILD_STORAGE_KEY_PREFIX; use timestamp; @@ -321,7 +325,7 @@ pub trait Trait: timestamp::Trait { type Currency: Currency; /// The outer call dispatch type. - type Call: Parameter + Dispatchable::Origin>; + type Call: Parameter + Dispatchable::Origin> + IsSubType, Self>; /// The overarching event type. type Event: From> + Into<::Event>; @@ -597,15 +601,17 @@ decl_module! { /// the sender is not eligible for the reward. fn claim_surcharge(origin, dest: T::AccountId, aux_sender: Option) { let origin = origin.into(); - let (signed, rewarded) = match origin { - Ok(system::RawOrigin::Signed(ref account)) if aux_sender.is_none() => { + let (signed, rewarded) = match (origin, aux_sender) { + (Ok(system::RawOrigin::Signed(account)), None) => { (true, account) }, - Ok(system::RawOrigin::None) if aux_sender.is_some() => { - (false, aux_sender.as_ref().expect("checked above")) + (Ok(system::RawOrigin::None), Some(aux_sender)) => { + (false, aux_sender) }, - _ => return Err("Invalid surcharge claim: origin must be signed or \ - inherent and auxiliary sender only provided on inherent") + _ => return Err( + "Invalid surcharge claim: origin must be signed or \ + inherent and auxiliary sender only provided on inherent" + ), }; // Add some advantage for block producers (who send unsigned extrinsics) by @@ -619,7 +625,7 @@ decl_module! { // If poking the contract has lead to eviction of the contract, give out the rewards. if rent::try_evict::(&dest, handicap) == rent::RentOutcome::Evicted { - T::Currency::deposit_into_existing(rewarded, T::SurchargeReward::get())?; + T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; } } @@ -937,3 +943,62 @@ impl Default for Schedule { } } } + +/// `SignedExtension` that checks if a transaction would exhausts the block gas limit. +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct CheckBlockGasLimit(PhantomData); + +#[cfg(feature = "std")] +impl Default for CheckBlockGasLimit { + fn default() -> Self { + Self(std::marker::PhantomData) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for CheckBlockGasLimit { + fn fmt(&self, _: &mut std::fmt::Formatter) -> std::fmt::Result { + Ok(()) + } +} + +impl SignedExtension for CheckBlockGasLimit { + type AccountId = T::AccountId; + type Call = ::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> rstd::result::Result<(), TransactionValidityError> { Ok(()) } + + fn validate( + &self, + _: &Self::AccountId, + call: &Self::Call, + _: DispatchInfo, + _: usize, + ) -> TransactionValidity { + let call = match call.is_sub_type() { + Some(call) => call, + None => return ValidTransaction::default().into(), + }; + + match call { + Call::claim_surcharge(_, _) | Call::update_schedule(_) => + ValidTransaction::default().into(), + Call::put_code(gas_limit, _) + | Call::call(_, _, gas_limit, _) + | Call::create(_, gas_limit, _, _) => { + // Check if the specified amount of gas is available in the current block. + // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. + let gas_available = T::BlockGasLimit::get() - >::gas_spent(); + if *gas_limit > gas_available { + // gas limit reached, revert the transaction and retry again in the future + InvalidTransaction::ExhaustsResources.into() + } else { + ValidTransaction::default().into() + } + }, + Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), + } + } +} \ No newline at end of file diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index 6ac1a50764f3f..f22885708c69c 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -22,27 +22,27 @@ use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; use crate::{ BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, - Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, - TrieIdGenerator, Schedule, + Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule, + TrieIdGenerator, CheckBlockGasLimit, }; use assert_matches::assert_matches; use hex_literal::*; use codec::{Decode, Encode, KeyedVec}; use runtime_io; use runtime_io::with_externalities; -use sr_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId, H256}; -use sr_primitives::traits::{BlakeTwo256, Hash, IdentityLookup}; -use sr_primitives::{Perbill, BuildStorage}; +use sr_primitives::{ + Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction}, + traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension}, + weights::{DispatchInfo, DispatchClass}, + testing::{Digest, DigestItem, Header, UintAuthorityId, H256}, +}; use srml_support::{ assert_ok, assert_err, impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, storage::child, StorageMap, StorageValue, traits::{Currency, Get}, }; -use std::cell::RefCell; -use std::sync::atomic::{AtomicUsize, Ordering}; -use primitives::storage::well_known_keys; -use primitives::Blake2Hasher; +use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}}; +use primitives::{storage::well_known_keys, Blake2Hasher}; use system::{self, EventRecord, Phase}; -use {balances, wabt}; mod contract { // Re-export contents of the root. This basically @@ -2390,3 +2390,25 @@ fn cannot_self_destruct_in_constructor() { } ); } + +#[test] +fn check_block_gas_limit_works() { + with_externalities( + &mut ExtBuilder::default().block_gas_limit(50).build(), + || { + let info = DispatchInfo { weight: 100, class: DispatchClass::Normal }; + let check = CheckBlockGasLimit::(Default::default()); + let call: Call = crate::Call::put_code(1000, vec![]).into(); + + assert_eq!( + check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(), + ); + + let call: Call = crate::Call::update_schedule(Default::default()).into(); + assert_eq!( + check.validate(&0, &call, info, 0), + ValidTransaction::default().into(), + ); + } + ); +} \ No newline at end of file diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index c75bbe99e44e2..c7aa40f142417 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -64,7 +64,7 @@ mod double_map; pub mod traits; pub use self::storage::{ - StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap + StorageValue, StorageMap, EnumerableStorageMap, StorageDoubleMap, AppendableStorageMap, }; pub use self::hashable::Hashable; pub use self::dispatch::{Parameter, Callable, IsSubType}; diff --git a/subkey/src/main.rs b/subkey/src/main.rs index ba9d1a6cce059..7e79e9600c8c2 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -103,6 +103,7 @@ fn execute(matches: clap::ArgMatches) where system::CheckNonce::::from(i), system::CheckWeight::::new(), balances::TakeFees::::from(f), + Default::default(), ) }; let password = matches.value_of("password"); From 513702c948084e2fd6c02fd6b751f9a4aa6211f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 09:51:34 +0200 Subject: [PATCH 57/80] Remove debug stuff --- srml/system/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 62c0b344f5023..3aa182d587780 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -87,7 +87,6 @@ //! ``` #![cfg_attr(not(feature = "std"), no_std)] -#![feature(trace_macros)] #[cfg(feature = "std")] use serde::Serialize; From c81d17ecd8e29ea2781ae7c78d201816b0754c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 11:16:23 +0200 Subject: [PATCH 58/80] Fix srml-balances test --- srml/balances/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/balances/src/tests.rs b/srml/balances/src/tests.rs index 20d5a40d1d413..37a26f536e2b3 100644 --- a/srml/balances/src/tests.rs +++ b/srml/balances/src/tests.rs @@ -359,7 +359,7 @@ fn force_transfer_works() { let _ = Balances::deposit_creating(&1, 111); assert_noop!( Balances::force_transfer(Some(2).into(), 1, 2, 69), - "bad origin: expected to be a root origin" + "RequireRootOrigin", ); assert_ok!(Balances::force_transfer(RawOrigin::Root.into(), 1, 2, 69)); assert_eq!(Balances::total_balance(&1), 42); From e48d2b5508057c7abd21320fb8588785b4e806d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 13:12:35 +0200 Subject: [PATCH 59/80] Rename `InvalidIndex` to `CannotLookup` --- core/sr-primitives/src/generic/unchecked_extrinsic.rs | 2 +- core/sr-primitives/src/transaction_validity.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 721d2df92a53a..09d6be8e33a57 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -105,7 +105,7 @@ where Some((signed, signature, extra)) => { let additional_signed = extra.additional_signed()?; let raw_payload = (self.function, extra, additional_signed); - let signed = lookup.lookup(signed).ok_or(UnknownTransaction::InvalidIndex)?; + let signed = lookup.lookup(signed).ok_or(UnknownTransaction::CannotLookup)?; if !raw_payload.using_encoded(|payload| { if payload.len() > 256 { signature.verify(&blake2_256(payload)[..], &signed) diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index c897a203dcc5a..e30fe628a07be 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -82,8 +82,8 @@ impl Into<&'static str> for InvalidTransaction { #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum UnknownTransaction { - /// An invalid/unknown account index - InvalidIndex, + /// Could not lookup some information that are required to validate the transaction. + CannotLookup, /// No validator found for the given unsigned transaction. NoUnsignedValidator, /// Any other custom unknown validity that is not covered by this enum. @@ -93,8 +93,8 @@ pub enum UnknownTransaction { impl Into<&'static str> for UnknownTransaction { fn into(self) -> &'static str { match self { - UnknownTransaction::InvalidIndex => - "Transaction used an invalid/unknown account index", + UnknownTransaction::CannotLookup => + "Could not lookup some information to validate the transaction", UnknownTransaction::NoUnsignedValidator => "Could not find an unsigned validator for the unsigned transaction", UnknownTransaction::Custom(_) => "UnknownTransaction custom error", From 1f16b00f371bd283b2fe6da530cea8fb87837255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 14:28:10 +0200 Subject: [PATCH 60/80] Remove weird generic parameters --- srml/council/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/srml/council/src/lib.rs b/srml/council/src/lib.rs index 95a1d904566b5..633db68a423a5 100644 --- a/srml/council/src/lib.rs +++ b/srml/council/src/lib.rs @@ -163,11 +163,11 @@ mod tests { type EmergencyVotingPeriod = VotingPeriod; type VotingPeriod = VotingPeriod; type MinimumDeposit = MinimumDeposit; - type ExternalOrigin = motions::EnsureProportionAtLeast<_1, _2, u64, &'static str>; - type ExternalMajorityOrigin = motions::EnsureProportionAtLeast<_2, _3, u64, &'static str>; - type EmergencyOrigin = motions::EnsureProportionAtLeast<_1, _1, u64, &'static str>; - type CancellationOrigin = motions::EnsureProportionAtLeast<_2, _3, u64, &'static str>; - type VetoOrigin = motions::EnsureMember; + type ExternalOrigin = motions::EnsureProportionAtLeast<_1, _2, u64>; + type ExternalMajorityOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; + type EmergencyOrigin = motions::EnsureProportionAtLeast<_1, _1, u64>; + type CancellationOrigin = motions::EnsureProportionAtLeast<_2, _3, u64>; + type VetoOrigin = motions::EnsureMember; type CooloffPeriod = CooloffPeriod; } parameter_types! { From ed0761c38817731f9d27cff39141395d794ab7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 14:30:21 +0200 Subject: [PATCH 61/80] Rename function again --- core/basic-authorship/src/basic_authorship.rs | 2 +- core/sr-primitives/src/lib.rs | 4 ++-- core/sr-primitives/src/transaction_validity.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index d90d0d728233f..ffc4d766c9bd3 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -171,7 +171,7 @@ impl Proposer, A> wh Ok(()) => { debug!("[{:?}] Pushed to the block.", pending.hash); } - Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausts_resources() => { + Err(error::Error::ApplyExtrinsicFailed(e)) if e.exhausted_resources() => { if is_first { debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending.hash); unqueue_invalid.push(pending.hash.clone()); diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 7db75623c39be..c2adfff138017 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -639,9 +639,9 @@ pub enum ApplyError { impl ApplyError { /// Returns if the reason for the error was block resource exhaustion. - pub fn exhausts_resources(&self) -> bool { + pub fn exhausted_resources(&self) -> bool { match self { - Self::Validity(e) => e.exhausts_resources(), + Self::Validity(e) => e.exhausted_resources(), _ => false, } } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index e30fe628a07be..7969ef9c227d1 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -53,7 +53,7 @@ pub enum InvalidTransaction { impl InvalidTransaction { /// Returns if the reason for the invalidity was block resource exhaustion. - pub fn exhausts_resources(&self) -> bool { + pub fn exhausted_resources(&self) -> bool { match self { Self::ExhaustsResources => true, _ => false, @@ -114,9 +114,9 @@ pub enum TransactionValidityError { impl TransactionValidityError { /// Returns if the reason for the error was block resource exhaustion. - pub fn exhausts_resources(&self) -> bool { + pub fn exhausted_resources(&self) -> bool { match self { - Self::Invalid(e) => e.exhausts_resources(), + Self::Invalid(e) => e.exhausted_resources(), Self::Unknown(_) => false, } } From 20c6706a55cb1c287cdcbb90a16db485f1d90831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 20:45:23 +0200 Subject: [PATCH 62/80] Fix import --- srml/democracy/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 7ae00de58de9b..4d1dd8148fcd9 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -27,7 +27,7 @@ use sr_primitives::{ use codec::{Encode, Decode, Input, Output, Error}; use srml_support::{ decl_module, decl_storage, decl_event, ensure, AppendableStorageMap, StorageValue, StorageMap, - Parameter, Dispatchable, EnumerableStorageMap, + Parameter, EnumerableStorageMap, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, OnFreeBalanceZero From 28bbc86662f94ee76778b6a75249d7db4dad60f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 21:24:29 +0200 Subject: [PATCH 63/80] Document the signed extension --- srml/contracts/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index b9bda1401547f..f0a2070e12cd2 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -63,6 +63,15 @@ //! This creates a new smart contract account and calls its contract deploy handler to initialize the contract. //! * `call` - Makes a call to an account, optionally transferring some balance. //! +//! ### Signed Extensions +//! +//! The contracts module defines the following extension: +//! +//! - [`CheckBlockGasLimit`]: Ensures that the transaction does not exceeds the block gas limit. +//! +//! The signed extension needs to be added as signed extra to the transaction type to be used in the +//! runtime. +//! //! ## Usage //! //! The Contract module is a work in progress. The following examples show how this Contract module can be From 92cec3ca9fe4f8816ed94ac438d1a71d22ff041b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 27 Aug 2019 21:55:24 +0200 Subject: [PATCH 64/80] Change from `Into` to `From` --- core/sr-primitives/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index c2adfff138017..fafda3ff97c0b 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -647,9 +647,9 @@ impl ApplyError { } } -impl Into<&'static str> for ApplyError { - fn into(self) -> &'static str { - match self { +impl From for &'static str { + fn from(err: ApplyError) -> &'static str { + match err { ApplyError::NoPermission => "Transaction does not have required permissions", ApplyError::BadState => "System in bad state", ApplyError::Validity(v) => v.into(), From 442db389062d3fa5e87302dfda77f3694518ff74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 28 Aug 2019 09:15:12 +0200 Subject: [PATCH 65/80] Update srml/contracts/src/lib.rs Co-Authored-By: Sergei Pepyakin --- srml/contracts/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index f0a2070e12cd2..11d1fb64d0ffe 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -1010,4 +1010,4 @@ impl SignedExtension for CheckBlockGasLimit { Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), } } -} \ No newline at end of file +} From 257684e575e58f581b99c68fd8cbd5916516f2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 10:09:52 +0200 Subject: [PATCH 66/80] Fix compilation --- core/rpc/src/author/mod.rs | 6 +----- core/rpc/src/author/tests.rs | 2 +- srml/democracy/src/lib.rs | 2 +- srml/im-online/src/lib.rs | 2 +- srml/system/src/lib.rs | 4 ++-- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/rpc/src/author/mod.rs b/core/rpc/src/author/mod.rs index 78a8ff804f3e4..50b5e30d578a3 100644 --- a/core/rpc/src/author/mod.rs +++ b/core/rpc/src/author/mod.rs @@ -28,10 +28,7 @@ use api::Subscriptions; use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId}; use log::warn; use codec::{Encode, Decode}; -use primitives::{ - Bytes, Blake2Hasher, H256, ed25519, sr25519, crypto::{Pair, Public, key_types}, - traits::BareCryptoStorePtr, -}; +use primitives::{Bytes, Blake2Hasher, H256, traits::BareCryptoStorePtr}; use sr_primitives::{generic, traits::{self, ProvideRuntimeApi}}; use transaction_pool::{ txpool::{ @@ -98,7 +95,6 @@ impl AuthorApi, BlockHash

> for Author whe ) -> Result<()> { let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?; let mut keystore = self.keystore.write(); - let maybe_password = keystore.password(); keystore.insert_unknown(key_type, &suri, &public[..]) .map_err(|_| Error::KeyStoreUnavailable)?; Ok(()) diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index 8e6243f40e3f5..2917f8448f697 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -26,7 +26,7 @@ use transaction_pool::{ use futures::Stream; use primitives::{ H256, blake2_256, hexdisplay::HexDisplay, traits::BareCryptoStore, testing::KeyStore, - ed25519, crypto::key_types, + ed25519, crypto::{key_types, Pair}, }; use test_client::{ self, AccountKeyring, runtime::{Extrinsic, Transfer, SessionKeys}, DefaultTestClientBuilderExt, diff --git a/srml/democracy/src/lib.rs b/srml/democracy/src/lib.rs index 9bdc07093dbfe..b3a56cfbe4f81 100644 --- a/srml/democracy/src/lib.rs +++ b/srml/democracy/src/lib.rs @@ -27,7 +27,7 @@ use sr_primitives::{ use codec::{Encode, Decode, Input, Output, Error}; use srml_support::{ decl_module, decl_storage, decl_event, ensure, StorageValue, StorageMap, StorageLinkedMap, - Parameter, Dispatchable, + Parameter, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, OnFreeBalanceZero diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index e6e53a3e3913a..d155f53547997 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -74,7 +74,7 @@ use rstd::prelude::*; use session::historical::IdentificationTuple; use sr_io::Printable; use sr_primitives::{ - traits::{Extrinsic as ExtrinsicT, Convert}, Perbill, + traits::{Extrinsic as ExtrinsicT, Convert, Member}, Perbill, transaction_validity::{ TransactionValidity, TransactionLongevity, ValidTransaction, InvalidTransaction, }, diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 69b298a72d667..bdadea0f7a87d 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -829,7 +829,7 @@ impl Module { match r { ApplyOutcome::Success => Event::ExtrinsicSuccess, ApplyOutcome::Fail(err) => Event::ExtrinsicFailed(err.clone()), - }.into() + } ); let next_extrinsic_index = Self::extrinsic_index().unwrap_or_default() + 1u32; @@ -1549,7 +1549,7 @@ mod tests { >::insert(16, H256::repeat_byte(1)); assert_eq!( - ext.validate(&1, CALL, normal, len).unwrap().longevity, + ext.validate(&1, CALL, normal, len).into_valid().unwrap().longevity, 15, ); }) From 14708751401c208da1f9bef7f012bdfeb3ea49c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 11:47:27 +0200 Subject: [PATCH 67/80] Update srml/contracts/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tomasz Drwięga --- srml/contracts/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 3d3a70cf8283f..cb5c77f24f490 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -957,7 +957,6 @@ impl Default for Schedule { #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckBlockGasLimit(PhantomData); -#[cfg(feature = "std")] impl Default for CheckBlockGasLimit { fn default() -> Self { Self(std::marker::PhantomData) From 23d5a93951fb46b08a23d7aded2994cc4663078a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 11:53:49 +0200 Subject: [PATCH 68/80] Update core/sr-primitives/src/transaction_validity.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Tomasz Drwięga --- core/sr-primitives/src/transaction_validity.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 7969ef9c227d1..1b9750f9fe49f 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -45,7 +45,9 @@ pub enum InvalidTransaction { BadProof, /// The transaction birth block is ancient. AncientBirthBlock, - /// The transaction **alone** would exhaust the resources of a block. + /// The transaction would exhaust the resources of current block. + /// + /// The transaction might be valid, but there is not enough resources left in the current block. ExhaustsResources, /// Any other custom invalid validity that is not covered by this enum. Custom(u8), From 39d9d47ab3cbd43e50be41ebaa310abd09f1a590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 13:54:56 +0200 Subject: [PATCH 69/80] Remove unused code --- srml/system/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index bdadea0f7a87d..a930e7906649f 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1213,15 +1213,6 @@ mod tests { type Version = (); } - impl From for u16 { - fn from(e: Event) -> u16 { - match e { - Event::ExtrinsicSuccess => 100, - Event::ExtrinsicFailed(err) => Encode::using_encoded(&err, |s| (s[0] as u16) | ((s[1] as u16) << 8)), - } - } - } - type System = Module; const CALL: &::Call = &(); From 7990a973b712c3bcc2175a38de35a57c20e685d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 13:55:33 +0200 Subject: [PATCH 70/80] Fix compilation --- srml/contracts/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index cb5c77f24f490..0da8698ff65ea 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -959,7 +959,7 @@ pub struct CheckBlockGasLimit(PhantomData); impl Default for CheckBlockGasLimit { fn default() -> Self { - Self(std::marker::PhantomData) + Self(PhantomData) } } From 7ecba8dbfe17a201b772e4aa8a9bdae6c1d246d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 30 Aug 2019 22:41:44 +0200 Subject: [PATCH 71/80] Some cleanups --- .../sr-primitives/src/transaction_validity.rs | 30 +++++++++---------- srml/system/src/lib.rs | 11 ++++++- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 1b9750f9fe49f..988be13f39bc1 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -63,9 +63,9 @@ impl InvalidTransaction { } } -impl Into<&'static str> for InvalidTransaction { - fn into(self) -> &'static str { - match self { +impl From for &'static str { + fn from(invalid: InvalidTransaction) -> &'static str { + match invalid { InvalidTransaction::Call => "Transaction call is not expected", InvalidTransaction::Future => "Transaction will be valid in the future", InvalidTransaction::Stale => "Transaction is outdated", @@ -92,9 +92,9 @@ pub enum UnknownTransaction { Custom(u8), } -impl Into<&'static str> for UnknownTransaction { - fn into(self) -> &'static str { - match self { +impl From for &'static str { + fn from(unknown: UnknownTransaction) -> &'static str { + match unknown { UnknownTransaction::CannotLookup => "Could not lookup some information to validate the transaction", UnknownTransaction::NoUnsignedValidator => @@ -124,9 +124,9 @@ impl TransactionValidityError { } } -impl Into<&'static str> for TransactionValidityError { - fn into(self) -> &'static str { - match self { +impl From for &'static str { + fn from(err: TransactionValidityError) -> &'static str { + match err { TransactionValidityError::Invalid(invalid) => invalid.into(), TransactionValidityError::Unknown(unknown) => unknown.into(), } @@ -145,15 +145,15 @@ impl From for TransactionValidityError { } } -impl Into for InvalidTransaction { - fn into(self) -> crate::ApplyError { - TransactionValidityError::from(self).into() +impl From for crate::ApplyError { + fn from(invalid: InvalidTransaction) -> crate::ApplyError { + TransactionValidityError::from(invalid).into() } } -impl Into for UnknownTransaction { - fn into(self) -> crate::ApplyError { - TransactionValidityError::from(self).into() +impl From for crate::ApplyError { + fn from(unknown: UnknownTransaction) -> crate::ApplyError { + TransactionValidityError::from(unknown).into() } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index a930e7906649f..df370d54705d2 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -1213,6 +1213,15 @@ mod tests { type Version = (); } + impl From for u16 { + fn from(e: Event) -> u16 { + match e { + Event::ExtrinsicSuccess => 100, + Event::ExtrinsicFailed(_) => 101, + } + } + } + type System = Module; const CALL: &::Call = &(); @@ -1269,7 +1278,7 @@ mod tests { vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16, topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: 100u16, topics: vec![] }, - EventRecord { phase: Phase::ApplyExtrinsic(1), event: 257u16, topics: vec![] }, + EventRecord { phase: Phase::ApplyExtrinsic(1), event: 101u16, topics: vec![] }, EventRecord { phase: Phase::Finalization, event: 3u16, topics: vec![] } ] ); From 3d7abc072ff4e306476d2015007e59d00fc54873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 2 Sep 2019 11:24:01 +0200 Subject: [PATCH 72/80] Fix compile errors --- core/sr-primitives/src/generic/unchecked_extrinsic.rs | 8 ++++---- node/cli/src/service.rs | 2 +- node/runtime/src/lib.rs | 1 + subkey/src/main.rs | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index a3bbb56d754ed..1bcdd9bd253fb 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -141,9 +141,9 @@ where /// is going to be different than the `SignaturePayload` - so the thing the extrinsic /// actually contains. pub struct SignedPayload(( - Call, - Extra, - Extra::AdditionalSigned, + Call, + Extra, + Extra::AdditionalSigned, )); impl SignedPayload where @@ -153,7 +153,7 @@ impl SignedPayload where /// Create new `SignedPayload`. /// /// This function may fail if `additional_signed` of `Extra` is not available. - pub fn new(call: Call, extra: Extra) -> Result { + pub fn new(call: Call, extra: Extra) -> Result { let additional_signed = extra.additional_signed()?; let raw_payload = (call, extra, additional_signed); Ok(Self(raw_payload)) diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 4784c5cd4cd9d..509de7a943815 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -482,7 +482,7 @@ mod tests { let raw_payload = SignedPayload::from_raw( function, extra, - (version, genesis_hash, genesis_hash, (), (), ()) + (version, genesis_hash, genesis_hash, (), (), (), ()) ); let signature = raw_payload.using_encoded(|payload| { signer.sign(payload) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 6b25d59dbdb74..0a632960f7ee8 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -445,6 +445,7 @@ impl system::offchain::CreateTransaction for Runtim system::CheckNonce::::from(index), system::CheckWeight::::new(), balances::TakeFees::::from(tip), + Default::default(), ); let raw_payload = SignedPayload::new(call, extra).ok()?; let signature = F::sign(account.clone(), &raw_payload)?; diff --git a/subkey/src/main.rs b/subkey/src/main.rs index 4c332d8dcc747..a68674513ad4d 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -186,7 +186,7 @@ fn execute(matches: clap::ArgMatches) where let raw_payload = SignedPayload::from_raw( function, extra(index, 0), - (VERSION.spec_version as u32, genesis_hash, genesis_hash, (), (), ()), + (VERSION.spec_version as u32, genesis_hash, genesis_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|payload| { println!("Signing {}", HexDisplay::from(&payload)); From f93f9d3fe18841a20e963be4c2f999c80b57a05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 2 Sep 2019 13:15:15 +0200 Subject: [PATCH 73/80] Make `TransactionValidity` a `Result` --- .../src/generic/checked_extrinsic.rs | 5 +- core/sr-primitives/src/testing.rs | 4 +- core/sr-primitives/src/traits.rs | 26 ++-- .../sr-primitives/src/transaction_validity.rs | 129 +----------------- core/test-runtime/src/lib.rs | 4 +- core/test-runtime/src/system.rs | 2 +- core/transaction-pool/graph/src/pool.rs | 12 +- core/transaction-pool/src/tests.rs | 22 +-- srml/balances/src/lib.rs | 2 +- srml/contracts/src/lib.rs | 6 +- srml/contracts/src/tests.rs | 7 +- srml/example/src/lib.rs | 5 +- srml/executive/src/lib.rs | 11 +- srml/im-online/src/lib.rs | 6 +- srml/system/src/lib.rs | 27 ++-- 15 files changed, 71 insertions(+), 197 deletions(-) diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index 4afb7eba3b9c2..d2b45f5a612b2 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -62,9 +62,8 @@ where if let Some((ref id, ref extra)) = self.signed { Extra::validate(extra, id, &self.function, info, len) } else { - Extra::validate_unsigned(&self.function, info, len).combine_with( - || U::validate_unsigned(&self.function) - ) + let valid = Extra::validate_unsigned(&self.function, info, len)?; + Ok(valid.combine_with(U::validate_unsigned(&self.function)?)) } } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 61d80ee346d02..eeb45f833c119 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -302,7 +302,7 @@ impl Applyable for TestXt where _info: DispatchInfo, _len: usize, ) -> TransactionValidity { - TransactionValidity::Valid(Default::default()) + Ok(Default::default()) } /// Executes all necessary logic needed prior to dispatch and deconstructs into function call, @@ -333,4 +333,4 @@ impl GetDispatchInfo for TestXt { ..Default::default() } } -} \ No newline at end of file +} diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index fa2d9eeb3ee61..dc1bd7274fd88 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -871,7 +871,7 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti _info: DispatchInfo, _len: usize, ) -> TransactionValidity { - ValidTransaction::default().into() + Ok(ValidTransaction::default()) } /// Do any pre-flight stuff for a signed transaction. @@ -890,7 +890,6 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti len: usize, ) -> Result { self.validate(who, call, info, len) - .into_result() .map(|_| Self::Pre::default()) .map_err(Into::into) } @@ -911,7 +910,7 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti _info: DispatchInfo, _len: usize, ) -> TransactionValidity { - ValidTransaction::default().into() + Ok(ValidTransaction::default()) } /// Do any pre-flight stuff for a unsigned transaction. @@ -928,7 +927,6 @@ pub trait SignedExtension: Codec + MaybeDebug + Sync + Send + Clone + Eq + Parti len: usize, ) -> Result { Self::validate_unsigned(call, info, len) - .into_result() .map(|_| Self::Pre::default()) .map_err(Into::into) } @@ -973,11 +971,13 @@ macro_rules! tuple_impl_indexed { len: usize, ) -> TransactionValidity { let aggregator = vec![ - $( <$direct as SignedExtension>::validate(&self.$index, who, call, info, len) ),+ + $( <$direct as SignedExtension>::validate(&self.$index, who, call, info, len)? ),+ ]; - aggregator.into_iter().fold( - TransactionValidity::Valid(ValidTransaction::default()), - |acc, a| acc.combine_with(|| a) + Ok( + aggregator.into_iter().fold( + ValidTransaction::default(), + |acc, a| acc.combine_with(a), + ) ) } fn pre_dispatch( @@ -994,11 +994,13 @@ macro_rules! tuple_impl_indexed { info: DispatchInfo, len: usize, ) -> TransactionValidity { - let aggregator = vec![ $( $direct::validate_unsigned(call, info, len) ),+ ]; + let aggregator = vec![ $( $direct::validate_unsigned(call, info, len)? ),+ ]; - aggregator.into_iter().fold( - TransactionValidity::Valid(ValidTransaction::default()), - |acc, a| acc.combine_with(|| a) + Ok( + aggregator.into_iter().fold( + ValidTransaction::default(), + |acc, a| acc.combine_with(a), + ) ) } fn pre_dispatch_unsigned( diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 988be13f39bc1..5e149fdade6ab 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -158,119 +158,22 @@ impl From for crate::ApplyError { } /// Information on a transaction's validity and, if valid, on how it relates to other transactions. -#[derive(Clone, PartialEq, Eq, Encode)] -#[cfg_attr(feature = "std", derive(Debug))] -pub enum TransactionValidity { - /// Transaction is invalid. - Invalid(InvalidTransaction), - /// Transaction is valid. - Valid(ValidTransaction), - /// Transaction validity can't be determined. - Unknown(UnknownTransaction), -} - -impl Into for TransactionValidityError { - fn into(self) -> TransactionValidity { - match self { - TransactionValidityError::Invalid(invalid) => TransactionValidity::Invalid(invalid), - TransactionValidityError::Unknown(unknown) => TransactionValidity::Unknown(unknown), - } - } -} +pub type TransactionValidity = Result; impl Into for InvalidTransaction { fn into(self) -> TransactionValidity { - TransactionValidity::Invalid(self) + Err(self.into()) } } impl Into for UnknownTransaction { fn into(self) -> TransactionValidity { - TransactionValidity::Unknown(self) - } -} - -impl Into for ValidTransaction { - fn into(self) -> TransactionValidity { - TransactionValidity::Valid(self) - } -} - -impl TransactionValidity { - /// Combine two `TransactionValidity`s. - /// - /// If both are valid, they are combined. - /// - /// If one of them is not valid, the non-valid one is returned. If both are not valid, `self` is - /// returned. - pub fn combine_with Self>(self, other: F) -> Self { - match self { - TransactionValidity::Valid(valid) => { - match other() { - TransactionValidity::Valid(other_valid) => { - TransactionValidity::Valid(valid.combine_with(other_valid)) - }, - o => o, - } - }, - _ => self, - } - } - - /// Convert this `TransactionValidity` into a `Result`. - pub fn into_result(self) -> Result { - match self { - TransactionValidity::Valid(valid) => Ok(valid), - TransactionValidity::Invalid(invalid) => Err(invalid.into()), - TransactionValidity::Unknown(unknown) => Err(unknown.into()), - } - } - - /// Returns if the validity `invalid` or `unknown`. - pub fn is_invalid_or_unknown(&self) -> bool { - match self { - TransactionValidity::Invalid(_) | TransactionValidity::Unknown(_) => true, - TransactionValidity::Valid(_) => false, - } - } - - /// Returns if the validity `valid`. - pub fn is_valid(&self) -> bool { - !self.is_invalid_or_unknown() - } - - /// Try to convert into `ValidTransaction`. - pub fn into_valid(self) -> Option { - match self { - TransactionValidity::Valid(valid) => Some(valid), - _ => None, - } - } -} - -impl Decode for TransactionValidity { - fn decode(value: &mut I) -> Result { - match value.read_byte()? { - 0 => Ok(TransactionValidity::Invalid(InvalidTransaction::decode(value)?)), - 1 => { - let priority = TransactionPriority::decode(value)?; - let requires = Vec::decode(value)?; - let provides = Vec::decode(value)?; - let longevity = TransactionLongevity::decode(value)?; - let propagate = bool::decode(value).unwrap_or(true); - - Ok(TransactionValidity::Valid(ValidTransaction { - priority, requires, provides, longevity, propagate, - })) - }, - 2 => Ok(TransactionValidity::Unknown(UnknownTransaction::decode(value)?)), - _ => Err("Invalid transaction validity variant".into()), - } + Err(self.into()) } } /// Information concerning a valid transaction. -#[derive(Clone, PartialEq, Eq, Encode)] +#[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub struct ValidTransaction { /// Priority of the transaction. @@ -334,31 +237,9 @@ impl ValidTransaction { mod tests { use super::*; - #[test] - fn should_decode_with_backward_compat() { - let old_encoding = vec![ - 1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, - ]; - - assert_eq!( - TransactionValidity::decode(&mut &*old_encoding), - Ok( - TransactionValidity::Valid( - ValidTransaction { - priority: 5, - requires: vec![vec![1, 2, 3, 4]], - provides: vec![vec![4, 5, 6]], - longevity: 42, - propagate: true, - } - ), - ) - ); - } - #[test] fn should_encode_and_decode() { - let v = TransactionValidity::Valid(ValidTransaction { + let v: TransactionValidity = Ok(ValidTransaction { priority: 5, requires: vec![vec![1, 2, 3, 4]], provides: vec![vec![4, 5, 6]], diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 7326d80c05d69..ec7ed9670c330 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -480,7 +480,7 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { - return TransactionValidity::Valid(ValidTransaction { + return Ok(ValidTransaction { priority: data.len() as u64, requires: vec![], provides: vec![data], @@ -664,7 +664,7 @@ cfg_if! { impl client_api::TaggedTransactionQueue for Runtime { fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { if let Extrinsic::IncludeData(data) = utx { - return TransactionValidity::Valid(ValidTransaction{ + return Ok(ValidTransaction{ priority: data.len() as u64, requires: vec![], provides: vec![data], diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 519af99ae10b8..36b67d4ade928 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -189,7 +189,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { p }; - TransactionValidity::Valid(ValidTransaction { + Ok(ValidTransaction { priority: tx.amount, requires, provides, diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 83c9311089ee2..06af044d418e1 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -34,7 +34,7 @@ use parking_lot::{Mutex, RwLock}; use sr_primitives::{ generic::BlockId, traits::{self, SaturatedConversion}, - transaction_validity::{TransactionValidity, TransactionTag as Tag}, + transaction_validity::{TransactionValidity, TransactionTag as Tag, TransactionValidityError}, }; pub use crate::base_pool::Limit; @@ -129,7 +129,7 @@ impl Pool { } match self.api.validate_transaction(at, xt.clone())? { - TransactionValidity::Valid(validity) => if validity.provides.is_empty() { + Ok(validity) => if validity.provides.is_empty() { Err(error::Error::NoTagsProvided.into()) } else { Ok(base::Transaction { @@ -146,10 +146,10 @@ impl Pool { .saturating_add(validity.longevity), }) }, - TransactionValidity::Invalid(e) => { + Err(TransactionValidityError::Invalid(e)) => { Err(error::Error::InvalidTransaction(e).into()) }, - TransactionValidity::Unknown(e) => { + Err(TransactionValidityError::Unknown(e)) => { self.listener.write().invalid(&hash); Err(error::Error::UnknownTransaction(e).into()) }, @@ -245,7 +245,7 @@ impl Pool { None => { let validity = self.api.validate_transaction(parent, extrinsic.clone()); match validity { - Ok(TransactionValidity::Valid(mut validity)) => { + Ok(Ok(mut validity)) => { tags.append(&mut validity.provides); }, // silently ignore invalid extrinsics, @@ -494,7 +494,7 @@ mod tests { if nonce < block_number { Ok(InvalidTransaction::Stale.into()) } else { - Ok(TransactionValidity::Valid(ValidTransaction { + Ok(Ok(ValidTransaction { priority: 4, requires: if nonce > block_number { vec![vec![nonce as u8 - 1]] } else { vec![] }, provides: if nonce == INVALID_NONCE { vec![] } else { vec![vec![nonce as u8]] }, diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs index 71ed988e5e7b3..1661b7108b9f8 100644 --- a/core/transaction-pool/src/tests.rs +++ b/core/transaction-pool/src/tests.rs @@ -39,7 +39,11 @@ impl txpool::ChainApi for TestApi { type Hash = Hash; type Error = error::Error; - fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { + fn validate_transaction( + &self, + at: &BlockId, + uxt: txpool::ExtrinsicFor, + ) -> error::Result { let expected = index(at); let requires = if expected == uxt.transfer().nonce { vec![] @@ -48,13 +52,15 @@ impl txpool::ChainApi for TestApi { }; let provides = vec![vec![uxt.transfer().nonce as u8]]; - Ok(TransactionValidity::Valid(ValidTransaction { - priority: 1, - requires, - provides, - longevity: 64, - propagate: true, - })) + Ok( + Ok(ValidTransaction { + priority: 1, + requires, + provides, + longevity: 64, + propagate: true, + }) + ) } fn block_id_to_number(&self, at: &BlockId) -> error::Result>> { diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 4a6ae26a58569..2116f2894d3a5 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1266,7 +1266,7 @@ impl, I: Instance + Clone + Eq> SignedExtension for TakeFees { // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which // will be a bit more than setting the priority to tip. For now, this is enough. r.priority = fee.saturated_into::(); - r.into() + Ok(r) } } diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 0da8698ff65ea..913bf695d717a 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -987,12 +987,12 @@ impl SignedExtension for CheckBlockGasLimit { ) -> TransactionValidity { let call = match call.is_sub_type() { Some(call) => call, - None => return ValidTransaction::default().into(), + None => return Ok(ValidTransaction::default()), }; match call { Call::claim_surcharge(_, _) | Call::update_schedule(_) => - ValidTransaction::default().into(), + Ok(ValidTransaction::default()), Call::put_code(gas_limit, _) | Call::call(_, _, gas_limit, _) | Call::create(_, gas_limit, _, _) => { @@ -1003,7 +1003,7 @@ impl SignedExtension for CheckBlockGasLimit { // gas limit reached, revert the transaction and retry again in the future InvalidTransaction::ExhaustsResources.into() } else { - ValidTransaction::default().into() + Ok(ValidTransaction::default()) } }, Call::__PhantomItem(_, _) => unreachable!("Variant is never constructed"), diff --git a/srml/contracts/src/tests.rs b/srml/contracts/src/tests.rs index f22885708c69c..b3bbd44cb6e79 100644 --- a/srml/contracts/src/tests.rs +++ b/srml/contracts/src/tests.rs @@ -2405,10 +2405,7 @@ fn check_block_gas_limit_works() { ); let call: Call = crate::Call::update_schedule(Default::default()).into(); - assert_eq!( - check.validate(&0, &call, info, 0), - ValidTransaction::default().into(), - ); + assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default())); } ); -} \ No newline at end of file +} diff --git a/srml/example/src/lib.rs b/srml/example/src/lib.rs index bf2356255c6cf..5d431de675586 100644 --- a/srml/example/src/lib.rs +++ b/srml/example/src/lib.rs @@ -583,9 +583,9 @@ impl SignedExtension for WatchDummy { let mut valid_tx = ValidTransaction::default(); valid_tx.priority = Bounded::max_value(); - valid_tx.into() + Ok(valid_tx) } - _ => ValidTransaction::default().into(), + _ => Ok(Default::default()), } } } @@ -716,7 +716,6 @@ mod tests { assert_eq!( WatchDummy::(PhantomData).validate(&1, &call, info, 150) - .into_valid() .unwrap() .priority, Bounded::max_value(), diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 61a1b5258f5a5..0e57bf597ca52 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -277,11 +277,7 @@ where /// Changes made to storage should be discarded. pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity { let encoded_len = uxt.using_encoded(|d| d.len()); - let xt = match uxt.check(&Default::default()) { - // Checks out. Carry on. - Ok(xt) => xt, - Err(err) => return err.into(), - }; + let xt = uxt.check(&Default::default())?; let dispatch_info = xt.get_dispatch_info(); xt.validate::(dispatch_info, encoded_len) @@ -377,7 +373,7 @@ mod tests { fn validate_unsigned(call: &Self::Call) -> TransactionValidity { match call { - Call::set_balance(_, _, _) => TransactionValidity::Valid(Default::default()), + Call::set_balance(_, _, _) => Ok(Default::default()), _ => UnknownTransaction::NoUnsignedValidator.into(), } } @@ -574,11 +570,10 @@ mod tests { #[test] fn validate_unsigned() { let xt = sr_primitives::testing::TestXt(None, Call::set_balance(33, 69, 69)); - let valid = TransactionValidity::Valid(Default::default()); let mut t = new_test_ext(1); with_externalities(&mut t, || { - assert_eq!(Executive::validate_transaction(xt.clone()), valid); + assert_eq!(Executive::validate_transaction(xt.clone()), Ok(Default::default())); assert_eq!( Executive::apply_extrinsic(xt), Ok( diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 35e3121ea751f..a06d758c57bdd 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -519,16 +519,16 @@ impl srml_support::unsigned::ValidateUnsigned for Module { return InvalidTransaction::BadProof.into(); } - return TransactionValidity::Valid(ValidTransaction { + Ok(ValidTransaction { priority: 0, requires: vec![], provides: vec![(current_session, authority_id).encode()], longevity: TransactionLongevity::max_value(), propagate: true, }) + } else { + InvalidTransaction::Call.into() } - - InvalidTransaction::Call.into() } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 8d269c609c30c..c0df53befb945 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -951,14 +951,14 @@ impl SignedExtension for CheckWeight { // discards any transaction which is bigger than the length or weight limit **alone**, which // is a guarantee that it will fail in the pre-dispatch phase. if let Err(e) = Self::check_block_length(info, len) { - return e.into(); + return Err(e); } if let Err(e) = Self::check_weight(info) { - return e.into(); + return Err(e); } - ValidTransaction { priority: Self::get_priority(info), ..Default::default() }.into() + Ok(ValidTransaction { priority: Self::get_priority(info), ..Default::default() }) } } @@ -1037,13 +1037,13 @@ impl SignedExtension for CheckNonce { vec![] }; - ValidTransaction { + Ok(ValidTransaction { priority: info.weight as TransactionPriority, requires, provides, longevity: TransactionLongevity::max_value(), propagate: true, - }.into() + }) } } @@ -1080,10 +1080,10 @@ impl SignedExtension for CheckEra { ) -> TransactionValidity { let current_u64 = >::block_number().saturated_into::(); let valid_till = (self.0).0.death(current_u64); - ValidTransaction { + Ok(ValidTransaction { longevity: valid_till.saturating_sub(current_u64), ..Default::default() - }.into() + }) } fn additional_signed(&self) -> Result { @@ -1384,13 +1384,13 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; // stale - assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_invalid_or_unknown()); + assert!(CheckNonce::(0).validate(&1, CALL, info, len).is_err()); assert!(CheckNonce::(0).pre_dispatch(&1, CALL, info, len).is_err()); // correct - assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_valid()); + assert!(CheckNonce::(1).validate(&1, CALL, info, len).is_ok()); assert!(CheckNonce::(1).pre_dispatch(&1, CALL, info, len).is_ok()); // future - assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_valid()); + assert!(CheckNonce::(5).validate(&1, CALL, info, len).is_ok()); assert!(CheckNonce::(5).pre_dispatch(&1, CALL, info, len).is_err()); }) } @@ -1481,14 +1481,12 @@ mod tests { let priority = CheckWeight::(PhantomData) .validate(&1, CALL, normal, len) - .into_valid() .unwrap() .priority; assert_eq!(priority, 100); let priority = CheckWeight::(PhantomData) .validate(&1, CALL, op, len) - .into_valid() .unwrap() .priority; assert_eq!(priority, Bounded::max_value()); @@ -1547,10 +1545,7 @@ mod tests { System::set_block_number(17); >::insert(16, H256::repeat_byte(1)); - assert_eq!( - ext.validate(&1, CALL, normal, len).into_valid().unwrap().longevity, - 15, - ); + assert_eq!(ext.validate(&1, CALL, normal, len).unwrap().longevity, 15); }) } } From 91b0869920fe2452a02e033c144ea01cb9b05b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 2 Sep 2019 21:20:07 +0200 Subject: [PATCH 74/80] Apply suggestions from code review Co-Authored-By: Gavin Wood --- core/sr-primitives/src/lib.rs | 2 +- srml/contracts/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 2e8808f46093b..0a66fcb15b39c 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -651,7 +651,7 @@ impl From for &'static str { fn from(err: ApplyError) -> &'static str { match err { ApplyError::NoPermission => "Transaction does not have required permissions", - ApplyError::BadState => "System in bad state", + ApplyError::BadState => "System state currently prevents this transaction", ApplyError::Validity(v) => v.into(), } } diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index 913bf695d717a..da1b9283998a5 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -995,7 +995,8 @@ impl SignedExtension for CheckBlockGasLimit { Ok(ValidTransaction::default()), Call::put_code(gas_limit, _) | Call::call(_, _, gas_limit, _) - | Call::create(_, gas_limit, _, _) => { + | Call::create(_, gas_limit, _, _) + => { // Check if the specified amount of gas is available in the current block. // This cannot underflow since `gas_spent` is never greater than `T::BlockGasLimit`. let gas_available = T::BlockGasLimit::get() - >::gas_spent(); From 86ef4eb9310f0c74ea46b3e8f51616ca5e609e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Mon, 2 Sep 2019 21:39:11 +0200 Subject: [PATCH 75/80] Beautify the code a little bit and fix test --- core/sr-primitives/src/generic/checked_extrinsic.rs | 3 +-- core/sr-primitives/src/lib.rs | 6 +++--- core/sr-primitives/src/testing.rs | 5 ++--- core/sr-primitives/src/transaction_validity.rs | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index d2b45f5a612b2..c82e1b077df09 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -22,7 +22,6 @@ use crate::traits::{ }; use crate::weights::{GetDispatchInfo, DispatchInfo}; use crate::transaction_validity::TransactionValidity; -use crate::DispatchError; /// Definition of something that the external world might want to say; its /// existence implies that it has been checked and is good, particularly with @@ -81,7 +80,7 @@ where }; let res = self.function.dispatch(Origin::from(maybe_who)); Extra::post_dispatch(pre, info, len); - Ok(res.map_err(|e| DispatchError::from(e.into()).into()).into()) + Ok(res.into()) } } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 0a66fcb15b39c..850810eb5c883 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -679,11 +679,11 @@ impl From for ApplyOutcome { } } -impl From> for ApplyOutcome { - fn from(res: Result<(), DispatchError>) -> Self { +impl> From> for ApplyOutcome { + fn from(res: Result<(), T>) -> Self { match res { Ok(()) => ApplyOutcome::Success, - Err(e) => e.into(), + Err(e) => ApplyOutcome::Fail(e.into()), } } } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index eeb45f833c119..2a3be078fa9ee 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -23,7 +23,7 @@ use crate::traits::{ self, Checkable, Applyable, BlakeTwo256, OpaqueKeys, ValidateUnsigned, SignedExtension, Dispatchable, }; -use crate::{generic, KeyTypeId, ApplyResult, DispatchError}; +use crate::{generic, KeyTypeId, ApplyResult}; use crate::weights::{GetDispatchInfo, DispatchInfo}; pub use primitives::H256; use primitives::{crypto::{CryptoType, Dummy, key_types, Public}, U256}; @@ -320,8 +320,7 @@ impl Applyable for TestXt where None }; - let res = self.1.dispatch(maybe_who.into()); - Ok(res.map_err(|e| DispatchError::from(e.into()).into()).into()) + Ok(self.1.dispatch(maybe_who.into()).into()) } } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 5e149fdade6ab..53bda23f82e76 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -250,7 +250,7 @@ mod tests { let encoded = v.encode(); assert_eq!( encoded, - vec![1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0] + vec![0, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0, 0] ); // decode back From 354e05f12758fb2564c65d7a4744bf2ced5688ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 3 Sep 2019 08:13:05 +0200 Subject: [PATCH 76/80] Make `CannotLookup` an inherent error declared by `decl_error!` --- .../src/generic/unchecked_extrinsic.rs | 7 ++--- core/sr-primitives/src/traits.rs | 28 +++++++++++++++---- srml/assets/src/lib.rs | 2 +- srml/balances/src/lib.rs | 8 +++--- srml/contracts/src/lib.rs | 2 +- srml/elections/src/lib.rs | 6 ++-- srml/indices/src/lib.rs | 6 ++-- srml/scored-pool/src/lib.rs | 4 +-- srml/staking/src/lib.rs | 7 ++--- srml/sudo/src/lib.rs | 2 +- srml/support/src/error.rs | 14 +++++++++- srml/system/src/lib.rs | 4 +-- srml/treasury/src/lib.rs | 2 +- 13 files changed, 59 insertions(+), 33 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 1bcdd9bd253fb..48614946d6d13 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -24,10 +24,7 @@ use runtime_io::blake2_256; use codec::{Decode, Encode, Input, Error}; use crate::{ traits::{self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic}, - generic::CheckedExtrinsic, - transaction_validity::{ - TransactionValidityError, InvalidTransaction, UnknownTransaction, - }, + generic::CheckedExtrinsic, transaction_validity::{TransactionValidityError, InvalidTransaction}, }; const TRANSACTION_VERSION: u8 = 3; @@ -113,7 +110,7 @@ where fn check(self, lookup: &Lookup) -> Result { Ok(match self.signature { Some((signed, signature, extra)) => { - let signed = lookup.lookup(signed).ok_or(UnknownTransaction::CannotLookup)?; + let signed = lookup.lookup(signed)?; let raw_payload = SignedPayload::new(self.function, extra)?; if !raw_payload.using_encoded(|payload| { signature.verify(payload, &signed) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index dc1bd7274fd88..0ac40e9942412 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -23,7 +23,9 @@ use runtime_io; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use primitives::{self, Hasher, Blake2Hasher}; use crate::codec::{Codec, Encode, Decode, HasCompact}; -use crate::transaction_validity::{ValidTransaction, TransactionValidity, TransactionValidityError}; +use crate::transaction_validity::{ + ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, +}; use crate::generic::{Digest, DigestItem}; use crate::weights::DispatchInfo; pub use integer_sqrt::IntegerSquareRoot; @@ -115,6 +117,22 @@ pub trait EnsureOrigin { fn try_origin(o: OuterOrigin) -> result::Result; } +/// An error that indicates that a lookup failed. +#[derive(Encode, Decode)] +pub struct LookupError; + +impl From for &'static str { + fn from(_: LookupError) -> &'static str { + "Can not lookup" + } +} + +impl From for TransactionValidityError { + fn from(_: LookupError) -> Self { + UnknownTransaction::CannotLookup.into() + } +} + /// Means of changing one type into another in a manner dependent on the source type. pub trait Lookup { /// Type to lookup from. @@ -122,7 +140,7 @@ pub trait Lookup { /// Type to lookup into. type Target; /// Attempt a lookup. - fn lookup(&self, s: Self::Source) -> Option; + fn lookup(&self, s: Self::Source) -> Result; } /// Means of changing one type into another in a manner dependent on the source type. @@ -134,7 +152,7 @@ pub trait StaticLookup { /// Type to lookup into. type Target; /// Attempt a lookup. - fn lookup(s: Self::Source) -> Option; + fn lookup(s: Self::Source) -> Result; /// Convert from Target back to Source. fn unlookup(t: Self::Target) -> Self::Source; } @@ -145,14 +163,14 @@ pub struct IdentityLookup(PhantomData); impl StaticLookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(x: T) -> Option { Some(x) } + fn lookup(x: T) -> Result { Ok(x) } fn unlookup(x: T) -> T { x } } impl Lookup for IdentityLookup { type Source = T; type Target = T; - fn lookup(&self, x: T) -> Option { Some(x) } + fn lookup(&self, x: T) -> Result { Ok(x) } } /// Extensible conversion trait. Generic over both source and destination types. diff --git a/srml/assets/src/lib.rs b/srml/assets/src/lib.rs index 252cae3bcfe6b..a8268d146305a 100644 --- a/srml/assets/src/lib.rs +++ b/srml/assets/src/lib.rs @@ -174,7 +174,7 @@ decl_module! { let origin = ensure_signed(origin)?; let origin_account = (id, origin.clone()); let origin_balance = >::get(&origin_account); - let target = T::Lookup::lookup(target).ok_or("could not find `target` account")?; + let target = T::Lookup::lookup(target)?; ensure!(!amount.is_zero(), "transfer amount should be non-zero"); ensure!(origin_balance >= amount, "origin account balance must be greater than or equal to the transfer amount"); diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 2116f2894d3a5..54e087abe7047 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -450,7 +450,7 @@ decl_module! { #[compact] value: T::Balance ) { let transactor = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; + let dest = T::Lookup::lookup(dest)?; >::transfer(&transactor, &dest, value)?; } @@ -475,7 +475,7 @@ decl_module! { #[compact] new_reserved: T::Balance ) { ensure_root(origin)?; - let who = T::Lookup::lookup(who).ok_or("could not find `who` account")?; + let who = T::Lookup::lookup(who)?; let current_free = >::get(&who); if new_free > current_free { @@ -504,8 +504,8 @@ decl_module! { #[compact] value: T::Balance ) { ensure_root(origin)?; - let source = T::Lookup::lookup(source).ok_or("could not find `source` account")?; - let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; + let source = T::Lookup::lookup(source)?; + let dest = T::Lookup::lookup(dest)?; >::transfer(&source, &dest, value)?; } } diff --git a/srml/contracts/src/lib.rs b/srml/contracts/src/lib.rs index da1b9283998a5..e0168c4602f40 100644 --- a/srml/contracts/src/lib.rs +++ b/srml/contracts/src/lib.rs @@ -571,7 +571,7 @@ decl_module! { data: Vec ) -> Result { let origin = ensure_signed(origin)?; - let dest = T::Lookup::lookup(dest).ok_or("could not find `dest` account")?; + let dest = T::Lookup::lookup(dest)?; Self::execute_wasm(origin, gas_limit, |ctx, gas_meter| { ctx.call(dest, value, gas_meter, data) diff --git a/srml/elections/src/lib.rs b/srml/elections/src/lib.rs index 51c9b2bcadc4d..42b31d86a00c2 100644 --- a/srml/elections/src/lib.rs +++ b/srml/elections/src/lib.rs @@ -365,7 +365,7 @@ decl_module! { #[compact] assumed_vote_index: VoteIndex ) { let reporter = ensure_signed(origin)?; - let who = T::Lookup::lookup(who).ok_or("Could not find `who` account")?; + let who = T::Lookup::lookup(who)?; ensure!(!Self::presentation_active(), "cannot reap during presentation period"); ensure!(Self::voter_info(&reporter).is_some(), "reporter must be a voter"); @@ -507,7 +507,7 @@ decl_module! { "stake deposited to present winner and be added to leaderboard should be non-zero", ); - let candidate = T::Lookup::lookup(candidate).ok_or("could not find `candidate` account")?; + let candidate = T::Lookup::lookup(candidate)?; ensure!(index == Self::vote_index(), "index not current"); let (_, _, expiring) = Self::next_finalize().ok_or("cannot present outside of presentation period")?; let bad_presentation_punishment = @@ -576,7 +576,7 @@ decl_module! { #[weight = SimpleDispatchInfo::FixedOperational(10_000)] fn remove_member(origin, who: ::Source) { ensure_root(origin)?; - let who = T::Lookup::lookup(who).ok_or("could not find `who` account")?; + let who = T::Lookup::lookup(who)?; let new_set: Vec<(T::AccountId, T::BlockNumber)> = Self::members() .into_iter() .filter(|i| i.0 != who) diff --git a/srml/indices/src/lib.rs b/srml/indices/src/lib.rs index db333a768956d..458e9a182c282 100644 --- a/srml/indices/src/lib.rs +++ b/srml/indices/src/lib.rs @@ -22,7 +22,7 @@ use rstd::{prelude::*, marker::PhantomData, convert::TryInto}; use codec::{Encode, Codec}; use srml_support::{StorageValue, StorageMap, Parameter, decl_module, decl_event, decl_storage}; -use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member}; +use sr_primitives::traits::{One, SimpleArithmetic, StaticLookup, Member, LookupError}; use system::{IsDeadAccount, OnNewAccount}; use self::address::Address as RawAddress; @@ -225,8 +225,8 @@ impl StaticLookup for Module { type Source = address::Address; type Target = T::AccountId; - fn lookup(a: Self::Source) -> Option { - Self::lookup_address(a) + fn lookup(a: Self::Source) -> Result { + Self::lookup_address(a).ok_or(LookupError) } fn unlookup(a: Self::Target) -> Self::Source { diff --git a/srml/scored-pool/src/lib.rs b/srml/scored-pool/src/lib.rs index 62dff884896df..dc27b3bba9958 100644 --- a/srml/scored-pool/src/lib.rs +++ b/srml/scored-pool/src/lib.rs @@ -304,7 +304,7 @@ decl_module! { .or_else(ensure_root) .map_err(|_| "bad origin")?; - let who = T::Lookup::lookup(dest).ok_or("Could not find `dest` account")?; + let who = T::Lookup::lookup(dest)?; let pool = >::get(); Self::ensure_index(&pool, &who, index)?; @@ -330,7 +330,7 @@ decl_module! { .or_else(ensure_root) .map_err(|_| "bad origin")?; - let who = T::Lookup::lookup(dest).ok_or("Could not find `dest` account")?; + let who = T::Lookup::lookup(dest)?; let mut pool = >::get(); Self::ensure_index(&pool, &who, index)?; diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 07ca92a70530e..69bd04f9e1fe7 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -704,8 +704,7 @@ decl_module! { return Err("stash already bonded") } - let controller = T::Lookup::lookup(controller) - .ok_or("could not find `controller` account")?; + let controller = T::Lookup::lookup(controller)?; if >::exists(&controller) { return Err("controller already paired") @@ -883,7 +882,7 @@ decl_module! { ensure!(!targets.is_empty(), "targets cannot be empty"); let targets = targets.into_iter() .take(MAX_NOMINATIONS) - .map(|t| T::Lookup::lookup(t).ok_or("could not find a target account")) + .map(|t| T::Lookup::lookup(t)) .collect::, _>>()?; >::remove(stash); @@ -944,7 +943,7 @@ decl_module! { fn set_controller(origin, controller: ::Source) { let stash = ensure_signed(origin)?; let old_controller = Self::bonded(&stash).ok_or("not a stash")?; - let controller = T::Lookup::lookup(controller).ok_or("could not find `controller` account")?; + let controller = T::Lookup::lookup(controller)?; if >::exists(&controller) { return Err("controller already paired") } diff --git a/srml/sudo/src/lib.rs b/srml/sudo/src/lib.rs index e915dfd77d91a..c4ee4319ad45a 100644 --- a/srml/sudo/src/lib.rs +++ b/srml/sudo/src/lib.rs @@ -146,7 +146,7 @@ decl_module! { // This is a public call, so we ensure that the origin is some signed account. let sender = ensure_signed(origin)?; ensure!(sender == Self::key(), "only the current sudo key can change the sudo key"); - let new = T::Lookup::lookup(new).ok_or("could not find requested account")?; + let new = T::Lookup::lookup(new)?; Self::deposit_event(RawEvent::KeyChanged(Self::key())); >::put(new); diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 3bc0f989ccbf4..157a5179fabeb 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -16,6 +16,9 @@ //! Macro for declaring a module error. +#[doc(hidden)] +pub use sr_primitives::traits::LookupError; + #[macro_export] macro_rules! decl_error { ( @@ -33,6 +36,7 @@ macro_rules! decl_error { $(#[$attr])* pub enum $error { Other(&'static str), + CannotLookup, $( $(#[$variant_attr])* $name @@ -46,7 +50,7 @@ macro_rules! decl_error { self $error {} - 1, + 2, $( $name ),* } } @@ -54,6 +58,7 @@ macro_rules! decl_error { fn as_str(&self) -> &'static str { match self { $error::Other(err) => err, + $error::CannotLookup => "Can not lookup", $( $error::$name => stringify!($name), )* @@ -67,6 +72,12 @@ macro_rules! decl_error { } } + impl From<$crate::error::LookupError> for $error { + fn from(_: $crate::error::LookupError) -> $error { + $error::CannotLookup + } + } + impl From<$error> for &'static str { fn from(err: $error) -> &'static str { use $crate::dispatch::ModuleDispatchError; @@ -109,6 +120,7 @@ macro_rules! decl_error { ) => { match $self { $error::Other(_) => 0, + $error::CannotLookup => 1, $( $generated )* } } diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index c0df53befb945..a46618edb8ce7 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -103,7 +103,7 @@ use sr_primitives::{ InvalidTransaction, TransactionValidity, }, traits::{ - self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, Lookup, + self, CheckEqual, SimpleArithmetic, Zero, SignedExtension, Convert, Lookup, LookupError, SimpleBitOps, Hash, Member, MaybeDisplay, EnsureOrigin, SaturatedConversion, MaybeSerializeDebugButNotDeserialize, MaybeSerializeDebug, StaticLookup, One, Bounded, }, @@ -1166,7 +1166,7 @@ impl Lookup for ChainContext { type Source = ::Source; type Target = ::Target; - fn lookup(&self, s: Self::Source) -> Option { + fn lookup(&self, s: Self::Source) -> Result { ::lookup(s) } } diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index df57f57c7dfe5..ef2b9e69fec9f 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -156,7 +156,7 @@ decl_module! { beneficiary: ::Source ) { let proposer = ensure_signed(origin)?; - let beneficiary = T::Lookup::lookup(beneficiary).ok_or("could not find `beneficiary`")?; + let beneficiary = T::Lookup::lookup(beneficiary)?; let bond = Self::calculate_bond(value); T::Currency::reserve(&proposer, bond) From 674371993805f8e6c79f9eaa42aa748bdb1bc014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 3 Sep 2019 08:52:54 +0200 Subject: [PATCH 77/80] Adds some documentation --- srml/support/src/error.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/srml/support/src/error.rs b/srml/support/src/error.rs index 157a5179fabeb..2f9d9379bfd04 100644 --- a/srml/support/src/error.rs +++ b/srml/support/src/error.rs @@ -19,6 +19,30 @@ #[doc(hidden)] pub use sr_primitives::traits::LookupError; +/// Declare an error type for a runtime module. +/// +/// The generated error type inherently has the variants `Other` and `CannotLookup`. `Other` can +/// hold any `&'static str` error message and is present for convenience/backward compatibility. +/// The `CannotLookup` variant indicates that some lookup could not be done. For both variants the +/// error type implements `From<&'static str>` and `From` to make them usable with the +/// try operator. +/// +/// # Usage +/// +/// ``` +/// # use srml_support::decl_error; +/// decl_error! { +/// /// Errors that can occur in my module. +/// pub enum MyError { +/// /// Hey this is an error message that indicates bla. +/// MyCoolErrorMessage, +/// /// You are just not cool enough for my module! +/// YouAreNotCoolEnough, +/// } +/// } +/// ``` +/// +/// `decl_error!` supports only variants that do not hold any data. #[macro_export] macro_rules! decl_error { ( From b9fc817b438daa4b24e101568a398f1e28400964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 3 Sep 2019 09:48:25 +0200 Subject: [PATCH 78/80] Make `ApplyOutcome` a result --- .../client/src/block_builder/block_builder.rs | 3 +-- .../src/generic/checked_extrinsic.rs | 2 +- core/sr-primitives/src/lib.rs | 20 ++----------------- core/sr-primitives/src/testing.rs | 2 +- core/test-runtime/src/system.rs | 13 ++++++------ node/executor/src/lib.rs | 6 ++++-- srml/executive/src/lib.rs | 16 +++++++-------- srml/system/src/lib.rs | 11 ++++------ 8 files changed, 27 insertions(+), 46 deletions(-) diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 75b3385e95d23..833555095d905 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -17,7 +17,6 @@ use super::api::BlockBuilder as BlockBuilderApi; use std::vec::Vec; use codec::Encode; -use sr_primitives::ApplyOutcome; use sr_primitives::generic::BlockId; use sr_primitives::traits::{ Header as HeaderT, Hash, Block as BlockT, One, HashFor, ProvideRuntimeApi, ApiRef, DigestFor, @@ -104,7 +103,7 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - Ok(ApplyOutcome::Success) | Ok(ApplyOutcome::Fail(_)) => { + Ok(Ok(())) | Ok(Err(_)) => { extrinsics.push(xt); Ok(()) } diff --git a/core/sr-primitives/src/generic/checked_extrinsic.rs b/core/sr-primitives/src/generic/checked_extrinsic.rs index c82e1b077df09..e8d41325c4324 100644 --- a/core/sr-primitives/src/generic/checked_extrinsic.rs +++ b/core/sr-primitives/src/generic/checked_extrinsic.rs @@ -80,7 +80,7 @@ where }; let res = self.function.dispatch(Origin::from(maybe_who)); Extra::post_dispatch(pre, info, len); - Ok(res.into()) + Ok(res.map_err(Into::into)) } } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 850810eb5c883..bcd54c660b8a7 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -664,27 +664,11 @@ impl From for ApplyError { } /// The outcome of applying a transaction. -#[derive(Eq, PartialEq, Clone, Copy, Decode, Encode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] -pub enum ApplyOutcome { - /// The transaction was applied successfully. - Success, - /// Any error that occurred in a module while dispatching the transaction. - Fail(DispatchError), -} +pub type ApplyOutcome = Result<(), DispatchError>; impl From for ApplyOutcome { fn from(err: DispatchError) -> Self { - ApplyOutcome::Fail(err) - } -} - -impl> From> for ApplyOutcome { - fn from(res: Result<(), T>) -> Self { - match res { - Ok(()) => ApplyOutcome::Success, - Err(e) => ApplyOutcome::Fail(e.into()), - } + Err(err) } } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 2a3be078fa9ee..9c827d8a704bd 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -320,7 +320,7 @@ impl Applyable for TestXt where None }; - Ok(self.1.dispatch(maybe_who.into()).into()) + Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into)) } } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index 36b67d4ade928..f1288f8b2806f 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -22,8 +22,7 @@ use runtime_io::{storage_root, ordered_trie_root, storage_changes_root, twox_128 use runtime_support::storage::{self, StorageValue, StorageMap}; use runtime_support::storage_items; use sr_primitives::{ - traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyOutcome, - ApplyResult, + traits::{Hash as HashT, BlakeTwo256, Header as _}, generic, ApplyError, ApplyResult, transaction_validity::{TransactionValidity, ValidTransaction, InvalidTransaction}, }; use codec::{KeyedVec, Encode}; @@ -120,7 +119,7 @@ fn execute_block_with_state_root_handler( // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); + let _ = execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); @@ -253,7 +252,7 @@ fn execute_transaction_backend(utx: &Extrinsic) -> ApplyResult { match utx { Extrinsic::Transfer(ref transfer, _) => execute_transfer_backend(transfer), Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth), - Extrinsic::IncludeData(_) => Ok(ApplyOutcome::Success), + Extrinsic::IncludeData(_) => Ok(Ok(())), Extrinsic::StorageChange(key, value) => execute_storage_change(key, value.as_ref().map(|v| &**v)), } } @@ -281,12 +280,12 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0); storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount)); storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount)); - Ok(ApplyOutcome::Success) + Ok(Ok(())) } fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { NewAuthorities::put(new_authorities.to_vec()); - Ok(ApplyOutcome::Success) + Ok(Ok(())) } fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult { @@ -294,7 +293,7 @@ fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyResult { Some(value) => storage::unhashed::put_raw(key, value), None => storage::unhashed::kill(key), } - Ok(ApplyOutcome::Success) + Ok(Ok(())) } #[cfg(feature = "std")] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index af2989c0ac877..472fce905783d 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -784,8 +784,10 @@ mod tests { assert!(r.is_ok()); let r = WasmExecutor::new() .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); - let r = ApplyResult::decode(&mut &r[..]).unwrap(); - assert_eq!(r, Ok(ApplyOutcome::Success)); + ApplyResult::decode(&mut &r[..]) + .unwrap() + .expect("Extrensic could be applied") + .expect("Extrensic did not fail"); runtime_io::with_externalities(&mut t, || { assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt())); diff --git a/srml/executive/src/lib.rs b/srml/executive/src/lib.rs index 0e57bf597ca52..245c294ec7b39 100644 --- a/srml/executive/src/lib.rs +++ b/srml/executive/src/lib.rs @@ -76,7 +76,7 @@ use rstd::{prelude::*, marker::PhantomData}; use sr_primitives::{ - generic::Digest, ApplyResult, ApplyOutcome, weights::GetDispatchInfo, + generic::Digest, ApplyResult, weights::GetDispatchInfo, traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize, NumberFor, Block as BlockT, OffchainWorker, ValidateUnsigned, Dispatchable @@ -216,8 +216,8 @@ where fn apply_extrinsic_no_note(uxt: Block::Extrinsic) { let l = uxt.encode().len(); match Self::apply_extrinsic_with_len(uxt, l, None) { - Ok(ApplyOutcome::Success) => (), - Ok(ApplyOutcome::Fail(e)) => runtime_io::print(e), + Ok(Ok(())) => (), + Ok(Err(e)) => runtime_io::print(e), Err(e) => { let err: &'static str = e.into(); panic!(err) }, } } @@ -552,9 +552,9 @@ mod tests { assert_eq!(>::all_extrinsics_weight(), 0); assert_eq!(>::all_extrinsics_weight(), 0); - assert_eq!(Executive::apply_extrinsic(xt.clone()).unwrap(), ApplyOutcome::Success); - assert_eq!(Executive::apply_extrinsic(x1.clone()).unwrap(), ApplyOutcome::Success); - assert_eq!(Executive::apply_extrinsic(x2.clone()).unwrap(), ApplyOutcome::Success); + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); // default weight for `TestXt` == encoded length. assert_eq!(>::all_extrinsics_weight(), (3 * len).into()); @@ -577,7 +577,7 @@ mod tests { assert_eq!( Executive::apply_extrinsic(xt), Ok( - ApplyOutcome::Fail( + Err( DispatchError { module: None, error: 0, message: Some("RequireRootOrigin") } ) ) @@ -611,7 +611,7 @@ mod tests { if lock == WithdrawReasons::except(WithdrawReason::TransactionPayment) { assert_eq!( Executive::apply_extrinsic(xt).unwrap(), - ApplyOutcome::Fail(DispatchError { + Err(DispatchError { module: None, error: 0, message: Some("account liquidity restrictions prevent withdrawal"), diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index a46618edb8ce7..375271ab1f496 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -829,8 +829,8 @@ impl Module { pub fn note_applied_extrinsic(r: &ApplyOutcome, _encoded_len: u32) { Self::deposit_event( match r { - ApplyOutcome::Success => Event::ExtrinsicSuccess, - ApplyOutcome::Fail(err) => Event::ExtrinsicFailed(err.clone()), + Ok(()) => Event::ExtrinsicSuccess, + Err(err) => Event::ExtrinsicFailed(err.clone()), } ); @@ -1264,11 +1264,8 @@ mod tests { System::initialize(&2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default()); System::deposit_event(42u16); - System::note_applied_extrinsic(&ApplyOutcome::Success, 0); - System::note_applied_extrinsic( - &ApplyOutcome::Fail(DispatchError::new(Some(1), 2, None)), - 0, - ); + System::note_applied_extrinsic(&Ok(()), 0); + System::note_applied_extrinsic(&Err(DispatchError::new(Some(1), 2, None)), 0); System::note_finished_extrinsics(); System::deposit_event(3u16); System::finalize(); From e1bd019e96754a8bb6cdf6413079a2d2af193199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Tue, 3 Sep 2019 10:17:50 +0200 Subject: [PATCH 79/80] Up the spec_version --- node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 9d028f9ebdf86..46667db36fe2c 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -80,8 +80,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 154, - impl_version: 159, + spec_version: 155, + impl_version: 155, apis: RUNTIME_API_VERSIONS, }; From e0fa417e1b71f5cab7a1a34d6f1785cc1f0430ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Wed, 4 Sep 2019 09:27:53 +0200 Subject: [PATCH 80/80] Apply suggestions from code review Co-Authored-By: Gavin Wood Co-Authored-By: DemiMarie-parity <48690212+DemiMarie-parity@users.noreply.github.com> --- core/client/src/block_builder/block_builder.rs | 2 +- core/sr-primitives/src/transaction_validity.rs | 10 +++++----- core/transaction-pool/graph/src/error.rs | 2 +- node/executor/src/lib.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index 833555095d905..b6fae5068a284 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -103,7 +103,7 @@ where ExecutionContext::BlockConstruction, xt.clone() )? { - Ok(Ok(())) | Ok(Err(_)) => { + Ok(_) => { extrinsics.push(xt); Ok(()) } diff --git a/core/sr-primitives/src/transaction_validity.rs b/core/sr-primitives/src/transaction_validity.rs index 53bda23f82e76..eb6cf3bdbb00e 100644 --- a/core/sr-primitives/src/transaction_validity.rs +++ b/core/sr-primitives/src/transaction_validity.rs @@ -47,7 +47,7 @@ pub enum InvalidTransaction { AncientBirthBlock, /// The transaction would exhaust the resources of current block. /// - /// The transaction might be valid, but there is not enough resources left in the current block. + /// The transaction might be valid, but there are not enough resources left in the current block. ExhaustsResources, /// Any other custom invalid validity that is not covered by this enum. Custom(u8), @@ -84,7 +84,7 @@ impl From for &'static str { #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum UnknownTransaction { - /// Could not lookup some information that are required to validate the transaction. + /// Could not lookup some information that is required to validate the transaction. CannotLookup, /// No validator found for the given unsigned transaction. NoUnsignedValidator, @@ -96,7 +96,7 @@ impl From for &'static str { fn from(unknown: UnknownTransaction) -> &'static str { match unknown { UnknownTransaction::CannotLookup => - "Could not lookup some information to validate the transaction", + "Could not lookup information required to validate the transaction", UnknownTransaction::NoUnsignedValidator => "Could not find an unsigned validator for the unsigned transaction", UnknownTransaction::Custom(_) => "UnknownTransaction custom error", @@ -104,7 +104,7 @@ impl From for &'static str { } } -/// The error that can occur while checking the validity of a transaction. +/// Errors that can occur while checking the validity of a transaction. #[derive(Clone, PartialEq, Eq, Encode, Decode, Copy)] #[cfg_attr(feature = "std", derive(Debug, serde::Serialize))] pub enum TransactionValidityError { @@ -115,7 +115,7 @@ pub enum TransactionValidityError { } impl TransactionValidityError { - /// Returns if the reason for the error was block resource exhaustion. + /// Returns `true` if the reason for the error was block resource exhaustion. pub fn exhausted_resources(&self) -> bool { match self { Self::Invalid(e) => e.exhausted_resources(), diff --git a/core/transaction-pool/graph/src/error.rs b/core/transaction-pool/graph/src/error.rs index a837fd6c2f86e..79006461c6e37 100644 --- a/core/transaction-pool/graph/src/error.rs +++ b/core/transaction-pool/graph/src/error.rs @@ -27,7 +27,7 @@ pub type Result = std::result::Result; #[derive(Debug, derive_more::Display, derive_more::From)] pub enum Error { /// Transaction is not verifiable yet, but might be in the future. - #[display(fmt="Unkown transaction validity: {:?}", _0)] + #[display(fmt="Unknown transaction validity: {:?}", _0)] UnknownTransaction(UnknownTransaction), /// Transaction is invalid. #[display(fmt="Invalid transaction validity: {:?}", _0)] diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 472fce905783d..fc0ca390497e4 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -786,8 +786,8 @@ mod tests { .call(&mut t, 8, COMPACT_CODE, "BlockBuilder_apply_extrinsic", &vec![].and(&xt())).unwrap(); ApplyResult::decode(&mut &r[..]) .unwrap() - .expect("Extrensic could be applied") - .expect("Extrensic did not fail"); + .expect("Extrinsic could be applied") + .expect("Extrinsic did not fail"); runtime_io::with_externalities(&mut t, || { assert_eq!(Balances::total_balance(&alice()), 42 * DOLLARS - 1 * transfer_fee(&xt()));