Remove pointer cast in CRPCTable::dumpArgMap

CRPCTable::dumpArgMap currently works by casting RPC command unique_id
integer field to a function pointer, and then calling the function. The
unique_id field wasn't supposed to be used this way (it's meant to be
used to detect RPC aliases), and this code segfaults in the rpc_help.py
test in multiprocess PR https://github.com/bitcoin/bitcoin/pull/10102
because wallet RPC functions aren't directly accessible from the node
process.

Fix this by adding a new GET_ARGS request mode to retrieve argument
information similar to the way the GET_HELP mode retrieves help
information.
This commit is contained in:
Russell Yanofsky
2021-01-29 18:15:48 -05:00
parent 14f3d9b908
commit 9048c58e10
5 changed files with 20 additions and 10 deletions

View File

@ -34,7 +34,7 @@ public:
UniValue id; UniValue id;
std::string strMethod; std::string strMethod;
UniValue params; UniValue params;
enum Mode { EXECUTE, GET_HELP } mode = EXECUTE; enum Mode { EXECUTE, GET_HELP, GET_ARGS } mode = EXECUTE;
std::string URI; std::string URI;
std::string authUser; std::string authUser;
std::string peerAddr; std::string peerAddr;

View File

@ -149,7 +149,7 @@ static RPCHelpMan help()
} }
if (strCommand == "dump_all_command_conversions") { if (strCommand == "dump_all_command_conversions") {
// Used for testing only, undocumented // Used for testing only, undocumented
return tableRPC.dumpArgMap(); return tableRPC.dumpArgMap(jsonRequest);
} }
return tableRPC.help(strCommand, jsonRequest); return tableRPC.help(strCommand, jsonRequest);
@ -492,13 +492,18 @@ std::vector<std::string> CRPCTable::listCommands() const
return commandList; return commandList;
} }
UniValue CRPCTable::dumpArgMap() const UniValue CRPCTable::dumpArgMap(const JSONRPCRequest& args_request) const
{ {
JSONRPCRequest request(args_request);
request.mode = JSONRPCRequest::GET_ARGS;
UniValue ret{UniValue::VARR}; UniValue ret{UniValue::VARR};
for (const auto& cmd : mapCommands) { for (const auto& cmd : mapCommands) {
for (const auto& c : cmd.second) { UniValue result;
const auto help = RpcMethodFnType(c->unique_id)(); if (ExecuteCommands(cmd.second, request, result)) {
help.AppendArgMap(ret); for (const auto& values : result.getValues()) {
ret.push_back(values);
}
} }
} }
return ret; return ret;

View File

@ -148,7 +148,7 @@ public:
/** /**
* Return all named arguments that need to be converted by the client from string to another JSON type * Return all named arguments that need to be converted by the client from string to another JSON type
*/ */
UniValue dumpArgMap() const; UniValue dumpArgMap(const JSONRPCRequest& request) const;
/** /**
* Appends a CRPCCommand to the dispatch table. * Appends a CRPCCommand to the dispatch table.

View File

@ -478,6 +478,9 @@ std::string RPCExamples::ToDescriptionString() const
UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request)
{ {
if (request.mode == JSONRPCRequest::GET_ARGS) {
return GetArgMap();
}
/* /*
* Check if the given request is valid according to this command or if * Check if the given request is valid according to this command or if
* the user is asking for help information, and throw help when appropriate. * the user is asking for help information, and throw help when appropriate.
@ -561,8 +564,9 @@ std::string RPCHelpMan::ToString() const
return ret; return ret;
} }
void RPCHelpMan::AppendArgMap(UniValue& arr) const UniValue RPCHelpMan::GetArgMap() const
{ {
UniValue arr{UniValue::VARR};
for (int i{0}; i < int(m_args.size()); ++i) { for (int i{0}; i < int(m_args.size()); ++i) {
const auto& arg = m_args.at(i); const auto& arg = m_args.at(i);
std::vector<std::string> arg_names; std::vector<std::string> arg_names;
@ -577,6 +581,7 @@ void RPCHelpMan::AppendArgMap(UniValue& arr) const
arr.push_back(map); arr.push_back(map);
} }
} }
return arr;
} }
std::string RPCArg::GetFirstName() const std::string RPCArg::GetFirstName() const

View File

@ -337,8 +337,8 @@ public:
UniValue HandleRequest(const JSONRPCRequest& request); UniValue HandleRequest(const JSONRPCRequest& request);
std::string ToString() const; std::string ToString() const;
/** Append the named args that need to be converted from string to another JSON type */ /** Return the named args that need to be converted from string to another JSON type */
void AppendArgMap(UniValue& arr) const; UniValue GetArgMap() const;
/** If the supplied number of args is neither too small nor too high */ /** If the supplied number of args is neither too small nor too high */
bool IsValidNumArgs(size_t num_args) const; bool IsValidNumArgs(size_t num_args) const;
std::vector<std::string> GetArgNames() const; std::vector<std::string> GetArgNames() const;