Add an system_syncState RPC method (#7315)

* Add system_syncState RPC method

* Update client/rpc-api/src/system/helpers.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Pierre Krieger
2020-10-13 17:53:49 +02:00
committed by GitHub
parent e4cb862123
commit bcde7b4f3f
6 changed files with 83 additions and 5 deletions
@@ -86,6 +86,18 @@ pub enum NodeRole {
Sentry,
}
/// The state of the syncing of the node.
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncState<Number> {
/// Height of the block at which syncing started.
pub starting_block: Number,
/// Height of the current best block of the node.
pub current_block: Number,
/// Height of the highest block learned from the network. Missing if no block is known yet.
#[serde(default = "Default::default", skip_serializing_if = "Option::is_none")]
pub highest_block: Option<Number>,
}
#[cfg(test)]
mod tests {
use super::*;
@@ -114,4 +126,25 @@ mod tests {
r#"{"peerId":"2","roles":"a","bestHash":5,"bestNumber":6}"#,
);
}
#[test]
fn should_serialize_sync_state() {
assert_eq!(
::serde_json::to_string(&SyncState {
starting_block: 12u32,
current_block: 50u32,
highest_block: Some(128u32),
}).unwrap(),
r#"{"startingBlock":12,"currentBlock":50,"highestBlock":128}"#,
);
assert_eq!(
::serde_json::to_string(&SyncState {
starting_block: 12u32,
current_block: 50u32,
highest_block: None,
}).unwrap(),
r#"{"startingBlock":12,"currentBlock":50}"#,
);
}
}
+6 -1
View File
@@ -27,7 +27,7 @@ use futures::{future::BoxFuture, compat::Compat};
use self::error::Result as SystemResult;
pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole};
pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole, SyncState};
pub use self::gen_client::Client as SystemClient;
/// Substrate system RPC API
@@ -103,4 +103,9 @@ pub trait SystemApi<Hash, Number> {
/// Returns the roles the node is running as.
#[rpc(name = "system_nodeRoles", returns = "Vec<NodeRole>")]
fn system_node_roles(&self) -> Receiver<Vec<NodeRole>>;
/// Returns the state of the syncing of the node: starting block, current best block, highest
/// known block.
#[rpc(name = "system_syncState", returns = "SyncState<Number>")]
fn system_sync_state(&self) -> Receiver<SyncState<Number>>;
}
+1
View File
@@ -44,6 +44,7 @@ lazy_static = { version = "1.4.0", optional = true }
[dev-dependencies]
assert_matches = "1.3.0"
futures01 = { package = "futures", version = "0.1.29" }
lazy_static = "1.4.0"
sc-network = { version = "0.8.0", path = "../network" }
sp-io = { version = "2.0.0", path = "../../primitives/io" }
substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" }
+10 -2
View File
@@ -30,7 +30,7 @@ use sp_runtime::traits::{self, Header as HeaderT};
use self::error::Result;
pub use sc_rpc_api::system::*;
pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole};
pub use self::helpers::{SystemInfo, Health, PeerInfo, NodeRole, SyncState};
pub use self::gen_client::Client as SystemClient;
macro_rules! bail_if_unsafe {
@@ -66,7 +66,9 @@ pub enum Request<B: traits::Block> {
/// Must return any potential parse error.
NetworkRemoveReservedPeer(String, oneshot::Sender<Result<()>>),
/// Must return the node role.
NodeRoles(oneshot::Sender<Vec<NodeRole>>)
NodeRoles(oneshot::Sender<Vec<NodeRole>>),
/// Must return the state of the node syncing.
SyncState(oneshot::Sender<SyncState<<B::Header as HeaderT>::Number>>),
}
impl<B: traits::Block> System<B> {
@@ -189,4 +191,10 @@ impl<B: traits::Block> SystemApi<B::Hash, <B::Header as HeaderT>::Number> for Sy
let _ = self.send_back.unbounded_send(Request::NodeRoles(tx));
Receiver(Compat::new(rx))
}
fn system_sync_state(&self) -> Receiver<SyncState<<B::Header as HeaderT>::Number>> {
let (tx, rx) = oneshot::channel();
let _ = self.send_back.unbounded_send(Request::SyncState(tx));
Receiver(Compat::new(rx))
}
}
+19
View File
@@ -104,6 +104,13 @@ fn api<T: Into<Option<Status>>>(sync: T) -> System<Block> {
Request::NodeRoles(sender) => {
let _ = sender.send(vec![NodeRole::Authority]);
}
Request::SyncState(sender) => {
let _ = sender.send(SyncState {
starting_block: 1,
current_block: 2,
highest_block: Some(3),
});
}
};
future::ready(())
@@ -291,6 +298,18 @@ fn system_node_roles() {
);
}
#[test]
fn system_sync_state() {
assert_eq!(
wait_receiver(api(None).system_sync_state()),
SyncState {
starting_block: 1,
current_block: 2,
highest_block: Some(3),
}
);
}
#[test]
fn system_network_add_reserved() {
let good_peer_id = "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV";
+14 -2
View File
@@ -80,7 +80,7 @@ pub use sc_tracing::TracingReceiver;
pub use task_manager::SpawnTaskHandle;
pub use task_manager::TaskManager;
pub use sp_consensus::import_queue::ImportQueue;
use sc_client_api::BlockchainEvents;
use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents};
const DEFAULT_PROTOCOL_ID: &str = "sup";
@@ -199,7 +199,7 @@ pub struct PartialComponents<Client, Backend, SelectChain, ImportQueue, Transact
/// The `status_sink` contain a list of senders to send a periodic network status to.
async fn build_network_future<
B: BlockT,
C: BlockchainEvents<B>,
C: BlockchainEvents<B> + HeaderBackend<B>,
H: sc_network::ExHashT
> (
role: Role,
@@ -212,6 +212,9 @@ async fn build_network_future<
) {
let mut imported_blocks_stream = client.import_notification_stream().fuse();
// Current best block at initialization, to report to the RPC layer.
let starting_block = client.info().best_number;
// Stream of finalized blocks reported by the client.
let mut finality_notification_stream = {
let mut finality_notification_stream = client.finality_notification_stream().fuse();
@@ -323,6 +326,15 @@ async fn build_network_future<
let _ = sender.send(vec![node_role]);
}
sc_rpc::system::Request::SyncState(sender) => {
use sc_rpc::system::SyncState;
let _ = sender.send(SyncState {
starting_block: starting_block,
current_block: client.info().best_number,
highest_block: network.best_seen_block(),
});
}
}
}