mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 14:47:55 +00:00
Make API backwards compatible with CC (#1697)
* Rework how a runtime api calls into the runtime Now we generate a default implementation for each api call that calls a generated method `method_runtime_api_impl`. This newly generated method is the one that will be implemented by the `impl_runtime_apis` macro in the runtime for the client side. * Support `changed_in` to change runtime api function signatures * Update documentation * Fixes tests * Implement checking the api version with a predicate * Make the implementation backwards compatible with CC * Update wasm files after merge * Check for wasm runtime differences by building master and current branch * Update spec_version and wasm files * Fixes * Revert my changes * Remove `patch.crates-io` from test-runtime
This commit is contained in:
@@ -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() {}
|
||||
```
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -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<TokenStream>,
|
||||
}
|
||||
|
||||
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<TraitItem>) -> Vec<TraitItem> {
|
||||
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<TraitItemMethod>) {
|
||||
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<TraitItemMethod> {
|
||||
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::<Vec<_>>(),
|
||||
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<u8>
|
||||
) -> #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::<Vec<_>>(),
|
||||
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<Option<u64>> {
|
||||
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<u64> {
|
||||
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<Block> );
|
||||
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 )* )
|
||||
|
||||
@@ -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<TokenStrea
|
||||
res
|
||||
}
|
||||
|
||||
fn has_api<A: #crate_::runtime_api::RuntimeApiInfo + ?Sized>(
|
||||
fn runtime_version_at(
|
||||
&self,
|
||||
at: &#block_id
|
||||
) -> #crate_::error::Result<bool> where Self: Sized {
|
||||
self.call.runtime_version_at(at).map(|r| r.has_api::<A>())
|
||||
) -> #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<TokenStrea
|
||||
at: &#block_id,
|
||||
function: &'static str,
|
||||
args: Vec<u8>,
|
||||
native_call: NC,
|
||||
) -> #crate_::error::Result<R> {
|
||||
native_call: Option<NC>,
|
||||
) -> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<R>> {
|
||||
let res = unsafe {
|
||||
self.call.call_api_at(
|
||||
at,
|
||||
@@ -345,21 +345,7 @@ fn generate_runtime_api_base_structures(impls: &[ItemImpl]) -> Result<TokenStrea
|
||||
args,
|
||||
&mut *self.changes.borrow_mut(),
|
||||
&mut *self.initialised_block.borrow_mut(),
|
||||
Some(native_call),
|
||||
).and_then(|r|
|
||||
match r {
|
||||
#crate_::runtime_api::NativeOrEncoded::Native(n) => {
|
||||
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::<Vec<_>>();
|
||||
|
||||
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::<Vec<_>>()
|
||||
};
|
||||
|
||||
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::<Vec<_>>(),
|
||||
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<u8>
|
||||
};
|
||||
|
||||
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 ),*
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
/// }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user