bitcoin_rpc_json/
net.rs

1// Copyright 2018 Jean Pierre Dudey <jeandudey@hotmail.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Network related RPC result types.
10
11use std::fmt::{self, Formatter};
12use std::str::FromStr;
13
14use serde::{de, ser};
15use strason::Json;
16
17/// The result of "getnetworkinfo"
18#[derive(Debug, Deserialize, Serialize)]
19pub struct NetworkInfo {
20    /// The server version
21    pub version: i64,
22    /// The server subversion string
23    pub subversion: String,
24    /// The protocol version
25    pub protocolversion: i64,
26    /// The services we offer to the network
27    pub localservices: Option<String>,
28    /// `true` if transaction relay is requested from peers
29    pub localrelay: bool,
30    /// The time offset
31    pub timeoffset: i64,
32    /// Wheter p2p networking is enabled
33    pub networkactive: Option<bool>,
34    /// The number of connections
35    pub connections: Option<i64>,
36    /// Information per network
37    pub networks: Vec<Network>,
38    /// Minimum relay fee for transactions in BTC/kB
39    pub relayfee: Json,
40    /// Minimum fee increment for mempool limiting or BIP 125 replacement in
41    /// BTC/kB
42    pub incrementalfee: Json,
43    /// List of local addresses
44    pub localaddresses: Vec<LocalAddress>,
45    /// Any network and blockchain warnings
46    pub warnings: String,
47}
48
49/// Network name.
50#[derive(Debug, Clone, Copy, Eq, PartialEq)]
51pub enum NetworkName {
52    /// IPv4
53    Ipv4,
54    /// IPv6
55    Ipv6,
56    /// Onion
57    Onion,
58}
59
60impl FromStr for NetworkName {
61    type Err = ();
62
63    fn from_str(s: &str) -> Result<Self, Self::Err> {
64        match s {
65            "ipv4" => Ok(NetworkName::Ipv4),
66            "ipv6" => Ok(NetworkName::Ipv6),
67            "onion" => Ok(NetworkName::Onion),
68            _ => Err(()),
69        }
70    }
71}
72
73impl<'de> de::Deserialize<'de> for NetworkName {
74    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
75    where
76        D: de::Deserializer<'de>,
77    {
78        struct Visitor;
79
80        impl<'de> de::Visitor<'de> for Visitor {
81            type Value = NetworkName;
82
83            fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
84                write!(fmt, "network name")
85            }
86
87            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
88            where
89                E: de::Error,
90            {
91                NetworkName::from_str(v)
92                    .map_err(|_e| de::Error::custom("invalid string"))
93            }
94
95            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
96            where
97                E: de::Error,
98            {
99                NetworkName::from_str(v)
100                    .map_err(|_e| de::Error::custom("invalid string"))
101            }
102
103            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
104            where
105                E: de::Error,
106            {
107                NetworkName::from_str(&*v)
108                    .map_err(|_e| de::Error::custom("invalid string"))
109            }
110        }
111
112        deserializer.deserialize_str(Visitor)
113    }
114}
115
116impl ser::Serialize for NetworkName {
117    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118    where
119        S: ser::Serializer,
120    {
121        let s = match *self {
122            NetworkName::Ipv4 => "ipv4",
123            NetworkName::Ipv6 => "ipv6",
124            NetworkName::Onion => "onion",
125        };
126
127        serializer.serialize_str(s)
128    }
129}
130
131/// Network information
132#[derive(Debug, Deserialize, Serialize)]
133pub struct Network {
134    /// The name
135    pub name: NetworkName,
136    /// Is the network limited using `-onlynet`?
137    pub limited: bool,
138    /// Is the network reachable?
139    pub reachable: bool,
140    /// The proxy that is used for this network
141    pub proxy: String,
142    /// Whether randomized credentials are used
143    pub proxy_randomize_credentials: bool,
144}
145
146#[derive(Debug, Clone, Deserialize, Serialize)]
147pub struct LocalAddress {
148    /// Network address
149    pub address: String,
150    /// Network port
151    pub port: u16,
152    /// Relative score
153    pub score: i64,
154}
155
156/// Models the result of "getpeerinfo"
157#[derive(Debug, Clone, Deserialize, Serialize)]
158pub struct PeerInfo {
159    /// Peer index
160    pub id: u64,
161    /// The IP address and port of the peer
162    // TODO: use a type for addr
163    pub addr: String,
164    /// Bind address of the connection to the peer
165    // TODO: use a type for addrbind
166    pub addrbind: String,
167    /// Local address as reported by the peer
168    // TODO: use a type for addrlocal
169    pub addrlocal: String,
170    /// The services offered
171    // TODO: use a type for services
172    pub services: String,
173    /// Whether peer has asked us to relay transactions to it
174    pub relaytxes: bool,
175    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last send
176    pub lastsend: u64,
177    /// The time in seconds since epoch (Jan 1 1970 GMT) of the last receive
178    pub lastrecv: u64,
179    /// The total bytes sent
180    pub bytessent: u64,
181    /// The total bytes received
182    pub bytesrecv: u64,
183    /// The connection time in seconds since epoch (Jan 1 1970 GMT)
184    pub conntime: u64,
185    /// The time offset in seconds
186    pub timeoffset: u64,
187    /// ping time (if available)
188    pub pingtime: u64,
189    /// minimum observed ping time (if any at all)
190    pub minping: u64,
191    /// ping wait (if non-zero)
192    pub pingwait: u64,
193    /// The peer version, such as 70001
194    pub version: u64,
195    /// The string version
196    pub subver: String,
197    /// Inbound (true) or Outbound (false)
198    pub inbound: bool,
199    /// Whether connection was due to `addnode`/`-connect` or if it was an
200    /// automatic/inbound connection
201    pub addnode: bool,
202    /// The starting height (block) of the peer
203    pub startingheight: u64,
204    /// The ban score
205    pub banscore: i64,
206    /// The last header we have in common with this peer
207    pub synced_headers: u64,
208    /// The last block we have in common with this peer
209    pub synced_blocks: u64,
210    /// The heights of blocks we're currently asking from this peer
211    pub inflight: Vec<u64>,
212    /// Whether the peer is whitelisted
213    pub whitelisted: bool,
214    /// The total bytes sent aggregated by message type
215    // TODO: use a type for bytessent_per_msg
216    pub bytessent_per_msg: Json,
217    /// The total bytes received aggregated by message type
218    // TODO: use a type for bytesrecv_per_msg
219    pub bytesrecv_per_msg: Json,
220}
221
222/// "addnode" command.
223#[derive(Debug, Clone, Copy, Eq, PartialEq)]
224pub enum AddNode {
225    /// Add the node
226    Add,
227    /// Remove the node
228    Remove,
229    /// Try to connect once to the node
230    OneTry,
231}
232
233impl FromStr for AddNode {
234    type Err = ();
235
236    fn from_str(s: &str) -> Result<Self, Self::Err> {
237        match s {
238            "add" => Ok(AddNode::Add),
239            "remove" => Ok(AddNode::Remove),
240            "onetry" => Ok(AddNode::OneTry),
241            _ => Err(()),
242        }
243    }
244}
245
246impl<'de> de::Deserialize<'de> for AddNode {
247    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
248    where
249        D: de::Deserializer<'de>,
250    {
251        struct Visitor;
252
253        impl<'de> de::Visitor<'de> for Visitor {
254            type Value = AddNode;
255
256            fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
257                write!(fmt, "network name")
258            }
259
260            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
261            where
262                E: de::Error,
263            {
264                AddNode::from_str(v)
265                    .map_err(|_e| de::Error::custom("invalid string"))
266            }
267
268            fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
269            where
270                E: de::Error,
271            {
272                AddNode::from_str(v)
273                    .map_err(|_e| de::Error::custom("invalid string"))
274            }
275
276            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
277            where
278                E: de::Error,
279            {
280                AddNode::from_str(&*v)
281                    .map_err(|_e| de::Error::custom("invalid string"))
282            }
283        }
284
285        deserializer.deserialize_str(Visitor)
286    }
287}
288
289impl ser::Serialize for AddNode {
290    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
291    where
292        S: ser::Serializer,
293    {
294        let s = match *self {
295            AddNode::Add => "add",
296            AddNode::Remove => "remove",
297            AddNode::OneTry => "onetry",
298        };
299
300        serializer.serialize_str(s)
301    }
302}