Move inherent implementation into the modules (#924)

* Adds new `ProvideInherent` trait

Also implements the new trait for `srml/consensus` and `srml/timestamp`.

* Adds `impl_outer_inherent!` macro

* Reexport macros from `alloc`

* Introduce `RuntimeString` and fix `ProvideInherent` on `no_std`

* Replace `VersionString` with `RuntimeString`

* Improvements for `impl_outer_inherent!`

* Make `construct_runtime!` support `impl_outer_inherent!`

* Fixes after rebase

* Whitespace
This commit is contained in:
Bastian Köcher
2018-10-18 10:55:52 +02:00
committed by Gav Wood
parent 36625faa9f
commit 4132a49fbb
31 changed files with 498 additions and 166 deletions
+2 -2
View File
@@ -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",
+5 -5
View File
@@ -91,7 +91,7 @@ pub struct Fork<Block: BlockT, T> {
head: Entry<Block, T>,
}
/// Outcome of Fork::try_append_or_fork.
/// Outcome of Fork::try_append_or_fork.
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
pub enum ForkAppendResult<Block: BlockT> {
@@ -356,7 +356,7 @@ impl<Block: BlockT, T: CacheItemT, S: Storage<Block, T>> ListCache<Block, T, S>
// 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<Block: BlockT, T: CacheItemT, S: Storage<Block, T>>(
#[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<u64>;
type Block = RawBlock<ExtrinsicWrapper<u64>>;
pub fn test_id(number: u64) -> ComplexBlockId<Block> {
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(
+2 -2
View File
@@ -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<u64>;
type Block = RawBlock<ExtrinsicWrapper<u64>>;
fn prepare_changes(changes: Vec<(Vec<u8>, Vec<u8>)>) -> (H256, MemoryDB<Blake2Hasher>) {
let mut changes_root = H256::default();
+2 -2
View File
@@ -402,10 +402,10 @@ impl<Block> LightBlockchainStorage<Block> for LightStorage<Block>
#[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<u32>;
type Block = RawBlock<ExtrinsicWrapper<u32>>;
fn prepare_header(parent: &Hash, number: u64, extrinsics_root: Hash) -> Header {
Header {
+2 -2
View File
@@ -1126,12 +1126,12 @@ impl<B, E, Block> api::BlockBuilder<Block> for Client<B, E, Block> where
self.call_api_at(at, "inherent_extrinsics", &(inherent))
}
fn check_inherents<InherentData: Encode + Decode>(
fn check_inherents<InherentData: Encode + Decode, InherentError: Encode + Decode>(
&self,
at: &BlockId<Block>,
block: &Block,
data: &InherentData
) -> Result<Result<(), api::BlockBuilderError>, Self::Error> {
) -> Result<Result<(), InherentError>, Self::Error> {
self.call_api_at(at, "check_inherents", &(block, data))
}
+2 -3
View File
@@ -179,11 +179,10 @@ impl<Block: BlockT> StorageNotifications<Block> {
#[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<Vec<(StorageKey, Option<StorageData>)>> for StorageChangeSet {
fn from(changes: Vec<(StorageKey, Option<StorageData>)>) -> Self {
@@ -201,7 +200,7 @@ mod tests {
}
}
type Block = RawBlock<Hash>;
type Block = RawBlock<ExtrinsicWrapper<Hash>>;
#[test]
fn triggering_change_should_notify_wildcard_listeners() {
+2 -2
View File
@@ -195,10 +195,10 @@ impl<B: BlockT> BlockCollection<B> {
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<u64>;
type Block = RawBlock<ExtrinsicWrapper<u64>>;
fn is_empty(bc: &BlockCollection<Block>) -> bool {
bc.blocks.is_empty() &&
@@ -310,11 +310,11 @@ impl<Block: BlockT> Specialization<Block> for ConsensusGossip<Block> 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<u64>;
type Block = RawBlock<ExtrinsicWrapper<u64>>;
#[test]
fn collects_garbage() {
-2
View File
@@ -5,7 +5,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
[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",
]
+1 -14
View File
@@ -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<Block: BlockT, AuthorityId> {
@@ -482,7 +469,7 @@ decl_apis! {
/// Generate inherent extrinsics.
fn inherent_extrinsics<InherentExtrinsic, UncheckedExtrinsic>(inherent: InherentExtrinsic) -> Vec<UncheckedExtrinsic>;
/// Check that the inherents are valid.
fn check_inherents<InherentData>(block: Block, data: InherentData) -> Result<(), BlockBuilderError>;
fn check_inherents<InherentData, Error>(block: Block, data: InherentData) -> Result<(), Error>;
/// Generate a random seed.
fn random_seed() -> <Block as BlockT>::Hash;
}
-2
View File
@@ -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",
]
@@ -72,7 +72,7 @@ pub struct Block<Header, Extrinsic> {
impl<Header, Extrinsic> traits::Block for Block<Header, Extrinsic>
where
Header: HeaderT,
Extrinsic: Member + Codec,
Extrinsic: Member + Codec + traits::Extrinsic,
{
type Extrinsic = Extrinsic;
type Header = Header;
@@ -102,4 +102,4 @@ pub struct SignedBlock<H, E> {
pub block: Block<H, E>,
/// Block justification.
pub justification: Justification,
}
}
@@ -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<Address, Index, Call, Signature> UncheckedMortalExtrinsic<Address, Index, C
function,
}
}
}
/// `true` if there is a signature.
pub fn is_signed(&self) -> bool {
self.signature.is_some()
impl<Address, Index, Call, Signature> Extrinsic for UncheckedMortalExtrinsic<Address, Index, Call, Signature> {
fn is_signed(&self) -> Option<bool> {
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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::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!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Err("bad signature in extrinsic"));
}
+6 -1
View File
@@ -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<u8>;
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};
+30 -2
View File
@@ -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>(Xt);
impl<Xt> traits::Extrinsic for ExtrinsicWrapper<Xt> {
fn is_signed(&self) -> Option<bool> {
None
}
}
impl<Xt> From<Xt> for ExtrinsicWrapper<Xt> {
fn from(xt: Xt) -> Self {
ExtrinsicWrapper(xt)
}
}
impl<Xt> Deref for ExtrinsicWrapper<Xt> {
type Target = Xt;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
pub struct Block<Xt> {
pub header: Header,
pub extrinsics: Vec<Xt>,
}
impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug> traits::Block for Block<Xt> {
impl<Xt: 'static + Codec + Sized + Send + Sync + Serialize + DeserializeOwned + Clone + Eq + Debug + traits::Extrinsic> traits::Block for Block<Xt> {
type Extrinsic = Xt;
type Header = Header;
type Hash = <Header as traits::Header>::Hash;
@@ -125,6 +148,11 @@ impl<Call: Codec + Sync + Send + Serialize, Context> Checkable<Context> for Test
type Checked = Self;
fn check(self, _: &Context) -> Result<Self::Checked, &'static str> { Ok(self) }
}
impl<Call: Codec + Sync + Send + Serialize> traits::Extrinsic for TestXt<Call> {
fn is_signed(&self) -> Option<bool> {
None
}
}
impl<Call> Applyable for TestXt<Call> where
Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Serialize + DeserializeOwned,
{
+41 -1
View File
@@ -383,6 +383,17 @@ pub trait MaybeDisplay {}
#[cfg(not(feature = "std"))]
impl<T> MaybeDisplay for T {}
#[cfg(feature = "std")]
pub trait MaybeDecode: ::codec::Decode {}
#[cfg(feature = "std")]
impl<T: ::codec::Decode> MaybeDecode for T {}
#[cfg(not(feature = "std"))]
pub trait MaybeDecode {}
#[cfg(not(feature = "std"))]
impl<T> MaybeDecode for T {}
pub trait Member: Send + Sync + Sized + MaybeSerializeDebug + Eq + PartialEq + Clone + 'static {}
impl<T: Send + Sync + Sized + MaybeSerializeDebug + Eq + PartialEq + Clone + 'static> 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<Hash=Self::Hash>;
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<Block: self::Block, F: Fn(&Block::Extrinsic) -> 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<bool>;
}
+2 -1
View File
@@ -15,7 +15,8 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#[cfg(feature = "nightly")]
extern crate alloc;
#[doc(hidden)]
pub extern crate alloc;
extern "C" {
fn ext_malloc(size: usize) -> *mut u8;
+2
View File
@@ -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",
]
+5 -6
View File
@@ -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.
+9 -3
View File
@@ -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<bool> {
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<Block, u32, u32, u32> for Runtime {
impl BlockBuilder<Block, u32, u32, u32, u32> for Runtime {
fn initialise_block(header: <Block as BlockT>::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!()
}
+1 -2
View File
@@ -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",
]
+6 -7
View File
@@ -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<B, E, Block> 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<C, A> bft::Proposer<<C as AuthoringApi>::Block> for Proposer<C, A> 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));
+4 -17
View File
@@ -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<Block>;
#[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<u8>);
///
/// 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<u32>,
}
impl InherentData {
/// Create a new `InherentData` instance.
pub fn new(timestamp: Timestamp, offline_indices: Vec<u32>) -> Self {
Self {
timestamp,
offline_indices
}
impl traits::Extrinsic for UncheckedExtrinsic {
fn is_signed(&self) -> Option<bool> {
None
}
}
+12 -47
View File
@@ -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<Hash, SessionKey>) {
pub enum Runtime with Log(InternalLog: DigestItem<Hash, SessionKey>) 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<Block, InherentData, UncheckedExtrinsic, InherentData> for Runtime {
impl BlockBuilder<Block, InherentData, UncheckedExtrinsic, InherentData, InherentError> for Runtime {
fn initialise_block(header: <Block as BlockT>::Header) {
Executive::initialise_block(&header)
}
@@ -283,49 +286,11 @@ impl_apis! {
}
fn inherent_extrinsics(data: InherentData) -> Vec<UncheckedExtrinsic> {
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() -> <Block as BlockT>::Hash {
+2 -2
View File
@@ -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",
+34 -2
View File
@@ -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<T: Trait> Module<T> {
}
}
impl<T: Trait> ProvideInherent for Module<T> {
type Inherent = Vec<u32>;
type Call = Call<T>;
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<Block: BlockT, F: Fn(&Block::Extrinsic) -> 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<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
fn on_finalise(_n: T::BlockNumber) {
@@ -246,4 +279,3 @@ impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
}
}
}
+128
View File
@@ -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 <http://www.gnu.org/licenses/>.
#[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), )*
}
};
}
+3 -10
View File
@@ -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;
+130 -9
View File
@@ -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,
)*
}
);
+2
View File
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
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",
+47 -5
View File
@@ -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<T: Trait> Module<T> {
fn set(origin: T::Origin, now: <T::Moment as HasCompact>::Type) -> Result {
ensure_inherent(origin)?;
let now = now.into();
assert!(!<Self as Store>::DidUpdate::exists(), "Timestamp must be updated only once in the block");
assert!(
<system::Module<T>>::extrinsic_index() == Some(T::TIMESTAMP_SET_POSITION),
@@ -123,12 +128,49 @@ impl<T: Trait> Module<T> {
}
/// 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) {
<Self as Store>::Now::put(now);
}
}
#[derive(Encode)]
#[cfg_attr(feature = "std", derive(Decode))]
pub enum InherentError {
Other(RuntimeString),
TimestampInFuture(u64),
}
impl<T: Trait> ProvideInherent for Module<T> {
type Inherent = T::Moment;
type Call = Call<T>;
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<Block: BlockT, F: Fn(&Block::Extrinsic) -> 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<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
fn on_finalise(_n: T::BlockNumber) {
assert!(<Self as Store>::DidUpdate::take(), "Timestamp must be updated once in the block");