Skip to content

Commit

Permalink
Merge #19994: Assert that RPCArg names are equal to CRPCCommand ones …
Browse files Browse the repository at this point in the history
…(net, rpcwallet)

fa14f57 Assert that RPCArg names are equal to CRPCCommand ones (net, rpcwallet) (MarcoFalke)

Pull request description:

  This is the last part split out from #18531 to just touch some RPC methods. Description from the main pr:

  ### Motivation

  RPCArg names in the rpc help are currently only used for documentation. However, in the future they could be used to teach the server the named arguments. Named arguments are currently registered by the `CRPCCommand`s and duplicate the RPCArg names from the documentation. This redundancy is fragile, and has lead to errors in the past (despite having linters to catch those kind of errors). See section "bugs found" for a list of bugs that have been found as a result of the changes here.

  ### Changes

  The changes here add an assert in the `CRPCCommand` constructor that the RPCArg names are identical to the ones in the `CRPCCommand`.

  ### Future work

  > Here or follow up, makes sense to also assert type of returned UniValue?

  Sure, but let's not get ahead of ourselves. I am going to submit any further works as follow-ups, including:

  * Removing the CRPCCommand arguments, now that they are asserted to be equal and thus redundant
  * Removing all python regex linters on the args, now that RPCMan can be used to generate any output, including the cli.cpp table
  * Auto-formatting and sanity checking the RPCExamples with RPCMan
  * Checking passed-in json in self-check. Removing redundant checks
  * Checking returned json against documentation to avoid regressions or false documentation
  * Compile the RPC documentation at compile-time to ensure it doesn't change at runtime and is completely static

  ### Bugs found

  * The assert identified issue #18607
  * The changes itself fixed bug #19250

ACKs for top commit:
  fjahr:
    tACK fa14f57
  ryanofsky:
    Code review ACK fa14f57. Just straightforward replacements except code moved in `addnode`, and displatching updated in `bumpfee_helper`

Tree-SHA512: e07af150f1d95a88e558256ce197a6b7dc6cd722a6d6c13c75d944c49c2e2441f8b8237e9f94b03db69fa18f9bda627b0781d5e1da70bf5415e09b38728a8cb1
  • Loading branch information
MarcoFalke committed Sep 23, 2020
2 parents 8235dca + fa14f57 commit 5e14faf
Show file tree
Hide file tree
Showing 3 changed files with 381 additions and 254 deletions.
148 changes: 91 additions & 57 deletions src/rpc/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@

#include <univalue.h>

static UniValue getconnectioncount(const JSONRPCRequest& request)
static RPCHelpMan getconnectioncount()
{
RPCHelpMan{"getconnectioncount",
return RPCHelpMan{"getconnectioncount",
"\nReturns the number of connections to other nodes.\n",
{},
RPCResult{
Expand All @@ -41,18 +41,20 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
HelpExampleCli("getconnectioncount", "")
+ HelpExampleRpc("getconnectioncount", "")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");

return (int)node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
},
};
}

static UniValue ping(const JSONRPCRequest& request)
static RPCHelpMan ping()
{
RPCHelpMan{"ping",
return RPCHelpMan{"ping",
"\nRequests that a ping be sent to all other nodes, to measure ping time.\n"
"Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n"
"Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n",
Expand All @@ -62,8 +64,8 @@ static UniValue ping(const JSONRPCRequest& request)
HelpExampleCli("ping", "")
+ HelpExampleRpc("ping", "")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -73,11 +75,13 @@ static UniValue ping(const JSONRPCRequest& request)
pnode->fPingQueued = true;
});
return NullUniValue;
},
};
}

static UniValue getpeerinfo(const JSONRPCRequest& request)
static RPCHelpMan getpeerinfo()
{
RPCHelpMan{"getpeerinfo",
return RPCHelpMan{"getpeerinfo",
"\nReturns data about each connected network node as a json array of objects.\n",
{},
RPCResult{
Expand Down Expand Up @@ -142,8 +146,8 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
HelpExampleCli("getpeerinfo", "")
+ HelpExampleRpc("getpeerinfo", "")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand Down Expand Up @@ -233,17 +237,13 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
}

return ret;
},
};
}

