Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 5: [PATCH 05/17] feat(net): preserve Roots peer controls and health view on v31

src/rpc/net.cpp

Before: src/rpc/net.cpp · After: src/rpc/net.cpp

File metadata
index e9fbd31cc3c830009f3ae3c3fefd2726996dc3d0..d6903f6d3b3010ddbf4d685bd7732a125ade0db5 100644

Download original patch · Release notes

Diff rows 1–90 of 90. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.

src/rpc/net.cpp CHANGED
@@ -151,6 +151,7 @@ static RPCHelpMan getpeerinfo()
151
  {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
152
  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
153
  {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
 
154
  {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
155
  {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
156
  {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in seconds, if any"},
@@ -165,6 +166,7 @@ static RPCHelpMan getpeerinfo()
165
  {RPCResult::Type::NUM, "presynced_headers", "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
166
  {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
167
  {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
 
168
  {RPCResult::Type::ARR, "inflight", "",
169
  {
170
  {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
@@ -176,6 +178,7 @@ static RPCHelpMan getpeerinfo()
176
  {
177
  {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
178
  }},
 
179
  {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
180
  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
181
  {
@@ -194,6 +197,7 @@ static RPCHelpMan getpeerinfo()
194
  "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
195
  "best capture connection behaviors."},
196
  {RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},
 
197
  {RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},
198
  }},
199
  }},
@@ -213,6 +217,7 @@ static RPCHelpMan getpeerinfo()
213
 
214
  UniValue ret(UniValue::VARR);
215
 
 
216
  for (const CNodeStats& stats : vstats) {
217
  UniValue obj(UniValue::VOBJ);
218
  CNodeStateStats statestats;
@@ -249,6 +254,9 @@ static RPCHelpMan getpeerinfo()
249
  obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
250
  obj.pushKV("bytessent", stats.nSendBytes);
251
  obj.pushKV("bytesrecv", stats.nRecvBytes);
 
 
 
252
  obj.pushKV("conntime", count_seconds(stats.m_connected));
253
  obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(statestats.time_offset));
254
  if (stats.m_last_ping_time > 0us) {
@@ -274,6 +282,7 @@ static RPCHelpMan getpeerinfo()
274
  obj.pushKV("presynced_headers", statestats.presync_height);
275
  obj.pushKV("synced_headers", statestats.nSyncHeight);
276
  obj.pushKV("synced_blocks", statestats.nCommonHeight);
 
277
  UniValue heights(UniValue::VARR);
278
  for (const int height : statestats.vHeightInFlight) {
279
  heights.push_back(height);
@@ -287,6 +296,7 @@ static RPCHelpMan getpeerinfo()
287
  permissions.push_back(permission);
288
  }
289
  obj.pushKV("permissions", std::move(permissions));
 
290
  obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
291
 
292
  UniValue sendPerMsgType(UniValue::VOBJ);
@@ -305,6 +315,7 @@ static RPCHelpMan getpeerinfo()
305
  obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
306
  obj.pushKV("transport_protocol_type", TransportTypeAsString(stats.m_transport_type));
307
  obj.pushKV("session_id", stats.m_session_id);
 
308
 
309
  ret.push_back(std::move(obj));
310
  }
@@ -455,7 +466,7 @@ static RPCHelpMan disconnectnode()
455
  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
456
  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
457
  {
458
- {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port of the node"},
459
  {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
460
  },
461
  RPCResult{RPCResult::Type::NONE, "", ""},
@@ -476,7 +487,16 @@ static RPCHelpMan disconnectnode()
476
 
477
  if (address && !node_id) {
478
  /* handle disconnect-by-address */
479
- success = connman.DisconnectNode(*address);
 
 
 
 
 
 
 
 
 
480
  } else if (node_id && (!address || address->empty())) {
481
  /* handle disconnect-by-id */
482
  success = connman.DisconnectNode(*node_id);
 
151
  {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
152
  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
153
  {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
154
+ {RPCResult::Type::NUM, "cpu_load", /*optional=*/true, "Current connection message-processing CPU time in per mille of connection duration; omitted if measurement or positive duration is unavailable"},
155
  {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
156
  {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
157
  {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in seconds, if any"},
 
166
  {RPCResult::Type::NUM, "presynced_headers", "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
167
  {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
168
  {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
169
+ {RPCResult::Type::NUM_TIME, "last_block_announcement", "Time of the last block announcement received from this peer, or 0"},
170
  {RPCResult::Type::ARR, "inflight", "",
171
  {
172
  {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
 
178
  {
179
  {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
180
  }},
181
+ {RPCResult::Type::BOOL, "forced_inbound", "Whether this inbound connection displaced another peer"},
182
  {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
183
  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
184
  {
 
197
  "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
198
  "best capture connection behaviors."},
199
  {RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},
200
+ {RPCResult::Type::NUM, "misbehavior_score", "Deprecated: 0, or 100 if discouragement is pending"},
201
  {RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},
202
  }},
203
  }},
 
217
 
218
  UniValue ret(UniValue::VARR);
219
 
220
+ const auto now{GetTime<std::chrono::seconds>()};
221
  for (const CNodeStats& stats : vstats) {
222
  UniValue obj(UniValue::VOBJ);
223
  CNodeStateStats statestats;
 
254
  obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
255
  obj.pushKV("bytessent", stats.nSendBytes);
256
  obj.pushKV("bytesrecv", stats.nRecvBytes);
257
+ if (stats.m_cpu_time > 0ns && now > stats.m_connected) {
258
+ obj.pushKV("cpu_load", 1000.0 * stats.m_cpu_time / (now - stats.m_connected));
259
+ }
260
  obj.pushKV("conntime", count_seconds(stats.m_connected));
261
  obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(statestats.time_offset));
262
  if (stats.m_last_ping_time > 0us) {
 
282
  obj.pushKV("presynced_headers", statestats.presync_height);
283
  obj.pushKV("synced_headers", statestats.nSyncHeight);
284
  obj.pushKV("synced_blocks", statestats.nCommonHeight);
285
+ obj.pushKV("last_block_announcement", count_seconds(statestats.m_last_block_announcement));
286
  UniValue heights(UniValue::VARR);
287
  for (const int height : statestats.vHeightInFlight) {
288
  heights.push_back(height);
 
296
  permissions.push_back(permission);
297
  }
298
  obj.pushKV("permissions", std::move(permissions));
299
+ obj.pushKV("forced_inbound", stats.m_forced_inbound);
300
  obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
301
 
302
  UniValue sendPerMsgType(UniValue::VOBJ);
 
315
  obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
316
  obj.pushKV("transport_protocol_type", TransportTypeAsString(stats.m_transport_type));
317
  obj.pushKV("session_id", stats.m_session_id);
318
+ obj.pushKV("misbehavior_score", statestats.m_misbehavior_score);
319
 
320
  ret.push_back(std::move(obj));
321
  }
 
466
  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
467
  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
468
  {
469
+ {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port or subnet of the node(s)"},
470
  {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
471
  },
472
  RPCResult{RPCResult::Type::NONE, "", ""},
 
487
 
488
  if (address && !node_id) {
489
  /* handle disconnect-by-address */
490
+ const bool only_subnet{address->find('/') != std::string::npos};
491
+ success = !only_subnet && connman.DisconnectNode(*address);
492
+ if (!success) {
493
+ const CSubNet subnet{LookupSubNet(std::string{*address})};
494
+ if (subnet.IsValid()) {
495
+ success = connman.DisconnectNode(subnet);
496
+ } else if (only_subnet) {
497
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid subnet");
498
+ }
499
+ }
500
  } else if (node_id && (!address || address->empty())) {
501
  /* handle disconnect-by-id */
502
  success = connman.DisconnectNode(*node_id);