Make API backwards compatible with CC (#1697)

* Rework how a runtime api calls into the runtime

Now we generate a default implementation for each api call that calls
a generated method `method_runtime_api_impl`. This newly generated
method is the one that will be implemented by the `impl_runtime_apis`
macro in the runtime for the client side.

* Support `changed_in` to change runtime api function signatures

* Update documentation

* Fixes tests

* Implement checking the api version with a predicate

* Make the implementation backwards compatible with CC

* Update wasm files after merge

* Check for wasm runtime differences by building master and current branch

* Update spec_version and wasm files

* Fixes

* Revert my changes

* Remove `patch.crates-io` from test-runtime
This commit is contained in:
Bastian Köcher
2019-02-06 11:47:47 +01:00
committed by Gav Wood
parent 1ba7e35c18
commit 190393d476
25 changed files with 731 additions and 224 deletions
+43 -1
View File
@@ -16,13 +16,50 @@
//! The runtime api for building blocks.
use runtime_primitives::{traits::Block as BlockT, ApplyResult};
use runtime_primitives::{traits::Block as BlockT, ApplyResult, RuntimeString};
use rstd::vec::Vec;
use sr_api_macros::decl_runtime_apis;
pub use inherents::{InherentData, CheckInherentsResult};
use parity_codec_derive::{Encode, Decode};
/// The old representation of the inherent data.
#[doc(hide)]
#[derive(Encode, Decode)]
pub struct OldInherentData {
/// Current timestamp.
pub timestamp: u64,
/// Blank report.
pub consensus: (),
/// Aura expected slot. Can take any value during block construction.
pub aura_expected_slot: u64,
}
impl OldInherentData {
/// Create a new `BasicInherentData` instance.
pub fn new(timestamp: u64, expected_slot: u64) -> Self {
Self {
timestamp,
consensus: (),
aura_expected_slot: expected_slot,
}
}
}
/// Error type used while checking inherents.
#[doc(hide)]
#[derive(Encode, PartialEq)]
#[cfg_attr(feature = "std", derive(Decode))]
pub enum OldCheckInherentError {
/// The inherents are generally valid but a delay until the given timestamp
/// is required.
ValidAtTimestamp(u64),
/// Some other error has occurred.
Other(RuntimeString),
}
decl_runtime_apis! {
/// The `BlockBuilder` api trait that provides required functions for building a block for a runtime.
#[api_version(2)]
pub trait BlockBuilder {
/// Apply the given extrinsics.
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult;
@@ -32,6 +69,11 @@ decl_runtime_apis! {
fn inherent_extrinsics(inherent: InherentData) -> Vec<<Block as BlockT>::Extrinsic>;
/// Check that the inherents are valid. The inherent data will vary from chain to chain.
fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult;
/// Check that the inherents are valid. The inherent data will vary from chain to chain.
///
/// Old version that is used by the CC network.
#[changed_in(2)]
fn check_inherents(block: Block, data: OldInherentData) -> ::std::result::Result<(), OldCheckInherentError>;
/// Generate a random seed.
fn random_seed() -> <Block as BlockT>::Hash;
}
+1 -12
View File
@@ -1426,7 +1426,7 @@ pub(crate) mod tests {
use runtime_primitives::generic::DigestItem;
use test_client::{self, TestClient};
use consensus::BlockOrigin;
use test_client::client::{backend::Backend as TestBackend, runtime_api::ApiExt};
use test_client::client::backend::Backend as TestBackend;
use test_client::BlockBuilderExt;
use test_client::runtime::{self, Block, Transfer, RuntimeApi, TestAPI};
@@ -1523,17 +1523,6 @@ pub(crate) mod tests {
);
}
#[test]
fn runtime_api_has_test_api() {
let client = test_client::new();
assert!(
client.runtime_api().has_api::<TestAPI<Block>>(
&BlockId::Number(client.info().unwrap().chain.best_number),
).unwrap()
);
}
#[test]
fn authorities_call_works() {
let client = test_client::new();
+2
View File
@@ -20,6 +20,8 @@
#![warn(missing_docs)]
#![recursion_limit="128"]
extern crate parity_codec as codec;
#[macro_use]
pub mod runtime_api;
#[cfg(feature = "std")]
+15 -1
View File
@@ -69,7 +69,21 @@ pub trait ApiExt<Block: BlockT> {
fn has_api<A: RuntimeApiInfo + ?Sized>(
&self,
at: &BlockId<Block>
) -> error::Result<bool> where Self: Sized;
) -> error::Result<bool> where Self: Sized {
self.runtime_version_at(at).map(|v| v.has_api::<A>())
}
/// Check if the given api is implemented and the version passes a predicate.
fn has_api_with<A: RuntimeApiInfo + ?Sized, P: Fn(u32) -> bool>(
&self,
at: &BlockId<Block>,
pred: P,
) -> error::Result<bool> where Self: Sized {
self.runtime_version_at(at).map(|v| v.has_api_with::<A, _>(pred))
}
/// Returns the runtime version at the given block id.
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion>;
}
/// Something that can call into the runtime at a given block.