mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Don't panic if parameter can not be converted between node and native runtime (#1659)
* Don't panic if parameter can not be converted between node and native runtime * FIxes after merge * Use correct copyright year
This commit is contained in:
Generated
+1
@@ -2832,6 +2832,7 @@ dependencies = [
|
||||
"sr-version 0.1.0",
|
||||
"substrate-client 0.1.0",
|
||||
"substrate-primitives 0.1.0",
|
||||
"substrate-state-machine 0.1.0",
|
||||
"substrate-test-client 0.1.0",
|
||||
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{sync::Arc, cmp::Ord, panic::UnwindSafe};
|
||||
use std::{sync::Arc, cmp::Ord, panic::UnwindSafe, result};
|
||||
use codec::{Encode, Decode};
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::Block as BlockT;
|
||||
@@ -61,7 +61,7 @@ where
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<B>,
|
||||
@@ -89,7 +89,7 @@ where
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(&self,
|
||||
state: &S,
|
||||
overlay: &mut OverlayedChanges,
|
||||
@@ -168,7 +168,7 @@ where
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let return_data = state_machine::execute_using_consensus_failure_handler::<
|
||||
_, _, _, _, _, _, fn() -> NeverNativeValue
|
||||
_, _, _, _, _, NeverNativeValue, fn() -> _
|
||||
>(
|
||||
&state,
|
||||
self.backend.changes_trie_storage(),
|
||||
@@ -192,7 +192,7 @@ where
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
@@ -208,7 +208,7 @@ where
|
||||
if method != "Core_initialise_block" && initialised_block.map(|id| id != *at).unwrap_or(true) {
|
||||
let header = prepare_environment_block()?;
|
||||
state_machine::execute_using_consensus_failure_handler::<
|
||||
_, _, _, _, _, R, fn() -> R,
|
||||
_, _, _, _, _, R, fn() -> _,
|
||||
>(
|
||||
&state,
|
||||
self.backend.changes_trie_storage(),
|
||||
@@ -254,7 +254,7 @@ where
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(&self,
|
||||
state: &S,
|
||||
changes: &mut OverlayedChanges,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Substrate Client
|
||||
|
||||
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe};
|
||||
use std::{marker::PhantomData, collections::{HashSet, BTreeMap}, sync::Arc, panic::UnwindSafe, result};
|
||||
use crate::error::Error;
|
||||
use futures::sync::mpsc;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
@@ -804,7 +804,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
|
||||
match transaction.state()? {
|
||||
Some(transaction_state) => {
|
||||
let mut overlay = Default::default();
|
||||
let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let (_, storage_update, changes_update) = self.executor.call_at_state::<_, _, NeverNativeValue, fn() -> _>(
|
||||
transaction_state,
|
||||
&mut overlay,
|
||||
"Core_execute_block",
|
||||
@@ -1244,7 +1244,9 @@ impl<B, E, Block, RA> CallRuntimeAt<Block> for Client<B, E, Block, RA> where
|
||||
E: CallExecutor<Block, Blake2Hasher> + Clone + Send + Sync,
|
||||
Block: BlockT<Hash=H256>
|
||||
{
|
||||
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
fn call_api_at<
|
||||
R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
function: &'static str,
|
||||
|
||||
@@ -116,6 +116,12 @@ error_chain! {
|
||||
display("Error decoding call result of {}", method)
|
||||
}
|
||||
|
||||
/// Error converting a parameter between runtime and node.
|
||||
RuntimeParamConversion(param: &'static str) {
|
||||
description("Error converting parameter between runtime and node")
|
||||
display("Error converting `{}` between runtime and node", param)
|
||||
}
|
||||
|
||||
/// Changes tries are not supported.
|
||||
ChangesTriesNotSupported {
|
||||
description("changes tries are not supported"),
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Light client call exector. Executes methods on remote full nodes, fetching
|
||||
//! execution proof and checking it locally.
|
||||
|
||||
use std::{collections::HashSet, sync::Arc, panic::UnwindSafe};
|
||||
use std::{collections::HashSet, sync::Arc, panic::UnwindSafe, result, marker::PhantomData};
|
||||
use futures::{IntoFuture, Future};
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
@@ -52,7 +52,7 @@ pub struct RemoteOrLocalCallExecutor<Block: BlockT<Hash=H256>, B, R, L> {
|
||||
backend: Arc<B>,
|
||||
remote: R,
|
||||
local: L,
|
||||
_block: ::std::marker::PhantomData<Block>,
|
||||
_block: PhantomData<Block>,
|
||||
}
|
||||
|
||||
impl<B, F> Clone for RemoteCallExecutor<B, F> {
|
||||
@@ -133,7 +133,7 @@ where
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R,
|
||||
NC: FnOnce() -> result::Result<R, &'static str>,
|
||||
>(&self,
|
||||
_state: &S,
|
||||
_changes: &mut OverlayedChanges,
|
||||
@@ -214,7 +214,7 @@ impl<Block, B, Remote, Local> CallExecutor<Block, Blake2Hasher> for
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
@@ -285,7 +285,7 @@ impl<Block, B, Remote, Local> CallExecutor<Block, Blake2Hasher> for
|
||||
Result<NativeOrEncoded<R>, Self::Error>
|
||||
) -> Result<NativeOrEncoded<R>, Self::Error>,
|
||||
R: Encode + Decode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe,
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe,
|
||||
>(&self,
|
||||
state: &S,
|
||||
changes: &mut OverlayedChanges,
|
||||
|
||||
@@ -77,7 +77,7 @@ pub trait ApiExt<Block: BlockT> {
|
||||
pub trait CallRuntimeAt<Block: BlockT> {
|
||||
/// Calls the given api function with the given encoded arguments at the given block
|
||||
/// and returns the encoded result.
|
||||
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
fn call_api_at<R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe>(
|
||||
&self,
|
||||
at: &BlockId<Block>,
|
||||
function: &'static str,
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
use state_machine;
|
||||
use serializer;
|
||||
use wasmi;
|
||||
use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed,
|
||||
impl_extract_backtrace, impl_error_chain_kind};
|
||||
use error_chain::{
|
||||
error_chain, error_chain_processing, impl_error_chain_processed,
|
||||
impl_extract_backtrace, impl_error_chain_kind
|
||||
};
|
||||
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::{RefMut, RefCell};
|
||||
use std::{borrow::BorrowMut, result, cell::{RefMut, RefCell}};
|
||||
use crate::error::{Error, ErrorKind, Result};
|
||||
use state_machine::{CodeExecutor, Externalities};
|
||||
use crate::wasm_executor::WasmExecutor;
|
||||
@@ -109,7 +108,7 @@ fn safe_call<F, U>(f: F) -> Result<U>
|
||||
///
|
||||
/// If the inner closure panics, it will be caught and return an error.
|
||||
pub fn with_native_environment<F, U>(ext: &mut Externalities<Blake2Hasher>, f: F) -> Result<U>
|
||||
where F: UnwindSafe + FnOnce() -> U
|
||||
where F: UnwindSafe + FnOnce() -> U
|
||||
{
|
||||
::runtime_io::with_externalities(ext, move || safe_call(f))
|
||||
}
|
||||
@@ -186,7 +185,7 @@ impl<D: NativeExecutionDispatch> CodeExecutor<Blake2Hasher> for NativeExecutor<D
|
||||
<
|
||||
E: Externalities<Blake2Hasher>,
|
||||
R:Decode + Encode + PartialEq,
|
||||
NC: FnOnce() -> R + UnwindSafe
|
||||
NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe
|
||||
>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
@@ -242,7 +241,8 @@ impl<D: NativeExecutionDispatch> CodeExecutor<Blake2Hasher> for NativeExecutor<D
|
||||
.map_or_else(||"<None>".into(), |v| format!("{}", v))
|
||||
);
|
||||
(
|
||||
with_native_environment(ext, move || (call)()).map(NativeOrEncoded::Native),
|
||||
with_native_environment(ext, move || (call)())
|
||||
.and_then(|r| r.map(NativeOrEncoded::Native).map_err(Into::into)),
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ blake2-rfc = "0.2"
|
||||
[dev-dependencies]
|
||||
substrate-client = { path = "../client" }
|
||||
substrate-test-client = { path = "../test-client" }
|
||||
substrate-state-machine = { path = "../state-machine" }
|
||||
sr-primitives = { path = "../sr-primitives" }
|
||||
sr-version = { path = "../sr-version" }
|
||||
substrate-primitives = { path = "../primitives" }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2018 - 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
use utils::{
|
||||
generate_crate_access, generate_hidden_includes, generate_runtime_mod_name_for_trait,
|
||||
fold_fn_decl_for_client_side, unwrap_or_error, extract_parameter_names_types_and_borrows,
|
||||
generate_native_call_generator_fn_name
|
||||
generate_native_call_generator_fn_name, return_type_extract_type,
|
||||
};
|
||||
|
||||
use proc_macro;
|
||||
@@ -157,12 +157,15 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
|
||||
// Auxilariy function that is used to convert between types that use different block types.
|
||||
// The function expects that both a convertable by encoding the one and decoding the other.
|
||||
result.push(quote!(
|
||||
#[cfg(any(feature = "std", test))]
|
||||
fn convert_between_block_types
|
||||
<I: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(input: &I) -> R
|
||||
<I: #crate_::runtime_api::Encode, R: #crate_::runtime_api::Decode>(
|
||||
input: &I, error_desc: &'static str,
|
||||
) -> ::std::result::Result<R, &'static str>
|
||||
{
|
||||
<R as #crate_::runtime_api::Decode>::decode(
|
||||
&mut &#crate_::runtime_api::Encode::encode(input)[..]
|
||||
).unwrap()
|
||||
).ok_or_else(|| error_desc)
|
||||
}
|
||||
));
|
||||
|
||||
@@ -172,20 +175,30 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
|
||||
let trait_fn_name = &fn_.ident;
|
||||
let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
|
||||
let output = return_type_replace_block_with_node_block(fn_.decl.output.clone());
|
||||
let output_ty = return_type_extract_type(&output);
|
||||
let output = quote!( ::std::result::Result<#output_ty, &'static str> );
|
||||
|
||||
// Every type that is using the `Block` generic parameter, we need to encode/decode,
|
||||
// to make it compatible between the runtime/node.
|
||||
let conversions = params.iter().filter(|v| type_is_using_block(&v.1)).map(|(n, t, _)| {
|
||||
let name_str = format!(
|
||||
"Could not convert parameter `{}` between node and runtime!", quote!(#n)
|
||||
);
|
||||
quote!(
|
||||
let #n: #t = convert_between_block_types(&#n);
|
||||
let #n: #t = convert_between_block_types(&#n, #name_str)?;
|
||||
)
|
||||
});
|
||||
// Same as for the input types, we need to check if we also need to convert the output,
|
||||
// before returning it.
|
||||
let output_conversion = if return_type_is_using_block(&fn_.decl.output) {
|
||||
quote!( convert_between_block_types(&res) )
|
||||
quote!(
|
||||
convert_between_block_types(
|
||||
&res,
|
||||
"Could not convert return value from runtime to node!"
|
||||
)
|
||||
)
|
||||
} else {
|
||||
quote!( res )
|
||||
quote!( Ok(res) )
|
||||
};
|
||||
|
||||
let input_names = params.iter().map(|v| &v.0);
|
||||
@@ -240,7 +253,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
|
||||
#(, #impl_generics_params)*
|
||||
>(
|
||||
#( #fn_inputs ),*
|
||||
) -> impl FnOnce() #output + 'a #where_clause {
|
||||
) -> impl FnOnce() -> #output + 'a #where_clause {
|
||||
move || {
|
||||
#( #conversions )*
|
||||
let res = ApiImpl::#trait_fn_name(#( #input_borrows #input_names ),*);
|
||||
|
||||
@@ -330,7 +330,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
impl<C: #crate_::runtime_api::CallRuntimeAt<#block>> RuntimeApiImpl<C> {
|
||||
fn call_api_at<
|
||||
R: #crate_::runtime_api::Encode + #crate_::runtime_api::Decode + PartialEq,
|
||||
NC: FnOnce() -> R + ::std::panic::UnwindSafe,
|
||||
NC: FnOnce() -> ::std::result::Result<R, &'static str> + ::std::panic::UnwindSafe,
|
||||
>(
|
||||
&self,
|
||||
at: &#block_id,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Macros for declaring and implementing runtime apis.
|
||||
|
||||
#![recursion_limit = "256"]
|
||||
#![recursion_limit = "512"]
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
extern crate quote;
|
||||
|
||||
@@ -58,6 +58,14 @@ pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident {
|
||||
Ident::new(&format!("runtime_decl_for_{}", trait_.to_string()), Span::call_site())
|
||||
}
|
||||
|
||||
/// Get the type of a `syn::ReturnType`.
|
||||
pub fn return_type_extract_type(rt: &syn::ReturnType) -> Type {
|
||||
match rt {
|
||||
syn::ReturnType::Default => parse_quote!( () ),
|
||||
syn::ReturnType::Type(_, ref ty) => *ty.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fold the given `FnDecl` to make it usable on the client side.
|
||||
pub fn fold_fn_decl_for_client_side(
|
||||
mut input: FnDecl,
|
||||
@@ -70,14 +78,8 @@ pub fn fold_fn_decl_for_client_side(
|
||||
|
||||
// Wrap the output in a `Result`
|
||||
input.output = {
|
||||
let generate_result = |ty: &Type| {
|
||||
parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> )
|
||||
};
|
||||
|
||||
match &input.output {
|
||||
syn::ReturnType::Default => generate_result(&parse_quote!( () )),
|
||||
syn::ReturnType::Type(_, ref ty) => generate_result(&ty),
|
||||
}
|
||||
let ty = return_type_extract_type(&input.output);
|
||||
parse_quote!( -> ::std::result::Result<#ty, #crate_::error::Error> )
|
||||
};
|
||||
|
||||
input
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2019 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/>.
|
||||
|
||||
extern crate substrate_client;
|
||||
extern crate substrate_test_client as test_client;
|
||||
extern crate sr_primitives as runtime_primitives;
|
||||
extern crate substrate_state_machine as state_machine;
|
||||
|
||||
use test_client::runtime::{TestAPI, DecodeFails};
|
||||
use runtime_primitives::{generic::BlockId, traits::ProvideRuntimeApi};
|
||||
use state_machine::ExecutionStrategy;
|
||||
|
||||
fn calling_function_with_strat(strat: ExecutionStrategy) {
|
||||
let client = test_client::new_with_api_execution_strat(strat);
|
||||
let runtime_api = client.runtime_api();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
|
||||
assert_eq!(runtime_api.benchmark_add_one(&block_id, &1).unwrap(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calling_native_runtime_function() {
|
||||
calling_function_with_strat(ExecutionStrategy::NativeWhenPossible);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calling_wasm_runtime_function() {
|
||||
calling_function_with_strat(ExecutionStrategy::AlwaysWasm);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Could not convert parameter `param` between node and runtime!")]
|
||||
fn calling_native_runtime_function_with_non_decodable_parameter() {
|
||||
let client = test_client::new_with_api_execution_strat(ExecutionStrategy::NativeWhenPossible);
|
||||
let runtime_api = client.runtime_api();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
runtime_api.fail_convert_parameter(&block_id, DecodeFails::new()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Could not convert return value from runtime to node!")]
|
||||
fn calling_native_runtime_function_with_non_decodable_return_value() {
|
||||
let client = test_client::new_with_api_execution_strat(ExecutionStrategy::NativeWhenPossible);
|
||||
let runtime_api = client.runtime_api();
|
||||
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
|
||||
runtime_api.fail_convert_return_value(&block_id).unwrap();
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use std::{fmt, panic::UnwindSafe};
|
||||
use std::{fmt, panic::UnwindSafe, result};
|
||||
use log::warn;
|
||||
use hash_db::Hasher;
|
||||
use heapsize::HeapSizeOf;
|
||||
@@ -45,7 +45,8 @@ pub use changes_trie::{
|
||||
InMemoryStorage as InMemoryChangesTrieStorage,
|
||||
key_changes, key_changes_proof, key_changes_proof_check,
|
||||
prune as prune_changes_tries,
|
||||
oldest_non_pruned_trie as oldest_non_pruned_changes_trie};
|
||||
oldest_non_pruned_trie as oldest_non_pruned_changes_trie
|
||||
};
|
||||
pub use overlayed_changes::OverlayedChanges;
|
||||
pub use proving_backend::{create_proof_check_backend, create_proof_check_backend_storage};
|
||||
pub use trie_backend_essence::{TrieBackendStorage, Storage};
|
||||
@@ -156,7 +157,9 @@ pub trait CodeExecutor<H: Hasher>: Sized + Send + Sync {
|
||||
|
||||
/// Call a given method in the runtime. Returns a tuple of the result (either the output data
|
||||
/// or an execution error) together with a `bool`, which is true if native execution was used.
|
||||
fn call<E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>(
|
||||
fn call<
|
||||
E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe
|
||||
>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
method: &str,
|
||||
@@ -248,7 +251,7 @@ where
|
||||
{
|
||||
// We are not giving a native call and thus we are sure that the result can never be a native
|
||||
// value.
|
||||
execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> _>(
|
||||
backend,
|
||||
changes_trie_storage,
|
||||
overlay,
|
||||
@@ -286,7 +289,7 @@ where
|
||||
/// Note: changes to code will be in place if this call is made again. For running partial
|
||||
/// blocks (e.g. a transaction at a time), ensure a different method is used.
|
||||
pub fn execute_using_consensus_failure_handler<
|
||||
H, B, T, Exec, Handler, R: Decode + Encode + PartialEq, NC: FnOnce() -> R + UnwindSafe
|
||||
H, B, T, Exec, Handler, R: Decode + Encode + PartialEq, NC: FnOnce() -> result::Result<R, &'static str> + UnwindSafe
|
||||
>(
|
||||
backend: &B,
|
||||
changes_trie_storage: Option<&T>,
|
||||
@@ -443,7 +446,7 @@ where
|
||||
{
|
||||
let proving_backend = proving_backend::ProvingBackend::new(trie_backend);
|
||||
let (result, _, _) = execute_using_consensus_failure_handler::
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> NeverNativeValue>
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> _>
|
||||
(
|
||||
&proving_backend,
|
||||
None,
|
||||
@@ -491,7 +494,7 @@ where
|
||||
H::Out: Ord + HeapSizeOf,
|
||||
{
|
||||
execute_using_consensus_failure_handler::
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> NeverNativeValue>
|
||||
<H, _, changes_trie::InMemoryStorage<H>, _, _, NeverNativeValue, fn() -> _>
|
||||
(
|
||||
trie_backend,
|
||||
None,
|
||||
@@ -621,7 +624,7 @@ mod tests {
|
||||
impl<H: Hasher> CodeExecutor<H> for DummyCodeExecutor {
|
||||
type Error = u8;
|
||||
|
||||
fn call<E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> R>(
|
||||
fn call<E: Externalities<H>, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result<R, &'static str>>(
|
||||
&self,
|
||||
ext: &mut E,
|
||||
_method: &str,
|
||||
@@ -684,7 +687,7 @@ mod tests {
|
||||
#[test]
|
||||
fn dual_execution_strategy_detects_consensus_failure() {
|
||||
let mut consensus_failed = false;
|
||||
assert!(execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
assert!(execute_using_consensus_failure_handler::<_, _, _, _, _, NeverNativeValue, fn() -> _>(
|
||||
&trie_backend::tests::test_trie(),
|
||||
Some(&InMemoryChangesTrieStorage::new()),
|
||||
&mut Default::default(),
|
||||
|
||||
@@ -38,6 +38,8 @@ use runtime_primitives::StorageMap;
|
||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT};
|
||||
use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis};
|
||||
use keyring::Keyring;
|
||||
use state_machine::ExecutionStrategy;
|
||||
use client::LocalCallExecutor;
|
||||
|
||||
mod local_executor {
|
||||
#![allow(missing_docs)]
|
||||
@@ -69,6 +71,23 @@ pub fn new() -> client::Client<Backend, Executor, runtime::Block, runtime::Runti
|
||||
new_with_backend(Arc::new(Backend::new()), false)
|
||||
}
|
||||
|
||||
/// Creates new client instance used for tests with the given api execution strategy.
|
||||
pub fn new_with_api_execution_strat(
|
||||
api_execution_strategy: ExecutionStrategy
|
||||
) -> client::Client<Backend, Executor, runtime::Block, runtime::RuntimeApi> {
|
||||
let backend = Arc::new(Backend::new());
|
||||
let executor = NativeExecutor::new();
|
||||
let executor = LocalCallExecutor::new(backend.clone(), executor);
|
||||
|
||||
client::Client::new(
|
||||
backend,
|
||||
executor,
|
||||
genesis_storage(false),
|
||||
ExecutionStrategy::NativeWhenPossible,
|
||||
api_execution_strategy
|
||||
).expect("Creates new client")
|
||||
}
|
||||
|
||||
/// Creates new test client instance that suports changes trie creation.
|
||||
pub fn new_with_changes_trie()
|
||||
-> client::Client<Backend, Executor, runtime::Block, runtime::RuntimeApi>
|
||||
|
||||
@@ -24,12 +24,13 @@ extern crate srml_support as runtime_support;
|
||||
#[cfg(feature = "std")] pub mod genesismap;
|
||||
pub mod system;
|
||||
|
||||
use rstd::prelude::*;
|
||||
use parity_codec::{Encode, Decode};
|
||||
use rstd::{prelude::*, marker::PhantomData};
|
||||
use parity_codec::{Encode, Decode, Input};
|
||||
use parity_codec_derive::{Encode, Decode};
|
||||
|
||||
use substrate_client::{runtime_api as client_api, block_builder::api as block_builder_api,
|
||||
decl_runtime_apis, impl_runtime_apis,
|
||||
use substrate_client::{
|
||||
runtime_api as client_api, block_builder::api as block_builder_api, decl_runtime_apis,
|
||||
impl_runtime_apis,
|
||||
};
|
||||
use runtime_primitives::{
|
||||
ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity,
|
||||
@@ -164,14 +165,47 @@ pub fn changes_trie_config() -> primitives::ChangesTrieConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
/// A type that can not be decoded.
|
||||
#[derive(PartialEq)]
|
||||
pub struct DecodeFails<B: BlockT> {
|
||||
_phantom: PhantomData<B>,
|
||||
}
|
||||
|
||||
impl<B: BlockT> Encode for DecodeFails<B> {
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT> DecodeFails<B> {
|
||||
/// Create a new instance.
|
||||
pub fn new() -> DecodeFails<B> {
|
||||
DecodeFails {
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT> Decode for DecodeFails<B> {
|
||||
fn decode<I: Input>(_: &mut I) -> Option<Self> {
|
||||
// decoding always fails
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
decl_runtime_apis! {
|
||||
pub trait TestAPI {
|
||||
/// Return the balance of the given account id.
|
||||
fn balance_of(id: AccountId) -> u64;
|
||||
/// A benchmkark function that adds one to the given value and returns the result.
|
||||
fn benchmark_add_one(val: &u64) -> u64;
|
||||
/// A benchmark function that adds one to each value in the given vector and returns the
|
||||
/// result.
|
||||
fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64>;
|
||||
/// A function that always fails to convert a parameter between runtime and node.
|
||||
fn fail_convert_parameter(param: DecodeFails<Block>);
|
||||
/// A function that always fails to convert its return value between runtime and node.
|
||||
fn fail_convert_return_value() -> DecodeFails<Block>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +286,12 @@ impl_runtime_apis! {
|
||||
vec.iter_mut().for_each(|v| *v += 1);
|
||||
vec
|
||||
}
|
||||
|
||||
fn fail_convert_parameter(_: DecodeFails<Block>) {}
|
||||
|
||||
fn fail_convert_return_value() -> DecodeFails<Block> {
|
||||
DecodeFails::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl consensus_aura::AuraApi<Block> for Runtime {
|
||||
|
||||
BIN
Binary file not shown.
@@ -118,7 +118,7 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
@@ -126,7 +126,7 @@ mod tests {
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
@@ -151,7 +151,7 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
@@ -159,7 +159,7 @@ mod tests {
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let v = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
@@ -184,7 +184,7 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
@@ -192,7 +192,7 @@ mod tests {
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
@@ -221,7 +221,7 @@ mod tests {
|
||||
twox_128(&<system::BlockHash<Runtime>>::key_for(0)).to_vec() => vec![0u8; 32]
|
||||
]);
|
||||
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_initialise_block",
|
||||
&vec![].and(&from_block_number(1u64)),
|
||||
@@ -229,7 +229,7 @@ mod tests {
|
||||
None,
|
||||
).0;
|
||||
assert!(r.is_ok());
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
let r = executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"BlockBuilder_apply_extrinsic",
|
||||
&vec![].and(&xt()),
|
||||
@@ -422,7 +422,7 @@ mod tests {
|
||||
fn full_native_block_import_works() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1(false).0,
|
||||
@@ -477,7 +477,7 @@ mod tests {
|
||||
]);
|
||||
});
|
||||
|
||||
executor().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
executor().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block2().0,
|
||||
@@ -729,7 +729,7 @@ mod tests {
|
||||
fn native_big_block_import_succeeds() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1big().0,
|
||||
@@ -743,7 +743,7 @@ mod tests {
|
||||
let mut t = new_test_ext(COMPACT_CODE, false);
|
||||
|
||||
assert!(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1big().0,
|
||||
@@ -805,7 +805,7 @@ mod tests {
|
||||
#[test]
|
||||
fn full_native_block_import_works_with_changes_trie() {
|
||||
let mut t = new_test_ext(COMPACT_CODE, true);
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> NeverNativeValue>(
|
||||
Executor::new().call::<_, NeverNativeValue, fn() -> _>(
|
||||
&mut t,
|
||||
"Core_execute_block",
|
||||
&block1(true).0,
|
||||
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user