diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 34c1f606c9..a74b25c4af 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2521,7 +2521,6 @@ name = "sr-api" version = "0.1.0" dependencies = [ "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -2555,7 +2554,6 @@ dependencies = [ "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", - "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -2587,6 +2585,7 @@ dependencies = [ "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -2806,6 +2805,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", diff --git a/substrate/core/client/db/src/cache/list_cache.rs b/substrate/core/client/db/src/cache/list_cache.rs index 59e49fbff3..6d95349ee3 100644 --- a/substrate/core/client/db/src/cache/list_cache.rs +++ b/substrate/core/client/db/src/cache/list_cache.rs @@ -91,7 +91,7 @@ pub struct Fork { head: Entry, } -/// Outcome of Fork::try_append_or_fork. +/// Outcome of Fork::try_append_or_fork. #[derive(Debug)] #[cfg_attr(test, derive(PartialEq))] pub enum ForkAppendResult { @@ -356,7 +356,7 @@ impl> ListCache // if there's an entry at this block: // - remove reference from this entry to the previous entry - // - destroy fork starting with previous entry + // - destroy fork starting with previous entry let current_entry = match self.storage.read_entry(&ancient_block)? { Some(current_entry) => current_entry, None => return Ok(()), @@ -583,12 +583,12 @@ fn read_forks>( #[cfg(test)] pub mod tests { - use runtime_primitives::testing::{Header, Block as RawBlock}; + use runtime_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; use runtime_primitives::traits::Header as HeaderT; use cache::list_storage::tests::{DummyStorage, FaultyStorage, DummyTransaction}; use super::*; - type Block = RawBlock; + type Block = RawBlock>; pub fn test_id(number: u64) -> ComplexBlockId { ComplexBlockId::new(From::from(number), number) @@ -834,7 +834,7 @@ pub mod tests { // when trying to insert block @ finalized number assert!(ListCache::new(DummyStorage::new(), 1024, test_id(100)) .on_block_insert(&mut DummyTransaction::new(), test_id(99), test_id(100), Some(100), false).unwrap().is_none()); - + // when trying to insert non-final block AND it appends to the best block of unfinalized fork // AND new value is the same as in the fork' best block let mut cache = ListCache::new( diff --git a/substrate/core/client/db/src/lib.rs b/substrate/core/client/db/src/lib.rs index 1b1671864e..2bdb9f7500 100644 --- a/substrate/core/client/db/src/lib.rs +++ b/substrate/core/client/db/src/lib.rs @@ -865,11 +865,11 @@ mod tests { use client::backend::Backend as BTrait; use client::backend::BlockImportOperation as Op; use client::blockchain::HeaderBackend as BlockchainHeaderBackend; - use runtime_primitives::testing::{Header, Block as RawBlock}; + use runtime_primitives::testing::{Header, Block as RawBlock, ExtrinsicWrapper}; use state_machine::{TrieMut, TrieDBMut, ChangesTrieRootsStorage, ChangesTrieStorage}; use test_client; - type Block = RawBlock; + type Block = RawBlock>; fn prepare_changes(changes: Vec<(Vec, Vec)>) -> (H256, MemoryDB) { let mut changes_root = H256::default(); diff --git a/substrate/core/client/db/src/light.rs b/substrate/core/client/db/src/light.rs index 19453b4278..49e5e85be1 100644 --- a/substrate/core/client/db/src/light.rs +++ b/substrate/core/client/db/src/light.rs @@ -402,10 +402,10 @@ impl LightBlockchainStorage for LightStorage #[cfg(test)] pub(crate) mod tests { use client::cht; - use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock}; + use runtime_primitives::testing::{H256 as Hash, Header, Block as RawBlock, ExtrinsicWrapper}; use super::*; - type Block = RawBlock; + type Block = RawBlock>; fn prepare_header(parent: &Hash, number: u64, extrinsics_root: Hash) -> Header { Header { diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 28c4a42d85..9182ab0a78 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -1126,12 +1126,12 @@ impl api::BlockBuilder for Client where self.call_api_at(at, "inherent_extrinsics", &(inherent)) } - fn check_inherents( + fn check_inherents( &self, at: &BlockId, block: &Block, data: &InherentData - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.call_api_at(at, "check_inherents", &(block, data)) } diff --git a/substrate/core/client/src/notifications.rs b/substrate/core/client/src/notifications.rs index 320ede9491..1856932ca9 100644 --- a/substrate/core/client/src/notifications.rs +++ b/substrate/core/client/src/notifications.rs @@ -179,11 +179,10 @@ impl StorageNotifications { #[cfg(test)] mod tests { - use runtime_primitives::testing::{H256 as Hash, Block as RawBlock}; + use runtime_primitives::testing::{H256 as Hash, Block as RawBlock, ExtrinsicWrapper}; use super::*; use futures::Stream; - #[cfg(test)] impl From)>> for StorageChangeSet { fn from(changes: Vec<(StorageKey, Option)>) -> Self { @@ -201,7 +200,7 @@ mod tests { } } - type Block = RawBlock; + type Block = RawBlock>; #[test] fn triggering_change_should_notify_wildcard_listeners() { diff --git a/substrate/core/network/src/blocks.rs b/substrate/core/network/src/blocks.rs index 7cc37624fc..db4c38af45 100644 --- a/substrate/core/network/src/blocks.rs +++ b/substrate/core/network/src/blocks.rs @@ -195,10 +195,10 @@ impl BlockCollection { mod test { use super::{BlockCollection, BlockData, BlockRangeState}; use message; - use runtime_primitives::testing::Block as RawBlock; + use runtime_primitives::testing::{Block as RawBlock, ExtrinsicWrapper}; use primitives::H256; - type Block = RawBlock; + type Block = RawBlock>; fn is_empty(bc: &BlockCollection) -> bool { bc.blocks.is_empty() && diff --git a/substrate/core/network/src/consensus_gossip.rs b/substrate/core/network/src/consensus_gossip.rs index b84d8d437f..0ecb0e5e68 100644 --- a/substrate/core/network/src/consensus_gossip.rs +++ b/substrate/core/network/src/consensus_gossip.rs @@ -310,11 +310,11 @@ impl Specialization for ConsensusGossip where #[cfg(test)] mod tests { - use runtime_primitives::testing::{H256, Block as RawBlock}; + use runtime_primitives::testing::{H256, Block as RawBlock, ExtrinsicWrapper}; use std::time::Instant; use super::*; - type Block = RawBlock; + type Block = RawBlock>; #[test] fn collects_garbage() { diff --git a/substrate/core/sr-api/Cargo.toml b/substrate/core/sr-api/Cargo.toml index 2d1197613d..2877dfa919 100644 --- a/substrate/core/sr-api/Cargo.toml +++ b/substrate/core/sr-api/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Parity Technologies "] [dependencies] parity-codec = { version = "2.1", default-features = false } -parity-codec-derive = { version = "2.1", default-features = false } sr-std = { path = "../sr-std", default-features = false } sr-primitives = { path = "../sr-primitives", default-features = false } sr-version = { path = "../sr-version", default-features = false } @@ -15,7 +14,6 @@ default = ["std"] std = [ "sr-std/std", "parity-codec/std", - "parity-codec-derive/std", "sr-primitives/std", "sr-version/std", ] diff --git a/substrate/core/sr-api/src/lib.rs b/substrate/core/sr-api/src/lib.rs index f338934f0d..2021e2f2a0 100644 --- a/substrate/core/sr-api/src/lib.rs +++ b/substrate/core/sr-api/src/lib.rs @@ -22,8 +22,6 @@ extern crate sr_std as rstd; extern crate sr_primitives as primitives; #[doc(hidden)] pub extern crate parity_codec as codec; -#[macro_use] -extern crate parity_codec_derive; extern crate sr_version as runtime_version; #[doc(hidden)] @@ -429,17 +427,6 @@ macro_rules! decl_apis { }; } -//TODO: Move into runtime! -#[derive(Encode)] -#[cfg_attr(feature = "std", derive(Debug, Decode))] -pub enum BlockBuilderError { - #[cfg(not(feature = "std"))] - Generic(&'static str), - #[cfg(feature = "std")] - Generic(String), - TimestampInFuture(u64), -} - decl_apis! { /// The `Core` api trait that is mandantory for each runtime. pub trait Core { @@ -482,7 +469,7 @@ decl_apis! { /// Generate inherent extrinsics. fn inherent_extrinsics(inherent: InherentExtrinsic) -> Vec; /// Check that the inherents are valid. - fn check_inherents(block: Block, data: InherentData) -> Result<(), BlockBuilderError>; + fn check_inherents(block: Block, data: InherentData) -> Result<(), Error>; /// Generate a random seed. fn random_seed() -> ::Hash; } diff --git a/substrate/core/sr-primitives/Cargo.toml b/substrate/core/sr-primitives/Cargo.toml index 0efb04f67b..df80d43a9f 100644 --- a/substrate/core/sr-primitives/Cargo.toml +++ b/substrate/core/sr-primitives/Cargo.toml @@ -13,7 +13,6 @@ parity-codec-derive = { version = "2.1", default-features = false } substrate-primitives = { path = "../primitives", default-features = false } sr-std = { path = "../sr-std", default-features = false } sr-io = { path = "../sr-io", default-features = false } -sr-version = { path = "../sr-version", default-features = false } log = {version = "0.4", optional = true } [dev-dependencies] @@ -28,7 +27,6 @@ std = [ "log", "sr-std/std", "sr-io/std", - "sr-version/std", "parity-codec/std", "substrate-primitives/std", ] diff --git a/substrate/core/sr-primitives/src/generic/block.rs b/substrate/core/sr-primitives/src/generic/block.rs index 4013cbc6a9..6cbb7929d8 100644 --- a/substrate/core/sr-primitives/src/generic/block.rs +++ b/substrate/core/sr-primitives/src/generic/block.rs @@ -72,7 +72,7 @@ pub struct Block { impl traits::Block for Block where Header: HeaderT, - Extrinsic: Member + Codec, + Extrinsic: Member + Codec + traits::Extrinsic, { type Extrinsic = Extrinsic; type Header = Header; @@ -102,4 +102,4 @@ pub struct SignedBlock { pub block: Block, /// Block justification. pub justification: Justification, -} \ No newline at end of file +} diff --git a/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs b/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs index abaa9e7a93..5d91556d8c 100644 --- a/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs +++ b/substrate/core/sr-primitives/src/generic/unchecked_mortal_extrinsic.rs @@ -22,7 +22,7 @@ use std::fmt; use rstd::prelude::*; use codec::{Decode, Encode, Input}; use traits::{self, Member, SimpleArithmetic, MaybeDisplay, CurrentHeight, BlockNumberToHash, Lookup, - Checkable}; + Checkable, Extrinsic}; use super::{CheckedExtrinsic, Era}; const TRANSACTION_VERSION: u8 = 1; @@ -56,10 +56,11 @@ impl UncheckedMortalExtrinsic bool { - self.signature.is_some() +impl Extrinsic for UncheckedMortalExtrinsic { + fn is_signed(&self) -> Option { + Some(self.signature.is_some()) } } @@ -221,49 +222,49 @@ mod tests { #[test] fn unsigned_check_should_work() { let ux = Ex::new_unsigned(DUMMY_FUNCTION); - assert!(!ux.is_signed()); + assert!(!ux.is_signed().unwrap_or(false)); assert!(>::check(ux, &TestContext).is_ok()); } #[test] fn badly_signed_check_should_fail() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, vec![0u8]), Era::immortal()); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); } #[test] fn immortal_signed_check_should_work() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::immortal(), 0u64).encode()), Era::immortal()); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); } #[test] fn mortal_signed_check_should_work() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 42), 42u64).encode()), Era::mortal(32, 42)); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); } #[test] fn later_mortal_signed_check_should_work() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 11), 11u64).encode()), Era::mortal(32, 11)); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Ok(CEx { signed: Some((DUMMY_ACCOUNTID, 0)), function: DUMMY_FUNCTION })); } #[test] fn too_late_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 10), 10u64).encode()), Era::mortal(32, 10)); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); } #[test] fn too_early_mortal_signed_check_should_fail() { let ux = Ex::new_signed(0, DUMMY_FUNCTION, DUMMY_ACCOUNTID, TestSig(DUMMY_ACCOUNTID, (DUMMY_ACCOUNTID, DUMMY_FUNCTION, Era::mortal(32, 43), 43u64).encode()), Era::mortal(32, 43)); - assert!(ux.is_signed()); + assert!(ux.is_signed().unwrap_or(false)); assert_eq!(>::check(ux, &TestContext), Err("bad signature in extrinsic")); } diff --git a/substrate/core/sr-primitives/src/lib.rs b/substrate/core/sr-primitives/src/lib.rs index c403cf5846..465b1e3f29 100644 --- a/substrate/core/sr-primitives/src/lib.rs +++ b/substrate/core/sr-primitives/src/lib.rs @@ -37,7 +37,6 @@ extern crate num_traits; extern crate integer_sqrt; extern crate sr_std as rstd; extern crate sr_io as runtime_io; -extern crate sr_version as runtime_version; #[doc(hidden)] pub extern crate parity_codec as codec; extern crate substrate_primitives; @@ -65,6 +64,12 @@ pub type Justification = Vec; use traits::{Verify, Lazy}; +/// A String that is a `&'static str` on `no_std` and a `String` on `std`. +#[cfg(not(feature = "std"))] +pub type RuntimeString = &'static str; +#[cfg(feature = "std")] +pub type RuntimeString = ::std::borrow::Cow<'static, str>; + #[cfg(feature = "std")] pub use serde::{Serialize, de::DeserializeOwned}; diff --git a/substrate/core/sr-primitives/src/testing.rs b/substrate/core/sr-primitives/src/testing.rs index fea8586f5a..ab57f1aa6c 100644 --- a/substrate/core/sr-primitives/src/testing.rs +++ b/substrate/core/sr-primitives/src/testing.rs @@ -17,7 +17,7 @@ //! Testing utilities. use serde::{Serialize, de::DeserializeOwned}; -use std::fmt::Debug; +use std::{fmt::Debug, ops::Deref}; use codec::Codec; use traits::{self, Checkable, Applyable, BlakeTwo256}; use generic::DigestItem as GenDigestItem; @@ -93,13 +93,36 @@ impl traits::Header for Header { } } +#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)] +pub struct ExtrinsicWrapper(Xt); + +impl traits::Extrinsic for ExtrinsicWrapper { + fn is_signed(&self) -> Option { + None + } +} + +impl From for ExtrinsicWrapper { + fn from(xt: Xt) -> Self { + ExtrinsicWrapper(xt) + } +} + +impl Deref for ExtrinsicWrapper { + type Target = Xt; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + #[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)] pub struct Block { pub header: Header, pub extrinsics: Vec, } -impl traits::Block for Block { +impl traits::Block for Block { type Extrinsic = Xt; type Header = Header; type Hash =
::Hash; @@ -125,6 +148,11 @@ impl Checkable for Test type Checked = Self; fn check(self, _: &Context) -> Result { Ok(self) } } +impl traits::Extrinsic for TestXt { + fn is_signed(&self) -> Option { + None + } +} impl Applyable for TestXt where Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Serialize + DeserializeOwned, { diff --git a/substrate/core/sr-primitives/src/traits.rs b/substrate/core/sr-primitives/src/traits.rs index 24dda09345..2841708e6e 100644 --- a/substrate/core/sr-primitives/src/traits.rs +++ b/substrate/core/sr-primitives/src/traits.rs @@ -383,6 +383,17 @@ pub trait MaybeDisplay {} #[cfg(not(feature = "std"))] impl MaybeDisplay for T {} +#[cfg(feature = "std")] +pub trait MaybeDecode: ::codec::Decode {} +#[cfg(feature = "std")] +impl MaybeDecode for T {} + +#[cfg(not(feature = "std"))] +pub trait MaybeDecode {} +#[cfg(not(feature = "std"))] +impl MaybeDecode for T {} + + pub trait Member: Send + Sync + Sized + MaybeSerializeDebug + Eq + PartialEq + Clone + 'static {} impl Member for T {} @@ -430,7 +441,7 @@ pub trait Header: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'stat /// /// You can get an iterator over each of the `extrinsics` and retrieve the `header`. pub trait Block: Clone + Send + Sync + Codec + Eq + MaybeSerializeDebug + 'static { - type Extrinsic: Member + Codec; + type Extrinsic: Member + Codec + Extrinsic; type Header: Header; type Hash: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]> + AsMut<[u8]>; @@ -532,3 +543,32 @@ pub trait DigestItem: Codec + Member { None } } + +/// Something that provides an inherent for a runtime. +pub trait ProvideInherent { + /// The inherent that is provided. + type Inherent: Encode + MaybeDecode; + /// The error used by this trait. + type Error: Encode + MaybeDecode; + /// The call for setting the inherent. + type Call: Encode + MaybeDecode; + + /// Create the inherent extrinsics. + /// + /// # Return + /// + /// Returns a vector with tuples containing the index for the extrinsic and the extrinsic itself. + fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)>; + + /// Check that the given inherent is valid. + fn check_inherent Option<&Self::Call>>( + block: &Block, data: Self::Inherent, extract_function: &F + ) -> Result<(), Self::Error>; +} + +/// Something that acts like an `Extrinsic`. +pub trait Extrinsic { + /// Is this `Extrinsic` signed? + /// If no information are available about signed/unsigned, `None` should be returned. + fn is_signed(&self) -> Option; +} diff --git a/substrate/core/sr-std/without_std.rs b/substrate/core/sr-std/without_std.rs index 4b5c6c7705..d5065648e9 100644 --- a/substrate/core/sr-std/without_std.rs +++ b/substrate/core/sr-std/without_std.rs @@ -15,7 +15,8 @@ // along with Substrate. If not, see . #[cfg(feature = "nightly")] -extern crate alloc; +#[doc(hidden)] +pub extern crate alloc; extern "C" { fn ext_malloc(size: usize) -> *mut u8; diff --git a/substrate/core/sr-version/Cargo.toml b/substrate/core/sr-version/Cargo.toml index 9f3cfe7f64..785eecdfa7 100644 --- a/substrate/core/sr-version/Cargo.toml +++ b/substrate/core/sr-version/Cargo.toml @@ -9,6 +9,7 @@ serde_derive = { version = "1.0", optional = true } parity-codec = { version = "2.1", default-features = false } parity-codec-derive = { version = "2.1", default-features = false } sr-std = { path = "../sr-std", default-features = false } +sr-primitives = { path = "../sr-primitives", default-features = false } [features] default = ["std"] @@ -17,4 +18,5 @@ std = [ "serde_derive", "parity-codec/std", "sr-std/std", + "sr-primitives/std", ] diff --git a/substrate/core/sr-version/src/lib.rs b/substrate/core/sr-version/src/lib.rs index f13eeef763..8af084da5e 100644 --- a/substrate/core/sr-version/src/lib.rs +++ b/substrate/core/sr-version/src/lib.rs @@ -29,15 +29,14 @@ extern crate sr_std as rstd; #[macro_use] extern crate parity_codec_derive; +extern crate sr_primitives as runtime_primitives; + #[cfg(feature = "std")] use std::fmt; #[cfg(feature = "std")] use std::collections::HashSet; -#[cfg(feature = "std")] -pub type VersionString = ::std::borrow::Cow<'static, str>; -#[cfg(not(feature = "std"))] -pub type VersionString = &'static str; +use runtime_primitives::RuntimeString; /// The identity of a particular API interface that the runtime might provide. pub type ApiId = [u8; 8]; @@ -80,14 +79,14 @@ pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and node. /// A different on-chain spec_name to that of the native runtime would normally result /// in node not attempting to sync or author blocks. - pub spec_name: VersionString, + pub spec_name: RuntimeString, /// Name of the implementation of the spec. This is of little consequence for the node /// and serves only to differentiate code of different implementation teams. For this /// codebase, it will be parity-polkadot. If there were a non-Rust implementation of the /// Polkadot runtime (e.g. C++), then it would identify itself with an accordingly different /// `impl_name`. - pub impl_name: VersionString, + pub impl_name: RuntimeString, /// `authoring_version` is the version of the authorship interface. An authoring node /// will not attempt to author blocks unless this is equal to its native runtime. diff --git a/substrate/core/test-runtime/src/lib.rs b/substrate/core/test-runtime/src/lib.rs index 73a2a54670..de678e7205 100644 --- a/substrate/core/test-runtime/src/lib.rs +++ b/substrate/core/test-runtime/src/lib.rs @@ -54,7 +54,7 @@ use rstd::prelude::*; use codec::{Encode, Decode}; use runtime_api::runtime::*; -use runtime_primitives::traits::{BlindCheckable, BlakeTwo256, Block as BlockT}; +use runtime_primitives::traits::{BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT}; use runtime_primitives::{ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity}; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; @@ -115,6 +115,12 @@ impl BlindCheckable for Extrinsic { } } +impl ExtrinsicT for Extrinsic { + fn is_signed(&self) -> Option { + Some(true) + } +} + /// An identifier for an account on this system. pub type AccountId = H256; /// A simple hash type for all our hashing. @@ -185,7 +191,7 @@ impl_apis! { } } - impl BlockBuilder for Runtime { + impl BlockBuilder for Runtime { fn initialise_block(header: ::Header) { system::initialise_block(header) } @@ -202,7 +208,7 @@ impl_apis! { unimplemented!() } - fn check_inherents(_block: Block, _data: u32) -> Result<(), runtime_api::BlockBuilderError> { + fn check_inherents(_block: Block, _data: u32) -> Result<(), u32> { unimplemented!() } diff --git a/substrate/core/test-runtime/wasm/Cargo.lock b/substrate/core/test-runtime/wasm/Cargo.lock index 3bc67944d2..b47c534a27 100644 --- a/substrate/core/test-runtime/wasm/Cargo.lock +++ b/substrate/core/test-runtime/wasm/Cargo.lock @@ -470,7 +470,6 @@ name = "sr-api" version = "0.1.0" dependencies = [ "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -503,7 +502,6 @@ dependencies = [ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", - "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -522,6 +520,7 @@ dependencies = [ "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", "sr-std 0.1.0", ] diff --git a/substrate/node/consensus/src/lib.rs b/substrate/node/consensus/src/lib.rs index e80a668ced..9638a39715 100644 --- a/substrate/node/consensus/src/lib.rs +++ b/substrate/node/consensus/src/lib.rs @@ -48,10 +48,10 @@ use std::sync::Arc; use std::time::{self, Duration, Instant}; use client::{Client as SubstrateClient, CallExecutor}; -use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, Miscellaneous, OldTxQueue, BlockBuilderError}; +use client::runtime_api::{Core, BlockBuilder as BlockBuilderAPI, Miscellaneous, OldTxQueue}; use codec::{Decode, Encode}; -use node_primitives::{AccountId, Timestamp, SessionKey, InherentData}; -use node_runtime::Runtime; +use node_primitives::{AccountId, Timestamp, SessionKey}; +use node_runtime::{Runtime, InherentError, TimestampInherentError, InherentData}; use primitives::{AuthorityId, ed25519, Blake2Hasher}; use runtime_primitives::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, As, BlockNumberToHash}; use runtime_primitives::generic::{BlockId, Era}; @@ -135,9 +135,8 @@ impl<'a, B, E, Block> AuthoringApi for SubstrateClient where let mut block_builder = self.new_block_at(at)?; if runtime_version.has_api(*b"inherent", 1) { - for inherent in self.inherent_extrinsics(at, &inherent_data)? { - block_builder.push(inherent)?; - } + self.inherent_extrinsics(at, &inherent_data)? + .into_iter().try_for_each(|i| block_builder.push(i))?; } build_ctx(&mut block_builder); @@ -383,7 +382,7 @@ impl bft::Proposer<::Block> for Proposer where &inherent ) { Ok(Ok(())) => None, - Ok(Err(BlockBuilderError::TimestampInFuture(timestamp))) => Some(timestamp), + Ok(Err(InherentError::Timestamp(TimestampInherentError::TimestampInFuture(timestamp)))) => Some(timestamp), Ok(Err(e)) => { debug!(target: "bft", "Invalid proposal (check_inherents): {:?}", e); return Box::new(future::ok(false)); diff --git a/substrate/node/primitives/src/lib.rs b/substrate/node/primitives/src/lib.rs index c6802c7164..2e436e31de 100644 --- a/substrate/node/primitives/src/lib.rs +++ b/substrate/node/primitives/src/lib.rs @@ -36,7 +36,7 @@ use rstd::prelude::*; use runtime_primitives::generic; #[cfg(feature = "std")] use primitives::bytes; -use runtime_primitives::traits::BlakeTwo256; +use runtime_primitives::traits::{BlakeTwo256, self}; /// An index to a block. pub type BlockNumber = u64; @@ -79,22 +79,9 @@ pub type BlockId = generic::BlockId; #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct UncheckedExtrinsic(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); -/// -/// Inherent data to include in a block. -#[derive(Encode, Decode)] -pub struct InherentData { - /// Current timestamp. - pub timestamp: Timestamp, - /// Indices of offline validators. - pub offline_indices: Vec, -} -impl InherentData { - /// Create a new `InherentData` instance. - pub fn new(timestamp: Timestamp, offline_indices: Vec) -> Self { - Self { - timestamp, - offline_indices - } +impl traits::Extrinsic for UncheckedExtrinsic { + fn is_signed(&self) -> Option { + None } } diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 45b5db63ad..b6dbda5c57 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -61,9 +61,9 @@ use rstd::prelude::*; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{ AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, - SessionKey, Signature, InherentData, Timestamp as TimestampType + SessionKey, Signature }; -use runtime_api::{BlockBuilderError, runtime::*}; +use runtime_api::runtime::*; use runtime_primitives::ApplyResult; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::generic; @@ -212,11 +212,14 @@ impl DigestItem for Log { } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) { + pub enum Runtime with Log(InternalLog: DigestItem) where + Block = Block, + UncheckedExtrinsic = UncheckedExtrinsic + { System: system::{default, Log(ChangesTrieRoot)}, - Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange)}, + Consensus: consensus::{Module, Call, Storage, Config, Log(AuthoritiesChange), Inherent}, Balances: balances, - Timestamp: timestamp::{Module, Call, Storage, Config}, + Timestamp: timestamp::{Module, Call, Storage, Config, Inherent}, Session: session, Staking: staking, Democracy: democracy, @@ -269,7 +272,7 @@ impl_apis! { } } - impl BlockBuilder for Runtime { + impl BlockBuilder for Runtime { fn initialise_block(header: ::Header) { Executive::initialise_block(&header) } @@ -283,49 +286,11 @@ impl_apis! { } fn inherent_extrinsics(data: InherentData) -> Vec { - let mut inherent = vec![generic::UncheckedMortalExtrinsic::new_unsigned( - Call::Timestamp(TimestampCall::set(data.timestamp.into())) - )]; - - if !data.offline_indices.is_empty() { - inherent.push(generic::UncheckedMortalExtrinsic::new_unsigned( - Call::Consensus(ConsensusCall::note_offline(data.offline_indices)) - )); - } - - inherent + data.create_inherent_extrinsics() } - fn check_inherents(block: Block, data: InherentData) -> Result<(), BlockBuilderError> { - // TODO: v1: should be automatically gathered - - // Timestamp module... - const MAX_TIMESTAMP_DRIFT: TimestampType = 60; - let xt = block.extrinsics.get(TIMESTAMP_SET_POSITION as usize) - .ok_or_else(|| BlockBuilderError::Generic("No valid timestamp inherent in block".into()))?; - let t = match (xt.is_signed(), &xt.function) { - (false, Call::Timestamp(TimestampCall::set(t))) => t, - _ => return Err(BlockBuilderError::Generic("No valid timestamp inherent in block".into())), - }; - let t = (*t).into(); - if t > data.timestamp + MAX_TIMESTAMP_DRIFT { - return Err(BlockBuilderError::TimestampInFuture(t)) - } - - // Offline indices - let noted_offline = - block.extrinsics.get(NOTE_OFFLINE_POSITION as usize).and_then(|xt| match xt.function { - Call::Consensus(ConsensusCall::note_offline(ref x)) => Some(&x[..]), - _ => None, - }).unwrap_or(&[]); - - noted_offline.iter().try_for_each(|n| - if !data.offline_indices.contains(n) { - Err(BlockBuilderError::Generic("Online node marked offline".into())) - } else { - Ok(()) - } - ) + fn check_inherents(block: Block, data: InherentData) -> Result<(), InherentError> { + data.check_inherents(block) } fn random_seed() -> ::Hash { diff --git a/substrate/node/runtime/wasm/Cargo.lock b/substrate/node/runtime/wasm/Cargo.lock index 7a655c6415..fc45e6f94c 100644 --- a/substrate/node/runtime/wasm/Cargo.lock +++ b/substrate/node/runtime/wasm/Cargo.lock @@ -530,7 +530,6 @@ name = "sr-api" version = "0.1.0" dependencies = [ "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", "sr-version 0.1.0", @@ -563,7 +562,6 @@ dependencies = [ "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", "sr-std 0.1.0", - "sr-version 0.1.0", "substrate-primitives 0.1.0", ] @@ -593,6 +591,7 @@ dependencies = [ "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 0.1.0", "sr-std 0.1.0", ] @@ -788,6 +787,7 @@ version = "0.1.0" dependencies = [ "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "sr-io 0.1.0", diff --git a/substrate/srml/consensus/src/lib.rs b/substrate/srml/consensus/src/lib.rs index b1d0905e9f..835d39a44c 100644 --- a/substrate/srml/consensus/src/lib.rs +++ b/substrate/srml/consensus/src/lib.rs @@ -41,11 +41,15 @@ extern crate substrate_primitives; extern crate sr_io as runtime_io; use rstd::prelude::*; +use rstd::result; use runtime_support::{storage, Parameter}; use runtime_support::dispatch::Result; use runtime_support::storage::StorageValue; use runtime_support::storage::unhashed::StorageVec; -use primitives::traits::{MaybeSerializeDebug, OnFinalise, Member}; +use primitives::RuntimeString; +use primitives::traits::{ + MaybeSerializeDebug, OnFinalise, Member, ProvideInherent, Block as BlockT +}; use substrate_primitives::storage::well_known_keys; use system::{ensure_signed, ensure_inherent}; @@ -235,6 +239,35 @@ impl Module { } } +impl ProvideInherent for Module { + type Inherent = Vec; + type Call = Call; + type Error = RuntimeString; + + fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { + vec![(T::NOTE_OFFLINE_POSITION, Call::note_offline(data))] + } + + fn check_inherent Option<&Self::Call>>( + block: &Block, data: Self::Inherent, extract_function: &F + ) -> result::Result<(), Self::Error> { + let noted_offline = block + .extrinsics().get(T::NOTE_OFFLINE_POSITION as usize) + .and_then(|xt| match extract_function(&xt) { + Some(Call::note_offline(ref x)) => Some(&x[..]), + _ => None, + }).unwrap_or(&[]); + + noted_offline.iter().try_for_each(|n| + if !data.contains(n) { + Err("Online node marked offline".into()) + } else { + Ok(()) + } + ) + } +} + /// Finalization hook for the consensus module. impl OnFinalise for Module { fn on_finalise(_n: T::BlockNumber) { @@ -246,4 +279,3 @@ impl OnFinalise for Module { } } } - diff --git a/substrate/srml/support/src/inherent.rs b/substrate/srml/support/src/inherent.rs new file mode 100644 index 0000000000..f87a41806a --- /dev/null +++ b/substrate/srml/support/src/inherent.rs @@ -0,0 +1,128 @@ +// Copyright 2018 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 rstd::{result::Result, vec::Vec}; +#[doc(hidden)] +pub use runtime_primitives::traits::ProvideInherent; + + +/// Implement the outer inherent. +/// All given modules need to implement `ProvideInherent`. +/// +/// # Example +/// +/// ```nocompile +/// impl_outer_inherent! { +/// pub struct InherentData where Block = Block, UncheckedExtrinsic = UncheckedExtrinsic { +/// timestamp: Timestamp export Error as TimestampInherentError, +/// consensus: Consensus, +/// } +/// } +/// ``` +/// +/// Additional parameters after `UncheckedExtrinsic` are `Error` and `Call`. +#[macro_export] +macro_rules! impl_outer_inherent { + ( + $(#[$attr:meta])* + pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident { + $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + } + ) => { + impl_outer_inherent!( + $( #[$attr] )* + pub struct $name where Block = $block, UncheckedExtrinsic = $unchecked, Error = InherentError, Call = Call { + $( $module: $module_ty $(export Error as $error_name)*, )* + } + ); + }; + ( + $(#[$attr:meta])* + pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident, Error = $error:ident { + $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + } + ) => { + impl_outer_inherent!( + $( #[$attr] )* + pub struct $name where Block = $block, UncheckedExtrinsic = $unchecked, Error = $error, Call = Call { + $( $module: $module_ty $(export Error as $error_name)*, )* + } + ); + }; + ( + $(#[$attr:meta])* + pub struct $name:ident where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident, Error = $error:ident, Call = $call:ident { + $( $module:ident: $module_ty:ident $(export Error as $error_name:ident)*, )* + } + ) => { + $( #[$attr] )* + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Encode, Decode)] + /// Inherent data to include in a block. + pub struct $name { + $( $module: <$module_ty as $crate::inherent::ProvideInherent>::Inherent, )* + } + + $( + $( + pub type $error_name =<$module_ty as $crate::inherent::ProvideInherent>::Error; + )* + )* + + impl $name { + /// Create a new instance. + pub fn new( $( $module: <$module_ty as $crate::inherent::ProvideInherent>::Inherent ),* ) -> Self { + Self { + $( $module, )* + } + } + + fn create_inherent_extrinsics(self) -> Vec<$unchecked> { + let mut inherent = $crate::inherent::Vec::new(); + + $( + inherent.extend( + <$module_ty as $crate::inherent::ProvideInherent>::create_inherent_extrinsics(self.$module) + .into_iter() + .map(|v| (v.0, $unchecked::new_unsigned($call::$module_ty(v.1)))) + ); + )* + + inherent.as_mut_slice().sort_unstable_by_key(|v| v.0); + inherent.into_iter().map(|v| v.1).collect() + } + + fn check_inherents(self, block: $block) -> $crate::inherent::Result<(), $error> { + $( + <$module_ty as $crate::inherent::ProvideInherent>::check_inherent( + &block, self.$module, &|xt| match xt.function { + Call::$module_ty(ref data) => Some(data), + _ => None, + }).map_err($error::$module_ty)?; + )* + Ok(()) + } + } + + // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted. + #[derive(Encode)] + #[cfg_attr(feature = "std", derive(Decode))] + pub enum $error { + $( $module_ty(<$module_ty as $crate::inherent::ProvideInherent>::Error), )* + } + }; +} diff --git a/substrate/srml/support/src/lib.rs b/substrate/srml/support/src/lib.rs index eba740ab7a..02747b199a 100644 --- a/substrate/srml/support/src/lib.rs +++ b/substrate/srml/support/src/lib.rs @@ -21,15 +21,12 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[cfg(not(feature = "std"))] -extern crate alloc; - #[cfg(feature = "std")] extern crate serde; extern crate sr_std as rstd; extern crate sr_io as runtime_io; -#[cfg(feature = "std")] +#[doc(hidden)] pub extern crate sr_primitives as runtime_primitives; extern crate substrate_metadata; @@ -49,12 +46,6 @@ extern crate parity_codec_derive; pub extern crate parity_codec as codec; pub use self::storage::generator::Storage as GenericStorage; -#[cfg(feature = "std")] -pub mod alloc { - pub use std::boxed; - pub use std::vec; -} - #[macro_use] pub mod dispatch; #[macro_use] @@ -68,6 +59,8 @@ mod origin; pub mod metadata; #[macro_use] mod runtime; +#[macro_use] +pub mod inherent; pub use self::storage::{StorageVec, StorageList, StorageValue, StorageMap}; pub use self::hashable::Hashable; diff --git a/substrate/srml/support/src/runtime.rs b/substrate/srml/support/src/runtime.rs index df8fa4c4d4..75cf0eaf24 100644 --- a/substrate/srml/support/src/runtime.rs +++ b/substrate/srml/support/src/runtime.rs @@ -47,12 +47,16 @@ #[macro_export] macro_rules! construct_runtime { ( - pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>) { + pub enum $runtime:ident with Log ($log_internal:ident: DigestItem<$( $log_genarg:ty ),+>) + where Block = $block:ident, UncheckedExtrinsic = $unchecked:ident + { $( $rest:tt )* } ) => { construct_runtime!( $runtime; + $block; + $unchecked; $log_internal < $( $log_genarg ),* >; ; $( $rest )* @@ -60,6 +64,8 @@ macro_rules! construct_runtime { }; ( $runtime:ident; + $block:ident; + $unchecked:ident; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -85,6 +91,8 @@ macro_rules! construct_runtime { ) => { construct_runtime!( $runtime; + $block; + $unchecked; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -110,6 +118,8 @@ macro_rules! construct_runtime { }; ( $runtime:ident; + $block:ident; + $unchecked:ident; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -142,6 +152,8 @@ macro_rules! construct_runtime { ) => { construct_runtime!( $runtime; + $block; + $unchecked; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -173,6 +185,8 @@ macro_rules! construct_runtime { }; ( $runtime:ident; + $block:ident; + $unchecked:ident; $log_internal:ident <$( $log_genarg:ty ),+>; $( $expanded_name:ident: $expanded_module:ident::{ @@ -204,6 +218,8 @@ macro_rules! construct_runtime { ) => { construct_runtime!( $runtime; + $block; + $unchecked; $log_internal < $( $log_genarg ),* >; $( $expanded_name: $expanded_module::{ @@ -234,6 +250,8 @@ macro_rules! construct_runtime { }; ( $runtime:ident; + $block:ident; + $unchecked:ident; $log_internal:ident <$( $log_genarg:ty ),+>; $( $name:ident: $module:ident::{ @@ -245,6 +263,13 @@ macro_rules! construct_runtime { } ),*; ) => { + mashup! { + $( + substrate_generate_ident_name["config-ident" $name] = $name Config; + substrate_generate_ident_name["inherent-error-ident" $name] = $name InherentError; + )* + } + #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub struct $runtime; @@ -298,6 +323,15 @@ macro_rules! construct_runtime { $name: $module::{ $( $modules $( <$modules_generic> )* ),* } ),*; ); + __decl_outer_inherent!( + $runtime; + $block; + $unchecked; + ; + $( + $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + ),*; + ); } } @@ -980,17 +1014,104 @@ macro_rules! __decl_outer_config { $( $parsed_modules:ident :: $parsed_name:ident ),*; ; ) => { - mashup! { - $( - substrate_generate_config_name["config-name" $parsed_name] = $parsed_name Config; - )* - } - - substrate_generate_config_name! { + substrate_generate_ident_name! { impl_outer_config!( pub struct GenesisConfig for $runtime { $( - "config-name" $parsed_name => $parsed_modules, + "config-ident" $parsed_name => $parsed_modules, + )* + } + ); + } + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __decl_outer_inherent { + ( + $runtime:ident; + $block:ident; + $unchecked:ident; + $( $parsed_modules:ident :: $parsed_name:ident ),*; + $name:ident: $module:ident::{ + Inherent $(, $modules:ident $( <$modules_generic:ident> )* )* + } + $(, $rest_name:ident : $rest_module:ident::{ + $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + })*; + ) => { + __decl_outer_inherent!( + $runtime; + $block; + $unchecked; + $( $parsed_modules :: $parsed_name, )* $module::$name; + $( + $rest_name: $rest_module::{ + $( $rest_modules $( <$rest_modules_generic> )* ),* + } + ),*; + ); + }; + ( + $runtime:ident; + $block:ident; + $unchecked:ident; + $( $parsed_modules:ident :: $parsed_name:ident ),*; + $name:ident: $module:ident::{ + $ingore:ident $( <$ignor:ident> )* $(, $modules:ident $( <$modules_generic:ident> )* )* + } + $(, $rest_name:ident : $rest_module:ident::{ + $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + })*; + ) => { + __decl_outer_inherent!( + $runtime; + $block; + $unchecked; + $( $parsed_modules :: $parsed_name ),*; + $name: $module::{ $( $modules $( <$modules_generic> )* ),* } + $( + , $rest_name: $rest_module::{ + $( $rest_modules $( <$rest_modules_generic> )* ),* + } + )*; + ); + }; + ( + $runtime:ident; + $block:ident; + $unchecked:ident; + $( $parsed_modules:ident :: $parsed_name:ident ),*; + $name:ident: $module:ident::{} + $(, $rest_name:ident : $rest_module:ident::{ + $( $rest_modules:ident $( <$rest_modules_generic:ident> )* ),* + })*; + ) => { + __decl_outer_inherent!( + $runtime; + $block; + $unchecked; + $( $parsed_modules :: $parsed_name ),*; + $( + $rest_name: $rest_module::{ + $( $rest_modules $( <$rest_modules_generic> )* ),* + } + ),*; + ); + }; + ( + $runtime:ident; + $block:ident; + $unchecked:ident; + $( $parsed_modules:ident :: $parsed_name:ident ),*; + ; + ) => { + substrate_generate_ident_name! { + impl_outer_inherent!( + pub struct InherentData where Block = $block, UncheckedExtrinsic = $unchecked { + $( + $parsed_modules: $parsed_name export Error as "inherent-error-ident" $parsed_name, )* } ); diff --git a/substrate/srml/timestamp/Cargo.toml b/substrate/srml/timestamp/Cargo.toml index 3b06f6c39a..c07a62aeda 100644 --- a/substrate/srml/timestamp/Cargo.toml +++ b/substrate/srml/timestamp/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] hex-literal = "0.1.0" serde = { version = "1.0", default-features = false } serde_derive = { version = "1.0", optional = true } +parity-codec-derive = { version = "2.1", default-features = false } parity-codec = { version = "2.1", default-features = false } substrate-primitives = { path = "../../core/primitives", default-features = false } sr-std = { path = "../../core/sr-std", default-features = false } @@ -29,6 +30,7 @@ std = [ "srml-consensus/std", "serde/std", "serde_derive", + "parity-codec-derive/std", "parity-codec/std", "substrate-primitives/std", "srml-system/std", diff --git a/substrate/srml/timestamp/src/lib.rs b/substrate/srml/timestamp/src/lib.rs index 6d64800189..02514289b5 100644 --- a/substrate/srml/timestamp/src/lib.rs +++ b/substrate/srml/timestamp/src/lib.rs @@ -33,6 +33,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[macro_use] extern crate sr_std as rstd; #[macro_use] @@ -50,14 +51,18 @@ extern crate sr_primitives as runtime_primitives; extern crate srml_system as system; extern crate srml_consensus as consensus; extern crate parity_codec as codec; +#[macro_use] +extern crate parity_codec_derive; use codec::HasCompact; use runtime_support::{StorageValue, Parameter}; use runtime_support::dispatch::Result; -use runtime_primitives::traits::{As, OnFinalise, SimpleArithmetic, Zero}; +use runtime_primitives::RuntimeString; +use runtime_primitives::traits::{ + As, OnFinalise, SimpleArithmetic, Zero, ProvideInherent, Block as BlockT, Extrinsic +}; use system::ensure_inherent; -use rstd::ops::{Mul, Div}; - +use rstd::{result, ops::{Mul, Div}, vec::Vec}; pub trait Trait: consensus::Trait + system::Trait { /// The position of the required timestamp-set extrinsic. @@ -106,7 +111,7 @@ impl Module { fn set(origin: T::Origin, now: ::Type) -> Result { ensure_inherent(origin)?; let now = now.into(); - + assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); assert!( >::extrinsic_index() == Some(T::TIMESTAMP_SET_POSITION), @@ -123,12 +128,49 @@ impl Module { } /// Set the timestamp to something in particular. Only used for tests. - #[cfg(any(feature = "std", test))] + #[cfg(feature = "std")] pub fn set_timestamp(now: T::Moment) { ::Now::put(now); } } +#[derive(Encode)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum InherentError { + Other(RuntimeString), + TimestampInFuture(u64), +} + +impl ProvideInherent for Module { + type Inherent = T::Moment; + type Call = Call; + type Error = InherentError; + + fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> { + vec![(T::TIMESTAMP_SET_POSITION, Call::set(data.into()))] + } + + fn check_inherent Option<&Self::Call>>( + block: &Block, data: Self::Inherent, extract_function: &F + ) -> result::Result<(), Self::Error> { + const MAX_TIMESTAMP_DRIFT: u64 = 60; + + let xt = block.extrinsics().get(T::TIMESTAMP_SET_POSITION as usize) + .ok_or_else(|| InherentError::Other("No valid timestamp inherent in block".into()))?; + + let t = match (xt.is_signed(), extract_function(&xt)) { + (Some(false), Some(Call::set(ref t))) => t.clone(), + _ => return Err(InherentError::Other("No valid timestamp inherent in block".into())), + }.into().as_(); + + if t > data.as_() + MAX_TIMESTAMP_DRIFT { + Err(InherentError::TimestampInFuture(t)) + } else { + Ok(()) + } + } +} + impl OnFinalise for Module { fn on_finalise(_n: T::BlockNumber) { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block");