Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't expose metadata for Runtime APIs that haven't been implemented #6337

Merged
merged 23 commits into from
Nov 6, 2024

Conversation

jsdw
Copy link
Contributor

@jsdw jsdw commented Nov 1, 2024

Description

Prior to this PR, the metadata for runtime APIs was entirely based on that generated by decl_runtime_apis. It therefore didn't take into account that impl_runtime_apis might implement older versions of APIs than what has been declared.

This PR filters the returned runtime API metadata to only include methods actually implemented, and also avoids including methods labelled with changed_in (which the previous code was atempting to do already but not successfully, owing to the attr being removed prior to the check).

We also change all version related things to be u32s (rather than VERSION being u32 and api_versions being u64) for consistency / ease of comparison.

A test is added which works with both the enable-staging-api feature in api/tests enabled or disabled, to check all of this.

@@ -134,7 +134,7 @@ pub enum ConsensusLog {
}

/// Configuration data used by the BABE consensus engine.
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug)]
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
Copy link
Contributor Author

@jsdw jsdw Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some random error I encountered: this type is used in a Runtime API and so must impl TypeInfo.

@@ -334,6 +334,88 @@ pub fn get_deprecation(crate_: &TokenStream, attrs: &[syn::Attribute]) -> Result
.unwrap_or_else(|| Ok(quote! {#crate_::metadata_ir::DeprecationStatusIR::NotDeprecated}))
}

/// Represents an API version.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't change any of this code; just moved it to the utils module so that I could use it in runtime_metadata too.

@@ -24,7 +24,7 @@ use substrate_test_runtime_client::runtime::{Block, Hash};

/// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real
/// runtime.
pub enum Runtime {}
pub struct Runtime {}
Copy link
Contributor Author

@jsdw jsdw Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to instantiate this to call runtime_metadata() on it in the test, hence changing to struct.

@jsdw jsdw added the R0-silent Changes should not be mentioned in any release notes label Nov 1, 2024
@jsdw jsdw added I2-bug The node fails to follow expected behavior. T4-runtime_API This PR/Issue is related to runtime APIs. and removed R0-silent Changes should not be mentioned in any release notes labels Nov 4, 2024
@jsdw jsdw marked this pull request as ready for review November 4, 2024 14:53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committed by accident?

@pkhry
Copy link
Contributor

pkhry commented Nov 4, 2024

I've taken a look, but I haven't run the macro expansion, it's remaining the same, minus the unimplemented methods, right?

Also can you update frame-support tests?

@@ -48,6 +48,8 @@ pub struct MetadataIR<T: Form = MetaForm> {
pub struct RuntimeApiMetadataIR<T: Form = MetaForm> {
/// Trait name.
pub name: T::String,
/// The base api_version declared on the trait.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need any of these changes, if you do the filtering directly in runtime_metadata by forwarding there the impl api version.

Copy link
Contributor Author

@jsdw jsdw Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense; I can remove the base_version from that and rely on mod_name::VERSION instead!

One small thing this bumps into is that VERSION is a u32 whereas we use u64s to track method versions (which causes a type error when comparing one with the other). Any objection to me making method_versions be treated as u32s too (or alternately, make VERSION a u64)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

u32 sounds reasonable.

@jsdw jsdw requested a review from a team as a code owner November 5, 2024 11:19
impl<T: Form> RuntimeApiMetadataIR<T> {
/// This returns a version of `Self` keeping only the
/// methods for which the provided function returns true.
pub fn keeping_methods<F>(self, f: F) -> Self
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that you can also remove this, just forward the api_version to runtime_metadata.

Copy link
Contributor Author

@jsdw jsdw Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But different methods can be implemented at different versions, so my understanding is that I need to look at the version that was implemented and then filter out all those methods that have a version greater than this?

Copy link
Contributor Author

@jsdw jsdw Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ie if we have:

decl_runtime_apis! {
	#[api_version(2)]
	pub trait ApiWithMultipleVersions {
		fn stable_one(data: u64);
		#[api_version(3)]
		fn new_one();
		#[api_version(4)]
		fn glory_one();
	}
}

impl_runtime_apis! {
	#[api_version(3)]
	impl self::ApiWithMultipleVersions<Block> for Runtime {
		fn stable_one(_: u64) {}
		fn new_one() {}
	}
}

Then I see that we are implementing version 3 of the APIs, and so I filter out methods declared higher than that (above, glory_one) using keeping_methods since they haven't been implemented

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn runtime_metadata(impl_version: u32);

runtime_metadata(version_from_the_attribute);

What I propose is to move the filtering to the runtime_metadata function. We are calling this function any way and then filter the functions. Instead we could filter directly in runtime_metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh I see, gotcha! I considered that early on but probably opted not to change the interface :) Lemme try this and see what it looks like!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! This means sp-metadata-ir is untouched now which is nice, though I guess means a major bump on sp-proc-macro since the interface changes a little. The code is a bit simpler I think now though which I like!

@jsdw
Copy link
Contributor Author

jsdw commented Nov 5, 2024

/cmd --help

Copy link

github-actions bot commented Nov 5, 2024

Command help:
usage: /cmd  [--help] [--quiet] [--clean] [--image IMAGE]
             {bench,fmt,update-ui,prdoc} ...

A command runner for polkadot-sdk repo

positional arguments:
  {bench,fmt,update-ui,prdoc}
                        a command to run
    bench               Runs benchmarks
    fmt                 Formats code (cargo +nightly-VERSION fmt) and configs
                        (taplo format)
    update-ui           Updates UI tests
    prdoc               Generates PR documentation

options:
  --help                help for help if you need some help
  --quiet               Won't print start/end/failed messages in PR
  --clean               Clean up the previous bot's & author's comments in PR
  --image IMAGE         Override docker image '--image
                        docker.io/paritytech/ci-unified:latest'

### Command 'bench'
usage: /cmd bench [-h] [--quiet] [--clean] [--image IMAGE]
                  [--runtime [{dev,westend,rococo,asset-hub-westend,asset-hub-rococo,bridge-hub-rococo,bridge-hub-westend,collectives-westend,contracts-rococo,coretime-rococo,coretime-westend,glutton-westend,people-rococo,people-westend} ...]]
                  [--pallet [PALLET ...]] [--fail-fast]

options:
  -h, --help            show this help message and exit
  --quiet               Won't print start/end/failed messages in PR
  --clean               Clean up the previous bot's & author's comments in PR
  --image IMAGE         Override docker image '--image
                        docker.io/paritytech/ci-unified:latest'
  --runtime [{dev,westend,rococo,asset-hub-westend,asset-hub-rococo,bridge-hub-rococo,bridge-hub-westend,collectives-westend,contracts-rococo,coretime-rococo,coretime-westend,glutton-westend,people-rococo,people-westend} ...]
                        Runtime(s) space separated
  --pallet [PALLET ...]
                        Pallet(s) space separated
  --fail-fast           Fail fast on first failed benchmark

**Examples**:
 Runs all benchmarks
 /cmd bench

 Runs benchmarks for pallet_balances and pallet_multisig for all runtimes which have these pallets. **--quiet** makes it to output nothing to PR but reactions
 /cmd bench --pallet pallet_balances pallet_xcm_benchmarks::generic --quiet

 Runs bench for all pallets for westend runtime and fails fast on first failed benchmark
 /cmd bench --runtime westend --fail-fast

 Does not output anything and cleans up the previous bot's & author command triggering comments in PR
 /cmd bench --runtime westend rococo --pallet pallet_balances pallet_multisig --quiet --clean


### Command 'fmt'
usage: /cmd fmt [-h] [--quiet] [--clean] [--image IMAGE]

options:
  -h, --help     show this help message and exit
  --quiet        Won't print start/end/failed messages in PR
  --clean        Clean up the previous bot's & author's comments in PR
  --image IMAGE  Override docker image '--image docker.io/paritytech/ci-
                 unified:latest'


### Command 'update-ui'
usage: /cmd update-ui [-h] [--quiet] [--clean] [--image IMAGE]

options:
  -h, --help     show this help message and exit
  --quiet        Won't print start/end/failed messages in PR
  --clean        Clean up the previous bot's & author's comments in PR
  --image IMAGE  Override docker image '--image docker.io/paritytech/ci-
                 unified:latest'


### Command 'prdoc'
usage: /cmd prdoc [-h] [--pr PR]
                  [--audience [{runtime_dev,runtime_user,node_dev,node_operator} ...]]
                  [--bump {patch,minor,major,silent,ignore,no_change}]
                  [--force]

options:
  -h, --help            show this help message and exit
  --pr PR               The PR number to generate the PrDoc for.
  --audience [{runtime_dev,runtime_user,node_dev,node_operator} ...]
                        The audience of whom the changes may concern. Example:
                        --audience runtime_dev node_dev
  --bump {patch,minor,major,silent,ignore,no_change}
                        A default bump level for all crates. Example: --bump
                        patch
  --force               Whether to overwrite any existing PrDoc.

@jsdw
Copy link
Contributor Author

jsdw commented Nov 5, 2024

/cmd fmt

Copy link

github-actions bot commented Nov 5, 2024

Command "fmt" has started 🚀 See logs here

Copy link

github-actions bot commented Nov 5, 2024

Command "fmt" has finished ✅ See logs here

@jsdw
Copy link
Contributor Author

jsdw commented Nov 6, 2024

/cmd fmt

Copy link

github-actions bot commented Nov 6, 2024

Command "fmt" has started 🚀 See logs here

Copy link

github-actions bot commented Nov 6, 2024

Command "fmt" has finished ✅ See logs here

@bkchr bkchr enabled auto-merge November 6, 2024 09:59
@bkchr bkchr added this pull request to the merge queue Nov 6, 2024
Merged via the queue into master with commit c81569e Nov 6, 2024
195 of 196 checks passed
@bkchr bkchr deleted the jsdw-versioned-runtime-api-metadata branch November 6, 2024 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I2-bug The node fails to follow expected behavior. T4-runtime_API This PR/Issue is related to runtime APIs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants