diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index a9eda33d0b..e845b1c8ac 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -3487,6 +3487,7 @@ dependencies = [ "kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", @@ -3981,6 +3982,7 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/core/basic-authorship/src/basic_authorship.rs b/substrate/core/basic-authorship/src/basic_authorship.rs index 41625273cb..d504500fa2 100644 --- a/substrate/core/basic-authorship/src/basic_authorship.rs +++ b/substrate/core/basic-authorship/src/basic_authorship.rs @@ -96,10 +96,10 @@ impl AuthoringApi for SubstrateClient where let mut block_builder = self.new_block_at(at)?; let runtime_api = self.runtime_api(); - if runtime_api.has_api::>(at)? { - runtime_api.inherent_extrinsics(at, inherent_data)? - .into_iter().try_for_each(|i| block_builder.push(i))?; - } + // We don't check the API versions any further here since the dispatch compatibility + // check should be enough. + runtime_api.inherent_extrinsics(at, inherent_data)? + .into_iter().try_for_each(|i| block_builder.push(i))?; build_ctx(&mut block_builder); diff --git a/substrate/core/client/Cargo.toml b/substrate/core/client/Cargo.toml index e21a3be127..79fd5bff9f 100644 --- a/substrate/core/client/Cargo.toml +++ b/substrate/core/client/Cargo.toml @@ -22,7 +22,8 @@ substrate-telemetry = { path = "../telemetry", optional = true } hash-db = { version = "0.9" , optional = true } kvdb = { git = "https://github.com/paritytech/parity-common", optional = true, rev="b0317f649ab2c665b7987b8475878fc4d2e1f81d" } -codec = { package = "parity-codec", version = "3.0", default-features = false } +parity-codec = { version = "3.0", default-features = false } +parity-codec-derive = { version = "3.0", default-features = false } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } runtime-primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } runtime-version = { package = "sr-version", path = "../sr-version", default-features = false } @@ -37,7 +38,8 @@ kvdb-memorydb = { git = "https://github.com/paritytech/parity-common", rev="b031 [features] default = ["std"] std = [ - "codec/std", + "parity-codec/std", + "parity-codec-derive/std", "consensus", "primitives/std", "inherents/std", diff --git a/substrate/core/client/src/block_builder/api.rs b/substrate/core/client/src/block_builder/api.rs index 72cfea309f..f0f9a23122 100644 --- a/substrate/core/client/src/block_builder/api.rs +++ b/substrate/core/client/src/block_builder/api.rs @@ -16,13 +16,50 @@ //! The runtime api for building blocks. -use runtime_primitives::{traits::Block as BlockT, ApplyResult}; +use runtime_primitives::{traits::Block as BlockT, ApplyResult, RuntimeString}; use rstd::vec::Vec; use sr_api_macros::decl_runtime_apis; pub use inherents::{InherentData, CheckInherentsResult}; +use parity_codec_derive::{Encode, Decode}; + +/// The old representation of the inherent data. +#[doc(hide)] +#[derive(Encode, Decode)] +pub struct OldInherentData { + /// Current timestamp. + pub timestamp: u64, + /// Blank report. + pub consensus: (), + /// Aura expected slot. Can take any value during block construction. + pub aura_expected_slot: u64, +} + +impl OldInherentData { + /// Create a new `BasicInherentData` instance. + pub fn new(timestamp: u64, expected_slot: u64) -> Self { + Self { + timestamp, + consensus: (), + aura_expected_slot: expected_slot, + } + } +} + +/// Error type used while checking inherents. +#[doc(hide)] +#[derive(Encode, PartialEq)] +#[cfg_attr(feature = "std", derive(Decode))] +pub enum OldCheckInherentError { + /// The inherents are generally valid but a delay until the given timestamp + /// is required. + ValidAtTimestamp(u64), + /// Some other error has occurred. + Other(RuntimeString), +} decl_runtime_apis! { /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. + #[api_version(2)] pub trait BlockBuilder { /// Apply the given extrinsics. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; @@ -32,6 +69,11 @@ decl_runtime_apis! { fn inherent_extrinsics(inherent: InherentData) -> Vec<::Extrinsic>; /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; + /// Check that the inherents are valid. The inherent data will vary from chain to chain. + /// + /// Old version that is used by the CC network. + #[changed_in(2)] + fn check_inherents(block: Block, data: OldInherentData) -> ::std::result::Result<(), OldCheckInherentError>; /// Generate a random seed. fn random_seed() -> ::Hash; } diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 2313c4733d..3d969285a9 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -1426,7 +1426,7 @@ pub(crate) mod tests { use runtime_primitives::generic::DigestItem; use test_client::{self, TestClient}; use consensus::BlockOrigin; - use test_client::client::{backend::Backend as TestBackend, runtime_api::ApiExt}; + use test_client::client::backend::Backend as TestBackend; use test_client::BlockBuilderExt; use test_client::runtime::{self, Block, Transfer, RuntimeApi, TestAPI}; @@ -1523,17 +1523,6 @@ pub(crate) mod tests { ); } - #[test] - fn runtime_api_has_test_api() { - let client = test_client::new(); - - assert!( - client.runtime_api().has_api::>( - &BlockId::Number(client.info().unwrap().chain.best_number), - ).unwrap() - ); - } - #[test] fn authorities_call_works() { let client = test_client::new(); diff --git a/substrate/core/client/src/lib.rs b/substrate/core/client/src/lib.rs index 4a8f06dfde..671c453e96 100644 --- a/substrate/core/client/src/lib.rs +++ b/substrate/core/client/src/lib.rs @@ -20,6 +20,8 @@ #![warn(missing_docs)] #![recursion_limit="128"] +extern crate parity_codec as codec; + #[macro_use] pub mod runtime_api; #[cfg(feature = "std")] diff --git a/substrate/core/client/src/runtime_api.rs b/substrate/core/client/src/runtime_api.rs index 72371bc95f..95465d050b 100644 --- a/substrate/core/client/src/runtime_api.rs +++ b/substrate/core/client/src/runtime_api.rs @@ -69,7 +69,21 @@ pub trait ApiExt { fn has_api( &self, at: &BlockId - ) -> error::Result where Self: Sized; + ) -> error::Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api::()) + } + + /// Check if the given api is implemented and the version passes a predicate. + fn has_api_with bool>( + &self, + at: &BlockId, + pred: P, + ) -> error::Result where Self: Sized { + self.runtime_version_at(at).map(|v| v.has_api_with::(pred)) + } + + /// Returns the runtime version at the given block id. + fn runtime_version_at(&self, at: &BlockId) -> error::Result; } /// Something that can call into the runtime at a given block. diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index 81c257671d..a5442e59b1 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -34,7 +34,8 @@ use consensus_common::{ }; use consensus_common::import_queue::{Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport}; use client::ChainHead; -use client::block_builder::api::BlockBuilder as BlockBuilderApi; +use client::block_builder::api::{BlockBuilder as BlockBuilderApi, self as block_builder_api}; +use client::runtime_api::ApiExt; use consensus_common::{ImportBlock, BlockOrigin}; use runtime_primitives::{generic, generic::BlockId, Justification}; use runtime_primitives::traits::{ @@ -465,6 +466,50 @@ impl AuraVerifier Ok(()) } } + + #[allow(deprecated)] + fn old_check_inherents( + &self, + block: B, + block_id: BlockId, + inherent_data: InherentData, + timestamp_now: u64, + ) -> Result<(), String> + where C: ProvideRuntimeApi, C::Api: BlockBuilderApi + { + use block_builder_api::{OldInherentData, OldCheckInherentError}; + const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; + + let (timestamp, slot) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data).map_err(|e| format!("{:?}", e))?; + let inherent_data = OldInherentData::new(timestamp, slot); + + let inherent_res = self.client.runtime_api().check_inherents_before_version_2( + &block_id, + block, + inherent_data, + ).map_err(|e| format!("{:?}", e))?; + + match inherent_res { + Ok(()) => Ok(()), + Err(OldCheckInherentError::ValidAtTimestamp(timestamp)) => { + // halt import until timestamp is valid. + // reject when too far ahead. + if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { + return Err("Rejecting block too far in future".into()); + } + + let diff = timestamp.saturating_sub(timestamp_now); + info!( + target: "aura", + "halting for block {} seconds in the future", + diff + ); + thread::sleep(Duration::from_secs(diff)); + Ok(()) + }, + Err(OldCheckInherentError::Other(e)) => Err(e.into()) + } + } } /// No-op extra verification. @@ -519,12 +564,25 @@ impl Verifier for AuraVerifier where inherent_data.aura_replace_inherent_data(slot_num); let block = B::new(pre_header.clone(), inner_body); - self.check_inherents( - block.clone(), - BlockId::Hash(parent_hash), - inherent_data, - timestamp_now, - )?; + if self.client + .runtime_api() + .has_api_with::, _>(&BlockId::Hash(parent_hash), |v| v < 2) + .map_err(|e| format!("{:?}", e))? + { + self.old_check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now, + )?; + } else { + self.check_inherents( + block.clone(), + BlockId::Hash(parent_hash), + inherent_data, + timestamp_now, + )?; + } let (_, inner_body) = block.deconstruct(); body = Some(inner_body); diff --git a/substrate/core/finality-grandpa/src/tests.rs b/substrate/core/finality-grandpa/src/tests.rs index c472c0d372..036d7e1870 100644 --- a/substrate/core/finality-grandpa/src/tests.rs +++ b/substrate/core/finality-grandpa/src/tests.rs @@ -34,8 +34,9 @@ use consensus_common::BlockOrigin; use consensus_common::import_queue::{SharedBlockImport, SharedJustificationImport}; use std::collections::{HashMap, HashSet}; use std::result; -use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi, RuntimeApiInfo}; +use runtime_primitives::traits::{ApiRef, ProvideRuntimeApi}; use runtime_primitives::generic::BlockId; +use substrate_primitives::NativeOrEncoded; use authorities::AuthoritySet; @@ -273,23 +274,39 @@ impl ProvideRuntimeApi for TestApi { } impl Core for RuntimeApi { - fn version(&self, _: &BlockId) -> Result { - unimplemented!("Not required for testing!") - } - - fn authorities(&self, _: &BlockId) -> Result> { - unimplemented!("Not required for testing!") - } - - fn execute_block(&self, _: &BlockId, _: Block) -> Result<()> { - unimplemented!("Not required for testing!") - } - - fn initialise_block( + fn version_runtime_api_impl( &self, _: &BlockId, - _: &::Header - ) -> Result<()> { + _: Option<()>, + _: Vec + ) -> Result> { + unimplemented!("Not required for testing!") + } + + fn authorities_runtime_api_impl( + &self, + _: &BlockId, + _: Option<()>, + _: Vec + ) -> Result>> { + unimplemented!("Not required for testing!") + } + + fn execute_block_runtime_api_impl( + &self, + _: &BlockId, + _: Option<(Block)>, + _: Vec + ) -> Result> { + unimplemented!("Not required for testing!") + } + + fn initialise_block_runtime_api_impl( + &self, + _: &BlockId, + _: Option<&::Header>, + _: Vec, + ) -> Result> { unimplemented!("Not required for testing!") } } @@ -302,26 +319,31 @@ impl ApiExt for RuntimeApi { unimplemented!("Not required for testing!") } - fn has_api(&self, _: &BlockId) -> Result { + fn runtime_version_at(&self, _: &BlockId) -> Result { unimplemented!("Not required for testing!") } } impl GrandpaApi for RuntimeApi { - fn grandpa_authorities( + fn grandpa_authorities_runtime_api_impl( &self, - at: &BlockId - ) -> Result> { + at: &BlockId, + _: Option<()>, + _: Vec, + ) -> Result>> { if at == &BlockId::Number(0) { - Ok(self.inner.genesis_authorities.clone()) + Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) } else { panic!("should generally only request genesis authorities") } } - fn grandpa_pending_change(&self, at: &BlockId, _: &DigestFor) - -> Result>>> - { + fn grandpa_pending_change_runtime_api_impl( + &self, + at: &BlockId, + _: Option<(&DigestFor)>, + _: Vec + ) -> Result>>>> { let parent_hash = match at { &BlockId::Hash(at) => at, _ => panic!("not requested by block hash!!"), @@ -329,7 +351,7 @@ impl GrandpaApi for RuntimeApi { // we take only scheduled changes at given block number where there are no // extrinsics. - Ok(self.inner.scheduled_changes.lock().get(&parent_hash).map(|c| c.clone())) + Ok(self.inner.scheduled_changes.lock().get(&parent_hash).map(|c| c.clone())).map(NativeOrEncoded::Native) } } diff --git a/substrate/core/rpc/src/state/tests.rs b/substrate/core/rpc/src/state/tests.rs index 87b3dfcc9f..8c5f18f24d 100644 --- a/substrate/core/rpc/src/state/tests.rs +++ b/substrate/core/rpc/src/state/tests.rs @@ -215,14 +215,9 @@ fn should_return_runtime_version() { let client = Arc::new(test_client::new()); let api = State::new(client.clone(), Subscriptions::new(core.executor())); - assert_matches!( - api.runtime_version(None.into()), - Ok(ref ver) if ver == &runtime::VERSION - ); - assert_eq!( ::serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), - r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",1],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",1],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1]]}"# + r#"{"specName":"test","implName":"parity-test","authoringVersion":1,"specVersion":1,"implVersion":1,"apis":[["0xdf6acb689907609b",1],["0x37e397fc7c91f5e4",1],["0xd2bc9897eed08f15",1],["0x40fe3ad401f8959a",2],["0xc6e9a76309f39b09",1],["0xdd718d5cc53262d4",1]]}"# ); } diff --git a/substrate/core/sr-api-macros/src/compile_fail_tests.rs b/substrate/core/sr-api-macros/src/compile_fail_tests.rs index 7d7be065fa..195d46430f 100644 --- a/substrate/core/sr-api-macros/src/compile_fail_tests.rs +++ b/substrate/core/sr-api-macros/src/compile_fail_tests.rs @@ -378,3 +378,35 @@ mod impl_two_traits_with_same_name { ``` */ } + +mod changed_at_unknown_version { + /*! + ```compile_fail + #[macro_use] + extern crate substrate_client; + extern crate substrate_test_client as test_client; + extern crate sr_primitives as runtime_primitives; + extern crate substrate_primitives as primitives; + + use runtime_primitives::traits::GetNodeBlockType; + use test_client::runtime::Block; + + /// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType` + /// trait are done by the `construct_runtime!` macro in a real runtime. + struct Runtime {} + impl GetNodeBlockType for Runtime { + type NodeBlock = Block; + } + + decl_runtime_apis! { + pub trait Api { + #[changed_in(2)] + fn test(data: u64); + fn test(data: u64); + } + } + + fn main() {} + ``` + */ +} 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 13498003c2..48e50b329c 100644 --- a/substrate/core/sr-api-macros/src/decl_runtime_apis.rs +++ b/substrate/core/sr-api-macros/src/decl_runtime_apis.rs @@ -18,6 +18,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, return_type_extract_type, + generate_method_runtime_api_impl_name }; use proc_macro; @@ -27,8 +28,9 @@ use quote::quote; use syn::{ spanned::Spanned, parse_macro_input, parse::{Parse, ParseStream, Result, Error}, ReturnType, - fold::{self, Fold}, FnDecl, parse_quote, ItemTrait, Generics, GenericParam, Attribute, - visit::{Visit, self}, FnArg, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type + fold::{self, Fold}, parse_quote, ItemTrait, Generics, GenericParam, Attribute, FnArg, + visit::{Visit, self}, Pat, TraitBound, Meta, NestedMeta, Lit, TraitItem, Ident, Type, + TraitItemMethod }; use std::collections::HashMap; @@ -44,9 +46,16 @@ const HIDDEN_INCLUDES_ID: &str = "DECL_RUNTIME_APIS"; /// The `core_trait` attribute. const CORE_TRAIT_ATTRIBUTE: &str = "core_trait"; /// The `api_version` attribute. +/// Is used to set the current version of the trait. const API_VERSION_ATTRIBUTE: &str = "api_version"; +/// The `changed_in` attribute. +/// Is used when the function signature changed between different versions of a trait. +/// This attribute should be placed on the old signature of the function. +const CHANGED_IN_ATTRIBUTE: &str = "changed_in"; /// All attributes that we support in the declaratio of a runtime api trait. -const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE]; +const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[ + CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE, CHANGED_IN_ATTRIBUTE +]; /// The structure used for parsing the runtime api declarations. struct RuntimeApiDecls { @@ -279,6 +288,20 @@ fn generate_runtime_decls(decls: &[ItemTrait]) -> TokenStream { generate_runtime_api_version(v as u32) })); let id = generate_runtime_api_id(&decl.ident.to_string()); + + // Remove methods that have the `changed_in` attribute as they are not required for the + // runtime anymore. + decl.items = decl.items.iter_mut().filter_map(|i| match i { + TraitItem::Method(ref mut method) => { + if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { + None + } else { + Some(TraitItem::Method(method.clone())) + } + } + r => Some(r.clone()), + }).collect(); + let native_call_generators = unwrap_or_error(generate_native_call_generators(&decl)); result.push(quote!( @@ -306,19 +329,164 @@ struct ToClientSideDecl<'a> { block_id: &'a TokenStream, crate_: &'a TokenStream, found_attributes: &'a mut HashMap<&'static str, Attribute>, + /// Any error that we found while converting this declaration. + errors: &'a mut Vec, } -impl<'a> Fold for ToClientSideDecl<'a> { - fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { - let input = fold_fn_decl_for_client_side( - input, +impl<'a> ToClientSideDecl<'a> { + fn fold_item_trait_items(&mut self, items: Vec) -> Vec { + let mut result = Vec::new(); + + items.into_iter().for_each(|i| match i { + TraitItem::Method(method) => { + let (fn_decl, fn_impl) = self.fold_trait_item_method(method); + result.push(fn_decl.into()); + + if let Some(fn_impl) = fn_impl { + result.push(fn_impl.into()); + } + }, + r => result.push(r), + }); + + result + } + + fn fold_trait_item_method(&mut self, method: TraitItemMethod) -> (TraitItemMethod, Option) { + let fn_impl = self.create_method_runtime_api_impl(method.clone()); + let fn_decl = self.create_method_decl(method); + + (fn_decl, fn_impl) + } + + /// Takes the given method and creates a `method_runtime_api_impl` method that will be + /// implemented in the runtime for the client side. + fn create_method_runtime_api_impl(&mut self, mut method: TraitItemMethod) -> Option { + if remove_supported_attributes(&mut method.attrs).contains_key(CHANGED_IN_ATTRIBUTE) { + return None; + } + + let fn_decl = &method.sig.decl; + let ret_type = return_type_extract_type(&fn_decl.output); + + // Get types and if the value is borrowed from all parameters. + // If there is an error, we push it as the block to the user. + let param_types = match extract_parameter_names_types_and_borrows(fn_decl) { + Ok(res) => res.into_iter().map(|v| { + let ty = v.1; + let borrow = v.2; + quote!( #borrow #ty ) + }).collect::>(), + Err(e) => { + self.errors.push(e.to_compile_error()); + Vec::new() + } + }; + let name = generate_method_runtime_api_impl_name(&method.sig.ident); + let block_id = self.block_id; + let crate_ = self.crate_; + + Some( + parse_quote!{ + #[doc(hidden)] + fn #name( + &self, + at: &#block_id, + params: Option<( #( #param_types ),* )>, + params_encoded: Vec + ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>>; + } + ) + } + + /// 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 { + let params = match extract_parameter_names_types_and_borrows(&method.sig.decl) { + Ok(res) => res.into_iter().map(|v| v.0).collect::>(), + Err(e) => { + self.errors.push(e.to_compile_error()); + Vec::new() + } + }; + let params2 = params.clone(); + let ret_type = return_type_extract_type(&method.sig.decl.output); + + method.sig.decl = fold_fn_decl_for_client_side( + method.sig.decl.clone(), &self.block_id, &self.crate_ ); + let name_impl = generate_method_runtime_api_impl_name(&method.sig.ident); + let crate_ = self.crate_; - fold::fold_fn_decl(self, input) + let found_attributes = remove_supported_attributes(&mut method.attrs); + // If the method has a `changed_in` attribute, we need to alter the method name to + // `method_before_version_VERSION`. + let (native_handling, param_tuple) = match get_changed_in(&found_attributes) { + Ok(Some(version)) => { + // Make sure that the `changed_in` version is at least the current `api_version`. + if get_api_version(&self.found_attributes).ok() < Some(version) { + self.errors.push( + Error::new( + method.span(), + "`changed_in` version can not be greater than the `api_version`", + ).to_compile_error() + ); + } + + let ident = Ident::new( + &format!("{}_before_version_{}", method.sig.ident, version), + method.sig.ident.span() + ); + method.sig.ident = ident; + method.attrs.push(parse_quote!( #[deprecated] )); + + let panic = format!("Calling `{}` should not return a native value!", method.sig.ident); + (quote!( panic!(#panic) ), quote!( None )) + }, + Ok(None) => (quote!( Ok(n) ), quote!( Some(( #( #params2 ),* )) )), + Err(e) => { + self.errors.push(e.to_compile_error()); + (quote!( unimplemented!() ), quote!( None )) + } + }; + + let function_name = method.sig.ident.to_string(); + + // Generate the default implementation that calls the `method_runtime_api_impl` method. + method.default = Some( + parse_quote! { + { + let runtime_api_impl_params_encoded = + #crate_::runtime_api::Encode::encode(&( #( &#params ),* )); + + self.#name_impl(at, #param_tuple, runtime_api_impl_params_encoded) + .and_then(|r| + match r { + #crate_::runtime_api::NativeOrEncoded::Native(n) => { + #native_handling + }, + #crate_::runtime_api::NativeOrEncoded::Encoded(r) => { + <#ret_type as #crate_::runtime_api::Decode>::decode(&mut &r[..]) + .ok_or_else(|| + #crate_::error::ErrorKind::CallResultDecode( + #function_name + ).into() + ) + } + } + ) + } + } + ); + + method } +} +impl<'a> Fold for ToClientSideDecl<'a> { fn fold_item_trait(&mut self, mut input: ItemTrait) -> ItemTrait { extend_generics_with_block(&mut input.generics); @@ -344,6 +512,7 @@ impl<'a> Fold for ToClientSideDecl<'a> { // The client side trait is only required when compiling with the feature `std` or `test`. input.attrs.push(parse_quote!( #[cfg(any(feature = "std", test))] )); + input.items = self.fold_item_trait_items(input.items); fold::fold_item_trait(self, input) } @@ -412,12 +581,16 @@ fn generate_runtime_info_impl(trait_: &ItemTrait, version: u64) -> TokenStream { ) } +/// Get changed in version from the user given attribute or `Ok(None)`, if no attribute was given. +fn get_changed_in(found_attributes: &HashMap<&'static str, Attribute>) -> Result> { + found_attributes.get(&CHANGED_IN_ATTRIBUTE) + .map(|v| parse_runtime_api_version(v).map(Some)) + .unwrap_or(Ok(None)) +} + /// Get the api version from the user given attribute or `Ok(1)`, if no attribute was given. fn get_api_version(found_attributes: &HashMap<&'static str, Attribute>) -> Result { - match found_attributes.get(&API_VERSION_ATTRIBUTE) { - Some(attr) => parse_runtime_api_version(attr), - None => Ok(1), - } + 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. @@ -430,12 +603,14 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); let block_id = quote!( #crate_::runtime_api::BlockId ); let mut found_attributes = HashMap::new(); + let mut errors = Vec::new(); let decl = { let mut to_client_side = ToClientSideDecl { crate_: &crate_, block_id: &block_id, - found_attributes: &mut found_attributes + found_attributes: &mut found_attributes, + errors: &mut errors, }; to_client_side.fold_item_trait(decl) }; @@ -446,7 +621,7 @@ fn generate_client_side_decls(decls: &[ItemTrait]) -> TokenStream { api_version.map(|v| generate_runtime_info_impl(&decl, v)) ); - result.push(quote!( #decl #runtime_info )); + result.push(quote!( #decl #runtime_info #( #errors )* )); } quote!( #( #result )* ) 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 2909b07413..190ead3b9d 100644 --- a/substrate/core/sr-api-macros/src/impl_runtime_apis.rs +++ b/substrate/core/sr-api-macros/src/impl_runtime_apis.rs @@ -16,8 +16,8 @@ use utils::{ unwrap_or_error, generate_crate_access, generate_hidden_includes, - generate_runtime_mod_name_for_trait, fold_fn_decl_for_client_side, generate_unique_pattern, - extract_parameter_names_types_and_borrows, generate_native_call_generator_fn_name + 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 }; use proc_macro; @@ -28,7 +28,7 @@ use quote::quote; use syn::{ spanned::Spanned, parse_macro_input, Ident, Type, ItemImpl, MethodSig, Path, ImplItem, parse::{Parse, ParseStream, Result, Error}, PathArguments, GenericArgument, TypePath, - fold::{self, Fold}, FnDecl, parse_quote, FnArg + fold::{self, Fold}, parse_quote }; use std::{collections::HashSet, iter}; @@ -300,11 +300,11 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result( + fn runtime_version_at( &self, at: &#block_id - ) -> #crate_::error::Result where Self: Sized { - self.call.runtime_version_at(at).map(|r| r.has_api::()) + ) -> #crate_::error::Result<#crate_::runtime_api::RuntimeVersion> { + self.call.runtime_version_at(at) } } @@ -336,8 +336,8 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result, - native_call: NC, - ) -> #crate_::error::Result { + native_call: Option, + ) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded> { let res = unsafe { self.call.call_api_at( at, @@ -345,21 +345,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result { - Ok(n) - }, - #crate_::runtime_api::NativeOrEncoded::Encoded(r) => { - R::decode(&mut &r[..]) - .ok_or_else(|| - #crate_::error::ErrorKind::CallResultDecode( - function - ).into() - ) - } - } + native_call, ) }; @@ -446,50 +432,69 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> { fold::fold_type_path(self, new_ty_path) } - fn fold_fn_decl(&mut self, input: FnDecl) -> FnDecl { - let input = fold_fn_decl_for_client_side( - input, - &self.node_block_id, - &generate_crate_access(HIDDEN_INCLUDES_ID) - ); - - fold::fold_fn_decl(self, input) - } - fn fold_impl_item_method(&mut self, mut input: syn::ImplItemMethod) -> syn::ImplItemMethod { let block = { - let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); - let mut generated_name_counter = 0; - // Replace `_` with unique patterns and collect all patterns. - let arg_names = input.sig.decl.inputs.iter_mut().filter_map(|i| match i { - FnArg::Captured(ref mut arg) => Some(&mut arg.pat), - _ => None, - }).map(|p| { - *p = generate_unique_pattern(p.clone(), &mut generated_name_counter); - p.clone() - }).collect::>(); - let runtime_mod_path = self.runtime_mod_path; let runtime = self.runtime_type; - let arg_names2 = arg_names.clone(); let fn_name = prefix_function_with_trait(self.impl_trait_ident, &input.sig.ident); let native_call_generator_ident = generate_native_call_generator_fn_name(&input.sig.ident); let trait_generic_arguments = self.trait_generic_arguments; let node_block = self.node_block; + let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID); + let block_id = self.node_block_id; + + // Generate the access to the native parameters + let param_tuple_access = if input.sig.decl.inputs.len() == 1 { + vec![ quote!( p ) ] + } else { + input.sig.decl.inputs.iter().enumerate().map(|(i, _)| { + let i = syn::Index::from(i); + quote!( p.#i ) + }).collect::>() + }; + + let (param_types, error) = match extract_parameter_names_types_and_borrows(&input.sig.decl) { + Ok(res) => ( + res.into_iter().map(|v| { + let ty = v.1; + let borrow = v.2; + quote!( #borrow #ty ) + }).collect::>(), + None + ), + Err(e) => (Vec::new(), Some(e.to_compile_error())), + }; + + // Rewrite the input parameters. + input.sig.decl.inputs = parse_quote! { + &self, at: &#block_id, params: Option<( #( #param_types ),* )>, params_encoded: Vec + }; + + input.sig.ident = generate_method_runtime_api_impl_name(&input.sig.ident); + let ret_type = return_type_extract_type(&input.sig.decl.output); + + // Generate the correct return type. + input.sig.decl.output = parse_quote!( + -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>> + ); // Generate the new method implementation that calls into the runime. parse_quote!( { - let args = #crate_::runtime_api::Encode::encode(&( #( &#arg_names ),* )); + // Get the error to the user (if we have one). + #( #error )* + self.call_api_at( at, #fn_name, - args, - #runtime_mod_path #native_call_generator_ident :: - <#runtime, #node_block #(, #trait_generic_arguments )*> ( - #( #arg_names2 ),* - ) + params_encoded, + params.map(|p| { + #runtime_mod_path #native_call_generator_ident :: + <#runtime, #node_block #(, #trait_generic_arguments )*> ( + #( #param_tuple_access ),* + ) + }) ) } ) diff --git a/substrate/core/sr-api-macros/src/lib.rs b/substrate/core/sr-api-macros/src/lib.rs index 52e96a57cc..b616835284 100644 --- a/substrate/core/sr-api-macros/src/lib.rs +++ b/substrate/core/sr-api-macros/src/lib.rs @@ -159,7 +159,11 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// /// To support versioning of the traits, the macro supports the attribute `#[api_version(1)]`. /// The attribute supports any `u32` as version. By default, each trait is at version `1`, if no -/// version is provided. +/// version is provided. We also support chaning the signature of a method. This signature +/// change is highlighted with the `#[changed_in(2)]` attribute above a method. A method that is +/// tagged with this attribute is callable by the name `METHOD_before_version_VERSION`. This +/// method will only support calling into wasm, trying to call into native will fail (change the +/// spec version!). Such a method also does not need to be implemented in the runtime. /// /// ```rust /// #[macro_use] @@ -171,8 +175,13 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream { /// pub trait Balance { /// /// Get the balance. /// fn get_balance() -> u64; -/// /// Set the balance. +/// /// Set balance. /// fn set_balance(val: u64); +/// /// Set balance, old version. +/// /// +/// /// Is callable by `set_balance_before_version_2`. +/// #[changed_in(2)] +/// fn set_balance(val: u8); /// /// In version 2, we added this new function. /// fn increase_balance(val: u64); /// } diff --git a/substrate/core/sr-api-macros/src/utils.rs b/substrate/core/sr-api-macros/src/utils.rs index 9df59b30a7..d619fcb389 100644 --- a/substrate/core/sr-api-macros/src/utils.rs +++ b/substrate/core/sr-api-macros/src/utils.rs @@ -58,6 +58,11 @@ pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident { Ident::new(&format!("runtime_decl_for_{}", trait_.to_string()), Span::call_site()) } +/// Generates a name for a method that needs to be implemented in the runtime for the client side. +pub fn generate_method_runtime_api_impl_name(method: &Ident) -> Ident { + Ident::new(&format!("{}_runtime_api_impl", method.to_string()), Span::call_site()) +} + /// Get the type of a `syn::ReturnType`. pub fn return_type_extract_type(rt: &syn::ReturnType) -> Type { match rt { diff --git a/substrate/core/sr-api-macros/tests/decl_and_impl.rs b/substrate/core/sr-api-macros/tests/decl_and_impl.rs index 1d87a15201..28c9d9d51a 100644 --- a/substrate/core/sr-api-macros/tests/decl_and_impl.rs +++ b/substrate/core/sr-api-macros/tests/decl_and_impl.rs @@ -28,6 +28,8 @@ decl_runtime_apis! { #[api_version(2)] pub trait ApiWithCustomVersion { fn same_name(); + #[changed_in(2)] + fn same_name() -> String; } } @@ -77,6 +79,11 @@ fn test_client_side_function_signature() { let _something_with_block: fn(&RuntimeApiImpl, &BlockId, Block) -> Result = RuntimeApiImpl::::something_with_block; + + #[allow(deprecated)] + let _same_name_before_version_2: + fn(&RuntimeApiImpl, &BlockId) -> Result = + RuntimeApiImpl::::same_name_before_version_2; } #[test] diff --git a/substrate/core/sr-api-macros/tests/runtime_calls.rs b/substrate/core/sr-api-macros/tests/runtime_calls.rs index d1d05eb48a..a4b36a6a21 100644 --- a/substrate/core/sr-api-macros/tests/runtime_calls.rs +++ b/substrate/core/sr-api-macros/tests/runtime_calls.rs @@ -58,3 +58,23 @@ fn calling_native_runtime_function_with_non_decodable_return_value() { let block_id = BlockId::Number(client.info().unwrap().chain.best_number); runtime_api.fail_convert_return_value(&block_id).unwrap(); } + +#[test] +fn calling_native_runtime_signature_changed_function() { + 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); + + assert_eq!(runtime_api.function_signature_changed(&block_id).unwrap(), 1); +} + +#[test] +fn calling_wasm_runtime_signature_changed_old_function() { + let client = test_client::new_with_api_execution_strat(ExecutionStrategy::AlwaysWasm); + let runtime_api = client.runtime_api(); + let block_id = BlockId::Number(client.info().unwrap().chain.best_number); + + #[allow(deprecated)] + let res = runtime_api.function_signature_changed_before_version_2(&block_id).unwrap(); + assert_eq!(&res, &[1, 2]); +} diff --git a/substrate/core/sr-version/src/lib.rs b/substrate/core/sr-version/src/lib.rs index 4a4c7174ba..58369dd1c2 100644 --- a/substrate/core/sr-version/src/lib.rs +++ b/substrate/core/sr-version/src/lib.rs @@ -136,6 +136,16 @@ impl RuntimeVersion { s == &A::ID && *v == A::VERSION }) } + + /// Check if the given api is implemented and the version passes a predicate. + pub fn has_api_with bool>( + &self, + pred: P, + ) -> bool { + self.apis.iter().any(|(s, v)| { + s == &A::ID && pred(*v) + }) + } } #[cfg(feature = "std")] diff --git a/substrate/core/test-runtime/Cargo.toml b/substrate/core/test-runtime/Cargo.toml index 80c6677bdc..5fdf54ba9b 100644 --- a/substrate/core/test-runtime/Cargo.toml +++ b/substrate/core/test-runtime/Cargo.toml @@ -21,6 +21,7 @@ runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } runtime_primitives = { package = "sr-primitives", path = "../sr-primitives", default-features = false } runtime_version = { package = "sr-version", path = "../sr-version", default-features = false } srml-support = { path = "../../srml/support", default-features = false } +cfg-if = "0.1.6" [dev-dependencies] substrate-executor = { path = "../executor" } @@ -44,13 +45,3 @@ std = [ "runtime_version/std", "consensus_aura/std", ] - -[patch.crates-io] -hash-db = { git = "https://github.com/paritytech/trie" } -hash256-std-hasher = { git = "https://github.com/paritytech/trie" } -keccak-hasher = { git = "https://github.com/paritytech/trie" } -memory-db = { git = "https://github.com/paritytech/trie" } -trie-bench = { git = "https://github.com/paritytech/trie" } -trie-db = { git = "https://github.com/paritytech/trie" } -trie-root = { git = "https://github.com/paritytech/trie" } -trie-standardmap = { git = "https://github.com/paritytech/trie" } diff --git a/substrate/core/test-runtime/src/lib.rs b/substrate/core/test-runtime/src/lib.rs index d804468a64..024532fbfb 100644 --- a/substrate/core/test-runtime/src/lib.rs +++ b/substrate/core/test-runtime/src/lib.rs @@ -46,6 +46,7 @@ use primitives::{Ed25519AuthorityId, OpaqueMetadata}; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; use inherents::{CheckInherentsResult, InherentData}; +use cfg_if::cfg_if; /// Test runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -193,19 +194,47 @@ impl Decode for DecodeFails { } } -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; +cfg_if! { + if #[cfg(feature = "std")] { + decl_runtime_apis! { + #[api_version(2)] + 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; + /// A function for that the signature changed in version `2`. + #[changed_in(2)] + fn function_signature_changed() -> Vec; + /// The new signature. + fn function_signature_changed() -> u64; + } + } + } else { + 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; + /// In wasm we just emulate the old behavior. + fn function_signature_changed() -> Vec; + } + } } } @@ -219,82 +248,177 @@ impl GetRuntimeBlockType for Runtime { type RuntimeBlock = Block; } -impl_runtime_apis! { - impl client_api::Core for Runtime { - fn version() -> RuntimeVersion { - version() +cfg_if! { + if #[cfg(feature = "std")] { + impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } + + fn authorities() -> Vec { + system::authorities() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialise_block(header: &::Header) { + system::initialise_block(header) + } + } + + impl client_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl client_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + system::validate_transaction(utx) + } + } + + impl block_builder_api::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + system::execute_transaction(extrinsic) + } + + fn finalise_block() -> ::Header { + system::finalise_block() + } + + fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { + vec![] + } + + fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { + CheckInherentsResult::new() + } + + fn random_seed() -> ::Hash { + unimplemented!() + } + } + + impl self::TestAPI for Runtime { + fn balance_of(id: AccountId) -> u64 { + system::balance_of(id) + } + + fn benchmark_add_one(val: &u64) -> u64 { + val + 1 + } + + fn benchmark_vector_add_one(vec: &Vec) -> Vec { + let mut vec = vec.clone(); + vec.iter_mut().for_each(|v| *v += 1); + vec + } + + fn fail_convert_parameter(_: DecodeFails) {} + + fn fail_convert_return_value() -> DecodeFails { + DecodeFails::new() + } + + fn function_signature_changed() -> u64 { + 1 + } + } + + impl consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1 } + } } + } else { + impl_runtime_apis! { + impl client_api::Core for Runtime { + fn version() -> RuntimeVersion { + version() + } - fn authorities() -> Vec { - system::authorities() + fn authorities() -> Vec { + system::authorities() + } + + fn execute_block(block: Block) { + system::execute_block(block) + } + + fn initialise_block(header: &::Header) { + system::initialise_block(header) + } + } + + impl client_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + unimplemented!() + } + } + + impl client_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { + system::validate_transaction(utx) + } + } + + impl block_builder_api::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { + system::execute_transaction(extrinsic) + } + + fn finalise_block() -> ::Header { + system::finalise_block() + } + + fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { + vec![] + } + + fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { + CheckInherentsResult::new() + } + + fn random_seed() -> ::Hash { + unimplemented!() + } + } + + impl self::TestAPI for Runtime { + fn balance_of(id: AccountId) -> u64 { + system::balance_of(id) + } + + fn benchmark_add_one(val: &u64) -> u64 { + val + 1 + } + + fn benchmark_vector_add_one(vec: &Vec) -> Vec { + let mut vec = vec.clone(); + vec.iter_mut().for_each(|v| *v += 1); + vec + } + + fn fail_convert_parameter(_: DecodeFails) {} + + fn fail_convert_return_value() -> DecodeFails { + DecodeFails::new() + } + + fn function_signature_changed() -> Vec { + let mut vec = Vec::new(); + vec.push(1); + vec.push(2); + vec + } + } + + impl consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { 1 } + } } - - fn execute_block(block: Block) { - system::execute_block(block) - } - - fn initialise_block(header: &::Header) { - system::initialise_block(header) - } - } - - impl client_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - unimplemented!() - } - } - - impl client_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(utx: ::Extrinsic) -> TransactionValidity { - system::validate_transaction(utx) - } - } - - impl block_builder_api::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult { - system::execute_transaction(extrinsic) - } - - fn finalise_block() -> ::Header { - system::finalise_block() - } - - fn inherent_extrinsics(_data: InherentData) -> Vec<::Extrinsic> { - vec![] - } - - fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { - CheckInherentsResult::new() - } - - fn random_seed() -> ::Hash { - unimplemented!() - } - } - - impl self::TestAPI for Runtime { - fn balance_of(id: AccountId) -> u64 { - system::balance_of(id) - } - - fn benchmark_add_one(val: &u64) -> u64 { - val + 1 - } - - fn benchmark_vector_add_one(vec: &Vec) -> Vec { - let mut vec = vec.clone(); - 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 { - fn slot_duration() -> u64 { 1 } } } diff --git a/substrate/core/test-runtime/wasm/Cargo.lock b/substrate/core/test-runtime/wasm/Cargo.lock index 576c8674b3..a12e3185e5 100644 --- a/substrate/core/test-runtime/wasm/Cargo.lock +++ b/substrate/core/test-runtime/wasm/Cargo.lock @@ -1155,6 +1155,7 @@ dependencies = [ "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", @@ -1320,6 +1321,7 @@ dependencies = [ name = "substrate-test-runtime" version = "0.1.0" dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 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 9e05b9f7dd..96e58fb7eb 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/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 3e8e1dc395..218f324927 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -66,8 +66,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 20, - impl_version: 20, + spec_version: 21, + impl_version: 21, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/node/runtime/wasm/Cargo.lock b/substrate/node/runtime/wasm/Cargo.lock index c28857422b..08244710f9 100644 --- a/substrate/node/runtime/wasm/Cargo.lock +++ b/substrate/node/runtime/wasm/Cargo.lock @@ -1525,6 +1525,7 @@ dependencies = [ "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common?rev=b0317f649ab2c665b7987b8475878fc4d2e1f81d)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-codec-derive 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.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 60132cd0ea..4c583a3897 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