Skip to content
Bitcoin Roots

v29.4-roots.2 · Commit 3: [PATCH 03/21] policy: restore conservative relay and network controls

src/rpc/net.cpp

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

File metadata
index 9942386c7fc0a990039723c331e5fa4710160eb4..69b7c82da345dbfebbade8b6ec33397f5947892a 100644

Download original patch · Release notes

Diff rows 1–97 of 97. 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
@@ -143,6 +143,10 @@ static RPCHelpMan getpeerinfo()
143
  {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
144
  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
145
  {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
 
 
 
 
146
  {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
147
  {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
148
  {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in seconds, if any"},
@@ -157,6 +161,7 @@ static RPCHelpMan getpeerinfo()
157
  {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"},
158
  {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
159
  {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
 
160
  {RPCResult::Type::ARR, "inflight", "",
161
  {
162
  {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
@@ -168,6 +173,7 @@ static RPCHelpMan getpeerinfo()
168
  {
169
  {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
170
  }},
 
171
  {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
172
  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
173
  {
@@ -187,6 +193,7 @@ static RPCHelpMan getpeerinfo()
187
  "best capture connection behaviors."},
188
  {RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},
189
  {RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},
 
190
  }},
191
  }},
192
  },
@@ -204,6 +211,7 @@ static RPCHelpMan getpeerinfo()
204
  connman.GetNodeStats(vstats);
205
 
206
  UniValue ret(UniValue::VARR);
 
207
 
208
  for (const CNodeStats& stats : vstats) {
209
  UniValue obj(UniValue::VOBJ);
@@ -239,6 +247,9 @@ static RPCHelpMan getpeerinfo()
239
  obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
240
  obj.pushKV("bytessent", stats.nSendBytes);
241
  obj.pushKV("bytesrecv", stats.nRecvBytes);
 
 
 
242
  obj.pushKV("conntime", count_seconds(stats.m_connected));
243
  obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(statestats.time_offset));
244
  if (stats.m_last_ping_time > 0us) {
@@ -262,6 +273,7 @@ static RPCHelpMan getpeerinfo()
262
  obj.pushKV("presynced_headers", statestats.presync_height);
263
  obj.pushKV("synced_headers", statestats.nSyncHeight);
264
  obj.pushKV("synced_blocks", statestats.nCommonHeight);
 
265
  UniValue heights(UniValue::VARR);
266
  for (const int height : statestats.vHeightInFlight) {
267
  heights.push_back(height);
@@ -275,6 +287,7 @@ static RPCHelpMan getpeerinfo()
275
  permissions.push_back(permission);
276
  }
277
  obj.pushKV("permissions", std::move(permissions));
 
278
  obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
279
 
280
  UniValue sendPerMsgType(UniValue::VOBJ);
@@ -293,6 +306,7 @@ static RPCHelpMan getpeerinfo()
293
  obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
294
  obj.pushKV("transport_protocol_type", TransportTypeAsString(stats.m_transport_type));
295
  obj.pushKV("session_id", stats.m_session_id);
 
296
 
297
  ret.push_back(std::move(obj));
298
  }
@@ -434,7 +448,7 @@ static RPCHelpMan disconnectnode()
434
  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
435
  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
436
  {
437
- {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port of the node"},
438
  {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
439
  },
440
  RPCResult{RPCResult::Type::NONE, "", ""},
@@ -455,7 +469,20 @@ static RPCHelpMan disconnectnode()
455
 
456
  if (!address_arg.isNull() && id_arg.isNull()) {
457
  /* handle disconnect-by-address */
458
- success = connman.DisconnectNode(address_arg.get_str());
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
460
  /* handle disconnect-by-id */
461
  NodeId nodeid = (NodeId) id_arg.getInt<int64_t>();
 
143
  {RPCResult::Type::NUM_TIME, "last_block", "The " + UNIX_EPOCH_TIME + " of the last block received from this peer"},
144
  {RPCResult::Type::NUM, "bytessent", "The total bytes sent"},
145
  {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"},
146
+ {RPCResult::Type::NUM, "cpu_load", /*optional=*/true, "Total CPU time spent processing "
147
+ "messages to/from the peer, in per milles (‰) of the connection duration, if "
148
+ "supported by the platform and measured. High CPU time is not necessarily a bad "
149
+ "thing - new valid transactions and blocks require it be validated."},
150
  {RPCResult::Type::NUM_TIME, "conntime", "The " + UNIX_EPOCH_TIME + " of the connection"},
151
  {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"},
152
  {RPCResult::Type::NUM, "pingtime", /*optional=*/true, "The last ping time in seconds, if any"},
 
161
  {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"},
162
  {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
163
  {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"},
164
+ {RPCResult::Type::NUM_TIME, "last_block_announcement", "The time of the last block announcement received from this peer, or 0 if none has been received"},
165
  {RPCResult::Type::ARR, "inflight", "",
166
  {
167
  {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
 
173
  {
174
  {RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
175
  }},
176
+ {RPCResult::Type::BOOL, "forced_inbound", "Whether this peer forced a connection by evicting another."},
177
  {RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
178
  {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
179
  {
 
193
  "best capture connection behaviors."},
194
  {RPCResult::Type::STR, "transport_protocol_type", "Type of transport protocol: \n" + Join(TRANSPORT_TYPE_DOC, ",\n") + ".\n"},
195
  {RPCResult::Type::STR, "session_id", "The session ID for this connection, or \"\" if there is none (\"v2\" transport protocol only).\n"},
196
+ {RPCResult::Type::NUM, "misbehavior_score", "The misbehavior score for this peer. Always 0, but may be 100 if the peer is about to be disconnected. (DEPRECATED)\n"},
197
  }},
198
  }},
199
  },
 
211
  connman.GetNodeStats(vstats);
212
 
213
  UniValue ret(UniValue::VARR);
214
+ const auto now{GetTime<std::chrono::seconds>()};
215
 
216
  for (const CNodeStats& stats : vstats) {
217
  UniValue obj(UniValue::VOBJ);
 
247
  obj.pushKV("last_block", count_seconds(stats.m_last_block_time));
248
  obj.pushKV("bytessent", stats.nSendBytes);
249
  obj.pushKV("bytesrecv", stats.nRecvBytes);
250
+ if (stats.m_cpu_time > 0s && now > stats.m_connected) {
251
+ obj.pushKV("cpu_load", /* ‰ */1000.0 * stats.m_cpu_time / (now - stats.m_connected));
252
+ }
253
  obj.pushKV("conntime", count_seconds(stats.m_connected));
254
  obj.pushKV("timeoffset", Ticks<std::chrono::seconds>(statestats.time_offset));
255
  if (stats.m_last_ping_time > 0us) {
 
273
  obj.pushKV("presynced_headers", statestats.presync_height);
274
  obj.pushKV("synced_headers", statestats.nSyncHeight);
275
  obj.pushKV("synced_blocks", statestats.nCommonHeight);
276
+ obj.pushKV("last_block_announcement", TicksSinceEpoch<std::chrono::seconds>(statestats.m_last_block_announcement));
277
  UniValue heights(UniValue::VARR);
278
  for (const int height : statestats.vHeightInFlight) {
279
  heights.push_back(height);
 
287
  permissions.push_back(permission);
288
  }
289
  obj.pushKV("permissions", std::move(permissions));
290
+ obj.pushKV("forced_inbound", stats.m_forced_inbound);
291
  obj.pushKV("minfeefilter", ValueFromAmount(statestats.m_fee_filter_received));
292
 
293
  UniValue sendPerMsgType(UniValue::VOBJ);
 
306
  obj.pushKV("connection_type", ConnectionTypeAsString(stats.m_conn_type));
307
  obj.pushKV("transport_protocol_type", TransportTypeAsString(stats.m_transport_type));
308
  obj.pushKV("session_id", stats.m_session_id);
309
+ obj.pushKV("misbehavior_score", statestats.m_misbehavior_score);
310
 
311
  ret.push_back(std::move(obj));
312
  }
 
448
  "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
449
  "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
450
  {
451
+ {"address", RPCArg::Type::STR, RPCArg::DefaultHint{"fallback to nodeid"}, "The IP address/port of the node or subnet"},
452
  {"nodeid", RPCArg::Type::NUM, RPCArg::DefaultHint{"fallback to address"}, "The node ID (see getpeerinfo for node IDs)"},
453
  },
454
  RPCResult{RPCResult::Type::NONE, "", ""},
 
469
 
470
  if (!address_arg.isNull() && id_arg.isNull()) {
471
  /* handle disconnect-by-address */
472
+ const bool only_subnet{address_arg.get_str().find('/') != std::string::npos};
473
+ if (only_subnet) {
474
+ success = false;
475
+ } else {
476
+ success = connman.DisconnectNode(address_arg.get_str());
477
+ }
478
+ if (!success) {
479
+ const CSubNet subnet = LookupSubNet(address_arg.get_str());
480
+ if (subnet.IsValid()) {
481
+ success = connman.DisconnectNode(subnet);
482
+ } else if (only_subnet) {
483
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid subnet");
484
+ }
485
+ }
486
  } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
487
  /* handle disconnect-by-id */
488
  NodeId nodeid = (NodeId) id_arg.getInt<int64_t>();