diff --git a/substrate/core/sr-primitives/src/testing.rs b/substrate/core/sr-primitives/src/testing.rs index 6e650eca20..e8e5aa20b4 100644 --- a/substrate/core/sr-primitives/src/testing.rs +++ b/substrate/core/sr-primitives/src/testing.rs @@ -199,7 +199,10 @@ impl<'a, Xt> Deserialize<'a> for Block where Block: Decode { } } -/// Test transaction +/// Test transaction, tuple of (sender, index, call) +/// with index only used if sender is some. +/// +/// If sender is some then the transaction is signed otherwise it is unsigned. #[derive(PartialEq, Eq, Clone, Encode, Decode)] pub struct TestXt(pub Option, pub u64, pub Call); @@ -222,7 +225,7 @@ impl Checkable for TestXt { } impl traits::Extrinsic for TestXt { fn is_signed(&self) -> Option { - None + Some(self.0.is_some()) } } impl Applyable for TestXt where diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index e765748b4f..dd41c3f685 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -23,6 +23,7 @@ use runtime_io; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use substrate_primitives::{self, Hasher, Blake2Hasher}; use crate::codec::{Codec, Encode, HasCompact}; +use crate::transaction_validity::TransactionValidity; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{ Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, @@ -786,3 +787,17 @@ pub trait RuntimeApiInfo { /// The version of the runtime api. const VERSION: u32; } + +/// Something that can validate unsigned extrinsics. +pub trait ValidateUnsigned { + /// The call to validate + type Call; + + /// Return the validity of the call + /// + /// This doesn't execute any side-effects; it merely checks + /// whether the transaction would panic if it were included or not. + /// + /// Changes made to storage should be discarded by caller. + fn validate_unsigned(call: &Self::Call) -> TransactionValidity; +} diff --git a/substrate/node-template/runtime/src/lib.rs b/substrate/node-template/runtime/src/lib.rs index 81adf200d0..30560989a8 100644 --- a/substrate/node-template/runtime/src/lib.rs +++ b/substrate/node-template/runtime/src/lib.rs @@ -224,7 +224,7 @@ pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive; +pub type Executive = executive::Executive; // Implement our runtime API endpoints. This is just a bunch of proxying. impl_runtime_apis! { diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index faaa724302..a2d9a310cb 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -34,7 +34,7 @@ use client::{ use runtime_primitives::{ApplyResult, generic, create_runtime_str}; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::traits::{ - BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, AuthorityIdFor, Convert + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, AuthorityIdFor, Convert, }; use version::RuntimeVersion; use council::{motions as council_motions, voting as council_voting}; @@ -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: 74, - impl_version: 74, + spec_version: 75, + impl_version: 75, apis: RUNTIME_API_VERSIONS, }; @@ -249,7 +249,7 @@ pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = executive::Executive, Balances, AllModules>; +pub type Executive = executive::Executive, Balances, Runtime, AllModules>; impl_runtime_apis! { impl client_api::Core for Runtime { diff --git a/substrate/srml/balances/src/lib.rs b/substrate/srml/balances/src/lib.rs index 0983c2757a..90f774dbf3 100644 --- a/substrate/srml/balances/src/lib.rs +++ b/substrate/srml/balances/src/lib.rs @@ -105,7 +105,7 @@ //! pub type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; //! //! # fn main() {} -//!``` +//! ``` //! //! The Staking module uses the `LockableCurrency` trait to lock a stash account's funds: //! diff --git a/substrate/srml/consensus/src/lib.rs b/substrate/srml/consensus/src/lib.rs index 031c489b8f..696b9d75f4 100644 --- a/substrate/srml/consensus/src/lib.rs +++ b/substrate/srml/consensus/src/lib.rs @@ -136,7 +136,7 @@ use srml_support::storage::StorageValue; use srml_support::storage::unhashed::StorageVec; use primitives::traits::{MaybeSerializeDebug, Member}; use substrate_primitives::storage::well_known_keys; -use system::{ensure_signed, ensure_inherent}; +use system::{ensure_signed, ensure_none}; use inherents::{ ProvideInherent, InherentData, InherentIdentifier, RuntimeString, MakeFatalError }; @@ -298,7 +298,7 @@ decl_module! { /// Note that the previous block's validator missed its opportunity to propose a block. fn note_offline(origin, offline: ::Inherent) { - ensure_inherent(origin)?; + ensure_none(origin)?; T::InherentOfflineReport::handle_report(offline); } diff --git a/substrate/srml/contract/src/lib.rs b/substrate/srml/contract/src/lib.rs index ec71573fb6..b6e8c70e8d 100644 --- a/substrate/srml/contract/src/lib.rs +++ b/substrate/srml/contract/src/lib.rs @@ -476,7 +476,7 @@ decl_module! { Some(system::RawOrigin::Signed(ref account)) if aux_sender.is_none() => { (true, account) }, - Some(system::RawOrigin::Inherent) if aux_sender.is_some() => { + Some(system::RawOrigin::None) if aux_sender.is_some() => { (false, aux_sender.as_ref().expect("checked above")) }, _ => return Err("Invalid surcharge claim: origin must be signed or \ diff --git a/substrate/srml/contract/src/tests.rs b/substrate/srml/contract/src/tests.rs index 8065999d5c..a428018f89 100644 --- a/substrate/srml/contract/src/tests.rs +++ b/substrate/srml/contract/src/tests.rs @@ -754,7 +754,7 @@ fn call_contract_removals() { #[test] fn inherent_claim_surcharge_contract_removals() { - removals(|| Contract::claim_surcharge(Origin::INHERENT, BOB, Some(ALICE)).is_ok()); + removals(|| Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok()); } #[test] @@ -765,10 +765,10 @@ fn signed_claim_surcharge_contract_removals() { #[test] fn claim_surcharge_malus() { // Test surcharge malus for inherent - claim_surcharge(4, || Contract::claim_surcharge(Origin::INHERENT, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(3, || Contract::claim_surcharge(Origin::INHERENT, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(2, || Contract::claim_surcharge(Origin::INHERENT, BOB, Some(ALICE)).is_ok(), true); - claim_surcharge(1, || Contract::claim_surcharge(Origin::INHERENT, BOB, Some(ALICE)).is_ok(), false); + claim_surcharge(4, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(3, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(2, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); + claim_surcharge(1, || Contract::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), false); // Test surcharge malus for signed claim_surcharge(4, || Contract::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); diff --git a/substrate/srml/example/src/lib.rs b/substrate/srml/example/src/lib.rs index 6960d635ed..33c023ee8a 100644 --- a/substrate/srml/example/src/lib.rs +++ b/substrate/srml/example/src/lib.rs @@ -107,9 +107,9 @@ //! //! \### Supported Origins //! -//! // What origins are used and supported in this module (root, signed, inherent) +//! // What origins are used and supported in this module (root, signed, none) //! // i.e. root when \`ensure_root\` used -//! // i.e. inherent when \`ensure_inherent\` used +//! // i.e. none when \`ensure_none\` used //! // i.e. signed when \`ensure_signed\` used //! //! \`inherent\` @@ -322,7 +322,9 @@ decl_event!( // Generally you'll want to split these into three groups: // - Public calls that are signed by an external account. // - Root calls that are allowed to be made only by the governance system. -// - Inherent calls that are allowed to be made only by the block authors and validators. +// - Unsigned calls that can be of two kinds: +// * "Inherent extrinsics" that are opinions generally held by the block authors that build child blocks. +// * Unsigned Transactions that are of intrinsic recognisable utility to the network, and are validated by the runtime. // // Information about where this dispatch initiated from is provided as the first argument // "origin". As such functions must always look like: @@ -337,10 +339,10 @@ decl_event!( // `fn foo(origin: T::Origin, bar: Bar, baz: Baz) { ... }` // // There are three entries in the `system::Origin` enum that correspond -// to the above bullets: `::Signed(AccountId)`, `::Root` and `::Inherent`. You should always match +// to the above bullets: `::Signed(AccountId)`, `::Root` and `::None`. You should always match // against them as the first thing you do in your function. There are three convenience calls // in system that do the matching for you and return a convenient result: `ensure_signed`, -// `ensure_root` and `ensure_inherent`. +// `ensure_root` and `ensure_none`. decl_module! { // Simple declaration of the `Module` type. Lets the macro know what its working on. pub struct Module for enum Call where origin: T::Origin { @@ -448,7 +450,7 @@ decl_module! { // For instance you can generate extrinsics for the upcoming produced block. fn offchain_worker(_n: T::BlockNumber) { // We don't do anything here. - // but we could dispatch extrinsic (transaction/inherent) using + // but we could dispatch extrinsic (transaction/unsigned/inherent) using // runtime_io::submit_extrinsic } } diff --git a/substrate/srml/executive/src/lib.rs b/substrate/srml/executive/src/lib.rs index f6dcae4a4c..3dc161bb0c 100644 --- a/substrate/srml/executive/src/lib.rs +++ b/substrate/srml/executive/src/lib.rs @@ -59,8 +59,17 @@ //! # pub type Balances = u64; //! # pub type AllModules = u64; //! # pub enum Runtime {}; +//! # use primitives::transaction_validity::TransactionValidity; +//! # use primitives::traits::ValidateUnsigned; +//! # impl ValidateUnsigned for Runtime { +//! # type Call = (); +//! # +//! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity { +//! # TransactionValidity::Invalid(0) +//! # } +//! # } //! /// Executive: handles dispatch to the various modules. -//! pub type Executive = executive::Executive; +//! pub type Executive = executive::Executive; //! ``` #![cfg_attr(not(feature = "std"), no_std)] @@ -70,7 +79,8 @@ use rstd::marker::PhantomData; use rstd::result; use primitives::traits::{ self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, - OnInitialize, Digest, NumberFor, Block as BlockT, OffchainWorker + OnInitialize, Digest, NumberFor, Block as BlockT, OffchainWorker, + ValidateUnsigned, }; use srml_support::{Dispatchable, traits::MakePayment}; use parity_codec::{Codec, Encode}; @@ -101,8 +111,8 @@ pub trait ExecuteBlock { fn execute_block(block: Block); } -pub struct Executive( - PhantomData<(System, Block, Context, Payment, AllModules)> +pub struct Executive( + PhantomData<(System, Block, Context, Payment, UnsignedValidator, AllModules)> ); impl< @@ -110,15 +120,18 @@ impl< Block: traits::Block, Context: Default, Payment: MakePayment, + UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, -> ExecuteBlock for Executive where +> ExecuteBlock for Executive +where Block::Extrinsic: Checkable + Codec, >::Checked: Applyable, <>::Checked as Applyable>::Call: Dispatchable, - <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> + <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From>, + UnsignedValidator: ValidateUnsigned>::Checked as Applyable>::Call> { fn execute_block(block: Block) { - Executive::::execute_block(block); + Executive::::execute_block(block); } } @@ -127,12 +140,15 @@ impl< Block: traits::Block, Context: Default, Payment: MakePayment, + UnsignedValidator, AllModules: OnInitialize + OnFinalize + OffchainWorker, -> Executive where +> Executive +where Block::Extrinsic: Checkable + Codec, >::Checked: Applyable, <>::Checked as Applyable>::Call: Dispatchable, - <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From> + <<>::Checked as Applyable>::Call as Dispatchable>::Origin: From>, + UnsignedValidator: ValidateUnsigned>::Checked as Applyable>::Call> { /// Start the execution of a particular block. pub fn initialize_block(header: &System::Header) { @@ -290,7 +306,7 @@ impl< assert!(header.state_root() == storage_root, "Storage root must match that calculated."); } - /// Check a given transaction for validity. This doesn't execute any + /// Check a given signed transaction for validity. This doesn't execute any /// side-effects; it merely checks whether the transaction would panic if it were included or not. /// /// Changes made to storage should be discarded. @@ -313,38 +329,37 @@ impl< Err(_) => return TransactionValidity::Invalid(UNKNOWN_ERROR), }; - if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) { - // pay any fees - if Payment::make_payment(sender, encoded_len).is_err() { - return TransactionValidity::Invalid(ApplyError::CantPay as i8) - } + match (xt.sender(), xt.index()) { + (Some(sender), Some(index)) => { + // pay any fees + if Payment::make_payment(sender, encoded_len).is_err() { + return TransactionValidity::Invalid(ApplyError::CantPay as i8) + } - // check index - let expected_index = >::account_nonce(sender); - if index < &expected_index { - return TransactionValidity::Invalid(ApplyError::Stale as i8) - } + // check index + let expected_index = >::account_nonce(sender); + if index < &expected_index { + return TransactionValidity::Invalid(ApplyError::Stale as i8) + } - let index = *index; - let provides = vec![(sender, index).encode()]; - let requires = if expected_index < index { - vec![(sender, index - One::one()).encode()] - } else { - vec![] - }; + let index = *index; + let provides = vec![(sender, index).encode()]; + let requires = if expected_index < index { + vec![(sender, index - One::one()).encode()] + } else { + vec![] + }; - TransactionValidity::Valid { - priority: encoded_len as TransactionPriority, - requires, - provides, - longevity: TransactionLongevity::max_value(), - } - } else { - return TransactionValidity::Invalid(if xt.sender().is_none() { - MISSING_SENDER - } else { - INVALID_INDEX - }) + TransactionValidity::Valid { + priority: encoded_len as TransactionPriority, + requires, + provides, + longevity: TransactionLongevity::max_value(), + } + }, + (None, None) => UnsignedValidator::validate_unsigned(&xt.deconstruct().0), + (Some(_), None) => TransactionValidity::Invalid(INVALID_INDEX), + (None, Some(_)) => TransactionValidity::Invalid(MISSING_SENDER), } } @@ -404,8 +419,24 @@ mod tests { type TransferPayment = (); } + impl ValidateUnsigned for Runtime { + type Call = Call; + + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { + match call { + Call::set_balance(_, _, _) => TransactionValidity::Valid { + priority: 0, + requires: vec![], + provides: vec![], + longevity: std::u64::MAX, + }, + _ => TransactionValidity::Invalid(0), + } + } + } + type TestXt = primitives::testing::TestXt>; - type Executive = super::Executive, system::ChainContext, balances::Module, ()>; + type Executive = super::Executive, system::ChainContext, balances::Module, Runtime, ()>; #[test] fn balance_transfer_dispatch_works() { @@ -527,4 +558,21 @@ mod tests { run_test(false); run_test(true); } + + #[test] + fn validate_unsigned() { + let xt = primitives::testing::TestXt(None, 0, Call::set_balance(33, 69, 69)); + let valid = TransactionValidity::Valid { + priority: 0, + requires: vec![], + provides: vec![], + longevity: 18446744073709551615 + }; + let mut t = new_test_ext(); + + with_externalities(&mut t, || { + assert_eq!(Executive::validate_transaction(xt.clone()), valid); + assert_eq!(Executive::apply_extrinsic(xt), Ok(ApplyOutcome::Fail)); + }); + } } diff --git a/substrate/srml/finality-tracker/src/lib.rs b/substrate/srml/finality-tracker/src/lib.rs index 34be4ea66a..91beefa66b 100644 --- a/substrate/srml/finality-tracker/src/lib.rs +++ b/substrate/srml/finality-tracker/src/lib.rs @@ -29,7 +29,7 @@ use srml_support::StorageValue; use primitives::traits::{As, One, Zero}; use rstd::{prelude::*, result, cmp, vec}; use parity_codec::Decode; -use srml_system::{ensure_inherent, Trait as SystemTrait}; +use srml_system::{ensure_none, Trait as SystemTrait}; #[cfg(feature = "std")] use parity_codec::Encode; @@ -117,7 +117,7 @@ decl_module! { /// Hint that the author of this block thinks the best finalized /// block is the given number. fn final_hint(origin, #[compact] hint: T::BlockNumber) { - ensure_inherent(origin)?; + ensure_none(origin)?; assert!(!::Update::exists(), "Final hint must be updated only once in the block"); assert!( srml_system::Module::::block_number() >= hint, @@ -372,7 +372,7 @@ mod tests { System::initialize(&i, &parent_hash, &Default::default()); assert_ok!(FinalityTracker::dispatch( Call::final_hint(i-1), - Origin::INHERENT, + Origin::NONE, )); FinalityTracker::on_finalize(i); let hdr = System::finalize(); diff --git a/substrate/srml/support/src/inherent.rs b/substrate/srml/support/src/inherent.rs index 8a4fb669d1..d886abbca7 100644 --- a/substrate/srml/support/src/inherent.rs +++ b/substrate/srml/support/src/inherent.rs @@ -29,7 +29,7 @@ pub use inherents::{InherentData, ProvideInherent, CheckInherentsResult, IsFatal /// /// ```nocompile /// impl_outer_inherent! { -/// pub struct InherentData where Block = Block, UncheckedExtrinsic = UncheckedExtrinsic { +/// impl Inherents where Block = Block, UncheckedExtrinsic = UncheckedExtrinsic { /// timestamp: Timestamp, /// consensus: Consensus, /// /// Aura module using the `Timestamp` call. diff --git a/substrate/srml/support/src/lib.rs b/substrate/srml/support/src/lib.rs index b0fe28c63c..60e03dfada 100644 --- a/substrate/srml/support/src/lib.rs +++ b/substrate/srml/support/src/lib.rs @@ -52,6 +52,8 @@ pub mod metadata; mod runtime; #[macro_use] pub mod inherent; +#[macro_use] +pub mod unsigned; mod double_map; pub mod traits; diff --git a/substrate/srml/support/src/metadata.rs b/substrate/srml/support/src/metadata.rs index 407408b52c..b1da7587be 100644 --- a/substrate/srml/support/src/metadata.rs +++ b/substrate/srml/support/src/metadata.rs @@ -265,14 +265,14 @@ mod tests { pub enum RawOrigin { Root, Signed(AccountId), - Inherent, + None, } impl From> for RawOrigin { fn from(s: Option) -> RawOrigin { match s { Some(who) => RawOrigin::Signed(who), - None => RawOrigin::Inherent, + None => RawOrigin::None, } } } diff --git a/substrate/srml/support/src/origin.rs b/substrate/srml/support/src/origin.rs index 2d97f218e0..48d4be80c6 100644 --- a/substrate/srml/support/src/origin.rs +++ b/substrate/srml/support/src/origin.rs @@ -101,7 +101,7 @@ macro_rules! impl_outer_origin { } #[allow(dead_code)] impl $name { - pub const INHERENT: Self = $name::system($system::RawOrigin::Inherent); + pub const NONE: Self = $name::system($system::RawOrigin::None); pub const ROOT: Self = $name::system($system::RawOrigin::Root); pub fn signed(by: <$runtime as $system::Trait>::AccountId) -> Self { $name::system($system::RawOrigin::Signed(by)) @@ -156,14 +156,14 @@ mod tests { pub enum RawOrigin { Root, Signed(AccountId), - Inherent, + None, } impl From> for RawOrigin { fn from(s: Option) -> RawOrigin { match s { Some(who) => RawOrigin::Signed(who), - None => RawOrigin::Inherent, + None => RawOrigin::None, } } } diff --git a/substrate/srml/support/src/runtime.rs b/substrate/srml/support/src/runtime.rs index bbaeed951f..a045c92806 100644 --- a/substrate/srml/support/src/runtime.rs +++ b/substrate/srml/support/src/runtime.rs @@ -66,6 +66,7 @@ /// - `Inherent $( (CALL) )*` - If the module provides/can check inherents. The optional parameter /// is for modules that use a `Call` from a different module as /// inherent. +/// - `ValidateUnsigned` - If the module validates unsigned extrinsics. /// /// # Note /// @@ -286,6 +287,13 @@ macro_rules! construct_runtime { $name: $module::{ $( $modules $( ( $( $modules_args ),* ) )* ),* } ),*; ); + $crate::__impl_outer_validate_unsigned!( + $runtime; + {}; + $( + $name: $module::{ $( $modules $( ( $( $modules_args )* ) )* )* } + )* + ); } } @@ -947,3 +955,65 @@ macro_rules! __decl_instance_import { } }; } + +/// A private macro that calls impl_outer_validate_unsigned for Call. +#[macro_export] +#[doc(hidden)] +macro_rules! __impl_outer_validate_unsigned { + ( + $runtime:ident; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + ValidateUnsigned $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* + } + $( $rest:tt )* + ) => { + $crate::__impl_outer_validate_unsigned!( + $runtime; + { $( $parsed )* $name }; + $( $rest )* + ); + }; + ( + $runtime:ident; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? { + $ignore:ident $( ( $( $args_ignore:ident )* ) )* + $( $modules:ident $( ( $( $modules_args:ident )* ) )* )* + } + $( $rest:tt )* + ) => { + $crate::__impl_outer_validate_unsigned!( + $runtime; + { $( $parsed )* }; + $name: $module:: $(<$module_instance>::)? { + $( $modules $( ( $( $modules_args )* ) )* )* + } + $( $rest )* + ); + }; + ( + $runtime:ident; + { $( $parsed:tt )* }; + $name:ident: $module:ident:: $(<$module_instance:ident>::)? {} + $( $rest:tt )* + ) => { + $crate::__impl_outer_validate_unsigned!( + $runtime; + { $( $parsed )* }; + $( $rest )* + ); + }; + ( + $runtime:ident; + { $( + $parsed_modules:ident + )* }; + ) => { + $crate::impl_outer_validate_unsigned!( + impl ValidateUnsigned for $runtime { + $( $parsed_modules )* + } + ); + }; +} diff --git a/substrate/srml/support/src/unsigned.rs b/substrate/srml/support/src/unsigned.rs new file mode 100644 index 0000000000..dcdf4b2683 --- /dev/null +++ b/substrate/srml/support/src/unsigned.rs @@ -0,0 +1,153 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +#[doc(hidden)] +pub use crate::runtime_primitives::traits::ValidateUnsigned; +#[doc(hidden)] +pub use crate::runtime_primitives::transaction_validity::TransactionValidity; +#[doc(hidden)] +pub use crate::runtime_primitives::ApplyError; + + +/// Implement `ValidateUnsigned` for `Runtime`. +/// All given modules need to implement `ValidateUnsigned`. +/// +/// # Example +/// +/// ``` +/// # mod timestamp { +/// # pub struct Module; +/// # +/// # impl srml_support::unsigned::ValidateUnsigned for Module { +/// # type Call = Call; +/// # +/// # fn validate_unsigned(call: &Self::Call) -> srml_support::unsigned::TransactionValidity { +/// # unimplemented!(); +/// # } +/// # } +/// # +/// # pub enum Call { +/// # } +/// # } +/// # +/// # pub type Timestamp = timestamp::Module; +/// # +/// # +/// # pub enum Call { +/// # Timestamp(timestamp::Call), +/// # } +/// # #[allow(unused)] +/// pub struct Runtime; +/// +/// srml_support::impl_outer_validate_unsigned! { +/// impl ValidateUnsigned for Runtime { +/// Timestamp +/// } +/// } +/// ``` +#[macro_export] +macro_rules! impl_outer_validate_unsigned { + ( + impl ValidateUnsigned for $runtime:ident { + $( $module:ident )* + } + ) => { + impl $crate::unsigned::ValidateUnsigned for $runtime { + type Call = Call; + + fn validate_unsigned(call: &Self::Call) -> $crate::unsigned::TransactionValidity { + #[allow(unreachable_patterns)] + match call { + $( Call::$module(inner_call) => $module::validate_unsigned(inner_call), )* + _ => $crate::unsigned::TransactionValidity::Invalid($crate::unsigned::ApplyError::BadSignature as i8), + } + } + } + }; +} + +#[cfg(test)] +mod test_empty_call { + pub enum Call { + } + + pub struct Runtime; + + impl_outer_validate_unsigned! { + impl ValidateUnsigned for Runtime { + } + } +} + +#[cfg(test)] +mod test_partial_and_full_call { + pub mod timestamp { + pub struct Module; + + impl super::super::ValidateUnsigned for Module { + type Call = Call; + + fn validate_unsigned(_call: &Self::Call) -> super::super::TransactionValidity { + unimplemented!(); + } + } + + pub enum Call { + Foo, + } + } + + mod test_full_unsigned { + pub type Timestamp = super::timestamp::Module; + + pub enum Call { + Timestamp(super::timestamp::Call), + } + + pub struct Runtime; + + impl_outer_validate_unsigned! { + impl ValidateUnsigned for Runtime { + Timestamp + } + } + + #[test] + fn used() { + let _ = Call::Timestamp(super::timestamp::Call::Foo); + let _ = Runtime; + } + } + + mod test_not_full_unsigned { + pub enum Call { + Timestamp(super::timestamp::Call), + } + + pub struct Runtime; + + impl_outer_validate_unsigned! { + impl ValidateUnsigned for Runtime { + } + } + + #[test] + fn used() { + let _ = Call::Timestamp(super::timestamp::Call::Foo); + let _ = Runtime; + } + } +} diff --git a/substrate/srml/support/test/src/lib.rs b/substrate/srml/support/test/src/lib.rs index e69de29bb2..7b23662e68 100644 --- a/substrate/srml/support/test/src/lib.rs +++ b/substrate/srml/support/test/src/lib.rs @@ -0,0 +1,18 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Test crate for srml_support. Allow to make use of `srml_support::decl_storage`. +//! See tests directory. diff --git a/substrate/srml/support/test/tests/final_keys.rs b/substrate/srml/support/test/tests/final_keys.rs index 122de26a2f..69b815e10a 100644 --- a/substrate/srml/support/test/tests/final_keys.rs +++ b/substrate/srml/support/test/tests/final_keys.rs @@ -1,3 +1,19 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// 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. + +// 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. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + use runtime_io::{with_externalities, Blake2Hasher}; use srml_support::{StorageValue, StorageMap, StorageDoubleMap}; use srml_support::storage::unhashed; diff --git a/substrate/srml/support/test/tests/instance.rs b/substrate/srml/support/test/tests/instance.rs index b958de8377..641ad9f4b5 100644 --- a/substrate/srml/support/test/tests/instance.rs +++ b/substrate/srml/support/test/tests/instance.rs @@ -75,14 +75,14 @@ mod system { pub enum RawOrigin { Root, Signed(AccountId), - Inherent, + None, } impl From> for RawOrigin { fn from(s: Option) -> RawOrigin { match s { Some(who) => RawOrigin::Signed(who), - None => RawOrigin::Inherent, + None => RawOrigin::None, } } } diff --git a/substrate/srml/system/src/lib.rs b/substrate/srml/system/src/lib.rs index 0d3264c5ab..cb54ea81ea 100644 --- a/substrate/srml/system/src/lib.rs +++ b/substrate/srml/system/src/lib.rs @@ -233,15 +233,17 @@ pub enum RawOrigin { Root, /// It is signed by some public key and we provide the `AccountId`. Signed(AccountId), - /// It is signed by nobody but included and agreed upon by the validators anyway: it's "inherently" true. - Inherent, + /// It is signed by nobody, can be either: + /// * included and agreed upon by the validators anyway, + /// * or unsigned transaction validated by a module. + None, } impl From> for RawOrigin { fn from(s: Option) -> RawOrigin { match s { Some(who) => RawOrigin::Signed(who), - None => RawOrigin::Inherent, + None => RawOrigin::None, } } } @@ -363,12 +365,12 @@ pub fn ensure_root(o: OuterOrigin) -> Result<(), &'stati } /// Ensure that the origin `o` represents an unsigned extrinsic. Returns `Ok` or an `Err` otherwise. -pub fn ensure_inherent(o: OuterOrigin) -> Result<(), &'static str> +pub fn ensure_none(o: OuterOrigin) -> Result<(), &'static str> where OuterOrigin: Into>> { match o.into() { - Some(RawOrigin::Inherent) => Ok(()), - _ => Err("bad origin: expected to be an inherent origin"), + Some(RawOrigin::None) => Ok(()), + _ => Err("bad origin: expected to be no origin"), } } diff --git a/substrate/srml/timestamp/src/lib.rs b/substrate/srml/timestamp/src/lib.rs index df89d0c1ff..bc998a8539 100644 --- a/substrate/srml/timestamp/src/lib.rs +++ b/substrate/srml/timestamp/src/lib.rs @@ -95,7 +95,7 @@ use inherents::ProvideInherentData; use srml_support::{StorageValue, Parameter, decl_storage, decl_module}; use srml_support::for_each_tuple; use runtime_primitives::traits::{As, SimpleArithmetic, Zero}; -use system::ensure_inherent; +use system::ensure_none; use rstd::{result, ops::{Mul, Div}, cmp}; use inherents::{RuntimeString, InherentIdentifier, ProvideInherent, IsFatalError, InherentData}; @@ -221,7 +221,7 @@ decl_module! { /// /// The dispatch origin for this call must be `Inherent`. fn set(origin, #[compact] now: T::Moment) { - ensure_inherent(origin)?; + ensure_none(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); assert!( Self::now().is_zero() || now >= Self::now() + >::get(), @@ -369,7 +369,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); assert_eq!(Timestamp::now(), 69); }); } @@ -384,8 +384,8 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::INHERENT)); - let _ = Timestamp::dispatch(Call::set(70), Origin::INHERENT); + assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); + let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); }); } @@ -399,7 +399,7 @@ mod tests { with_externalities(&mut TestExternalities::new(t), || { Timestamp::set_timestamp(42); - let _ = Timestamp::dispatch(Call::set(46), Origin::INHERENT); + let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); }); } }