diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 7caa98e8dc..535a77a056 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -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)", ] diff --git a/substrate/core/client/src/call_executor.rs b/substrate/core/client/src/call_executor.rs index 4c274fc436..03cec8885a 100644 --- a/substrate/core/client/src/call_executor.rs +++ b/substrate/core/client/src/call_executor.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -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, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, @@ -89,7 +89,7 @@ where Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + 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, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, @@ -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, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, changes: &mut OverlayedChanges, diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index e8c46156f7..2313c4733d 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -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 Client 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 CallRuntimeAt for Client where E: CallExecutor + Clone + Send + Sync, Block: BlockT { - fn call_api_at R + UnwindSafe>( + fn call_api_at< + R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe + >( &self, at: &BlockId, function: &'static str, diff --git a/substrate/core/client/src/error.rs b/substrate/core/client/src/error.rs index f8ac292c25..bfc073f634 100644 --- a/substrate/core/client/src/error.rs +++ b/substrate/core/client/src/error.rs @@ -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"), diff --git a/substrate/core/client/src/light/call_executor.rs b/substrate/core/client/src/light/call_executor.rs index 05fd9dffed..601cb0732f 100644 --- a/substrate/core/client/src/light/call_executor.rs +++ b/substrate/core/client/src/light/call_executor.rs @@ -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, B, R, L> { backend: Arc, remote: R, local: L, - _block: ::std::marker::PhantomData, + _block: PhantomData, } impl Clone for RemoteCallExecutor { @@ -133,7 +133,7 @@ where Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R, + NC: FnOnce() -> result::Result, >(&self, _state: &S, _changes: &mut OverlayedChanges, @@ -214,7 +214,7 @@ impl CallExecutor for Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >( &self, at: &BlockId, @@ -285,7 +285,7 @@ impl CallExecutor for Result, Self::Error> ) -> Result, Self::Error>, R: Encode + Decode + PartialEq, - NC: FnOnce() -> R + UnwindSafe, + NC: FnOnce() -> result::Result + UnwindSafe, >(&self, state: &S, changes: &mut OverlayedChanges, diff --git a/substrate/core/client/src/runtime_api.rs b/substrate/core/client/src/runtime_api.rs index fbe5d1378b..72371bc95f 100644 --- a/substrate/core/client/src/runtime_api.rs +++ b/substrate/core/client/src/runtime_api.rs @@ -77,7 +77,7 @@ pub trait ApiExt { pub trait CallRuntimeAt { /// Calls the given api function with the given encoded arguments at the given block /// and returns the encoded result. - fn call_api_at R + UnwindSafe>( + fn call_api_at result::Result + UnwindSafe>( &self, at: &BlockId, function: &'static str, diff --git a/substrate/core/executor/src/error.rs b/substrate/core/executor/src/error.rs index c5a6160ac1..98993519f4 100644 --- a/substrate/core/executor/src/error.rs +++ b/substrate/core/executor/src/error.rs @@ -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 { diff --git a/substrate/core/executor/src/native_executor.rs b/substrate/core/executor/src/native_executor.rs index 753c2227f6..cd1ab3bca2 100644 --- a/substrate/core/executor/src/native_executor.rs +++ b/substrate/core/executor/src/native_executor.rs @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -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: F) -> Result /// /// If the inner closure panics, it will be caught and return an error. pub fn with_native_environment(ext: &mut Externalities, f: F) -> Result -where F: UnwindSafe + FnOnce() -> U + where F: UnwindSafe + FnOnce() -> U { ::runtime_io::with_externalities(ext, move || safe_call(f)) } @@ -186,7 +185,7 @@ impl CodeExecutor for NativeExecutor, R:Decode + Encode + PartialEq, - NC: FnOnce() -> R + UnwindSafe + NC: FnOnce() -> result::Result + UnwindSafe >( &self, ext: &mut E, @@ -242,7 +241,8 @@ impl CodeExecutor for NativeExecutor".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 ) } diff --git a/substrate/core/sr-api-macros/Cargo.toml b/substrate/core/sr-api-macros/Cargo.toml index 7cc414a732..1856d3702c 100644 --- a/substrate/core/sr-api-macros/Cargo.toml +++ b/substrate/core/sr-api-macros/Cargo.toml @@ -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" } diff --git a/substrate/core/sr-api-macros/benches/bench.rs b/substrate/core/sr-api-macros/benches/bench.rs index 54f8c8a3d1..0b829052e6 100644 --- a/substrate/core/sr-api-macros/benches/bench.rs +++ b/substrate/core/sr-api-macros/benches/bench.rs @@ -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 diff --git a/substrate/core/sr-api-macros/src/decl_runtime_apis.rs b/substrate/core/sr-api-macros/src/decl_runtime_apis.rs index 54f8d81bef..13498003c2 100644 --- a/substrate/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/substrate/core/sr-api-macros/src/decl_runtime_apis.rs @@ -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 { // 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 - (input: &I) -> R + ( + input: &I, error_desc: &'static str, + ) -> ::std::result::Result { ::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 { 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 { #(, #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 ),*); diff --git a/substrate/core/sr-api-macros/src/impl_runtime_apis.rs b/substrate/core/sr-api-macros/src/impl_runtime_apis.rs index 6663cae85f..2909b07413 100644 --- a/substrate/core/sr-api-macros/src/impl_runtime_apis.rs +++ b/substrate/core/sr-api-macros/src/impl_runtime_apis.rs @@ -330,7 +330,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result> RuntimeApiImpl { 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 + ::std::panic::UnwindSafe, >( &self, at: &#block_id, diff --git a/substrate/core/sr-api-macros/src/lib.rs b/substrate/core/sr-api-macros/src/lib.rs index 3dfc26c442..52e96a57cc 100644 --- a/substrate/core/sr-api-macros/src/lib.rs +++ b/substrate/core/sr-api-macros/src/lib.rs @@ -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; diff --git a/substrate/core/sr-api-macros/src/utils.rs b/substrate/core/sr-api-macros/src/utils.rs index e35ed52084..9df59b30a7 100644 --- a/substrate/core/sr-api-macros/src/utils.rs +++ b/substrate/core/sr-api-macros/src/utils.rs @@ -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 diff --git a/substrate/core/sr-api-macros/tests/runtime_calls.rs b/substrate/core/sr-api-macros/tests/runtime_calls.rs new file mode 100644 index 0000000000..d1d05eb48a --- /dev/null +++ b/substrate/core/sr-api-macros/tests/runtime_calls.rs @@ -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 . + +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(); +} diff --git a/substrate/core/state-machine/src/lib.rs b/substrate/core/state-machine/src/lib.rs index 69d257c8a9..c2427fb0d3 100644 --- a/substrate/core/state-machine/src/lib.rs +++ b/substrate/core/state-machine/src/lib.rs @@ -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: 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, R: Encode + Decode + PartialEq, NC: FnOnce() -> R + UnwindSafe>( + fn call< + E: Externalities, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + 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 + 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:: - , _, _, NeverNativeValue, fn() -> NeverNativeValue> + , _, _, NeverNativeValue, fn() -> _> ( &proving_backend, None, @@ -491,7 +494,7 @@ where H::Out: Ord + HeapSizeOf, { execute_using_consensus_failure_handler:: - , _, _, NeverNativeValue, fn() -> NeverNativeValue> + , _, _, NeverNativeValue, fn() -> _> ( trie_backend, None, @@ -621,7 +624,7 @@ mod tests { impl CodeExecutor for DummyCodeExecutor { type Error = u8; - fn call, R: Encode + Decode + PartialEq, NC: FnOnce() -> R>( + fn call, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result>( &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(), diff --git a/substrate/core/test-client/src/lib.rs b/substrate/core/test-client/src/lib.rs index af22cb2be7..eec5770fc1 100644 --- a/substrate/core/test-client/src/lib.rs +++ b/substrate/core/test-client/src/lib.rs @@ -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 client::Client { + 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 diff --git a/substrate/core/test-runtime/src/lib.rs b/substrate/core/test-runtime/src/lib.rs index a19c966969..d804468a64 100644 --- a/substrate/core/test-runtime/src/lib.rs +++ b/substrate/core/test-runtime/src/lib.rs @@ -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 { + _phantom: PhantomData, +} + +impl Encode for DecodeFails { + fn encode(&self) -> Vec { + Vec::new() + } +} + +impl DecodeFails { + /// Create a new instance. + pub fn new() -> DecodeFails { + DecodeFails { + _phantom: Default::default(), + } + } +} + +impl Decode for DecodeFails { + fn decode(_: &mut I) -> Option { + // 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) -> Vec; + /// A function that always fails to convert a parameter between runtime and node. + fn fail_convert_parameter(param: DecodeFails); + /// A function that always fails to convert its return value between runtime and node. + fn fail_convert_return_value() -> DecodeFails; } } @@ -252,6 +286,12 @@ impl_runtime_apis! { vec.iter_mut().for_each(|v| *v += 1); vec } + + fn fail_convert_parameter(_: DecodeFails) {} + + fn fail_convert_return_value() -> DecodeFails { + DecodeFails::new() + } } impl consensus_aura::AuraApi for Runtime { diff --git a/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 24b6ef4ef6..ec7eee0ddd 100644 Binary files a/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index f769b284e2..d98a8f32cc 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -118,7 +118,7 @@ mod tests { twox_128(&>::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(&>::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(&>::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(&>::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, diff --git a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 2d410ff28c..151d49c6a3 100644 Binary files a/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/substrate/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