Skip to content

[pallet-revive]: Version the trace_block runtime API function#12244

Open
0xOmarA wants to merge 14 commits into
masterfrom
0xOmarA/versioned-tracing-runtime-api-functions
Open

[pallet-revive]: Version the trace_block runtime API function#12244
0xOmarA wants to merge 14 commits into
masterfrom
0xOmarA/versioned-tracing-runtime-api-functions

Conversation

@0xOmarA
Copy link
Copy Markdown
Contributor

@0xOmarA 0xOmarA commented Jun 1, 2026

Description

This PR is a follow up from the various discussions we have had as a team around versioning of the runtime API and the approach that we should take.

This PR versions a single runtime API function in pallet-revive: the trace_block function. In the process, I also implemented #11532 to demonstrate how the various pieces connect together when we want to version a specific runtime API function as the last commit in the PR.

This PR is meant to show case how everything in versioning works e2e before we go ahead and version the rest of the runtime API using this strategy.

All of the wire types we use for tracing have been added to the types crate. It houses the wire types and the payload types that we use for the runtime APIs.

The following concepts were added to the codebase:

  • On the wire types:
    • ${name}V${version} - A version of a specific type. For example CallLogV1.
    • ${name}InputPayloadV${version} - A specific version of the input payload for some runtime API function. For example TraceBlockInputPayloadV1.
    • ${name}OutputPayloadV${version} - A specific version of the output payload for some runtime API function. For example TraceBlockOutputPayloadV1.
    • ${name}VersionedInputPayload - An enum of all of the possible versions that the input payload for some runtime API function can have.
    • ${name}VersionedOutputPayload - An enum of all of the possible versions that the output payload for some runtime API function can have.
  • On the execution types:
    • ${name}InputPayload - Execution type input payload of some runtime API function.
    • ${name}OutputPayload - Execution type output payload of some runtime API function.

There are a few things worth noting:

  • In the process of working on this I needed to move some of the JSON functionality from pallet-revive and into the types crate.
  • Some of the execution models for tracing no longer implement SCALE which is done to ensure that these types never cross the wire and are indeed internal to pallet-revive (and anybody who imports pallet-revive as a direct dependency)

Tests

The new test_trace_block_returns_v1_trace_on_v1_input_and_v2_trace_on_v2_input test is probably the best test for this functionality. It shows that the versioned runtime API function for trace_block functions exactly in the way that we expect it to do: given a V1 input we get a V1 output back and given a V2 input we get a V2 output back. It shows that versioning works end to end.

@0xOmarA 0xOmarA requested a review from a team as a code owner June 1, 2026 10:14

sp_api::decl_runtime_apis! {
/// The API used to dry-run contract interactions.
#[api_version(1)]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this needs a bump too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree with you. I just read the docs here and I think that we would want to bump the API version at the top too:

/// # Declaring multiple api versions
///
/// Optionally multiple versions of the same api can be declared. This is useful for
/// development purposes. For example you want to have a testing version of the api which is
/// available only on a testnet. You can define one stable and one development version. This
/// can be done like this:
/// ```rust
/// sp_api::decl_runtime_apis! {
/// /// Declare the api trait.
/// #[api_version(2)]
/// pub trait Balance {
/// /// Get the balance.
/// fn get_balance() -> u64;
/// /// Set the balance.
/// fn set_balance(val: u64);
/// /// Transfer the balance to another user id
/// #[api_version(3)]
/// fn transfer_balance(uid: u64);
/// }
/// }
///
/// # fn main() {}
/// ```
/// The example above defines two api versions - 2 and 3. Version 2 contains `get_balance` and
/// `set_balance`. Version 3 additionally contains `transfer_balance`, which is not available
/// in version 2. Version 2 in this case is considered the default/base version of the api.
/// More than two versions can be defined this way. For example:
/// ```rust
/// sp_api::decl_runtime_apis! {
/// /// Declare the api trait.
/// #[api_version(2)]
/// pub trait Balance {
/// /// Get the balance.
/// fn get_balance() -> u64;
/// /// Set the balance.
/// fn set_balance(val: u64);
/// /// Transfer the balance to another user id
/// #[api_version(3)]
/// fn transfer_balance(uid: u64);
/// /// Clears the balance
/// #[api_version(4)]
/// fn clear_balance();
/// }
/// }
///
/// # fn main() {}
/// ```
/// Note that the latest version (4 in our example above) always contains all methods from all
/// the versions before.
///
/// ## Note on deprecation.
///
/// - Usage of `deprecated` attribute will propagate deprecation information to the metadata.
/// - For general usage examples of `deprecated` attribute please refer to <https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-deprecated-attribute>
pub use sp_api_proc_macro::decl_runtime_apis;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants