Make runtime api generate version and identifier information (#1226)

* Make `decl_runtime_apis!` implement `RuntimeApiInfo` for all runtime
apis

* Make the runtime side generate the info constants as well

* Make `RuntimeApiInfo` implementation use the correct generics

* Adds a test for the runtime api info stuff

* Remove duplicated code by using block from `test-client`

* Adds `compile_fail` tests for `api_version`

* Adds documentation for `api_version`

* Make `impl_runtime_apis!` generate `RUNTIME_API_VERSIONS`

* Update documentation and tests for `RUNTIME_API_VERSIONS`

* Implement `has_api` by using the `RuntimeApiInfo`

* Make `impl_runtime_apis` check that trait identifiers are unique

* Prefix all runtime api function with the corresponding trait

So `execute_block` will be called `Core_execute_block`.
This makes it possible to have traits implement a function with the
same name.

* Rebase master

* Update after master rebase
This commit is contained in:
Bastian Köcher
2018-12-10 11:48:07 +01:00
committed by GitHub
parent a4a67ccbe7
commit 1f6719346f
25 changed files with 661 additions and 396 deletions
@@ -2,42 +2,14 @@
extern crate substrate_client;
extern crate sr_primitives as runtime_primitives;
extern crate substrate_primitives as primitives;
#[macro_use]
extern crate parity_codec_derive;
extern crate serde;
extern crate core;
extern crate substrate_test_client as test_client;
use primitives::hash::H256;
use runtime_primitives::traits::{
BlakeTwo256, GetNodeBlockType, Extrinsic as ExtrinsicT, Block as BlockT
};
use runtime_primitives::traits::{GetNodeBlockType, Block as BlockT};
use runtime_primitives::generic::BlockId;
use substrate_client::runtime_api;
use primitives::AuthorityId;
use substrate_client::runtime_api::{self, RuntimeApiInfo};
use substrate_client::error::Result;
// All the stuff we need to declare our `Block`
pub type BlockNumber = u64;
pub type DigestItem = runtime_primitives::generic::DigestItem<H256, u64>;
pub type Digest = runtime_primitives::generic::Digest<DigestItem>;
#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)]
pub struct Extrinsic {}
impl serde::Serialize for Extrinsic {
fn serialize<S>(
&self,
_: S
) -> ::std::result::Result<S::Ok, S::Error> where S: ::serde::Serializer {
unimplemented!()
}
}
impl ExtrinsicT for Extrinsic {
fn is_signed(&self) -> Option<bool> {
unimplemented!()
}
}
pub type Header = runtime_primitives::generic::Header<BlockNumber, BlakeTwo256, DigestItem>;
pub type Block = runtime_primitives::generic::Block<Header, Extrinsic>;
use test_client::runtime::Block;
/// The declaration of the `Runtime` type and the implementation of the `GetNodeBlockType`
/// trait are done by the `construct_runtime!` macro in a real runtime.
@@ -51,6 +23,12 @@ decl_runtime_apis! {
fn test(data: u64);
fn something_with_block(block: Block) -> Block;
fn function_with_two_args(data: u64, block: Block);
fn same_name();
}
#[api_version(2)]
pub trait ApiWithCustomVersion {
fn same_name();
}
}
@@ -67,6 +45,12 @@ impl_runtime_apis! {
fn function_with_two_args(_: u64, _: Block) {
unimplemented!()
}
fn same_name() {}
}
impl self::ApiWithCustomVersion<Block> for Runtime {
fn same_name() {}
}
impl runtime_api::Core<Block> for Runtime {
@@ -91,3 +75,34 @@ fn test_client_side_function_signature() {
let _something_with_block: fn(&RuntimeApi, &BlockId<Block>, &Block) -> Result<Block> =
RuntimeApi::something_with_block;
}
#[test]
fn test_runtime_side_function_signature() {
let _api_same_name: fn(input_data: *mut u8, input_len: usize) -> u64 = api::Api_same_name;
let _api_with_version_same_name: fn(input_data: *mut u8, input_len: usize) -> u64 =
api::ApiWithCustomVersion_same_name;
}
#[test]
fn check_runtime_api_info() {
assert_eq!(&Api::<Block>::ID, &runtime_decl_for_Api::ID);
assert_eq!(Api::<Block>::VERSION, runtime_decl_for_Api::VERSION);
assert_eq!(Api::<Block>::VERSION, 1);
assert_eq!(
ApiWithCustomVersion::<Block>::VERSION, runtime_decl_for_ApiWithCustomVersion::VERSION
);
assert_eq!(&ApiWithCustomVersion::<Block>::ID, &runtime_decl_for_ApiWithCustomVersion::ID);
assert_eq!(ApiWithCustomVersion::<Block>::VERSION, 2);
}
fn check_runtime_api_versions_contains<T: RuntimeApiInfo + ?Sized>() {
assert!(RUNTIME_API_VERSIONS.iter().any(|v| v == &(T::ID, T::VERSION)));
}
#[test]
fn check_runtime_api_versions() {
check_runtime_api_versions_contains::<Api<Block>>();
check_runtime_api_versions_contains::<ApiWithCustomVersion<Block>>();
check_runtime_api_versions_contains::<runtime_api::Core<Block>>();
}