static UniValue addnode(const JSONRPCRequest& request)
static RPCHelpMan addnode()
{
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
if (request.fHelp || request.params.size() != 2 ||
(strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
throw std::runtime_error(
RPCHelpMan{"addnode",
return RPCHelpMan{"addnode",
"\nAttempts to add or remove a node from the addnode list.\n"
"Or try a connection to a node once.\n"
"Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n"
Expand All @@ -257,7 +257,15 @@ static UniValue addnode(const JSONRPCRequest& request)
HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"")
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
},
}.ToString());
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
if (request.fHelp || request.params.size() != 2 ||
(strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
throw std::runtime_error(
self.ToString());

NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
Expand All @@ -284,11 +292,13 @@ static UniValue addnode(const JSONRPCRequest& request)
}

return NullUniValue;
},
};
}

static UniValue disconnectnode(const JSONRPCRequest& request)
static RPCHelpMan disconnectnode()
{
RPCHelpMan{"disconnectnode",
return RPCHelpMan{"disconnectnode",
"\nImmediately disconnects from the specified peer node.\n"
"\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n"
"\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n",
Expand All @@ -303,8 +313,8 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
+ HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
+ HelpExampleRpc("disconnectnode", "\"\", 1")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -329,11 +339,13 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
}

return NullUniValue;
},
};
}

static UniValue getaddednodeinfo(const JSONRPCRequest& request)
static RPCHelpMan getaddednodeinfo()
{
RPCHelpMan{"getaddednodeinfo",
return RPCHelpMan{"getaddednodeinfo",
"\nReturns information about the given added node, or all added nodes\n"
"(note that onetry addnodes are not listed here)\n",
{
Expand Down Expand Up @@ -361,8 +373,8 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"")
+ HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand Down Expand Up @@ -401,11 +413,13 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
}

return ret;
},
};
}

static UniValue getnettotals(const JSONRPCRequest& request)
static RPCHelpMan getnettotals()
{
RPCHelpMan{"getnettotals",
return RPCHelpMan{"getnettotals",
"\nReturns information about network traffic, including bytes in, bytes out,\n"
"and current time.\n",
{},
Expand All @@ -430,7 +444,8 @@ static UniValue getnettotals(const JSONRPCRequest& request)
HelpExampleCli("getnettotals", "")
+ HelpExampleRpc("getnettotals", "")
},
}.Check(request);
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -449,6 +464,8 @@ static UniValue getnettotals(const JSONRPCRequest& request)
outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
obj.pushKV("uploadtarget", outboundLimit);
return obj;
},
};
}

static UniValue GetNetworksInfo()
Expand All @@ -472,9 +489,9 @@ static UniValue GetNetworksInfo()
return networks;
}

static UniValue getnetworkinfo(const JSONRPCRequest& request)
static RPCHelpMan getnetworkinfo()
{
RPCHelpMan{"getnetworkinfo",
return RPCHelpMan{"getnetworkinfo",
"Returns an object containing various state info regarding P2P networking.\n",
{},
RPCResult{
Expand Down Expand Up @@ -523,8 +540,8 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
HelpExampleCli("getnetworkinfo", "")
+ HelpExampleRpc("getnetworkinfo", "")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
obj.pushKV("version", CLIENT_VERSION);
Expand Down Expand Up @@ -562,11 +579,13 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
obj.pushKV("localaddresses", localAddresses);
obj.pushKV("warnings", GetWarnings(false).original);
return obj;
},
};
}

static UniValue setban(const JSONRPCRequest& request)
static RPCHelpMan setban()
{
const RPCHelpMan help{"setban",
return RPCHelpMan{"setban",
"\nAttempts to add or remove an IP/Subnet from the banned list.\n",
{
{"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
Expand All @@ -580,7 +599,8 @@ static UniValue setban(const JSONRPCRequest& request)
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
+ HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
},
};
[&](const RPCHelpMan& help, const JSONRPCRequest& request) -> UniValue
{
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
Expand Down Expand Up @@ -643,11 +663,13 @@ static UniValue setban(const JSONRPCRequest& request)
}
}
return NullUniValue;
},
};
}

static UniValue listbanned(const JSONRPCRequest& request)
static RPCHelpMan listbanned()
{
RPCHelpMan{"listbanned",
return RPCHelpMan{"listbanned",
"\nList all manually banned IPs/Subnets.\n",
{},
RPCResult{RPCResult::Type::ARR, "", "",
Expand All @@ -663,8 +685,8 @@ static UniValue listbanned(const JSONRPCRequest& request)
HelpExampleCli("listbanned", "")
+ HelpExampleRpc("listbanned", "")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if(!node.banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
Expand All @@ -686,19 +708,22 @@ static UniValue listbanned(const JSONRPCRequest& request)
}

return bannedAddresses;
},
};
}

static UniValue clearbanned(const JSONRPCRequest& request)
static RPCHelpMan clearbanned()
{
RPCHelpMan{"clearbanned",
return RPCHelpMan{"clearbanned",
"\nClear all banned IPs.\n",
{},
RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
HelpExampleCli("clearbanned", "")
+ HelpExampleRpc("clearbanned", "")
},
}.Check(request);
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if (!node.banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
Expand All @@ -707,19 +732,21 @@ static UniValue clearbanned(const JSONRPCRequest& request)
node.banman->ClearBanned();

return NullUniValue;
},
};
}

static UniValue setnetworkactive(const JSONRPCRequest& request)
static RPCHelpMan setnetworkactive()
{
RPCHelpMan{"setnetworkactive",
return RPCHelpMan{"setnetworkactive",
"\nDisable/enable all p2p network activity.\n",
{
{"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"},
},
RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"},
RPCExamples{""},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if (!node.connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -728,11 +755,13 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
node.connman->SetNetworkActive(request.params[0].get_bool());

return node.connman->GetNetworkActive();
},
};
}

static UniValue getnodeaddresses(const JSONRPCRequest& request)
static RPCHelpMan getnodeaddresses()
{
RPCHelpMan{"getnodeaddresses",
return RPCHelpMan{"getnodeaddresses",
"\nReturn known addresses which can potentially be used to find new nodes in the network\n",
{
{"count", RPCArg::Type::NUM, /* default */ "1", "The maximum number of addresses to return. Specify 0 to return all known addresses."},
Expand All @@ -753,7 +782,8 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
HelpExampleCli("getnodeaddresses", "8")
+ HelpExampleRpc("getnodeaddresses", "8")
},
}.Check(request);
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if (!node.connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -779,11 +809,13 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
ret.push_back(obj);
}
return ret;
},
};
}

static UniValue addpeeraddress(const JSONRPCRequest& request)
static RPCHelpMan addpeeraddress()
{
RPCHelpMan{"addpeeraddress",
return RPCHelpMan{"addpeeraddress",
"\nAdd the address of a potential peer to the address manager. This RPC is for testing only.\n",
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address of the peer"},
Expand All @@ -799,8 +831,8 @@ static UniValue addpeeraddress(const JSONRPCRequest& request)
HelpExampleCli("addpeeraddress", "\"1.2.3.4\" 8333")
+ HelpExampleRpc("addpeeraddress", "\"1.2.3.4\", 8333")
},
}.Check(request);

[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
if (!node.connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
Expand All @@ -827,6 +859,8 @@ static UniValue addpeeraddress(const JSONRPCRequest& request)

obj.pushKV("success", true);
return obj;
},
};
}

void RegisterNetRPCCommands(CRPCTable &t)
Expand Down
Loading

0 comments on commit 5e14faf

Please sign in to comment.