Skip to content

Commit 9edf94c

Browse files
committed
draft(rpc): add scaffolding for ping RPC and getpeerinfo latency metrics
1 parent 7479fa9 commit 9edf94c

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

zebra-rpc/src/methods.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,17 @@ pub trait Rpc {
544544
#[method(name = "getpeerinfo")]
545545
async fn get_peer_info(&self) -> Result<Vec<PeerInfo>>;
546546

547+
/// Requests that a ping be sent to all other nodes, to measure ping time.
548+
///
549+
/// Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.
550+
/// Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.
551+
///
552+
/// zcashd reference: [`ping`](https://zcash.github.io/rpc/ping.html)
553+
/// method: post
554+
/// tags: network
555+
#[method(name = "ping")]
556+
async fn ping(&self) -> Result<()>;
557+
547558
/// Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.
548559
/// Returns information about the given address if valid.
549560
///
@@ -2645,6 +2656,15 @@ where
26452656
.collect())
26462657
}
26472658

2659+
async fn ping(&self) -> Result<()> {
2660+
tracing::debug!("Receiving ping request via RPC");
2661+
2662+
// TODO: Send Message::Ping(nonce) to all connected peers,
2663+
// and track response round-trip time for getpeerinfo's pingtime/pingwait fields.
2664+
2665+
Ok(())
2666+
}
2667+
26482668
async fn validate_address(&self, raw_address: String) -> Result<ValidateAddressResponse> {
26492669
let network = self.network.clone();
26502670

zebra-rpc/src/methods/tests/vectors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,6 +2895,8 @@ async fn rpc_addnode() {
28952895
[PeerInfo {
28962896
addr,
28972897
inbound: false,
2898+
pingtime: None,
2899+
pingwait: None,
28982900
}]
28992901
);
29002902

zebra-rpc/src/methods/types/peer_info.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,22 @@ use derive_new::new;
55
use zebra_network::{types::MetaAddr, PeerSocketAddr};
66

77
/// Item of the `getpeerinfo` response
8-
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Getters, new)]
8+
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Getters, new)]
99
pub struct PeerInfo {
1010
/// The IP address and port of the peer
1111
#[getter(copy)]
1212
pub(crate) addr: PeerSocketAddr,
1313

1414
/// Inbound (true) or Outbound (false)
1515
pub(crate) inbound: bool,
16+
17+
/// The round-trip ping time in seconds.
18+
#[serde(skip_serializing_if = "Option::is_none")]
19+
pub(crate) pingtime: Option<f64>,
20+
21+
/// The wait time on a ping response in seconds.
22+
#[serde(skip_serializing_if = "Option::is_none")]
23+
pub(crate) pingwait: Option<f64>,
1624
}
1725

1826
/// Response type for the `getpeerinfo` RPC method.
@@ -23,6 +31,9 @@ impl From<MetaAddr> for PeerInfo {
2331
Self {
2432
addr: meta_addr.addr(),
2533
inbound: meta_addr.is_inbound(),
34+
// TODO: Fill in pingtime and pingwait once live ping tracking is implemented.
35+
pingtime: None,
36+
pingwait: None,
2637
}
2738
}
2839
}
@@ -32,6 +43,8 @@ impl Default for PeerInfo {
3243
Self {
3344
addr: PeerSocketAddr::unspecified(),
3445
inbound: false,
46+
pingtime: None,
47+
pingwait: None,
3548
}
3649
}
3750
}

zebra-rpc/tests/serialization_tests.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,47 @@ fn test_get_peer_info() -> Result<(), Box<dyn std::error::Error>> {
11331133
let inbound1 = obj[1].inbound();
11341134

11351135
let new_obj = vec![
1136-
PeerInfo::new(addr0.into(), inbound0),
1137-
PeerInfo::new(addr1.into(), inbound1),
1136+
PeerInfo::new(addr0.into(), inbound0, None, None),
1137+
PeerInfo::new(addr1.into(), inbound1, None, None),
1138+
];
1139+
assert_eq!(obj, new_obj);
1140+
1141+
Ok(())
1142+
}
1143+
1144+
#[test]
1145+
fn test_get_peer_info_with_ping_values_serialization() -> Result<(), Box<dyn std::error::Error>> {
1146+
let json = r#"
1147+
[
1148+
{
1149+
"addr": "192.168.0.1:8233",
1150+
"inbound": false,
1151+
"pingtime": 123,
1152+
"pingwait": 45
1153+
},
1154+
{
1155+
"addr": "[2000:2000:2000:0000::]:8233",
1156+
"inbound": false,
1157+
"pingtime": 67,
1158+
"pingwait": 89
1159+
}
1160+
]
1161+
"#;
1162+
let obj: GetPeerInfoResponse = serde_json::from_str(json)?;
1163+
1164+
let addr0 = *obj[0].addr().deref();
1165+
let inbound0 = obj[0].inbound();
1166+
let pingtime0 = obj[0].pingtime();
1167+
let pingwait0 = obj[0].pingwait();
1168+
1169+
let addr1 = *obj[1].addr().deref();
1170+
let inbound1 = obj[1].inbound();
1171+
let pingtime1 = obj[1].pingtime();
1172+
let pingwait1 = obj[1].pingwait();
1173+
1174+
let new_obj = vec![
1175+
PeerInfo::new(addr0.into(), inbound0, *pingtime0, *pingwait0),
1176+
PeerInfo::new(addr1.into(), inbound1, *pingtime1, *pingwait1),
11381177
];
11391178
assert_eq!(obj, new_obj);
11401179

0 commit comments

Comments
 (0)