Skip to content

Commit 09b0496

Browse files
committed
Merge #171: Add missing networking RPC calls.
150953a Add missing networking RPC calls. (Elias Rohrer) Pull request description: This pull request adds the missing networking RPC calls (cf. [API](https://developer.bitcoin.org/reference/rpc/index.html#network-rpcs)). I locally tested the calls in regtest as far as I could, looks like they behave as expected. ACKs for top commit: RCasatta: utACK 150953a Tree-SHA512: c154f75c0ee97b41bb9eedc7b392f22a0518dd5eae373e7d256ec208fe14ca126d7f9551b56e59b0d842ce3f350917509509b30458bd3e32f640e305962db3ef
2 parents c1d160b + 150953a commit 09b0496

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed

client/src/client.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,77 @@ pub trait RpcApi: Sized {
908908
)
909909
}
910910

911+
/// Attempts to add a node to the addnode list.
912+
/// Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be full nodes/support SegWit as other outbound peers are (though such peers will not be synced from).
913+
fn add_node(&self, addr: &str) -> Result<()> {
914+
self.call("addnode", &[into_json(&addr)?, into_json("add")?])
915+
}
916+
917+
/// Attempts to remove a node from the addnode list.
918+
fn remove_node(&self, addr: &str) -> Result<()> {
919+
self.call("addnode", &[into_json(&addr)?, into_json("remove")?])
920+
}
921+
922+
/// Attempts to connect to a node without permanently adding it to the addnode list.
923+
fn onetry_node(&self, addr: &str) -> Result<()> {
924+
self.call("addnode", &[into_json(&addr)?, into_json("onetry")?])
925+
}
926+
927+
/// Immediately disconnects from the specified peer node.
928+
fn disconnect_node(&self, addr: &str) -> Result<()> {
929+
self.call("disconnectnode", &[into_json(&addr)?])
930+
}
931+
932+
fn disconnect_node_by_id(&self, node_id: u32) -> Result<()> {
933+
self.call("disconnectnode", &[into_json("")?, into_json(node_id)?])
934+
}
935+
936+
/// Returns information about the given added node, or all added nodes (note that onetry addnodes are not listed here)
937+
fn get_added_node_info(&self, node: Option<&str>) -> Result<Vec<json::GetAddedNodeInfoResult>> {
938+
if let Some(addr) = node {
939+
self.call("getaddednodeinfo", &[into_json(&addr)?])
940+
} else {
941+
self.call("getaddednodeinfo", &[])
942+
}
943+
}
944+
945+
/// Return known addresses which can potentially be used to find new nodes in the network
946+
fn get_node_addresses(
947+
&self,
948+
count: Option<usize>,
949+
) -> Result<Vec<json::GetNodeAddressesResult>> {
950+
let cnt = count.unwrap_or(1);
951+
self.call("getnodeaddresses", &[into_json(&cnt)?])
952+
}
953+
954+
/// List all banned IPs/Subnets.
955+
fn list_banned(&self) -> Result<Vec<json::ListBannedResult>> {
956+
self.call("listbanned", &[])
957+
}
958+
959+
/// Clear all banned IPs.
960+
fn clear_banned(&self) -> Result<()> {
961+
self.call("clearbanned", &[])
962+
}
963+
964+
/// Attempts to add an IP/Subnet to the banned list.
965+
fn add_ban(&self, subnet: &str, bantime: u64, absolute: bool) -> Result<()> {
966+
self.call(
967+
"setban",
968+
&[into_json(&subnet)?, into_json("add")?, into_json(&bantime)?, into_json(&absolute)?],
969+
)
970+
}
971+
972+
/// Attempts to remove an IP/Subnet from the banned list.
973+
fn remove_ban(&self, subnet: &str) -> Result<()> {
974+
self.call("setban", &[into_json(&subnet)?, into_json("remove")?])
975+
}
976+
977+
/// Disable/enable all p2p network activity.
978+
fn set_network_active(&self, state: bool) -> Result<bool> {
979+
self.call("setnetworkactive", &[into_json(&state)?])
980+
}
981+
911982
/// Returns data about each connected network node as an array of
912983
/// [`PeerInfo`][]
913984
///

integration_test/src/main.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,12 @@ fn main() {
203203
//TODO load_wallet(&self, wallet: &str) -> Result<json::LoadWalletResult> {
204204
//TODO unload_wallet(&self, wallet: Option<&str>) -> Result<()> {
205205
//TODO backup_wallet(&self, destination: Option<&str>) -> Result<()> {
206+
test_add_node(&cl);
207+
test_get_added_node_info(&cl);
208+
test_get_node_addresses(&cl);
209+
test_disconnect_node(&cl);
210+
test_add_ban(&cl);
211+
test_set_network_active(&cl);
206212
test_stop(cl);
207213
}
208214

@@ -1007,6 +1013,61 @@ fn test_get_chain_tips(cl: &Client) {
10071013
assert_eq!(tips.len(), 1);
10081014
}
10091015

1016+
fn test_add_node(cl: &Client) {
1017+
cl.add_node("127.0.0.1:1234").unwrap();
1018+
assert_error_message!(cl.add_node("127.0.0.1:1234"), -23, "Error: Node already added");
1019+
cl.remove_node("127.0.0.1:1234").unwrap();
1020+
cl.onetry_node("127.0.0.1:1234").unwrap();
1021+
}
1022+
1023+
fn test_get_added_node_info(cl: &Client) {
1024+
cl.add_node("127.0.0.1:1234").unwrap();
1025+
let added_info = cl.get_added_node_info(None).unwrap();
1026+
assert_eq!(added_info.len(), 1);
1027+
}
1028+
1029+
fn test_get_node_addresses(cl: &Client) {
1030+
cl.get_node_addresses(None).unwrap();
1031+
}
1032+
1033+
fn test_disconnect_node(cl: &Client) {
1034+
assert_error_message!(
1035+
cl.disconnect_node("127.0.0.1:1234"),
1036+
-29,
1037+
"Node not found in connected nodes"
1038+
);
1039+
assert_error_message!(cl.disconnect_node_by_id(1), -29, "Node not found in connected nodes");
1040+
}
1041+
1042+
fn test_add_ban(cl: &Client) {
1043+
cl.add_ban("127.0.0.1", 0, false).unwrap();
1044+
let res = cl.list_banned().unwrap();
1045+
assert_eq!(res.len(), 1);
1046+
1047+
cl.remove_ban("127.0.0.1").unwrap();
1048+
let res = cl.list_banned().unwrap();
1049+
assert_eq!(res.len(), 0);
1050+
1051+
cl.add_ban("127.0.0.1", 0, false).unwrap();
1052+
let res = cl.list_banned().unwrap();
1053+
assert_eq!(res.len(), 1);
1054+
1055+
cl.clear_banned().unwrap();
1056+
let res = cl.list_banned().unwrap();
1057+
assert_eq!(res.len(), 0);
1058+
1059+
assert_error_message!(
1060+
cl.add_ban("INVALID_STRING", 0, false),
1061+
-30,
1062+
"Error: Invalid IP/Subnet"
1063+
);
1064+
}
1065+
1066+
fn test_set_network_active(cl: &Client) {
1067+
cl.set_network_active(false).unwrap();
1068+
cl.set_network_active(true).unwrap();
1069+
}
1070+
10101071
fn test_get_net_totals(cl: &Client) {
10111072
cl.get_net_totals().unwrap();
10121073
}

json/src/lib.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,51 @@ pub enum GetPeerInfoResultConnectionType {
10911091
Feeler,
10921092
}
10931093

1094+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1095+
pub struct GetAddedNodeInfoResult {
1096+
/// The node IP address or name (as provided to addnode)
1097+
#[serde(rename = "addednode")]
1098+
pub added_node: String,
1099+
/// If connected
1100+
pub connected: bool,
1101+
/// Only when connected = true
1102+
pub addresses: Vec<GetAddedNodeInfoResultAddress>,
1103+
}
1104+
1105+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1106+
pub struct GetAddedNodeInfoResultAddress {
1107+
/// The bitcoin server IP and port we're connected to
1108+
pub address: String,
1109+
/// connection, inbound or outbound
1110+
pub connected: GetAddedNodeInfoResultAddressType,
1111+
}
1112+
1113+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1114+
#[serde(rename_all = "lowercase")]
1115+
pub enum GetAddedNodeInfoResultAddressType {
1116+
Inbound,
1117+
Outbound,
1118+
}
1119+
1120+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1121+
pub struct GetNodeAddressesResult {
1122+
/// Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen
1123+
pub time: u64,
1124+
/// The services offered
1125+
pub services: usize,
1126+
/// The address of the node
1127+
pub address: String,
1128+
/// The port of the node
1129+
pub port: u16,
1130+
}
1131+
1132+
#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
1133+
pub struct ListBannedResult {
1134+
pub address: String,
1135+
pub banned_until: u64,
1136+
pub ban_created: u64,
1137+
}
1138+
10941139
/// Models the result of "estimatesmartfee"
10951140
#[derive(Clone, Debug, Deserialize, Serialize)]
10961141
pub struct EstimateSmartFeeResult {

0 commit comments

Comments
 (0)