Skip to content

Commit 1cdd5df

Browse files
committed
draft(rpc): add scaffolding for ping RPC and getpeerinfo latency metrics
1 parent 1bd1259 commit 1cdd5df

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
@@ -564,6 +564,17 @@ pub trait Rpc {
564564
#[method(name = "getpeerinfo")]
565565
async fn get_peer_info(&self) -> Result<Vec<PeerInfo>>;
566566

567+
/// Requests that a ping be sent to all other nodes, to measure ping time.
568+
///
569+
/// Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.
570+
/// Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.
571+
///
572+
/// zcashd reference: [`ping`](https://zcash.github.io/rpc/ping.html)
573+
/// method: post
574+
/// tags: network
575+
#[method(name = "ping")]
576+
async fn ping(&self) -> Result<()>;
577+
567578
/// Checks if a zcash transparent address of type P2PKH, P2SH or TEX is valid.
568579
/// Returns information about the given address if valid.
569580
///
@@ -2755,6 +2766,15 @@ where
27552766
.collect())
27562767
}
27572768

2769+
async fn ping(&self) -> Result<()> {
2770+
tracing::debug!("Receiving ping request via RPC");
2771+
2772+
// TODO: Send Message::Ping(nonce) to all connected peers,
2773+
// and track response round-trip time for getpeerinfo's pingtime/pingwait fields.
2774+
2775+
Ok(())
2776+
}
2777+
27582778
async fn validate_address(&self, raw_address: String) -> Result<ValidateAddressResponse> {
27592779
let network = self.network.clone();
27602780

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,6 +2940,8 @@ async fn rpc_addnode() {
29402940
[PeerInfo {
29412941
addr,
29422942
inbound: false,
2943+
pingtime: None,
2944+
pingwait: None,
29432945
}]
29442946
);
29452947

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
@@ -1264,8 +1264,47 @@ fn test_get_peer_info() -> Result<(), Box<dyn std::error::Error>> {
12641264
let inbound1 = obj[1].inbound();
12651265

12661266
let new_obj = vec![
1267-
PeerInfo::new(addr0.into(), inbound0),
1268-
PeerInfo::new(addr1.into(), inbound1),
1267+
PeerInfo::new(addr0.into(), inbound0, None, None),
1268+
PeerInfo::new(addr1.into(), inbound1, None, None),
1269+
];
1270+
assert_eq!(obj, new_obj);
1271+
1272+
Ok(())
1273+
}
1274+
1275+
#[test]
1276+
fn test_get_peer_info_with_ping_values_serialization() -> Result<(), Box<dyn std::error::Error>> {
1277+
let json = r#"
1278+
[
1279+
{
1280+
"addr": "192.168.0.1:8233",
1281+
"inbound": false,
1282+
"pingtime": 123,
1283+
"pingwait": 45
1284+
},
1285+
{
1286+
"addr": "[2000:2000:2000:0000::]:8233",
1287+
"inbound": false,
1288+
"pingtime": 67,
1289+
"pingwait": 89
1290+
}
1291+
]
1292+
"#;
1293+
let obj: GetPeerInfoResponse = serde_json::from_str(json)?;
1294+
1295+
let addr0 = *obj[0].addr().deref();
1296+
let inbound0 = obj[0].inbound();
1297+
let pingtime0 = obj[0].pingtime();
1298+
let pingwait0 = obj[0].pingwait();
1299+
1300+
let addr1 = *obj[1].addr().deref();
1301+
let inbound1 = obj[1].inbound();
1302+
let pingtime1 = obj[1].pingtime();
1303+
let pingwait1 = obj[1].pingwait();
1304+
1305+
let new_obj = vec![
1306+
PeerInfo::new(addr0.into(), inbound0, *pingtime0, *pingwait0),
1307+
PeerInfo::new(addr1.into(), inbound1, *pingtime1, *pingwait1),
12691308
];
12701309
assert_eq!(obj, new_obj);
12711310

0 commit comments

Comments
 (0)