Adds new execution strategy nativeElseWasm (#1546)

* fix: adds new execution strategy nativeElseWasm and replace nativeWhenPossible with it

* feat: adds cmd line params for execution strategies

* fix: uses of cmd line execution strategies

* chore: remove white spaces

* chore: remove println

* chore: remove whitespace

* fix: generating functions with context

* feat: add function to generate with_context declarations

* fix: add implementation for with_context function calls

* fix: add execution context to call_api_at function

* fix: making use of context to select strategy for block_builder

* chore: cleaning up

* fix: merging issues

* fix tests

* add wasm files

* chore: small doc for context fields

* chore: delete redundant docs

* fix: use full path for ExecutionContext

* fix: add context functions from inside fold_item_impl

* chore: remove clone

* fix: moving generative function to utils, remove unused imports

* fix: add missing full path for ExecutionContext

* fix: merge issues

* update wasm files

* fix: update to keep up with changes in master

* chore: remove unused functions, clean up

* fix test

* fix grumbles

* fix: add more tests

* fix: some refactorings

* feat: add execution strategy to call

* chore: small improvements

* fix: add message to panic

* fix tests
This commit is contained in:
Marcio Diaz
2019-02-11 15:22:44 +01:00
committed by GitHub
parent f9975af020
commit b8bd49961a
31 changed files with 837 additions and 544 deletions
@@ -275,7 +275,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
Ok(quote!( #( #result )* ))
}
/// Generate the decleration of the trait for the runtime.
/// Generate the declaration of the trait for the runtime.
fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream {
let mut result = Vec::new();
@@ -339,8 +339,9 @@ impl<'a> ToClientSideDecl<'a> {
items.into_iter().for_each(|i| match i {
TraitItem::Method(method) => {
let (fn_decl, fn_impl) = self.fold_trait_item_method(method);
let (fn_decl, fn_impl, fn_decl_ctx) = self.fold_trait_item_method(method);
result.push(fn_decl.into());
result.push(fn_decl_ctx.into());
if let Some(fn_impl) = fn_impl {
result.push(fn_impl.into());
@@ -352,11 +353,25 @@ impl<'a> ToClientSideDecl<'a> {
result
}
fn fold_trait_item_method(&mut self, method: TraitItemMethod) -> (TraitItemMethod, Option<TraitItemMethod>) {
fn fold_trait_item_method(&mut self, method: TraitItemMethod)
-> (TraitItemMethod, Option<TraitItemMethod>, TraitItemMethod) {
let crate_ = self.crate_;
let context_other = quote!( #crate_::runtime_api::ExecutionContext::Other );
let fn_impl = self.create_method_runtime_api_impl(method.clone());
let fn_decl = self.create_method_decl(method);
let fn_decl = self.create_method_decl(method.clone(), context_other);
let fn_decl_ctx = self.create_method_decl_with_context(method);
(fn_decl, fn_impl)
(fn_decl, fn_impl, fn_decl_ctx)
}
fn create_method_decl_with_context(&mut self, method: TraitItemMethod) -> TraitItemMethod {
let crate_ = self.crate_;
let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext );
let mut fn_decl_ctx = self.create_method_decl(method, quote!( context ));
fn_decl_ctx.sig.ident = Ident::new(&format!("{}_with_context", &fn_decl_ctx.sig.ident), Span::call_site());
fn_decl_ctx.sig.decl.inputs.insert(2, context_arg);
fn_decl_ctx
}
/// Takes the given method and creates a `method_runtime_api_impl` method that will be
@@ -392,8 +407,9 @@ impl<'a> ToClientSideDecl<'a> {
fn #name(
&self,
at: &#block_id,
context: #crate_::runtime_api::ExecutionContext,
params: Option<( #( #param_types ),* )>,
params_encoded: Vec<u8>
params_encoded: Vec<u8>,
) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>>;
}
)
@@ -402,7 +418,7 @@ impl<'a> ToClientSideDecl<'a> {
/// Takes the method declared by the user and creates the declaration we require for the runtime
/// api client side. This method will call by default the `method_runtime_api_impl` for doing
/// the actual call into the runtime.
fn create_method_decl(&mut self, mut method: TraitItemMethod) -> TraitItemMethod {
fn create_method_decl(&mut self, mut method: TraitItemMethod, context: TokenStream) -> TraitItemMethod {
let params = match extract_parameter_names_types_and_borrows(&method.sig.decl) {
Ok(res) => res.into_iter().map(|v| v.0).collect::<Vec<_>>(),
Err(e) => {
@@ -462,7 +478,7 @@ impl<'a> ToClientSideDecl<'a> {
let runtime_api_impl_params_encoded =
#crate_::runtime_api::Encode::encode(&( #( &#params ),* ));
self.#name_impl(at, #param_tuple, runtime_api_impl_params_encoded)
self.#name_impl(at, #context, #param_tuple, runtime_api_impl_params_encoded)
.and_then(|r|
match r {
#crate_::runtime_api::NativeOrEncoded::Native(n) => {
@@ -571,7 +587,7 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = trait_.generics.split_for_impl();
quote!(
#[cfg(any(feature = "std", test))]
#[cfg(any(feature = "std", test))]
impl #impl_generics #crate_::runtime_api::RuntimeApiInfo
for #trait_name #ty_generics #where_clause
{
@@ -593,7 +609,7 @@ fn get_api_version(found_attributes: &HashMap<&'static str, Attribute>) -> Resul
found_attributes.get(&API_VERSION_ATTRIBUTE).map(parse_runtime_api_version).unwrap_or(Ok(1))
}
/// Generate the decleration of the trait for the client side.
/// Generate the declaration of the trait for the client side.
fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream {
let mut result = Vec::new();
@@ -17,7 +17,8 @@
use utils::{
unwrap_or_error, generate_crate_access, generate_hidden_includes,
generate_runtime_mod_name_for_trait, generate_method_runtime_api_impl_name,
extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name, return_type_extract_type
extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name,
return_type_extract_type
};
use proc_macro;
@@ -337,6 +338,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
function: &'static str,
args: Vec<u8>,
native_call: Option<NC>,
context: #crate_::runtime_api::ExecutionContext
) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<R>> {
let res = unsafe {
self.call.call_api_at(
@@ -346,6 +348,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
&mut *self.changes.borrow_mut(),
&mut *self.initialised_block.borrow_mut(),
native_call,
context
)
};
@@ -466,9 +469,11 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
Err(e) => (Vec::new(), Some(e.to_compile_error())),
};
let context_arg: syn::FnArg = parse_quote!( context: #crate_::runtime_api::ExecutionContext );
// Rewrite the input parameters.
input.sig.decl.inputs = parse_quote! {
&self, at: &#block_id, params: Option<( #( #param_types ),* )>, params_encoded: Vec<u8>
&self, at: &#block_id, #context_arg, params: Option<( #( #param_types ),* )>, params_encoded: Vec<u8>
};
input.sig.ident = generate_method_runtime_api_impl_name(&input.sig.ident);
@@ -494,7 +499,8 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
<#runtime, #node_block #(, #trait_generic_arguments )*> (
#( #param_tuple_access ),*
)
})
}),
context,
)
}
)
@@ -561,7 +567,6 @@ fn generate_api_impl_for_runtime_api(impls: &[ItemImpl]) -> Result<TokenStream>
result.push(visitor.fold_item_impl(impl_.clone()));
}
Ok(quote!( #( #result )* ))
}
@@ -611,13 +616,14 @@ fn generate_runtime_api_versions(impls: &[ItemImpl]) -> Result<TokenStream> {
pub fn impl_runtime_apis_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Parse all impl blocks
let RuntimeApiImpls { impls: api_impls } = parse_macro_input!(input as RuntimeApiImpls);
let dispatch_impl = unwrap_or_error(generate_dispatch_function(&api_impls));
let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls));
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls));
let api_impls_for_runtime = unwrap_or_error(generate_api_impl_for_runtime(&api_impls));
let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls));
let base_runtime_api = unwrap_or_error(generate_runtime_api_base_structures(&api_impls));
let hidden_includes = generate_hidden_includes(HIDDEN_INCLUDES_ID);
let runtime_api_versions = unwrap_or_error(generate_runtime_api_versions(&api_impls));
let wasm_interface = unwrap_or_error(generate_wasm_interface(&api_impls));
let api_impls_for_runtime_api = unwrap_or_error(generate_api_impl_for_runtime_api(&api_impls));
quote!(
#hidden_includes
@@ -24,7 +24,7 @@ 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 client = test_client::new_with_execution_strategy(strat);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
@@ -44,7 +44,7 @@ fn calling_wasm_runtime_function() {
#[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 client = test_client::new_with_execution_strategy(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();
@@ -53,7 +53,7 @@ fn calling_native_runtime_function_with_non_decodable_parameter() {
#[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 client = test_client::new_with_execution_strategy(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();
@@ -61,7 +61,7 @@ fn calling_native_runtime_function_with_non_decodable_return_value() {
#[test]
fn calling_native_runtime_signature_changed_function() {
let client = test_client::new_with_api_execution_strat(ExecutionStrategy::NativeWhenPossible);
let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeWhenPossible);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
@@ -70,7 +70,7 @@ fn calling_native_runtime_signature_changed_function() {
#[test]
fn calling_wasm_runtime_signature_changed_old_function() {
let client = test_client::new_with_api_execution_strat(ExecutionStrategy::AlwaysWasm);
let client = test_client::new_with_execution_strategy(ExecutionStrategy::AlwaysWasm);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
@@ -78,3 +78,36 @@ fn calling_wasm_runtime_signature_changed_old_function() {
let res = runtime_api.function_signature_changed_before_version_2(&block_id).unwrap();
assert_eq!(&res, &[1, 2]);
}
#[test]
fn calling_with_both_strategy_and_fail_on_wasm_should_return_error() {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::Both);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
assert!(runtime_api.fail_on_wasm(&block_id).is_err());
}
#[test]
fn calling_with_both_strategy_and_fail_on_native_should_work() {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::Both);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1);
}
#[test]
fn calling_with_native_else_wasm_and_faild_on_wasm_should_work() {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeElseWasm);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
assert_eq!(runtime_api.fail_on_wasm(&block_id).unwrap(), 1);
}
#[test]
fn calling_with_native_else_wasm_and_fail_on_native_should_work() {
let client = test_client::new_with_execution_strategy(ExecutionStrategy::NativeElseWasm);
let runtime_api = client.runtime_api();
let block_id = BlockId::Number(client.info().unwrap().chain.best_number);
assert_eq!(runtime_api.fail_on_native(&block_id).unwrap(), 1);
}