diff options
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/blockchain.cpp | 3 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 7 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 41 | ||||
-rw-r--r-- | src/rpc/net.cpp | 98 | ||||
-rw-r--r-- | src/rpc/net.h | 15 |
5 files changed, 112 insertions, 52 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 438b6ce6e6..59f7657c0e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1338,7 +1338,8 @@ static RPCHelpMan verifychain() LOCK(cs_main); CChainState& active_chainstate = chainman.ActiveChainstate(); - return CVerifyDB().VerifyDB(Params(), active_chainstate, &active_chainstate.CoinsTip(), check_level, check_depth); + return CVerifyDB().VerifyDB( + active_chainstate, Params(), active_chainstate.CoinsTip(), check_level, check_depth); }, }; } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 32318dd484..f7cf1a7851 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -18,6 +18,7 @@ #include <pow.h> #include <rpc/blockchain.h> #include <rpc/mining.h> +#include <rpc/net.h> #include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> @@ -671,11 +672,9 @@ static RPCHelpMan getblocktemplate() if (strMode != "template") throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - if (!Params().IsTestChain()) { - if (node.connman->GetNodeCount(ConnectionDirection::Both) == 0) { + const CConnman& connman = EnsureConnman(node); + if (connman.GetNodeCount(ConnectionDirection::Both) == 0) { throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!"); } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index dd495850d3..0e0da8f22b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -8,6 +8,9 @@ #include <index/coinstatsindex.h> #include <index/txindex.h> #include <interfaces/chain.h> +#include <interfaces/echo.h> +#include <interfaces/init.h> +#include <interfaces/ipc.h> #include <key_io.h> #include <node/context.h> #include <outputtype.h> @@ -645,6 +648,43 @@ static RPCHelpMan echo(const std::string& name) static RPCHelpMan echo() { return echo("echo"); } static RPCHelpMan echojson() { return echo("echojson"); } +static RPCHelpMan echoipc() +{ + return RPCHelpMan{ + "echoipc", + "\nEcho back the input argument, passing it through a spawned process in a multiprocess build.\n" + "This command is for testing.\n", + {{"arg", RPCArg::Type::STR, RPCArg::Optional::NO, "The string to echo",}}, + RPCResult{RPCResult::Type::STR, "echo", "The echoed string."}, + RPCExamples{HelpExampleCli("echo", "\"Hello world\"") + + HelpExampleRpc("echo", "\"Hello world\"")}, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { + std::unique_ptr<interfaces::Echo> echo; + if (interfaces::Ipc* ipc = Assert(EnsureAnyNodeContext(request.context).init)->ipc()) { + // Spawn a new bitcoin-node process and call makeEcho to get a + // client pointer to a interfaces::Echo instance running in + // that process. This is just for testing. A slightly more + // realistic test spawning a different executable instead of + // the same executable would add a new bitcoin-echo executable, + // and spawn bitcoin-echo below instead of bitcoin-node. But + // using bitcoin-node avoids the need to build and install a + // new executable just for this one test. + auto init = ipc->spawnProcess("bitcoin-node"); + echo = init->makeEcho(); + ipc->addCleanup(*echo, [init = init.release()] { delete init; }); + } else { + // IPC support is not available because this is a bitcoind + // process not a bitcoind-node process, so just create a local + // interfaces::Echo object and return it so the `echoipc` RPC + // method will work, and the python test calling `echoipc` + // can expect the same result. + echo = interfaces::MakeEcho(); + } + return echo->echo(request.params[0].get_str()); + }, + }; +} + static UniValue SummaryToJSON(const IndexSummary&& summary, std::string index_name) { UniValue ret_summary(UniValue::VOBJ); @@ -724,6 +764,7 @@ static const CRPCCommand commands[] = { "hidden", &mockscheduler, }, { "hidden", &echo, }, { "hidden", &echojson, }, + { "hidden", &echoipc, }, }; // clang-format on for (const auto& c : commands) { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index be068edf68..2bfcaeafc9 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -39,6 +39,22 @@ const std::vector<std::string> CONNECTION_TYPE_DOC{ "feeler (short-lived automatic connection for testing addresses)" }; +CConnman& EnsureConnman(const NodeContext& node) +{ + if (!node.connman) { + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + } + return *node.connman; +} + +PeerManager& EnsurePeerman(const NodeContext& node) +{ + if (!node.peerman) { + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + } + return *node.peerman; +} + static RPCHelpMan getconnectioncount() { return RPCHelpMan{"getconnectioncount", @@ -54,10 +70,9 @@ static RPCHelpMan getconnectioncount() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + const CConnman& connman = EnsureConnman(node); - return (int)node.connman->GetNodeCount(ConnectionDirection::Both); + return (int)connman.GetNodeCount(ConnectionDirection::Both); }, }; } @@ -77,12 +92,10 @@ static RPCHelpMan ping() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.peerman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - } + PeerManager& peerman = EnsurePeerman(node); // Request that each node send a ping during next message processing pass - node.peerman->SendPings(); + peerman.SendPings(); return NullUniValue; }, }; @@ -166,19 +179,18 @@ static RPCHelpMan getpeerinfo() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman || !node.peerman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - } + const CConnman& connman = EnsureConnman(node); + const PeerManager& peerman = EnsurePeerman(node); std::vector<CNodeStats> vstats; - node.connman->GetNodeStats(vstats); + connman.GetNodeStats(vstats); UniValue ret(UniValue::VARR); for (const CNodeStats& stats : vstats) { UniValue obj(UniValue::VOBJ); CNodeStateStats statestats; - bool fStateStats = node.peerman->GetNodeStateStats(stats.nodeid, statestats); + bool fStateStats = peerman.GetNodeStateStats(stats.nodeid, statestats); obj.pushKV("id", stats.nodeid); obj.pushKV("addr", stats.addrName); if (stats.addrBind.IsValid()) { @@ -286,27 +298,28 @@ static RPCHelpMan addnode() } NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + CConnman& connman = EnsureConnman(node); std::string strNode = request.params[0].get_str(); if (strCommand == "onetry") { CAddress addr; - node.connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL); + connman.OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL); return NullUniValue; } if (strCommand == "add") { - if(!node.connman->AddNode(strNode)) + if (!connman.AddNode(strNode)) { throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added"); + } } else if(strCommand == "remove") { - if(!node.connman->RemoveAddedNode(strNode)) + if (!connman.RemoveAddedNode(strNode)) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node could not be removed. It has not been added previously."); + } } return NullUniValue; @@ -351,11 +364,9 @@ static RPCHelpMan addconnection() } NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.connman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled."); - } + CConnman& connman = EnsureConnman(node); - const bool success = node.connman->AddConnection(address, conn_type); + const bool success = connman.AddConnection(address, conn_type); if (!success) { throw JSONRPCError(RPC_CLIENT_NODE_CAPACITY_REACHED, "Error: Already at capacity for specified connection type."); } @@ -389,8 +400,7 @@ static RPCHelpMan disconnectnode() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + CConnman& connman = EnsureConnman(node); bool success; const UniValue &address_arg = request.params[0]; @@ -398,11 +408,11 @@ static RPCHelpMan disconnectnode() if (!address_arg.isNull() && id_arg.isNull()) { /* handle disconnect-by-address */ - success = node.connman->DisconnectNode(address_arg.get_str()); + success = connman.DisconnectNode(address_arg.get_str()); } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) { /* handle disconnect-by-id */ NodeId nodeid = (NodeId) id_arg.get_int64(); - success = node.connman->DisconnectNode(nodeid); + success = connman.DisconnectNode(nodeid); } else { throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided."); } @@ -449,10 +459,9 @@ static RPCHelpMan getaddednodeinfo() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + const CConnman& connman = EnsureConnman(node); - std::vector<AddedNodeInfo> vInfo = node.connman->GetAddedNodeInfo(); + std::vector<AddedNodeInfo> vInfo = connman.GetAddedNodeInfo(); if (!request.params[0].isNull()) { bool found = false; @@ -520,21 +529,20 @@ static RPCHelpMan getnettotals() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if(!node.connman) - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + const CConnman& connman = EnsureConnman(node); UniValue obj(UniValue::VOBJ); - obj.pushKV("totalbytesrecv", node.connman->GetTotalBytesRecv()); - obj.pushKV("totalbytessent", node.connman->GetTotalBytesSent()); + obj.pushKV("totalbytesrecv", connman.GetTotalBytesRecv()); + obj.pushKV("totalbytessent", connman.GetTotalBytesSent()); obj.pushKV("timemillis", GetTimeMillis()); UniValue outboundLimit(UniValue::VOBJ); - outboundLimit.pushKV("timeframe", count_seconds(node.connman->GetMaxOutboundTimeframe())); - outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget()); - outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false)); - outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true)); - outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft()); - outboundLimit.pushKV("time_left_in_cycle", count_seconds(node.connman->GetMaxOutboundTimeLeftInCycle())); + outboundLimit.pushKV("timeframe", count_seconds(connman.GetMaxOutboundTimeframe())); + outboundLimit.pushKV("target", connman.GetMaxOutboundTarget()); + outboundLimit.pushKV("target_reached", connman.OutboundTargetReached(false)); + outboundLimit.pushKV("serve_historical_blocks", !connman.OutboundTargetReached(true)); + outboundLimit.pushKV("bytes_left_in_cycle", connman.GetOutboundTargetBytesLeft()); + outboundLimit.pushKV("time_left_in_cycle", count_seconds(connman.GetMaxOutboundTimeLeftInCycle())); obj.pushKV("uploadtarget", outboundLimit); return obj; }, @@ -826,13 +834,11 @@ static RPCHelpMan setnetworkactive() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.connman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - } + CConnman& connman = EnsureConnman(node); - node.connman->SetNetworkActive(request.params[0].get_bool()); + connman.SetNetworkActive(request.params[0].get_bool()); - return node.connman->GetNetworkActive(); + return connman.GetNetworkActive(); }, }; } @@ -864,15 +870,13 @@ static RPCHelpMan getnodeaddresses() [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { NodeContext& node = EnsureAnyNodeContext(request.context); - if (!node.connman) { - throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - } + const CConnman& connman = EnsureConnman(node); const int count{request.params[0].isNull() ? 1 : request.params[0].get_int()}; if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address count out of range"); // returns a shuffled list of CAddress - const std::vector<CAddress> vAddr{node.connman->GetAddresses(count, /* max_pct */ 0)}; + const std::vector<CAddress> vAddr{connman.GetAddresses(count, /* max_pct */ 0)}; UniValue ret(UniValue::VARR); for (const CAddress& addr : vAddr) { diff --git a/src/rpc/net.h b/src/rpc/net.h new file mode 100644 index 0000000000..7a4d8440ba --- /dev/null +++ b/src/rpc/net.h @@ -0,0 +1,15 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RPC_NET_H +#define BITCOIN_RPC_NET_H + +class CConnman; +class PeerManager; +struct NodeContext; + +CConnman& EnsureConnman(const NodeContext& node); +PeerManager& EnsurePeerman(const NodeContext& node); + +#endif // BITCOIN_RPC_NET_H |