diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 0d586d4806..505d8eb229 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2630,6 +2630,7 @@ dependencies = [ "substrate-extrinsic-pool 0.1.0", "substrate-primitives 0.1.0", "substrate-runtime-primitives 0.1.0", + "substrate-runtime-version 0.1.0", "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/substrate/rpc/Cargo.toml b/substrate/substrate/rpc/Cargo.toml index 9f25736492..b209a3cd4e 100644 --- a/substrate/substrate/rpc/Cargo.toml +++ b/substrate/substrate/rpc/Cargo.toml @@ -16,6 +16,7 @@ substrate-executor = { path = "../executor" } substrate-extrinsic-pool = { path = "../extrinsic-pool" } substrate-primitives = { path = "../primitives" } substrate-runtime-primitives = { path = "../runtime/primitives" } +substrate-runtime-version = { path = "../runtime/version" } substrate-state-machine = { path = "../state-machine" } tokio = "0.1.7" diff --git a/substrate/substrate/rpc/src/chain/mod.rs b/substrate/substrate/rpc/src/chain/mod.rs index 5662a5a0b3..bae10a50c0 100644 --- a/substrate/substrate/rpc/src/chain/mod.rs +++ b/substrate/substrate/rpc/src/chain/mod.rs @@ -21,10 +21,12 @@ use std::sync::Arc; use client::{self, Client, BlockchainEvents}; use jsonrpc_macros::pubsub; use jsonrpc_pubsub::SubscriptionId; +use jsonrpc_macros::Trailing; use rpc::Result as RpcResult; use rpc::futures::{stream, Future, Sink, Stream}; use runtime_primitives::generic::{BlockId, SignedBlock}; use runtime_primitives::traits::Block as BlockT; +use runtime_version::RuntimeVersion; use tokio::runtime::TaskExecutor; use primitives::{KeccakHasher, RlpCodec}; @@ -53,6 +55,10 @@ build_rpc_trait! { #[rpc(name = "chain_getHead")] fn head(&self) -> Result; + /// Get the runtime version. + #[rpc(name = "chain_getRuntimeVersion")] + fn runtime_version(&self, Trailing) -> Result; + #[pubsub(name = "chain_newHead")] { /// New head subscription #[rpc(name = "chain_subscribeNewHead", alias = ["subscribe_newHead", ])] @@ -83,6 +89,19 @@ impl Chain { } } +impl Chain where + Block: BlockT + 'static, + B: client::backend::Backend + Send + Sync + 'static, + E: client::CallExecutor + Send + Sync + 'static, +{ + fn unwrap_or_best(&self, hash: Trailing) -> Result { + Ok(match hash.into() { + None => self.client.info()?.chain.best_hash, + Some(hash) => hash, + }) + } +} + impl ChainApi for Chain where Block: BlockT + 'static, B: client::backend::Backend + Send + Sync + 'static, @@ -102,6 +121,11 @@ impl ChainApi for Cha Ok(self.client.info()?.chain.best_hash) } + fn runtime_version(&self, at: Trailing) -> Result { + let at = self.unwrap_or_best(at)?; + Ok(self.client.runtime_version_at(&BlockId::Hash(at))?) + } + fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber) { self.subscriptions.add(subscriber, |sink| { // send current head right at the start. diff --git a/substrate/substrate/rpc/src/chain/tests.rs b/substrate/substrate/rpc/src/chain/tests.rs index eac9abd5c4..1f32705f80 100644 --- a/substrate/substrate/rpc/src/chain/tests.rs +++ b/substrate/substrate/rpc/src/chain/tests.rs @@ -117,3 +117,25 @@ fn should_notify_about_latest_block() { // no more notifications on this channel assert_eq!(core.block_on(next.into_future()).unwrap().0, None); } + +#[test] +fn should_return_runtime_version() { + let core = ::tokio::runtime::Runtime::new().unwrap(); + let remote = core.executor(); + + let client = Chain { + client: Arc::new(test_client::new()), + subscriptions: Subscriptions::new(remote), + }; + + assert_matches!( + client.runtime_version(None.into()), + Ok(ref ver) if ver == &RuntimeVersion { + spec_name: "test".into(), + impl_name: "parity-test".into(), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + } + ); +} diff --git a/substrate/substrate/rpc/src/lib.rs b/substrate/substrate/rpc/src/lib.rs index 2cd0023bb3..3f76c1b5dd 100644 --- a/substrate/substrate/rpc/src/lib.rs +++ b/substrate/substrate/rpc/src/lib.rs @@ -27,6 +27,7 @@ extern crate substrate_extrinsic_pool as extrinsic_pool; extern crate substrate_primitives as primitives; extern crate substrate_runtime_primitives as runtime_primitives; extern crate substrate_state_machine as state_machine; +extern crate substrate_runtime_version as runtime_version; extern crate tokio; #[macro_use] diff --git a/substrate/substrate/runtime/version/src/lib.rs b/substrate/substrate/runtime/version/src/lib.rs index c4f223f8c3..1dbf4aa2da 100644 --- a/substrate/substrate/runtime/version/src/lib.rs +++ b/substrate/substrate/runtime/version/src/lib.rs @@ -64,7 +64,7 @@ macro_rules! ver_str { /// This triplet have different semantics and mis-interpretation could cause problems. /// In particular: bug fixes should result in an increment of `spec_version` and possibly `authoring_version`, /// absolutely not `impl_version` since they change the semantics of the runtime. -#[derive(Clone, Encode)] +#[derive(Clone, PartialEq, Eq, Encode)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize, Decode))] pub struct RuntimeVersion { /// Identifies the different Substrate runtimes. There'll be at least polkadot and demo.