Skip to content
Snippets Groups Projects
Unverified Commit 1e89a311 authored by Bastian Köcher's avatar Bastian Köcher Committed by GitHub
Browse files

Fix runtime api impl detection by construct runtime (#6665)


Construct runtime uses autoref-based specialization to fetch the
metadata about the implemented runtime apis. This is done to not fail to
compile when there are no runtime apis implemented. However, there was
an issue with detecting runtime apis when they were implemented in a
different file. The problem is solved by moving the trait implemented by
`impl_runtime_apis!` to the metadata ir crate.


Closes: https://github.com/paritytech/polkadot-sdk/issues/6659

---------

Co-authored-by: default avatarGitHub Action <action@github.com>
parent 447902ef
No related merge requests found
Pipeline #507609 waiting for manual action with stages
in 1 hour, 29 minutes, and 50 seconds
......@@ -25548,6 +25548,7 @@ dependencies = [
"sp-api 26.0.0",
"sp-consensus",
"sp-core 28.0.0",
"sp-metadata-ir 0.6.0",
"sp-runtime 31.0.1",
"sp-state-machine 0.35.0",
"sp-tracing 16.0.0",
......
title: Fix runtime api impl detection by construct runtime
doc:
- audience: Runtime Dev
description: |-
Construct runtime uses autoref-based specialization to fetch the metadata about the implemented runtime apis. This is done to not fail to compile when there are no runtime apis implemented. However, there was an issue with detecting runtime apis when they were implemented in a different file. The problem is solved by moving the trait implemented by `impl_runtime_apis!` to the metadata ir crate.
Closes: https://github.com/paritytech/polkadot-sdk/issues/6659
crates:
- name: frame-support-procedural
bump: patch
- name: sp-api-proc-macro
bump: patch
- name: sp-metadata-ir
bump: patch
......@@ -113,6 +113,8 @@ pub fn expand_runtime_metadata(
<#extrinsic as #scrate::traits::SignedTransactionBuilder>::Extension
>();
use #scrate::__private::metadata_ir::InternalImplRuntimeApis;
#scrate::__private::metadata_ir::MetadataIR {
pallets: #scrate::__private::vec![ #(#pallets),* ],
extrinsic: #scrate::__private::metadata_ir::ExtrinsicMetadataIR {
......
......@@ -466,7 +466,6 @@ fn construct_runtime_final_expansion(
// Therefore, the `Deref` trait will resolve the `runtime_metadata` from `impl_runtime_apis!`
// when both macros are called; and will resolve an empty `runtime_metadata` when only the `construct_runtime!`
// is called.
#[doc(hidden)]
trait InternalConstructRuntime {
#[inline(always)]
......@@ -477,6 +476,8 @@ fn construct_runtime_final_expansion(
#[doc(hidden)]
impl InternalConstructRuntime for &#name {}
use #scrate::__private::metadata_ir::InternalImplRuntimeApis;
#outer_event
#outer_error
......
......@@ -80,34 +80,39 @@ sp_api::decl_runtime_apis! {
}
}
sp_api::impl_runtime_apis! {
impl self::Api<Block> for Runtime {
fn test(_data: u64) {
unimplemented!()
}
// Module to emulate having the implementation in a different file.
mod apis {
use super::{Block, BlockT, Runtime};
fn something_with_block(_: Block) -> Block {
unimplemented!()
}
sp_api::impl_runtime_apis! {
impl crate::Api<Block> for Runtime {
fn test(_data: u64) {
unimplemented!()
}
fn function_with_two_args(_: u64, _: Block) {
unimplemented!()
}
fn something_with_block(_: Block) -> Block {
unimplemented!()
}
fn same_name() {}
fn function_with_two_args(_: u64, _: Block) {
unimplemented!()
}
fn wild_card(_: u32) {}
}
fn same_name() {}
impl sp_api::Core<Block> for Runtime {
fn version() -> sp_version::RuntimeVersion {
unimplemented!()
}
fn execute_block(_: Block) {
unimplemented!()
fn wild_card(_: u32) {}
}
fn initialize_block(_: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
unimplemented!()
impl sp_api::Core<Block> for Runtime {
fn version() -> sp_version::RuntimeVersion {
unimplemented!()
}
fn execute_block(_: Block) {
unimplemented!()
}
fn initialize_block(_: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
unimplemented!()
}
}
}
}
......
......@@ -298,18 +298,14 @@ pub fn generate_impl_runtime_metadata(impls: &[ItemImpl]) -> Result<TokenStream2
// Therefore, the `Deref` trait will resolve the `runtime_metadata` from `impl_runtime_apis!`
// when both macros are called; and will resolve an empty `runtime_metadata` when only the
// `construct_runtime!` is called.
Ok(quote!(
#crate_::frame_metadata_enabled! {
#[doc(hidden)]
trait InternalImplRuntimeApis {
#[inline(always)]
impl #crate_::metadata_ir::InternalImplRuntimeApis for #runtime_name {
fn runtime_metadata(&self) -> #crate_::vec::Vec<#crate_::metadata_ir::RuntimeApiMetadataIR> {
#crate_::vec![ #( #metadata, )* ]
}
}
#[doc(hidden)]
impl InternalImplRuntimeApis for #runtime_name {}
}
))
}
......@@ -21,6 +21,7 @@ sp-version = { workspace = true, default-features = true }
sp-tracing = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-consensus = { workspace = true, default-features = true }
sp-metadata-ir = { workspace = true, default-features = true }
sc-block-builder = { workspace = true, default-features = true }
codec = { workspace = true, default-features = true }
sp-state-machine = { workspace = true, default-features = true }
......@@ -40,5 +41,5 @@ name = "bench"
harness = false
[features]
"enable-staging-api" = []
enable-staging-api = []
disable-ui-tests = []
......@@ -309,6 +309,8 @@ fn mock_runtime_api_works_with_advanced() {
#[test]
fn runtime_api_metadata_matches_version_implemented() {
use sp_metadata_ir::InternalImplRuntimeApis;
let rt = Runtime {};
let runtime_metadata = rt.runtime_metadata();
......
......@@ -87,6 +87,16 @@ pub fn into_unstable(metadata: MetadataIR) -> RuntimeMetadataPrefixed {
latest.into()
}
/// INTERNAL USE ONLY
///
/// Special trait that is used together with `InternalConstructRuntime` by `construct_runtime!` to
/// fetch the runtime api metadata without exploding when there is no runtime api implementation
/// available.
#[doc(hidden)]
pub trait InternalImplRuntimeApis {
fn runtime_metadata(&self) -> alloc::vec::Vec<RuntimeApiMetadataIR>;
}
#[cfg(test)]
mod test {
use super::*;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment