mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
Merge #21595: cli: create -addrinfo
06c43201a7
cli: use C++17 std::array class template argument deduction (CTAD) (Jon Atack)edf3167151
addrinfo: raise helpfully on server error or incompatible server version (Jon Atack)bb85cbc4f7
doc: add cli -addrinfo release note (Jon Atack)5056a37624
cli: add -addrinfo command (Jon Atack)db4d2c282a
cli: create AddrinfoRequestHandler class (Jon Atack) Pull request description: While looking at issue #21351, it turned out that the problem was a lack of tor v3 addresses known to the node. It became clear (e.g. https://github.com/bitcoin/bitcoin/issues/21351#issuecomment-811004779) that a CLI command returning the number of addresses the node knows per network (with a tor v2 / v3 breakdown) would be very helpful. This patch adds that. `-addrinfo` is useful to see if your node knows enough addresses in a network to use options like `-onlynet=<network>`, or to upgrade to the upcoming tor release that no longer supports tor v2, for which you'll need to be sure your node knows enough tor v3 peers. ``` $ bitcoin-cli --help | grep -A1 addrinfo -addrinfo Get the number of addresses known to the node, per network and total. $ bitcoin-cli -addrinfo { "addresses_known": { "ipv4": 14406, "ipv6": 2511, "torv2": 5563, "torv3": 2842, "i2p": 8, "total": 25330 } } $ bitcoin-cli -addrinfo 1 error: -addrinfo takes no arguments ``` This can be manually tested, for example, with commands like this: ``` $ bitcoin-cli getnodeaddresses 0 | jq '.[] | (select(.address | contains(".onion")) | select(.address | length <= 22)) | .address' | wc -l 5563 $ bitcoin-cli getnodeaddresses 0 | jq '.[] | (select(.address | contains(".onion")) | select(.address | length > 22)) | .address' | wc -l 2842 $ bitcoin-cli getnodeaddresses 0 | jq '.[] | .address' | wc -l 25330 ``` ACKs for top commit: laanwj: Tested ACK06c43201a7
Tree-SHA512: b668b47718a4ce052aff218789f3da629bca730592c18fcce9a51034d95a0a65f8e6da33dd47443cdd8f60c056c02696db175b0fe09a688e4385a76c1d8b7aeb
This commit is contained in:
commit
0180453471
2 changed files with 73 additions and 11 deletions
|
@ -136,6 +136,12 @@ Changes to Wallet or GUI related settings can be found in the GUI or Wallet sect
|
|||
Tools and Utilities
|
||||
-------------------
|
||||
|
||||
- A new CLI `-addrinfo` command returns the number of addresses known to the
|
||||
node per network type (including Tor v2 versus v3) and total. This can be
|
||||
useful to see if the node knows enough addresses in a network to use options
|
||||
like `-onlynet=<network>` or to upgrade to current and future Tor releases
|
||||
that support Tor v3 addresses only. (#21595)
|
||||
|
||||
Wallet
|
||||
------
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
|
|||
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
||||
static const bool DEFAULT_NAMED=false;
|
||||
static const int CONTINUE_EXECUTION=-1;
|
||||
static constexpr int8_t UNKNOWN_NETWORK{-1};
|
||||
|
||||
/** Default number of blocks to generate for RPC generatetoaddress. */
|
||||
static const std::string DEFAULT_NBLOCKS = "1";
|
||||
|
@ -59,6 +60,7 @@ static void SetupCliArgs(ArgsManager& argsman)
|
|||
argsman.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-generate", strprintf("Generate blocks immediately, equivalent to RPC getnewaddress followed by RPC generatetoaddress. Optional positional integer arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000", DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
|
||||
|
@ -228,6 +230,60 @@ public:
|
|||
virtual UniValue ProcessReply(const UniValue &batch_in) = 0;
|
||||
};
|
||||
|
||||
/** Process addrinfo requests */
|
||||
class AddrinfoRequestHandler : public BaseRequestHandler
|
||||
{
|
||||
private:
|
||||
static constexpr std::array m_networks{"ipv4", "ipv6", "torv2", "torv3", "i2p"};
|
||||
int8_t NetworkStringToId(const std::string& str) const
|
||||
{
|
||||
for (size_t i = 0; i < m_networks.size(); ++i) {
|
||||
if (str == m_networks.at(i)) return i;
|
||||
}
|
||||
return UNKNOWN_NETWORK;
|
||||
}
|
||||
|
||||
public:
|
||||
UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
|
||||
{
|
||||
if (!args.empty()) {
|
||||
throw std::runtime_error("-addrinfo takes no arguments");
|
||||
}
|
||||
UniValue params{RPCConvertValues("getnodeaddresses", std::vector<std::string>{{"0"}})};
|
||||
return JSONRPCRequestObj("getnodeaddresses", params, 1);
|
||||
}
|
||||
|
||||
UniValue ProcessReply(const UniValue& reply) override
|
||||
{
|
||||
if (!reply["error"].isNull()) return reply;
|
||||
const std::vector<UniValue>& nodes{reply["result"].getValues()};
|
||||
if (!nodes.empty() && nodes.at(0)["network"].isNull()) {
|
||||
throw std::runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up");
|
||||
}
|
||||
// Count the number of peers we know by network, including torv2 versus torv3.
|
||||
std::array<uint64_t, m_networks.size()> counts{{}};
|
||||
for (const UniValue& node : nodes) {
|
||||
std::string network_name{node["network"].get_str()};
|
||||
if (network_name == "onion") {
|
||||
network_name = node["address"].get_str().size() > 22 ? "torv3" : "torv2";
|
||||
}
|
||||
const int8_t network_id{NetworkStringToId(network_name)};
|
||||
if (network_id == UNKNOWN_NETWORK) continue;
|
||||
++counts.at(network_id);
|
||||
}
|
||||
// Prepare result to return to user.
|
||||
UniValue result{UniValue::VOBJ}, addresses{UniValue::VOBJ};
|
||||
uint64_t total{0}; // Total address count
|
||||
for (size_t i = 0; i < m_networks.size(); ++i) {
|
||||
addresses.pushKV(m_networks.at(i), counts.at(i));
|
||||
total += counts.at(i);
|
||||
}
|
||||
addresses.pushKV("total", total);
|
||||
result.pushKV("addresses_known", addresses);
|
||||
return JSONRPCReplyObj(result, NullUniValue, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/** Process getinfo requests */
|
||||
class GetinfoRequestHandler: public BaseRequestHandler
|
||||
{
|
||||
|
@ -299,16 +355,14 @@ public:
|
|||
class NetinfoRequestHandler : public BaseRequestHandler
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t UNKNOWN_NETWORK{-1};
|
||||
static constexpr uint8_t m_networks_size{4};
|
||||
static constexpr uint8_t MAX_DETAIL_LEVEL{4};
|
||||
const std::array<std::string, m_networks_size> m_networks{{"ipv4", "ipv6", "onion", "i2p"}};
|
||||
std::array<std::array<uint16_t, m_networks_size + 1>, 3> m_counts{{{}}}; //!< Peer counts by (in/out/total, networks/total)
|
||||
static constexpr std::array m_networks{"ipv4", "ipv6", "onion", "i2p"};
|
||||
std::array<std::array<uint16_t, m_networks.size() + 1>, 3> m_counts{{{}}}; //!< Peer counts by (in/out/total, networks/total)
|
||||
uint8_t m_block_relay_peers_count{0};
|
||||
uint8_t m_manual_peers_count{0};
|
||||
int8_t NetworkStringToId(const std::string& str) const
|
||||
{
|
||||
for (uint8_t i = 0; i < m_networks_size; ++i) {
|
||||
for (size_t i = 0; i < m_networks.size(); ++i) {
|
||||
if (str == m_networks.at(i)) return i;
|
||||
}
|
||||
return UNKNOWN_NETWORK;
|
||||
|
@ -405,10 +459,10 @@ public:
|
|||
const bool is_outbound{!peer["inbound"].get_bool()};
|
||||
const bool is_block_relay{!peer["relaytxes"].get_bool()};
|
||||
const std::string conn_type{peer["connection_type"].get_str()};
|
||||
++m_counts.at(is_outbound).at(network_id); // in/out by network
|
||||
++m_counts.at(is_outbound).at(m_networks_size); // in/out overall
|
||||
++m_counts.at(2).at(network_id); // total by network
|
||||
++m_counts.at(2).at(m_networks_size); // total overall
|
||||
++m_counts.at(is_outbound).at(network_id); // in/out by network
|
||||
++m_counts.at(is_outbound).at(m_networks.size()); // in/out overall
|
||||
++m_counts.at(2).at(network_id); // total by network
|
||||
++m_counts.at(2).at(m_networks.size()); // total overall
|
||||
if (conn_type == "block-relay-only") ++m_block_relay_peers_count;
|
||||
if (conn_type == "manual") ++m_manual_peers_count;
|
||||
if (DetailsRequested()) {
|
||||
|
@ -478,11 +532,11 @@ public:
|
|||
if (any_i2p_peers) result += " i2p";
|
||||
result += " total block";
|
||||
if (m_manual_peers_count) result += " manual";
|
||||
const std::array<std::string, 3> rows{{"in", "out", "total"}};
|
||||
const std::array rows{"in", "out", "total"};
|
||||
for (uint8_t i = 0; i < 3; ++i) {
|
||||
result += strprintf("\n%-5s %5i %5i %5i", rows.at(i), m_counts.at(i).at(0), m_counts.at(i).at(1), m_counts.at(i).at(2)); // ipv4/ipv6/onion peers counts
|
||||
if (any_i2p_peers) result += strprintf(" %5i", m_counts.at(i).at(3)); // i2p peers count
|
||||
result += strprintf(" %5i", m_counts.at(i).at(m_networks_size)); // total peers count
|
||||
result += strprintf(" %5i", m_counts.at(i).at(m_networks.size())); // total peers count
|
||||
if (i == 1) { // the outbound row has two extra columns for block relay and manual peer counts
|
||||
result += strprintf(" %5i", m_block_relay_peers_count);
|
||||
if (m_manual_peers_count) result += strprintf(" %5i", m_manual_peers_count);
|
||||
|
@ -914,6 +968,8 @@ static int CommandLineRPC(int argc, char *argv[])
|
|||
} else {
|
||||
ParseError(error, strPrint, nRet);
|
||||
}
|
||||
} else if (gArgs.GetBoolArg("-addrinfo", false)) {
|
||||
rh.reset(new AddrinfoRequestHandler());
|
||||
} else {
|
||||
rh.reset(new DefaultRequestHandler());
|
||||
if (args.size() < 1) {
|
||||
|
|
Loading…
Add table
Reference in a new issue