Skip to content
This repository was archived by the owner on Nov 26, 2024. It is now read-only.

Commit 1c8433c

Browse files
committed
v17: Finish network section
Finish implementing all JSON types for stuff under the network section. Includes various cleanups and testing.
1 parent 9346904 commit 1c8433c

File tree

9 files changed

+172
-38
lines changed

9 files changed

+172
-38
lines changed

client/src/client_sync/v17/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ crate::impl_client_v17__generatetoaddress!();
4646
crate::impl_client_v17__generate!();
4747

4848
// == Network ==
49+
crate::impl_client_v17__getaddednodeinfo!();
4950
crate::impl_client_v17__getnettotals!();
5051
crate::impl_client_v17__getnetworkinfo!();
5152
crate::impl_client_v17__getpeerinfo!();

client/src/client_sync/v17/network.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99
//!
1010
//! See, or use the `define_jsonrpc_minreq_client!` macro to define a `Client`.
1111
12+
/// Implements bitcoind JSON-RPC API method `getaddednodeinfo`
13+
#[macro_export]
14+
macro_rules! impl_client_v17__getaddednodeinfo {
15+
() => {
16+
impl Client {
17+
pub fn get_added_node_info(&self) -> Result<GetAddedNodeInfo> {
18+
self.call("getaddednodeinfo", &[])
19+
}
20+
}
21+
};
22+
}
23+
1224
/// Implements bitcoind JSON-RPC API method `getnettotals`
1325
#[macro_export]
1426
macro_rules! impl_client_v17__getnettotals {

integration_test/src/v17/network.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@
55
//! Specifically this is methods found under the `== Network ==` section of the
66
//! API docs of `bitcoind v0.17.1`.
77
8+
/// Requires `Client` to be in scope and to implement `get_network_info`.
9+
#[macro_export]
10+
macro_rules! impl_test_v17__getaddednodeinfo {
11+
() => {
12+
#[test]
13+
fn get_added_node_info() {
14+
let bitcoind = $crate::bitcoind_no_wallet();
15+
let _ = bitcoind.client.get_added_node_info().expect("getaddednodeinfo");
16+
}
17+
};
18+
}
19+
820
/// Requires `Client` to be in scope and to implement `get_network_info`.
921
#[macro_export]
1022
macro_rules! impl_test_v17__getnettotals {
@@ -17,15 +29,18 @@ macro_rules! impl_test_v17__getnettotals {
1729
};
1830
}
1931

20-
/// Requires `Client` to be in scope and to implement `get_network_info`.
32+
/// Requires `Client` to be in scope and to implement `get_network_info` and
33+
/// `check_expected_server_version`.
2134
#[macro_export]
2235
macro_rules! impl_test_v17__getnetworkinfo {
2336
() => {
2437
#[test]
2538
fn get_network_info() {
2639
let bitcoind = $crate::bitcoind_no_wallet();
27-
let _ = bitcoind.client.get_network_info().expect("getnetworkinfo");
40+
let json = bitcoind.client.get_network_info().expect("getnetworkinfo");
41+
assert!(json.into_model().is_ok());
2842

43+
// Server version is returned as part of the getnetworkinfo method.
2944
bitcoind.client.check_expected_server_version().expect("unexpected version");
3045
}
3146
};

integration_test/tests/v17_api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ mod generating {
4343
mod network {
4444
use super::*;
4545

46+
impl_test_v17__getaddednodeinfo!();
4647
impl_test_v17__getnettotals!();
4748
impl_test_v17__getnetworkinfo!();
4849
impl_test_v17__getpeerinfo!();

json/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,17 @@ pub mod v27;
2222

2323
// JSON types that model _all_ `bitcoind` versions.
2424
pub mod model;
25+
26+
use bitcoin::amount::ParseAmountError;
27+
use bitcoin::{Amount, FeeRate};
28+
29+
/// Converts `fee_rate` in BTC/kB to `FeeRate`.
30+
fn btc_per_kb(btc_per_kb: f64) -> Result<Option<FeeRate>, ParseAmountError> {
31+
let btc_per_byte = btc_per_kb / 1000 as f64;
32+
let sats_per_byte = Amount::from_btc(btc_per_byte)?;
33+
34+
// Virtual bytes equal bytes before segwit.
35+
let rate = FeeRate::from_sat_per_vb(sats_per_byte.to_sat());
36+
37+
Ok(rate)
38+
}

json/src/model/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod blockchain;
1212
mod control;
1313
mod generating;
1414
mod mining;
15+
mod network;
1516
mod raw_transactions;
1617
mod util;
1718
mod wallet;
@@ -32,6 +33,7 @@ pub use self::{
3233
GetMempoolAncestorsVerbose, GetTxOut, Softfork, SoftforkType,
3334
},
3435
generating::{Generate, GenerateToAddress},
36+
network::{GetNetworkInfo, GetNetworkInfoAddress, GetNetworkInfoNetwork},
3537
raw_transactions::SendRawTransaction,
3638
wallet::{
3739
CreateWallet, GetBalance, GetBalances, GetBalancesMine, GetBalancesWatchOnly,

json/src/model/network.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,20 @@ pub struct GetNetworkInfo {
1919
pub protocol_version: usize,
2020
/// The services we offer to the network (hex string).
2121
pub local_services: String,
22-
/// The services we offer to the network, in human-readable form.
23-
pub local_services_names: Vec<String>,
2422
/// `true` if transaction relay is requested from peers.
2523
pub local_relay: bool,
2624
/// The time offset.
2725
pub time_offset: isize,
2826
/// The total number of connections.
2927
pub connections: usize,
30-
/// The number of inbound connections.
31-
pub connections_in: usize,
32-
/// The number of outbound connections.
33-
pub connections_out: usize,
3428
/// Whether p2p networking is enabled.
3529
pub network_active: bool,
3630
/// Information per network.
3731
pub networks: Vec<GetNetworkInfoNetwork>,
3832
/// Minimum relay fee rate for transactions.
39-
pub relay_fee: FeeRate,
33+
pub relay_fee: Option<FeeRate>, // `Some` if parsing succeeds.
4034
/// Minimum fee rate increment for mempool limiting or replacement.
41-
pub incremental_fee: FeeRate,
35+
pub incremental_fee: Option<FeeRate>, // `Some` if parsing succeeds.
4236
/// List of local addresses.
4337
pub local_addresses: Vec<GetNetworkInfoAddress>,
4438
/// Any network and blockchain warnings.

json/src/v17/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
//! Key:
1111
//! - `[ ]` means not yet done.
1212
//! - `[x]` means implemented _and_ tested.
13-
//! - `[-]` means intentionally not done, typically because method does not return anything or is deprecated.
13+
//! - `[-]` means intentionally not done, typically because method does not return anything, returns
14+
//! a single integer, anything or is deprecated.
1415
//!
1516
//! **== Blockchain ==**
1617
//! - [x] `getbestblockhash`
@@ -60,7 +61,7 @@
6061
//! - [-] `addnode "node" "add|remove|onetry"`
6162
//! - [-] `clearbanned`
6263
//! - [-] `disconnectnode "[address]" [nodeid]`
63-
//! - [ ] `getaddednodeinfo ( "node" )`
64+
//! - [x] `getaddednodeinfo ( "node" )`
6465
//! - [-] `getconnectioncount`
6566
//! - [x] `getnettotals`
6667
//! - [x] `getnetworkinfo`
@@ -180,8 +181,9 @@ pub use self::{
180181
control::{GetMemoryInfoStats, Locked, Logging, Uptime},
181182
generating::{Generate, GenerateToAddress},
182183
network::{
183-
AddedNodeAddress, BytesPerMessage, GetAddedNodeInfo, GetNetTotals, GetNetworkInfo,
184-
GetNetworkInfoAddress, GetNetworkInfoNetwork, GetPeerInfo, PeerInfo, UploadTarget,
184+
AddedNode, AddedNodeAddress, Banned, GetAddedNodeInfo, GetNetTotals, GetNetworkInfo,
185+
GetNetworkInfoAddress, GetNetworkInfoNetwork, GetPeerInfo, ListBanned, PeerInfo,
186+
UploadTarget,
185187
},
186188
raw_transactions::SendRawTransaction,
187189
wallet::{

json/src/v17/network.rs

Lines changed: 117 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66
//!
77
/// These types do not implement `into_model` because apart from fee rate there is no additional
88
/// `rust-bitcoin` types needed.
9+
use core::fmt;
10+
use std::collections::BTreeMap;
11+
12+
use bitcoin::amount::ParseAmountError;
13+
use internals::write_err;
914
use serde::{Deserialize, Serialize};
1015

16+
use crate::model;
17+
1118
/// Result of JSON-RPC method `getaddednodeinfo`.
1219
///
1320
/// > getaddednodeinfo ( "node" )
@@ -18,17 +25,17 @@ use serde::{Deserialize, Serialize};
1825
/// > Arguments:
1926
/// > 1. "node" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.
2027
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
21-
pub struct GetAddedNodeInfo(Vec<AddedNode>);
28+
pub struct GetAddedNodeInfo(pub Vec<AddedNode>);
2229

2330
/// An item from the list returned by the JSON-RPC method `getaddednodeinfo`.
2431
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
2532
pub struct AddedNode {
26-
/// The node IP address or name (as provided to addnode)
33+
/// The node IP address or name (as provided to addnode).
2734
#[serde(rename = "addednode")]
2835
pub added_node: String,
29-
/// If connected
36+
/// If connected.
3037
pub connected: bool,
31-
/// Only when connected = true
38+
/// Only when connected = true.
3239
pub addresses: Vec<AddedNodeAddress>,
3340
}
3441

@@ -37,7 +44,7 @@ pub struct AddedNode {
3744
pub struct AddedNodeAddress {
3845
/// The bitcoin server IP and port we're connected to.
3946
pub address: String,
40-
/// connection, inbound or outbound
47+
/// Connection, inbound or outbound.
4148
pub connected: String,
4249
}
4350

@@ -105,8 +112,8 @@ pub struct GetNetworkInfo {
105112
pub time_offset: isize,
106113
/// The total number of connections.
107114
pub connections: usize,
108-
#[serde(rename = "networkactive")]
109115
/// Whether p2p networking is enabled.
116+
#[serde(rename = "networkactive")]
110117
pub network_active: bool,
111118
/// Information per network.
112119
pub networks: Vec<GetNetworkInfoNetwork>,
@@ -141,14 +148,92 @@ pub struct GetNetworkInfoNetwork {
141148
/// Part of the result of the JSON-RPC method `getnetworkinfo` (local address info).
142149
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
143150
pub struct GetNetworkInfoAddress {
144-
/// Network address
151+
/// Network address.
145152
pub address: String,
146-
/// Network port
153+
/// Network port.
147154
pub port: u16,
148-
/// Relative score
155+
/// Relative score.
149156
pub score: u32,
150157
}
151158

159+
impl GetNetworkInfo {
160+
/// Converts version specific type to a version in-specific, more strongly typed type.
161+
pub fn into_model(self) -> Result<model::GetNetworkInfo, GetNetworkInfoError> {
162+
use GetNetworkInfoError as E;
163+
164+
let relay_fee = crate::btc_per_kb(self.relay_fee).map_err(E::RelayFee)?;
165+
let incremental_fee = crate::btc_per_kb(self.incremental_fee).map_err(E::IncrementalFee)?;
166+
167+
Ok(model::GetNetworkInfo {
168+
version: self.version,
169+
subversion: self.subversion,
170+
protocol_version: self.protocol_version,
171+
local_services: self.local_services,
172+
local_relay: self.local_relay,
173+
time_offset: self.time_offset,
174+
connections: self.connections,
175+
network_active: self.network_active,
176+
networks: self.networks.into_iter().map(|n| n.into_model()).collect(),
177+
relay_fee,
178+
incremental_fee,
179+
local_addresses: self.local_addresses.into_iter().map(|a| a.into_model()).collect(),
180+
warnings: self.warnings,
181+
})
182+
}
183+
}
184+
185+
/// Error when converting a `GetTransaction` type into the model type.
186+
#[derive(Debug)]
187+
pub enum GetNetworkInfoError {
188+
/// Conversion of the `relay_fee` field failed.
189+
RelayFee(ParseAmountError),
190+
/// Conversion of the `incremental_fee` field failed.
191+
IncrementalFee(ParseAmountError),
192+
}
193+
194+
impl fmt::Display for GetNetworkInfoError {
195+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196+
use GetNetworkInfoError as E;
197+
198+
match *self {
199+
E::RelayFee(ref e) => write_err!(f, "conversion of the `relay_fee` field failed"; e),
200+
E::IncrementalFee(ref e) =>
201+
write_err!(f, "conversion of the `incremental_fee` field failed"; e),
202+
}
203+
}
204+
}
205+
206+
impl std::error::Error for GetNetworkInfoError {
207+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
208+
use GetNetworkInfoError as E;
209+
210+
match *self {
211+
E::RelayFee(ref e) => Some(e),
212+
E::IncrementalFee(ref e) => Some(e),
213+
}
214+
}
215+
}
216+
217+
impl GetNetworkInfoNetwork {
218+
/// Converts version specific type to a version in-specific, more strongly typed type.
219+
pub fn into_model(self) -> model::GetNetworkInfoNetwork {
220+
model::GetNetworkInfoNetwork {
221+
name: self.name,
222+
limited: self.limited,
223+
reachable: self.reachable,
224+
proxy: self.proxy,
225+
proxy_randomize_credentials: self.proxy_randomize_credentials,
226+
}
227+
}
228+
}
229+
230+
impl GetNetworkInfoAddress {
231+
/// Converts version specific type to a version in-specific, more strongly typed type.
232+
pub fn into_model(self) -> model::GetNetworkInfoAddress {
233+
model::GetNetworkInfoAddress { address: self.address, port: self.port, score: self.score }
234+
}
235+
}
236+
152237
/// Result of JSON-RPC method `getpeerinfo`.
153238
///
154239
/// > getpeerinfo
@@ -160,7 +245,7 @@ pub struct GetPeerInfo(pub Vec<PeerInfo>);
160245
/// An item from the list returned by the JSON-RPC method `getpeerinfo`.
161246
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
162247
pub struct PeerInfo {
163-
/// Peer index
248+
/// Peer index.
164249
pub id: u32,
165250
/// The IP address and port of the peer ("host:port").
166251
#[serde(rename = "addr")]
@@ -176,22 +261,22 @@ pub struct PeerInfo {
176261
/// Whether peer has asked us to relay transactions to it.
177262
#[serde(rename = "relaytxes")]
178263
pub relay_transactions: bool,
179-
/// The time in seconds since epoch (Jan 1 1970 GMT) of the last send
264+
/// The time in seconds since epoch (Jan 1 1970 GMT) of the last send.
180265
#[serde(rename = "lastsend")]
181266
pub last_send: u32,
182-
/// The time in seconds since epoch (Jan 1 1970 GMT) of the last receive
267+
/// The time in seconds since epoch (Jan 1 1970 GMT) of the last receive.
183268
#[serde(rename = "lastrecv")]
184269
pub last_received: u32,
185-
/// The total bytes sent
270+
/// The total bytes sent.
186271
#[serde(rename = "bytessent")]
187272
pub bytes_sent: u64,
188-
/// The total bytes received
273+
/// The total bytes received.
189274
#[serde(rename = "bytesrecv")]
190275
pub bytes_received: u64,
191-
/// The connection time in seconds since epoch (Jan 1 1970 GMT)
276+
/// The connection time in seconds since epoch (Jan 1 1970 GMT).
192277
#[serde(rename = "conntime")]
193278
pub connection_time: u32,
194-
/// The time offset in seconds
279+
/// The time offset in seconds.
195280
#[serde(rename = "timeoffset")]
196281
pub time_offset: u32,
197282
/// Ping time (if available).
@@ -206,7 +291,8 @@ pub struct PeerInfo {
206291
/// The peer version, such as 70001.
207292
pub version: u32,
208293
/// The string version (e.g. "/Satoshi:0.8.5/").
209-
pub subver: String,
294+
#[serde(rename = "subver")]
295+
pub subversion: String,
210296
/// Inbound (true) or Outbound (false).
211297
pub inbound: bool,
212298
/// Whether connection was due to addnode/-connect or if it was an automatic/inbound connection.
@@ -227,14 +313,21 @@ pub struct PeerInfo {
227313
/// Whether the peer is whitelisted.
228314
pub whitelisted: bool,
229315
/// The total bytes sent aggregated by message type.
230-
pub bytes_sent_per_message: Vec<BytesPerMessage>,
316+
#[serde(rename = "bytessent_per_msg")]
317+
pub bytes_sent_per_message: BTreeMap<String, u64>,
231318
/// The total bytes received aggregated by message type.
232-
pub bytes_received_per_message: Vec<BytesPerMessage>,
319+
#[serde(rename = "bytesrecv_per_msg")]
320+
pub bytes_received_per_message: BTreeMap<String, u64>,
233321
}
234322

235-
/// An item from the list returned by the JSON-RPC method `getpeerinfo`.
323+
/// Result of JSON-RPC method `listbanned`.
324+
///
325+
/// > listbanned
326+
///
327+
/// > List all banned IPs/Subnets.
236328
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
237-
pub struct BytesPerMessage {
238-
#[serde(rename = "addr")]
239-
pub address: u32, // FIXME: This looks wrong.
240-
}
329+
pub struct ListBanned(pub Vec<Banned>);
330+
331+
/// An item from the list returned by the JSON-RPC method `listbanned`
332+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
333+
pub struct Banned(String); // FIXME: The docs are empty so I don't know what shape this is.

0 commit comments

Comments
 (0)