mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 08:47:57 +00:00
Runtime API versioning (#11779)
* Runtime API versioning Related to issue #11577 Add support for multiple versions of a Runtime API. The purpose is to have one main version of the API, which is considered stable and multiple unstable (aka staging) ones. How it works =========== Some methods of the API trait can be tagged with `#[api_version(N)]` attribute where N is version number bigger than the main one. Let's call them **staging methods** for brevity. The implementor of the API decides which version to implement. Example (from https://github.com/paritytech/substrate/issues/11577#issuecomment-1145347025): ``` decl_runtime_apis! { #{api_version(10)] trait Test { fn something() -> Vec<u8>; #[api_version(11)] fn new_cool_function() -> u32; } } ``` ``` impl_runtime_apis! { #[api_version(11)] impl Test for Runtime { fn something() -> Vec<u8> { vec![1, 2, 3] } fn new_cool_function() -> u32 { 10 } } } ``` Version safety checks (currently not implemented) ================================================= By default in the API trait all staging methods has got default implementation calling `unimplemented!()`. This is a problem because if the developer wants to implement version 11 in the example above and forgets to add `fn new_cool_function()` in `impl_runtime_apis!` the runtime will crash when the function is executed. Ideally a compilation error should be generated in such cases. TODOs ===== Things not working well at the moment: [ ] Version safety check [ ] Integration tests of `primitives/api` are messed up a bit. More specifically `primitives/api/test/tests/decl_and_impl.rs` [ ] Integration test covering the new functionality. [ ] Some duplicated code * Update primitives/api/proc-macro/src/impl_runtime_apis.rs Code review feedback and formatting Co-authored-by: asynchronous rob <rphmeier@gmail.com> * Code review feedback Applying suggestions from @bkchr * fmt * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Code review feedback * dummy trait -> versioned trait * Implement only versioned traits (not compiling) * Remove native API calls (still not compiling) * fmt * Fix compilation * Comments * Remove unused code * Remove native runtime tests * Remove unused code * Fix UI tests * Code review feedback * Code review feedback * attribute_names -> common * Rework `append_api_version` * Code review feedback * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Code review feedback * Code review feedback * Code review feedback * Use type alias for the default trait - doesn't compile * Fixes * Better error for `method_api_ver < trait_api_version` * fmt * Rework how we call runtime functions * Update UI tests * Fix warnings * Fix doctests * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Fix formatting and small compilation errors * Update primitives/api/proc-macro/src/impl_runtime_apis.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: asynchronous rob <rphmeier@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Bastian Köcher <info@kchr.de>
This commit is contained in:
committed by
GitHub
parent
8e927daa77
commit
2bff2f84e3
@@ -18,16 +18,18 @@
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
|
||||
use syn::{
|
||||
parse_quote, spanned::Spanned, token::And, Error, FnArg, GenericArgument, Ident, ImplItem,
|
||||
ItemImpl, Pat, Path, PathArguments, Result, ReturnType, Signature, Type, TypePath,
|
||||
parse_quote, spanned::Spanned, token::And, Attribute, Error, FnArg, GenericArgument, Ident,
|
||||
ImplItem, ItemImpl, Pat, Path, PathArguments, Result, ReturnType, Signature, Type, TypePath,
|
||||
};
|
||||
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
use std::env;
|
||||
|
||||
use proc_macro_crate::{crate_name, FoundCrate};
|
||||
|
||||
use crate::common::API_VERSION_ATTRIBUTE;
|
||||
|
||||
fn generate_hidden_includes_mod_name(unique_id: &'static str) -> Ident {
|
||||
Ident::new(&format!("sp_api_hidden_includes_{}", unique_id), Span::call_site())
|
||||
}
|
||||
@@ -68,11 +70,6 @@ pub fn generate_runtime_mod_name_for_trait(trait_: &Ident) -> Ident {
|
||||
Ident::new(&format!("runtime_decl_for_{}", trait_), 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(trait_: &Ident, method: &Ident) -> Ident {
|
||||
Ident::new(&format!("{}_{}_runtime_api_impl", trait_, method), Span::call_site())
|
||||
}
|
||||
|
||||
/// Get the type of a `syn::ReturnType`.
|
||||
pub fn return_type_extract_type(rt: &ReturnType) -> Type {
|
||||
match rt {
|
||||
@@ -166,16 +163,6 @@ pub fn extract_parameter_names_types_and_borrows(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Generates the name for the native call generator function.
|
||||
pub fn generate_native_call_generator_fn_name(fn_name: &Ident) -> Ident {
|
||||
Ident::new(&format!("{}_native_call_generator", fn_name), Span::call_site())
|
||||
}
|
||||
|
||||
/// Generates the name for the call api at function.
|
||||
pub fn generate_call_api_at_fn_name(fn_name: &Ident) -> Ident {
|
||||
Ident::new(&format!("{}_call_api_at", fn_name), Span::call_site())
|
||||
}
|
||||
|
||||
/// Prefix the given function with the trait name.
|
||||
pub fn prefix_function_with_trait<F: ToString>(trait_: &Ident, function: &F) -> String {
|
||||
format!("{}_{}", trait_, function.to_string())
|
||||
@@ -267,3 +254,23 @@ pub fn extract_impl_trait(impl_: &ItemImpl, require: RequireQualifiedTraitPath)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse the given attribute as `API_VERSION_ATTRIBUTE`.
|
||||
pub fn parse_runtime_api_version(version: &Attribute) -> Result<u64> {
|
||||
let version = version.parse_args::<syn::LitInt>().map_err(|_| {
|
||||
Error::new(
|
||||
version.span(),
|
||||
&format!(
|
||||
"Unexpected `{api_version}` attribute. The supported format is `{api_version}(1)`",
|
||||
api_version = API_VERSION_ATTRIBUTE
|
||||
),
|
||||
)
|
||||
})?;
|
||||
|
||||
version.base10_parse()
|
||||
}
|
||||
|
||||
// Each versioned trait is named 'ApiNameVN' where N is the specific version. E.g. ParachainHostV2
|
||||
pub fn versioned_trait_name(trait_ident: &Ident, version: u64) -> Ident {
|
||||
format_ident!("{}V{}", trait_ident, version)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user