Expand description
Runtime API module declares the trait ParachainHost
which is part
of the Runtime API exposed from the Runtime to the Host.
The functions in trait ParachainHost` can be part of the stable API (which is versioned) or they can be staging (aka unstable/testing functions).
The separation outlined above is achieved with the versioned API feature
of decl_runtime_apis!
and impl_runtime_apis!
. Before moving on let’s
see a quick example about how API versioning works.
Runtime API versioning crash course
The versioning is achieved with the api_version
attribute. It can be
placed on:
- trait declaration - represents the base version of the API.
- method declaration (inside a trait declaration) - represents a versioned method, which is not available in the base version.
- trait implementation - represents which version of the API is being implemented.
Let’s see a quick example:
sp_api::decl_runtime_apis! {
#[api_version(2)]
pub trait MyApi {
fn fn1();
fn fn2();
#[api_version(3)]
fn fn3();
#[api_version(4)]
fn fn4();
}
}
struct Runtime {}
sp_api::impl_runtime_apis! {
#[api_version(3)]
impl self::MyApi<Block> for Runtime {
fn fn1() {}
fn fn2() {}
fn fn3() {}
}
}
A new API named MyApi
is declared with decl_runtime_apis!
. The trait declaration
has got an api_version
attribute which represents its base version - 2 in this case.
The API has got three methods - fn1
, fn2
, fn3
and fn4
. fn3
and fn4
has got
an api_version
attribute which makes them versioned methods. These methods do not exist
in the base version of the API. Behind the scenes the declaration above creates three
runtime APIs:
MyApiV2
withfn1
andfn2
MyApiV3
withfn1
,fn2
andfn3
.MyApiV4
withfn1
,fn2
,fn3
andfn4
.
Please note that v4
contains all methods from v3
, v3
all methods from v2
and so on.
Back to our example. At the end runtime API is implemented for struct Runtime
with
impl_runtime_apis
macro. api_version
attribute is attached to the impl
block which
means that a version different from the base one is being implemented - in our case this
is v3
.
This version of the API contains three methods so the impl
block has got definitions
for them. Note that fn4
is not implemented as it is not part of this version of the API.
impl_runtime_apis
generates a default implementation for it calling unimplemented!()
.
Hopefully this should be all you need to know in order to use versioned methods in the node.
For more details about how the API versioning works refer to spi_api
documentation here.
How versioned methods are used for ParachainHost
Let’s introduce two types of ParachainHost
API implementation:
- stable - used on stable production networks like Polkadot and Kusama. There is only one stable API at a single point in time.
- staging - methods that are ready for production, but will be released on Rococo first. We can batch together multiple changes and then release all of them to production, by making staging production (bump base version). We can not change or remove any method in staging after a release, as this would break Rococo. It should be ok to keep adding methods to staging across several releases. For experimental methods, you have to keep them on a separate branch until ready.
The stable version of ParachainHost
is indicated by the base version of the API. Any staging
method must use api_version
attribute so that it is assigned to a specific version of a
staging API. This way in a single declaration one can see what’s the stable version of
ParachainHost
and what staging versions/functions are available.
All stable API functions should use primitives from the latest version.
In the time of writing of this document - this is v2
. So for example:
fn validators() -> Vec<v2::ValidatorId>;
indicates a function from the stable v2
API.
All staging API functions should use primitives from vstaging
. They should be clearly
separated from the stable primitives.
Traits
- The API for querying the state of parachains on-chain.