Support authoring for multiple runtime versions (#816)

This commit is contained in:
Arkadiy Paronyan
2018-09-27 14:56:40 +02:00
committed by Gav Wood
parent 5eb1aefde6
commit 29c9719568
11 changed files with 77 additions and 32 deletions
+4 -4
View File
@@ -20,7 +20,7 @@ use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::Block as BlockT;
use state_machine::{self, OverlayedChanges, Ext,
CodeExecutor, ExecutionManager, native_when_possible};
use executor::{RuntimeVersion, RuntimeInfo};
use executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
use hash_db::Hasher;
use trie::MemoryDB;
use codec::Decode;
@@ -89,7 +89,7 @@ where
) -> Result<(Vec<u8>, Vec<Vec<u8>>), error::Error>;
/// Get runtime version if supported.
fn native_runtime_version(&self) -> Option<RuntimeVersion>;
fn native_runtime_version(&self) -> Option<&NativeVersion>;
}
/// Call executor that executes methods locally, querying all required
@@ -194,7 +194,7 @@ where
.map_err(Into::into)
}
fn native_runtime_version(&self) -> Option<RuntimeVersion> {
<E as RuntimeInfo>::NATIVE_VERSION
fn native_runtime_version(&self) -> Option<&NativeVersion> {
Some(self.executor.native_version())
}
}
+2 -2
View File
@@ -905,8 +905,8 @@ impl<B, E, Block> bft::Authorities<Block> for Client<B, E, Block>
let native_version: Result<_, bft::Error> = self.executor.native_runtime_version()
.ok_or_else(|| bft::ErrorKind::NativeRuntimeMissing.into());
let native_version = native_version?;
if !on_chain_version.can_author_with(&native_version) {
return Err(bft::ErrorKind::IncompatibleAuthoringRuntime(on_chain_version, native_version).into())
if !native_version.can_author_with(&on_chain_version) {
return Err(bft::ErrorKind::IncompatibleAuthoringRuntime(on_chain_version, native_version.runtime_version.clone()).into())
}
self.authorities_at(at).map_err(|_| {
let descriptor = format!("{:?}", at);
+1 -1
View File
@@ -52,7 +52,7 @@ mod tests {
use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic};
use primitives::{Blake2Hasher, ed25519::{Public, Pair}};
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"));
native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
fn executor() -> ::executor::NativeExecutor<Executor> {
NativeExecutionDispatch::new()
@@ -31,7 +31,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;
use executor::{RuntimeVersion, NativeVersion};
use codec::Decode;
use heapsize::HeapSizeOf;
use trie::MemoryDB;
@@ -118,7 +118,7 @@ where
Err(ClientErrorKind::NotAvailableOnLightClient.into())
}
fn native_runtime_version(&self) -> Option<RuntimeVersion> {
fn native_runtime_version(&self) -> Option<&NativeVersion> {
None
}
}
+5 -4
View File
@@ -46,7 +46,8 @@ extern crate parking_lot;
extern crate twox_hash;
extern crate hash_db;
#[macro_use] extern crate log;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
@@ -75,14 +76,14 @@ 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 runtime_version::{RuntimeVersion, NativeVersion};
pub use codec::Codec;
use primitives::Blake2Hasher;
/// Provides runtime information.
pub trait RuntimeInfo {
/// Native runtime information if any.
const NATIVE_VERSION: Option<RuntimeVersion>;
/// Native runtime information.
fn native_version(&self) -> &NativeVersion;
/// Extract RuntimeVersion of given :code block
fn runtime_version<E: Externalities<Blake2Hasher>> (
+18 -11
View File
@@ -18,7 +18,7 @@ use error::{Error, ErrorKind, Result};
use state_machine::{CodeExecutor, Externalities};
use wasm_executor::WasmExecutor;
use wasmi::Module as WasmModule;
use runtime_version::RuntimeVersion;
use runtime_version::{NativeVersion, RuntimeVersion};
use std::collections::HashMap;
use codec::Decode;
use primitives::hashing::blake2_256;
@@ -106,13 +106,11 @@ pub trait NativeExecutionDispatch: Send + Sync {
// fn dispatch<H: hash_db::Hasher>(ext: &mut Externalities<H>, method: &str, data: &[u8]) -> Result<Vec<u8>>;
fn dispatch(ext: &mut Externalities<Blake2Hasher>, method: &str, data: &[u8]) -> Result<Vec<u8>>;
/// Get native runtime version.
const VERSION: RuntimeVersion;
/// Provide native runtime version.
fn native_version() -> NativeVersion;
/// Construct corresponding `NativeExecutor`
fn new() -> NativeExecutor<Self> where Self: Sized {
NativeExecutor::new()
}
fn new() -> NativeExecutor<Self> where Self: Sized;
}
/// A generic `CodeExecutor` implementation that uses a delegate to determine wasm code equivalence
@@ -123,6 +121,8 @@ pub struct NativeExecutor<D: NativeExecutionDispatch> {
_dummy: ::std::marker::PhantomData<D>,
/// The fallback executor in case native isn't available.
fallback: WasmExecutor,
/// Native runtime version info.
native_version: NativeVersion,
}
impl<D: NativeExecutionDispatch> NativeExecutor<D> {
@@ -131,6 +131,7 @@ impl<D: NativeExecutionDispatch> NativeExecutor<D> {
NativeExecutor {
_dummy: Default::default(),
fallback: WasmExecutor::new(),
native_version: D::native_version(),
}
}
}
@@ -140,12 +141,15 @@ impl<D: NativeExecutionDispatch> Clone for NativeExecutor<D> {
NativeExecutor {
_dummy: Default::default(),
fallback: self.fallback.clone(),
native_version: D::native_version(),
}
}
}
impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
const NATIVE_VERSION: Option<RuntimeVersion> = Some(D::VERSION);
fn native_version(&self) -> &NativeVersion {
&self.native_version
}
fn runtime_version<E: Externalities<Blake2Hasher>>(
&self,
@@ -174,16 +178,16 @@ impl<D: NativeExecutionDispatch> CodeExecutor<Blake2Hasher> for NativeExecutor<D
Ok((module, onchain_version)) => (module, onchain_version),
Err(_) => return (Err(ErrorKind::InvalidCode(code.into()).into()), false),
};
match (use_native, onchain_version.as_ref().map_or(false, |v| v.can_call_with(&D::VERSION))) {
match (use_native, onchain_version.as_ref().map_or(false, |v| v.can_call_with(&self.native_version.runtime_version))) {
(_, false) => {
trace!(target: "executor", "Request for native execution failed (native: {}, chain: {})", D::VERSION, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
trace!(target: "executor", "Request for native execution failed (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
(self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false)
}
(false, _) => {
(self.fallback.call_in_wasm_module(ext, heap_pages, module, method, data), false)
}
_ => {
trace!(target: "executor", "Request for native execution succeeded (native: {}, chain: {})", D::VERSION, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
trace!(target: "executor", "Request for native execution succeeded (native: {}, chain: {})", self.native_version.runtime_version, onchain_version.as_ref().map_or_else(||"<None>".into(), |v| format!("{}", v)));
(D::dispatch(ext, method, data), true)
}
}
@@ -205,7 +209,6 @@ macro_rules! native_executor_instance {
// TODO: this is not so great I think I should go back to have dispatch take a type param and modify this macro to accept a type param and then pass it in from the test-client instead
use primitives::Blake2Hasher as _Blake2Hasher;
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.
@@ -216,6 +219,10 @@ macro_rules! native_executor_instance {
.ok_or_else(|| $crate::error::ErrorKind::MethodNotFound(method.to_owned()).into())
}
fn native_version() -> $crate::NativeVersion {
$version()
}
fn new() -> $crate::NativeExecutor<$name> {
$crate::NativeExecutor::new()
}
+21 -6
View File
@@ -36,6 +36,8 @@ extern crate parity_codec as codec;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(feature = "std")]
use std::collections::HashSet;
#[cfg(feature = "std")]
pub type VersionString = ::std::borrow::Cow<'static, str>;
@@ -129,14 +131,27 @@ impl RuntimeVersion {
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
}
/// Check if this version supports a particular API.
pub fn has_api(&self, api: ApiId, version: u32) -> bool {
self.apis.iter().any(|&(ref s, v)| &api == s && version == v)
}
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct NativeVersion {
/// Basic runtime version info.
pub runtime_version: RuntimeVersion,
/// Authoring runtimes that this native runtime supports.
pub can_author_with: HashSet<u32>,
}
#[cfg(feature = "std")]
impl NativeVersion {
/// Check if this version matches other version for authoring blocks.
pub fn can_author_with(&self, other: &RuntimeVersion) -> bool {
self.runtime_version.spec_name == other.spec_name &&
(self.runtime_version.authoring_version == other.authoring_version ||
self.can_author_with.contains(&other.authoring_version))
}
}
+1 -1
View File
@@ -54,7 +54,7 @@ mod local_executor {
#![allow(missing_docs)]
use super::runtime;
// TODO: change the macro and pass in the `BlakeHasher` that dispatch needs from here instead
native_executor_instance!(pub LocalExecutor, runtime::api::dispatch, runtime::VERSION, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
native_executor_instance!(pub LocalExecutor, runtime::api::dispatch, runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"));
}
/// Native executor used for tests.
+11
View File
@@ -59,6 +59,8 @@ use runtime_primitives::traits::{BlindCheckable, BlakeTwo256};
use runtime_primitives::Ed25519Signature;
use runtime_version::RuntimeVersion;
pub use primitives::hash::H256;
#[cfg(any(feature = "std", test))]
use runtime_version::NativeVersion;
/// Test runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
@@ -74,6 +76,15 @@ fn version() -> RuntimeVersion {
VERSION
}
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
/// Calls in transactions.
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
+1 -1
View File
@@ -39,7 +39,7 @@ extern crate substrate_trie as trie;
#[cfg(test)] #[macro_use] extern crate hex_literal;
pub use substrate_executor::NativeExecutor;
native_executor_instance!(pub Executor, node_runtime::api::dispatch, node_runtime::VERSION, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"));
native_executor_instance!(pub Executor, node_runtime::api::dispatch, node_runtime::native_version, include_bytes!("../../runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm"));
#[cfg(test)]
mod tests {
+11
View File
@@ -69,6 +69,8 @@ use runtime_primitives::generic;
use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem};
use version::{RuntimeVersion, ApiId};
use council::{motions as council_motions, voting as council_voting};
#[cfg(any(feature = "std", test))]
use version::NativeVersion;
#[cfg(any(feature = "std", test))]
pub use runtime_primitives::BuildStorage;
@@ -94,6 +96,15 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
apis: apis_vec!([(INHERENT, 1), (VALIDATX, 1)]),
};
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
impl system::Trait for Runtime {
type Origin = Origin;
type Index = Index;