diff --git a/substrate/core/rpc/api/src/system/helpers.rs b/substrate/core/rpc/api/src/system/helpers.rs index 00e2ba9f40..10319d57b6 100644 --- a/substrate/core/rpc/api/src/system/helpers.rs +++ b/substrate/core/rpc/api/src/system/helpers.rs @@ -50,6 +50,14 @@ pub struct Health { pub should_have_peers: bool, } +impl fmt::Display for Health { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { + "syncing" + } else { "idle" }) + } +} + /// Network Peer information #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -66,12 +74,17 @@ pub struct PeerInfo { pub best_number: Number, } -impl fmt::Display for Health { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{} peers ({})", self.peers, if self.is_syncing { - "syncing" - } else { "idle" }) - } +/// The role the node is running as +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum NodeRole { + /// The node is a full node + Full, + /// The node is a light client + LightClient, + /// The node is an authority + Authority, + /// An unknown role with a bit number + UnknownRole(u8) } #[cfg(test)] diff --git a/substrate/core/rpc/api/src/system/mod.rs b/substrate/core/rpc/api/src/system/mod.rs index b5eacc5d61..f59fd84c7c 100644 --- a/substrate/core/rpc/api/src/system/mod.rs +++ b/substrate/core/rpc/api/src/system/mod.rs @@ -24,7 +24,7 @@ use jsonrpc_derive::rpc; use self::error::Result; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo}; +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; /// Substrate system RPC API @@ -64,4 +64,8 @@ pub trait SystemApi { // TODO: make this stable and move structs https://github.com/paritytech/substrate/issues/1890 #[rpc(name = "system_networkState", returns = "jsonrpc_core::Value")] fn system_network_state(&self) -> Receiver; + + /// Returns the roles the node is running as. + #[rpc(name = "system_nodeRoles", returns = "Vec")] + fn system_node_roles(&self) -> Receiver>; } diff --git a/substrate/core/rpc/src/system/mod.rs b/substrate/core/rpc/src/system/mod.rs index 8eeff6758b..8907151d9a 100644 --- a/substrate/core/rpc/src/system/mod.rs +++ b/substrate/core/rpc/src/system/mod.rs @@ -25,7 +25,7 @@ use sr_primitives::traits::{self, Header as HeaderT}; use self::error::Result; pub use api::system::*; -pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo}; +pub use self::helpers::{Properties, SystemInfo, Health, PeerInfo, NodeRole}; pub use self::gen_client::Client as SystemClient; /// System API implementation @@ -42,6 +42,8 @@ pub enum Request { Peers(oneshot::Sender::Number>>>), /// Must return the state of the network. NetworkState(oneshot::Sender), + /// Must return the node role. + NodeRoles(oneshot::Sender>) } impl System { @@ -94,4 +96,10 @@ impl SystemApi::Number> for Sy let _ = self.send_back.unbounded_send(Request::NetworkState(tx)); Receiver(Compat::new(rx)) } + + fn system_node_roles(&self) -> Receiver> { + let (tx, rx) = oneshot::channel(); + let _ = self.send_back.unbounded_send(Request::NodeRoles(tx)); + Receiver(Compat::new(rx)) + } } diff --git a/substrate/core/rpc/src/system/tests.rs b/substrate/core/rpc/src/system/tests.rs index 5b271af9ac..1c532be372 100644 --- a/substrate/core/rpc/src/system/tests.rs +++ b/substrate/core/rpc/src/system/tests.rs @@ -79,6 +79,9 @@ fn api>>(sync: T) -> System { average_upload_per_sec: 0, peerset: serde_json::Value::Null, }).unwrap()); + }, + Request::NodeRoles(sender) => { + let _ = sender.send(vec![NodeRole::Authority]); } }; @@ -221,3 +224,11 @@ fn system_network_state() { } ); } + +#[test] +fn system_node_roles() { + assert_eq!( + wait_receiver(api(None).system_node_roles()), + vec![NodeRole::Authority] + ); +} \ No newline at end of file diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index fccf04d8a1..5dd9ea8270 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -368,6 +368,7 @@ macro_rules! new_impl { let _ = to_spawn_tx.unbounded_send(Box::new(build_network_future( + $config.roles, network_mut, client.clone(), network_status_sinks.clone(), @@ -662,6 +663,7 @@ fn build_network_future< S: network::specialization::NetworkSpecialization, H: network::ExHashT > ( + roles: Roles, mut network: network::NetworkWorker, client: Arc, status_sinks: Arc, NetworkState)>>>>, @@ -669,7 +671,7 @@ fn build_network_future< should_have_peers: bool, dht_event_tx: Option>, ) -> impl Future { - // Compatibility shim while we're transitionning to stable Futures. + // Compatibility shim while we're transitioning to stable Futures. // See https://github.com/paritytech/substrate/issues/3099 let mut rpc_rx = futures03::compat::Compat::new(rpc_rx.map(|v| Ok::<_, ()>(v))); @@ -725,6 +727,21 @@ fn build_network_future< let _ = sender.send(network_state); } } + rpc::system::Request::NodeRoles(sender) => { + use rpc::system::NodeRole; + + let node_roles = (0 .. 8) + .filter(|&bit_number| (roles.bits() >> bit_number) & 1 == 1) + .map(|bit_number| match Roles::from_bits(1 << bit_number) { + Some(Roles::AUTHORITY) => NodeRole::Authority, + Some(Roles::LIGHT) => NodeRole::LightClient, + Some(Roles::FULL) => NodeRole::Full, + _ => NodeRole::UnknownRole(bit_number), + }) + .collect(); + + let _ = sender.send(node_roles); + } }; }