Skip to content

Commit ad4bf8a

Browse files
author
MarcoFalke
committed
Merge bitcoin#20459: rpc: Fail to return undocumented return values
fa8192f rpc: Fail to return undocumented return values (MarcoFalke) Pull request description: Currently a few return values are undocumented. This is causing confusion at the least. See for example bitcoin#18476 Fix this by treating it as an internal bug to return undocumented return values. ACKs for top commit: ryanofsky: Code review ACK fa8192f. Only changes: rebase, no const_cast suggestion, and tostring cleanups needed after suggestion Tree-SHA512: c006905639bafe3045de152b00c34d9864731becb3c4f468bdd61a392f10d7e7cd89a54862c8daa8c11ac4eea0eb5f13b0f647d21e21a0a797b54191cff7238c
2 parents 9565daf + fa8192f commit ad4bf8a

File tree

5 files changed

+53
-7
lines changed

5 files changed

+53
-7
lines changed

src/qt/test/rpcnestedtests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static RPCHelpMan rpcNestedTest_rpc()
2424
{"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
2525
{"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
2626
},
27-
{},
27+
RPCResult{RPCResult::Type::ANY, "", ""},
2828
RPCExamples{""},
2929
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
3030
return request.params.write(0, 0);

src/rpc/misc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ static RPCHelpMan echo(const std::string& name)
628628
{"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
629629
{"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
630630
},
631-
RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"},
631+
RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
632632
RPCExamples{""},
633633
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
634634
{

src/rpc/server.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,9 @@ static RPCHelpMan help()
137137
{
138138
{"command", RPCArg::Type::STR, /* default */ "all commands", "The command to get help on"},
139139
},
140-
RPCResult{
141-
RPCResult::Type::STR, "", "The help text"
140+
{
141+
RPCResult{RPCResult::Type::STR, "", "The help text"},
142+
RPCResult{RPCResult::Type::ANY, "", ""},
142143
},
143144
RPCExamples{""},
144145
[&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue

src/rpc/util.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ std::string RPCResults::ToDescriptionString() const
442442
{
443443
std::string result;
444444
for (const auto& r : m_results) {
445+
if (r.m_type == RPCResult::Type::ANY) continue; // for testing only
445446
if (r.m_cond.empty()) {
446447
result += "\nResult:\n";
447448
} else {
@@ -459,7 +460,7 @@ std::string RPCExamples::ToDescriptionString() const
459460
return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
460461
}
461462

462-
UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request)
463+
UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
463464
{
464465
if (request.mode == JSONRPCRequest::GET_ARGS) {
465466
return GetArgMap();
@@ -471,7 +472,9 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request)
471472
if (request.mode == JSONRPCRequest::GET_HELP || !IsValidNumArgs(request.params.size())) {
472473
throw std::runtime_error(ToString());
473474
}
474-
return m_fun(*this, request);
475+
const UniValue ret = m_fun(*this, request);
476+
CHECK_NONFATAL(std::any_of(m_results.m_results.begin(), m_results.m_results.end(), [ret](const RPCResult& res) { return res.MatchesType(ret); }));
477+
return ret;
475478
}
476479

477480
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
@@ -677,6 +680,9 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
677680
sections.PushSection({indent + "..." + maybe_separator, m_description});
678681
return;
679682
}
683+
case Type::ANY: {
684+
CHECK_NONFATAL(false); // Only for testing
685+
}
680686
case Type::NONE: {
681687
sections.PushSection({indent + "null" + maybe_separator, Description("json null")});
682688
return;
@@ -742,6 +748,42 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
742748
CHECK_NONFATAL(false);
743749
}
744750

751+
bool RPCResult::MatchesType(const UniValue& result) const
752+
{
753+
switch (m_type) {
754+
case Type::ELISION: {
755+
return false;
756+
}
757+
case Type::ANY: {
758+
return true;
759+
}
760+
case Type::NONE: {
761+
return UniValue::VNULL == result.getType();
762+
}
763+
case Type::STR:
764+
case Type::STR_HEX: {
765+
return UniValue::VSTR == result.getType();
766+
}
767+
case Type::NUM:
768+
case Type::STR_AMOUNT:
769+
case Type::NUM_TIME: {
770+
return UniValue::VNUM == result.getType();
771+
}
772+
case Type::BOOL: {
773+
return UniValue::VBOOL == result.getType();
774+
}
775+
case Type::ARR_FIXED:
776+
case Type::ARR: {
777+
return UniValue::VARR == result.getType();
778+
}
779+
case Type::OBJ_DYN:
780+
case Type::OBJ: {
781+
return UniValue::VOBJ == result.getType();
782+
}
783+
} // no default case, so the compiler can warn about missing cases
784+
CHECK_NONFATAL(false);
785+
}
786+
745787
std::string RPCArg::ToStringObj(const bool oneline) const
746788
{
747789
std::string res;

src/rpc/util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ struct RPCResult {
223223
NUM,
224224
BOOL,
225225
NONE,
226+
ANY, //!< Special type to disable type checks (for testing only)
226227
STR_AMOUNT, //!< Special string to represent a floating point amount
227228
STR_HEX, //!< Special string with only hex chars
228229
OBJ_DYN, //!< Special dictionary with keys that are not literals
@@ -295,6 +296,8 @@ struct RPCResult {
295296
std::string ToStringObj() const;
296297
/** Return the description string, including the result type. */
297298
std::string ToDescriptionString() const;
299+
/** Check whether the result JSON type matches. */
300+
bool MatchesType(const UniValue& result) const;
298301
};
299302

300303
struct RPCResults {
@@ -333,7 +336,7 @@ class RPCHelpMan
333336
using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>;
334337
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
335338

336-
UniValue HandleRequest(const JSONRPCRequest& request);
339+
UniValue HandleRequest(const JSONRPCRequest& request) const;
337340
std::string ToString() const;
338341
/** Return the named args that need to be converted from string to another JSON type */
339342
UniValue GetArgMap() const;

0 commit comments

Comments
 (0)