Runtime version (#256)

* Runtime version

* Updated genesis.wasm

* Minor fixes

* Fresh runtime

* Default version for pre Poc-2; Fixed authorship interface check

* Fixed authoring check
This commit is contained in:
Arkadiy Paronyan authored and Gav Wood committed 2018-07-03 17:44:43 +02:00
1 parent e6a7c64518
commit 12268ae700
52 files changed
+503 -179

No files matched your search

+6
View File
@@ -54,6 +54,12 @@ error_chain! {
display("Message sender {:?} is not a valid authority.", a),
}
/// Authoring interface does not match the runtime.
InvalidRuntime {
description("Authoring for current runtime is not supported"),
display("Authoring for current runtime is not supported."),
}
/// Justification requirements not met.
InvalidJustification {
description("Invalid justification"),
+1
View File
@@ -18,6 +18,7 @@ substrate-client = { path = "../../../substrate/client" }
substrate-state-machine = { path = "../../../substrate/state-machine" }
substrate-runtime-support = { path = "../../../substrate/runtime-support" }
substrate-codec = { path = "../../../substrate/codec" }
substrate-executor = { path = "../../../substrate/executor" }
substrate-state-db = { path = "../../../substrate/state-db" }
[dev-dependencies]
+3 -1
View File
@@ -27,6 +27,7 @@ extern crate substrate_primitives as primitives;
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_runtime_primitives as runtime_primitives;
extern crate substrate_codec as codec;
extern crate substrate_executor as executor;
extern crate substrate_state_db as state_db;
#[macro_use]
@@ -52,6 +53,7 @@ use runtime_primitives::bft::Justification;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, Hashing, HashingFor, Zero};
use runtime_primitives::BuildStorage;
use state_machine::backend::Backend as StateBackend;
use executor::RuntimeInfo;
use state_machine::{CodeExecutor, TrieH256, DBValue};
use utils::{Meta, db_err, meta_keys, number_to_db_key, open_database, read_db, read_id, read_meta};
use state_db::StateDb;
@@ -82,7 +84,7 @@ pub fn new_client<E, S, Block>(
Block: BlockT,
<Block::Header as HeaderT>::Number: As<u32>,
Block::Hash: Into<[u8; 32]>, // TODO: remove when patricia_trie generic.
E: CodeExecutor,
E: CodeExecutor + RuntimeInfo,
S: BuildStorage,
{
let backend = Arc::new(Backend::new(settings, FINALIZATION_WINDOW)?);
@@ -18,6 +18,7 @@ use std::sync::Arc;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::Block as BlockT;
use state_machine::{self, OverlayedChanges, Backend as StateBackend, CodeExecutor};
use executor::{RuntimeVersion, RuntimeInfo};
use backend;
use error;
@@ -50,6 +51,9 @@ pub trait CallExecutor<B: BlockT> {
///
/// No changes are made.
fn prove_at_state<S: state_machine::Backend>(&self, state: S, overlay: &mut OverlayedChanges, method: &str, call_data: &[u8]) -> Result<(Vec<u8>, Vec<Vec<u8>>), error::Error>;
/// Get runtime version if supported.
fn native_runtime_version(&self) -> Option<RuntimeVersion>;
}
/// Call executor that executes methods locally, querying all required
@@ -78,7 +82,7 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<B, E>
where
B: backend::LocalBackend<Block>,
E: CodeExecutor,
E: CodeExecutor + RuntimeInfo,
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
@@ -111,4 +115,8 @@ impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<B, E>
.map(|(result, proof, _)| (result, proof))
.map_err(Into::into)
}
}
fn native_runtime_version(&self) -> Option<RuntimeVersion> {
<E as RuntimeInfo>::NATIVE_VERSION
}
}
+19 -4
View File
@@ -30,12 +30,13 @@ use state_machine::{self, Ext, OverlayedChanges, Backend as StateBackend, CodeEx
use backend::{self, BlockImportOperation};
use blockchain::{self, Info as ChainInfo, Backend as ChainBackend, HeaderBackend as ChainHeaderBackend};
use call_executor::{CallExecutor, LocalCallExecutor};
use executor::{RuntimeVersion, RuntimeInfo};
use {error, in_mem, block_builder, runtime_io, bft, genesis};
/// Type that implements `futures::Stream` of block import events.
pub type BlockchainEventStream<Block> = mpsc::UnboundedReceiver<BlockImportNotification<Block>>;
/// Polkadot Client
/// Substrate Client
pub struct Client<B, E, Block> where Block: BlockT {
backend: Arc<B>,
executor: E,
@@ -146,7 +147,7 @@ pub fn new_in_mem<E, Block, S>(
genesis_storage: S
) -> error::Result<Client<in_mem::Backend<Block>, LocalCallExecutor<in_mem::Backend<Block>, E>, Block>>
where
E: CodeExecutor,
E: CodeExecutor + RuntimeInfo,
S: BuildStorage,
Block: BlockT,
{
@@ -161,7 +162,7 @@ impl<B, E, Block> Client<B, E, Block> where
Block: BlockT,
error::Error: From<<<B as backend::Backend<Block>>::State as StateBackend>::Error>,
{
/// Creates new Polkadot Client with given blockchain and code executor.
/// Creates new Substrate Client with given blockchain and code executor.
pub fn new<S: BuildStorage>(
backend: Arc<B>,
executor: E,
@@ -210,11 +211,20 @@ impl<B, E, Block> Client<B, E, Block> where
/// Get the set of authorities at a given block.
pub fn authorities_at(&self, id: &BlockId<Block>) -> error::Result<Vec<AuthorityId>> {
self.executor.call(id, "authorities",&[])
self.executor.call(id, "authorities", &[])
.and_then(|r| Vec::<AuthorityId>::decode(&mut &r.return_data[..])
.ok_or(error::ErrorKind::AuthLenInvalid.into()))
}
/// Get the set of authorities at a given block.
pub fn runtime_version_at(&self, id: &BlockId<Block>) -> error::Result<RuntimeVersion> {
// TODO: Post Poc-2 return an error if version is missing
Ok(self.executor.call(id, "version", &[])
.and_then(|r| RuntimeVersion::decode(&mut &r.return_data[..])
.ok_or(error::ErrorKind::VersionInvalid.into()))
.unwrap_or_default())
}
/// Get call executor reference.
pub fn executor(&self) -> &E {
&self.executor
@@ -439,6 +449,11 @@ impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
error::Error: From<<B::State as state_machine::backend::Backend>::Error>,
{
fn authorities(&self, at: &BlockId<Block>) -> Result<Vec<AuthorityId>, bft::Error> {
let version: Result<_, bft::Error> = self.runtime_version_at(at).map_err(|_| bft::ErrorKind::InvalidRuntime.into());
let version = version?;
if !self.executor.native_runtime_version().map_or(true, |v| v.can_author_with(&version)) {
return Err(bft::ErrorKind::InvalidRuntime.into())
}
self.authorities_at(at).map_err(|_| {
let descriptor = format!("{:?}", at);
bft::ErrorKind::StateUnavailable(descriptor).into()
+6
View File
@@ -70,6 +70,12 @@ error_chain! {
display("Current state of blockchain has invalid authority count value"),
}
/// Cound not get runtime version.
VersionInvalid {
description("Runtime version error"),
display("On-chain runtime does not specify version"),
}
/// Invalid state data.
AuthInvalid(i: u32) {
description("authority value state error"),
+1 -1
View File
@@ -52,7 +52,7 @@ mod tests {
use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic};
use ed25519::{Public, Pair};
native_executor_instance!(Executor, test_client::runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
fn construct_block(backend: &InMemory, number: BlockNumber, parent_hash: Hash, state_root: Hash, txs: Vec<Transfer>) -> (Vec<u8>, Hash) {
use triehash::ordered_trie_root;
+1 -1
View File
@@ -36,7 +36,7 @@ extern crate triehash;
#[macro_use] extern crate error_chain;
#[macro_use] extern crate log;
#[cfg(test)] #[macro_use] extern crate substrate_executor as executor;
#[cfg_attr(test, macro_use)] extern crate substrate_executor as executor;
#[cfg(test)] #[macro_use] extern crate hex_literal;
pub mod error;
@@ -28,6 +28,7 @@ use blockchain::Backend as ChainBackend;
use call_executor::{CallExecutor, CallResult};
use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult};
use light::fetcher::{Fetcher, RemoteCallRequest};
use executor::RuntimeVersion;
/// Call executor that executes methods on remote node, querying execution proof
/// and checking proof by re-executing locally.
@@ -72,6 +73,10 @@ impl<B, F, Block> CallExecutor<Block> for RemoteCallExecutor<B, F>
fn prove_at_state<S: StateBackend>(&self, _state: S, _changes: &mut OverlayedChanges, _method: &str, _call_data: &[u8]) -> ClientResult<(Vec<u8>, Vec<Vec<u8>>)> {
Err(ClientErrorKind::NotAvailableOnLightClient.into())
}
fn native_runtime_version(&self) -> Option<RuntimeVersion> {
None
}
}
/// Check remote execution proof using given backend.
+1 -1
View File
@@ -38,6 +38,6 @@ mod slicable;
mod joiner;
mod keyedvec;
pub use self::slicable::{Input, Slicable};
pub use self::slicable::{Input, Slicable, encode_slice};
pub use self::joiner::Joiner;
pub use self::keyedvec::KeyedVec;
+11 -6
View File
@@ -63,6 +63,16 @@ pub trait Slicable: Sized {
}
}
/// Encode a bytes slice as `Slicable` that can be decoded into a vector.
pub fn encode_slice(bytes: &[u8]) -> Vec<u8> {
let len = bytes.len();
assert!(len <= u32::max_value() as usize, "Attempted to serialize a collection with too many elements.");
let mut r: Vec<u8> = Vec::new().and(&(len as u32));
r.extend_from_slice(bytes);
r
}
impl<T: Slicable, E: Slicable> Slicable for Result<T, E> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
match input.read_byte()? {
@@ -182,12 +192,7 @@ impl Slicable for Vec<u8> {
}
fn encode(&self) -> Vec<u8> {
let len = self.len();
assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements.");
let mut r: Vec<u8> = Vec::new().and(&(len as u32));
r.extend_from_slice(self);
r
encode_slice(&self)
}
}
+1
View File
@@ -10,6 +10,7 @@ substrate-runtime-io = { path = "../runtime-io" }
substrate-primitives = { path = "../primitives" }
substrate-serializer = { path = "../serializer" }
substrate-state-machine = { path = "../state-machine" }
substrate-runtime-version = { path = "../runtime/version" }
ed25519 = { path = "../ed25519" }
serde = "1.0"
serde_derive = "1.0"
+10
View File
@@ -26,12 +26,14 @@
//! I leave it as is for now as it might be removed before this is ever done.
#![warn(missing_docs)]
#![recursion_limit="128"]
extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_primitives as primitives;
extern crate substrate_serializer as serializer;
extern crate substrate_state_machine as state_machine;
extern crate substrate_runtime_version as runtime_version;
extern crate ed25519;
extern crate serde;
@@ -61,3 +63,11 @@ pub mod error;
pub use wasm_executor::WasmExecutor;
pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch};
pub use state_machine::Externalities;
pub use runtime_version::RuntimeVersion;
pub use codec::Slicable;
/// Provides runtime information.
pub trait RuntimeInfo {
/// Native runtime information if any.
const NATIVE_VERSION: Option<RuntimeVersion>;
}
@@ -17,6 +17,9 @@
use error::{Error, ErrorKind, Result};
use state_machine::{CodeExecutor, Externalities};
use wasm_executor::WasmExecutor;
use runtime_version::RuntimeVersion;
use codec::Slicable;
use RuntimeInfo;
fn safe_call<F, U>(f: F) -> Result<U>
where F: ::std::panic::UnwindSafe + FnOnce() -> U
@@ -41,22 +44,40 @@ pub trait NativeExecutionDispatch {
/// Dispatch a method and input data to be executed natively. Returns `Some` result or `None`
/// if the `method` is unknown. Panics if there's an unrecoverable error.
fn dispatch(ext: &mut Externalities, method: &str, data: &[u8]) -> Result<Vec<u8>>;
/// Get native runtime version.
const VERSION: RuntimeVersion;
}
/// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence
/// and dispatch to native code when possible, falling back on `WasmExecutor` when not.
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct NativeExecutor<D: NativeExecutionDispatch + Sync + Send> {
/// Dummy field to avoid the compiler complaining about us not using `D`.
pub _dummy: ::std::marker::PhantomData<D>,
_dummy: ::std::marker::PhantomData<D>,
}
impl<D: NativeExecutionDispatch + Sync + Send> NativeExecutor<D> {
/// Create new instance.
pub fn new() -> Self {
NativeExecutor {
_dummy: Default::default(),
}
}
}
impl<D: NativeExecutionDispatch + Sync + Send> Clone for NativeExecutor<D> {
fn clone(&self) -> Self {
NativeExecutor { _dummy: Default::default() }
NativeExecutor {
_dummy: Default::default(),
}
}
}
impl<D: NativeExecutionDispatch + Sync + Send> RuntimeInfo for NativeExecutor<D> {
const NATIVE_VERSION: Option<RuntimeVersion> = Some(D::VERSION);
}
impl<D: NativeExecutionDispatch + Sync + Send> CodeExecutor for NativeExecutor<D> {
type Error = Error;
@@ -71,6 +92,11 @@ impl<D: NativeExecutionDispatch + Sync + Send> CodeExecutor for NativeExecutor<D
// call native
D::dispatch(ext, method, data)
} else {
let version = WasmExecutor.call(ext, code, "version", &[])?;
let version = RuntimeVersion::decode(&mut version.as_slice());
if version.map_or(false, |v| D::VERSION.can_call_with(&v)) {
return D::dispatch(ext, method, data)
}
// call into wasm.
WasmExecutor.call(ext, code, method, data)
}
@@ -79,17 +105,18 @@ impl<D: NativeExecutionDispatch + Sync + Send> CodeExecutor for NativeExecutor<D
#[macro_export]
macro_rules! native_executor_instance {
(pub $name:ident, $dispatcher:path, $code:expr) => {
(pub $name:ident, $dispatcher:path, $version:path, $code:expr) => {
pub struct $name;
native_executor_instance!(IMPL $name, $dispatcher, $code);
native_executor_instance!(IMPL $name, $dispatcher, $version, $code);
};
($name:ident, $dispatcher:path, $code:expr) => {
($name:ident, $dispatcher:path, $version:path, $code:expr) => {
/// A unit struct which implements `NativeExecutionDispatch` feeding in the hard-coded runtime.
struct $name;
native_executor_instance!(IMPL $name, $dispatcher, $code);
native_executor_instance!(IMPL $name, $dispatcher, $version, $code);
};
(IMPL $name:ident, $dispatcher:path, $code:expr) => {
(IMPL $name:ident, $dispatcher:path, $version:path, $code:expr) => {
impl $crate::NativeExecutionDispatch for $name {
const VERSION: $crate::RuntimeVersion = $version;
fn native_equivalent() -> &'static [u8] {
// WARNING!!! This assumes that the runtime was built *before* the main project. Until we
// get a proper build script, this must be strictly adhered to or things will go wrong.
@@ -104,9 +131,8 @@ macro_rules! native_executor_instance {
impl $name {
pub fn new() -> $crate::NativeExecutor<$name> {
$crate::NativeExecutor { _dummy: Default::default() }
$crate::NativeExecutor::new()
}
}
}
}
+2 -2
View File
@@ -34,7 +34,7 @@ fn should_return_header() {
Ok(Some(ref x)) if x == &Header {
parent_hash: 0.into(),
number: 0,
state_root: "987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d".into(),
state_root: "17dccc74bd9200b7ce5a2f6a1bf379f1cdcf91bca3d19c3d17e1478b8d404703".into(),
extrinsics_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into(),
digest: Default::default(),
}
@@ -70,7 +70,7 @@ fn should_notify_about_latest_block() {
// assert notification send to transport
let (notification, next) = core.run(transport.into_future()).unwrap();
assert_eq!(notification, Some(
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x27f04d7574733bb155bbf5a0399fcc99d3c4dbf15bf99862d261bced9444179a","stateRoot":"0x987aa0851a133413b42c6d9aa3c91b1dddc2ad5337508ee8815116b11e44c64d"},"subscription":0}}"#.to_owned()
r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"digest":{"logs":[]},"extrinsicsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","number":1,"parentHash":"0x50fb1e7f32e8ad17f553846f4338861e17eb95132e7c3b433e0429ffab2f8f13","stateRoot":"0x17dccc74bd9200b7ce5a2f6a1bf379f1cdcf91bca3d19c3d17e1478b8d404703"},"subscription":0}}"#.to_owned()
));
// no more notifications on this channel
assert_eq!(core.run(next.into_future()).unwrap().0, None);
@@ -0,0 +1,21 @@
[package]
name = "substrate-runtime-version"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
substrate-runtime-support = { path = "../../runtime-support", default_features = false }
[features]
default = ["std"]
std = [
"serde/std",
"serde_derive",
"substrate-codec/std",
"substrate-runtime-std/std",
"substrate-runtime-support/std",
]
@@ -0,0 +1,154 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Substrate Demo.
// Substrate Demo 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 Demo 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 Demo. If not, see <http://www.gnu.org/licenses/>.
//! Version module for runtime; Provide a function that returns runtime version.
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[allow(unused_imports)]
#[macro_use]
extern crate substrate_runtime_std as rstd;
#[macro_use]
extern crate substrate_runtime_support as runtime_support;
extern crate substrate_codec as codec;
use rstd::prelude::*;
use codec::Slicable;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
pub type VersionString = ::std::borrow::Cow<'static, str>;
#[cfg(not(feature = "std"))]
pub type VersionString = &'static str;
#[cfg(feature = "std")]
#[macro_export]
macro_rules! ver_str {
( $y:expr ) => {{ ::std::borrow::Cow::Borrowed($y) }}
}
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! ver_str {
( $y:expr ) => {{ $y }}
}
/// Runtime version.
/// This should not be thought of as classic Semver (major/minor/tiny).
/// This triplet have different semantics and mis-interpretation could cause problems.
/// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`,
/// absolutely not `impl_version` since they change the semantics of the runtime.
#[derive(Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct RuntimeVersion {
/// Identifies the different Substrate runtimes. There'll be at least polkadot and demo. A different on-chain spec_name to that of the native runtime would normally result in node not attempting to sync further.
pub spec_name: VersionString,
/// 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,
/// `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.
pub authoring_version: u32,
/// Version of the runtime specification. A full-node will not attempt to use its native runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`, `spec_version` and `authoring_version`
/// are the same between Wasm and native.
pub spec_version: u32,
/// Version of the implementation of the specification. Nodes are free to ignore this; it serves only as an indication that the code is different;
/// as long as the other two versions are the same then while the code may be different, it is nonetheless required to do the same thing.
/// Non-consensus-breaking optimisations are about the only changes that could be made which would result in only the impl_version changing.
pub impl_version: u32,
}
// TODO: remove this after PoC-2
#[cfg(feature = "std")]
impl Default for RuntimeVersion {
fn default() -> RuntimeVersion {
RuntimeVersion {
spec_name: ver_str!("polkadot"),
impl_name: ver_str!("parity-polkadot"),
authoring_version: 0,
spec_version: 0,
impl_version: 0,
}
}
}
#[cfg(feature = "std")]
impl RuntimeVersion {
/// Check if this version matches other version for calling into runtime.
pub fn can_call_with(&self, other: &RuntimeVersion) -> bool {
self.spec_version == other.spec_version &&
self.spec_name == other.spec_name &&
self.authoring_version == other.authoring_version
}
/// Check if this version matches other version for authoring blocks.
pub fn can_author_with(&self, other: &RuntimeVersion) -> bool {
self.authoring_version == other.authoring_version &&
self.spec_name == other.spec_name
}
}
impl Slicable for RuntimeVersion {
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
v.extend(codec::encode_slice(self.spec_name.as_bytes()));
v.extend(codec::encode_slice(self.impl_name.as_bytes()));
self.authoring_version.using_encoded(|s| v.extend(s));
self.spec_version.using_encoded(|s| v.extend(s));
self.impl_version.using_encoded(|s| v.extend(s));
v
}
#[cfg(not(feature = "std"))]
fn decode<I: codec::Input>(_value: &mut I) -> Option<Self> {
unreachable!()
}
#[cfg(feature = "std")]
fn decode<I: codec::Input>(value: &mut I) -> Option<Self> {
Some(RuntimeVersion {
spec_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()),
impl_name: Cow::Owned(String::from_utf8_lossy(&Vec::decode(value)?).into()),
authoring_version: Slicable::decode(value)?,
spec_version: Slicable::decode(value)?,
impl_version: Slicable::decode(value)?,
})
}
}
pub trait Trait {
const VERSION: RuntimeVersion;
}
decl_module! {
pub struct Module<T: Trait>;
}
impl<T: Trait> Module<T> {
/// Get runtime version.
pub fn version() -> RuntimeVersion {
T::VERSION.clone()
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ mod native_executor {
#![allow(missing_docs)]
use super::runtime;
native_executor_instance!(pub NativeExecutor, runtime::api::dispatch, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
native_executor_instance!(pub NativeExecutor, runtime::api::dispatch, runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
}
/// Native executor used for tests.
+3 -1
View File
@@ -16,6 +16,7 @@ substrate-runtime-io = { path = "../runtime-io", default-features = false }
substrate-runtime-support = { path = "../runtime-support", default-features = false }
substrate-primitives = { path = "../primitives", default-features = false }
substrate-runtime-primitives = { path = "../runtime/primitives", default-features = false }
substrate-runtime-version = { path = "../runtime/version", default-features = false }
[features]
default = ["std"]
@@ -31,5 +32,6 @@ std = [
"substrate-runtime-io/std",
"substrate-runtime-support/std",
"substrate-primitives/std",
"substrate-runtime-primitives/std"
"substrate-runtime-primitives/std",
"substrate-runtime-version/std"
]
+17 -1
View File
@@ -43,6 +43,8 @@ extern crate substrate_keyring as keyring;
extern crate substrate_primitives as primitives;
#[macro_use]
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_runtime_version as runtime_version;
#[cfg(feature = "std")] pub mod genesismap;
@@ -53,8 +55,22 @@ use codec::Slicable;
use runtime_primitives::traits::{BlindCheckable, BlakeTwo256};
use runtime_primitives::Ed25519Signature;
use runtime_version::RuntimeVersion;
pub use primitives::hash::H256;
/// Test runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: ver_str!("test"),
impl_name: ver_str!("parity-test"),
authoring_version: 1,
spec_version: 1,
impl_version: 1,
};
fn version() -> RuntimeVersion {
VERSION
}
/// Calls in transactions.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
@@ -146,8 +162,8 @@ pub fn run_tests(mut input: &[u8]) -> Vec<u8> {
pub mod api {
use system;
impl_stubs!(
version => |()| super::version(),
authorities => |()| system::authorities(),
initialise_block => |header| system::initialise_block(header),
execute_block => |block| system::execute_block(block),
+12
View File
@@ -730,6 +730,17 @@ dependencies = [
"substrate-runtime-std 0.1.0",
]
[[package]]
name = "substrate-runtime-version"
version = "0.1.0"
dependencies = [
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-codec 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
]
[[package]]
name = "substrate-state-machine"
version = "0.1.0"
@@ -759,6 +770,7 @@ dependencies = [
"substrate-runtime-primitives 0.1.0",
"substrate-runtime-std 0.1.0",
"substrate-runtime-support 0.1.0",
"substrate-runtime-version 0.1.0",
]
[[package]]
@@ -11,6 +11,7 @@ substrate-codec = { path = "../../codec", default-features = false }
substrate-runtime-std = { path = "../../runtime-std", default-features = false }
substrate-runtime-io = { path = "../../runtime-io", default-features = false }
substrate-runtime-support = { path = "../../runtime-support", default-features = false }
substrate-runtime-version = { path = "../../runtime/version", default-features = false }
substrate-primitives = { path = "../../primitives", default-features = false }
substrate-runtime-primitives = { path = "../../runtime/primitives", default-features = false }
@@ -24,6 +25,7 @@ std = [
"substrate-runtime-std/std",
"substrate-runtime-io/std",
"substrate-runtime-support/std",
"substrate-runtime-version/std",
"substrate-primitives/std",
"substrate-runtime-primitives/std"
]
Binary file not shown.