mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 14:11:09 +00:00
Support authoring for multiple runtime versions (#816)
This commit is contained in:
committed by
Gav Wood
parent
5eb1aefde6
commit
29c9719568
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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()
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user