Skip to content

Commit 7799f53

Browse files
committed
Merge bitcoin/bitcoin#26039: refactor: Run type check against RPCArgs (1/2)
fa9f6d7 rpc: Run type check against RPCArgs (MarcoFalke) faf9672 test: Fix wrong types passed to RPCs (MarcoFalke) Pull request description: It seems brittle to require `RPCTypeCheck` being called inside the code logic. Without compile-time enforcement this will lead to places where it is forgotten and thus to inconsistencies and bugs. Fix this by removing the calls to `RPCTypeCheck` and doing the check internally. The changes should be reviewed as refactoring changes. However, if they change behavior, it will be a bugfix. For example the changes here happen to also detect/fix bugs like the one fixed in commit 3b5fb6e. ACKs for top commit: ajtowns: ACK fa9f6d7 Tree-SHA512: fb2c0981fe6e24da3ca7dbc06898730779ea4e02ea485458505a281cf421015e44dad0221a04023fc547ea2c660d94657909843fc85d92b847611ec097532439
2 parents 8339f3c + fa9f6d7 commit 7799f53

File tree

14 files changed

+85
-155
lines changed

14 files changed

+85
-155
lines changed

src/rpc/blockchain.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -445,11 +445,6 @@ static RPCHelpMan getblockfrompeer()
445445
},
446446
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
447447
{
448-
RPCTypeCheck(request.params, {
449-
UniValue::VSTR, // blockhash
450-
UniValue::VNUM, // peer_id
451-
});
452-
453448
const NodeContext& node = EnsureAnyNodeContext(request.context);
454449
ChainstateManager& chainman = EnsureChainman(node);
455450
PeerManager& peerman = EnsurePeerman(node);
@@ -655,7 +650,8 @@ static RPCHelpMan getblock()
655650
"If verbosity is 3, returns an Object with information about block <hash> and information about each transaction, including prevout information for inputs (only for unpruned blocks in the current best chain).\n",
656651
{
657652
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
658-
{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{1}, "0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs"},
653+
{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{1}, "0 for hex-encoded data, 1 for a JSON object, 2 for JSON object with transaction data, and 3 for JSON object with transaction data including prevout information for inputs",
654+
RPCArgOptions{.skip_type_check = true}},
659655
},
660656
{
661657
RPCResult{"for verbosity = 0",
@@ -873,7 +869,11 @@ static RPCHelpMan gettxoutsetinfo()
873869
"Note this call may take some time if you are not using coinstatsindex.\n",
874870
{
875871
{"hash_type", RPCArg::Type::STR, RPCArg::Default{"hash_serialized_2"}, "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
876-
{"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).", RPCArgOptions{.type_str={"", "string or numeric"}}},
872+
{"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).",
873+
RPCArgOptions{
874+
.skip_type_check = true,
875+
.type_str = {"", "string or numeric"},
876+
}},
877877
{"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."},
878878
},
879879
RPCResult{
@@ -1743,7 +1743,11 @@ static RPCHelpMan getblockstats()
17431743
"\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
17441744
"It won't work for some heights with pruning.\n",
17451745
{
1746-
{"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block", RPCArgOptions{.type_str={"", "string or numeric"}}},
1746+
{"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block hash or height of the target block",
1747+
RPCArgOptions{
1748+
.skip_type_check = true,
1749+
.type_str = {"", "string or numeric"},
1750+
}},
17471751
{"stats", RPCArg::Type::ARR, RPCArg::DefaultHint{"all values"}, "Values to plot (see result below)",
17481752
{
17491753
{"height", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Selected statistic"},
@@ -2145,8 +2149,6 @@ static RPCHelpMan scantxoutset()
21452149
},
21462150
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
21472151
{
2148-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});
2149-
21502152
UniValue result(UniValue::VOBJ);
21512153
if (request.params[0].get_str() == "status") {
21522154
CoinsViewScanReserver reserver;

src/rpc/fees.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ static RPCHelpMan estimatesmartfee()
6363
},
6464
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
6565
{
66-
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
67-
6866
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
6967
const NodeContext& node = EnsureAnyNodeContext(request.context);
7068
const CTxMemPool& mempool = EnsureMemPool(node);
@@ -155,8 +153,6 @@ static RPCHelpMan estimaterawfee()
155153
},
156154
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
157155
{
158-
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
159-
160156
CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
161157

162158
unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);

src/rpc/mempool.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,6 @@ static RPCHelpMan sendrawtransaction()
6161
},
6262
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
6363
{
64-
RPCTypeCheck(request.params, {
65-
UniValue::VSTR,
66-
UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
67-
});
68-
6964
CMutableTransaction mtx;
7065
if (!DecodeHexTx(mtx, request.params[0].get_str())) {
7166
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
@@ -147,10 +142,6 @@ static RPCHelpMan testmempoolaccept()
147142
},
148143
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
149144
{
150-
RPCTypeCheck(request.params, {
151-
UniValue::VARR,
152-
UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
153-
});
154145
const UniValue raw_transactions = request.params[0].get_array();
155146
if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
156147
throw JSONRPCError(RPC_INVALID_PARAMETER,
@@ -800,9 +791,6 @@ static RPCHelpMan submitpackage()
800791
if (!Params().IsMockableChain()) {
801792
throw std::runtime_error("submitpackage is for regression testing (-regtest mode) only");
802793
}
803-
RPCTypeCheck(request.params, {
804-
UniValue::VARR,
805-
});
806794
const UniValue raw_transactions = request.params[0].get_array();
807795
if (raw_transactions.size() < 1 || raw_transactions.size() > MAX_PACKAGE_COUNT) {
808796
throw JSONRPCError(RPC_INVALID_PARAMETER,

src/rpc/net.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,6 @@ static RPCHelpMan addconnection()
362362
throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");
363363
}
364364

365-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VSTR});
366365
const std::string address = request.params[0].get_str();
367366
const std::string conn_type_in{TrimString(request.params[1].get_str())};
368367
ConnectionType conn_type{};

src/rpc/node.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ static RPCHelpMan setmocktime()
5353
// ensure all call sites of GetTime() are accessing this safely.
5454
LOCK(cs_main);
5555

56-
RPCTypeCheck(request.params, {UniValue::VNUM});
5756
const int64_t time{request.params[0].getInt<int64_t>()};
5857
if (time < 0) {
5958
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime cannot be negative: %s.", time));
@@ -107,8 +106,6 @@ static RPCHelpMan mockscheduler()
107106
throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");
108107
}
109108

110-
// check params are valid values
111-
RPCTypeCheck(request.params, {UniValue::VNUM});
112109
int64_t delta_seconds = request.params[0].getInt<int64_t>();
113110
if (delta_seconds <= 0 || delta_seconds > 3600) {
114111
throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");
@@ -296,18 +293,18 @@ static RPCHelpMan echo(const std::string& name)
296293
"\nIt will return an internal bug report when arg9='trigger_internal_bug' is passed.\n"
297294
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
298295
"bitcoin-cli and the GUI. There is no server-side difference.",
299-
{
300-
{"arg0", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
301-
{"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
302-
{"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
303-
{"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
304-
{"arg4", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
305-
{"arg5", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
306-
{"arg6", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
307-
{"arg7", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
308-
{"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
309-
{"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
310-
},
296+
{
297+
{"arg0", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
298+
{"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
299+
{"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
300+
{"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
301+
{"arg4", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
302+
{"arg5", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
303+
{"arg6", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
304+
{"arg7", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
305+
{"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
306+
{"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "", RPCArgOptions{.skip_type_check = true}},
307+
},
311308
RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
312309
RPCExamples{""},
313310
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue

src/rpc/output_script.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,6 @@ static RPCHelpMan getdescriptorinfo()
195195
},
196196
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
197197
{
198-
RPCTypeCheck(request.params, {UniValue::VSTR});
199-
200198
FlatSigningProvider provider;
201199
std::string error;
202200
auto desc = Parse(request.params[0].get_str(), provider, error);
@@ -247,7 +245,6 @@ static RPCHelpMan deriveaddresses()
247245
},
248246
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
249247
{
250-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later
251248
const std::string desc_str = request.params[0].get_str();
252249

253250
int64_t range_begin = 0;

src/rpc/rawtransaction.cpp

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static std::vector<RPCArg> CreateTxDoc()
162162
},
163163
},
164164
},
165-
},
165+
RPCArgOptions{.skip_type_check = true}},
166166
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
167167
{"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Marks this transaction as BIP125-replaceable.\n"
168168
"Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
@@ -185,7 +185,8 @@ static RPCHelpMan getrawtransaction()
185185
"If verbosity is 2, returns a JSON Object with information about the transaction, including fee and prevout information.",
186186
{
187187
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
188-
{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for hex-encoded data, 1 for a JSON object, and 2 for JSON object with fee and prevout"},
188+
{"verbosity|verbose", RPCArg::Type::NUM, RPCArg::Default{0}, "0 for hex-encoded data, 1 for a JSON object, and 2 for JSON object with fee and prevout",
189+
RPCArgOptions{.skip_type_check = true}},
189190
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "The block in which to look for the transaction"},
190191
},
191192
{
@@ -354,14 +355,6 @@ static RPCHelpMan createrawtransaction()
354355
},
355356
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
356357
{
357-
RPCTypeCheck(request.params, {
358-
UniValue::VARR,
359-
UniValueType(), // ARR or OBJ, checked later
360-
UniValue::VNUM,
361-
UniValue::VBOOL
362-
}, true
363-
);
364-
365358
std::optional<bool> rbf;
366359
if (!request.params[3].isNull()) {
367360
rbf = request.params[3].get_bool();
@@ -397,8 +390,6 @@ static RPCHelpMan decoderawtransaction()
397390
},
398391
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
399392
{
400-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
401-
402393
CMutableTransaction mtx;
403394

404395
bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
@@ -451,8 +442,6 @@ static RPCHelpMan decodescript()
451442
},
452443
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
453444
{
454-
RPCTypeCheck(request.params, {UniValue::VSTR});
455-
456445
UniValue r(UniValue::VOBJ);
457446
CScript script;
458447
if (request.params[0].get_str().size() > 0){
@@ -702,8 +691,6 @@ static RPCHelpMan signrawtransactionwithkey()
702691
},
703692
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
704693
{
705-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
706-
707694
CMutableTransaction mtx;
708695
if (!DecodeHexTx(mtx, request.params[0].get_str())) {
709696
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
@@ -981,8 +968,6 @@ static RPCHelpMan decodepsbt()
981968
},
982969
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
983970
{
984-
RPCTypeCheck(request.params, {UniValue::VSTR});
985-
986971
// Unserialize the transactions
987972
PartiallySignedTransaction psbtx;
988973
std::string error;
@@ -1395,8 +1380,6 @@ static RPCHelpMan combinepsbt()
13951380
},
13961381
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
13971382
{
1398-
RPCTypeCheck(request.params, {UniValue::VARR}, true);
1399-
14001383
// Unserialize the transactions
14011384
std::vector<PartiallySignedTransaction> psbtxs;
14021385
UniValue txs = request.params[0].get_array();
@@ -1450,8 +1433,6 @@ static RPCHelpMan finalizepsbt()
14501433
},
14511434
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
14521435
{
1453-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true);
1454-
14551436
// Unserialize the transactions
14561437
PartiallySignedTransaction psbtx;
14571438
std::string error;
@@ -1499,14 +1480,6 @@ static RPCHelpMan createpsbt()
14991480
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
15001481
{
15011482

1502-
RPCTypeCheck(request.params, {
1503-
UniValue::VARR,
1504-
UniValueType(), // ARR or OBJ, checked later
1505-
UniValue::VNUM,
1506-
UniValue::VBOOL,
1507-
}, true
1508-
);
1509-
15101483
std::optional<bool> rbf;
15111484
if (!request.params[3].isNull()) {
15121485
rbf = request.params[3].get_bool();
@@ -1560,8 +1533,6 @@ static RPCHelpMan converttopsbt()
15601533
},
15611534
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
15621535
{
1563-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true);
1564-
15651536
// parse hex string from parameter
15661537
CMutableTransaction tx;
15671538
bool permitsigdata = request.params[1].isNull() ? false : request.params[1].get_bool();
@@ -1623,8 +1594,6 @@ static RPCHelpMan utxoupdatepsbt()
16231594
},
16241595
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
16251596
{
1626-
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true);
1627-
16281597
// Unserialize the transactions
16291598
PartiallySignedTransaction psbtx;
16301599
std::string error;
@@ -1714,8 +1683,6 @@ static RPCHelpMan joinpsbts()
17141683
},
17151684
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
17161685
{
1717-
RPCTypeCheck(request.params, {UniValue::VARR}, true);
1718-
17191686
// Unserialize the transactions
17201687
std::vector<PartiallySignedTransaction> psbtxs;
17211688
UniValue txs = request.params[0].get_array();
@@ -1842,8 +1809,6 @@ static RPCHelpMan analyzepsbt()
18421809
},
18431810
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
18441811
{
1845-
RPCTypeCheck(request.params, {UniValue::VSTR});
1846-
18471812
// Unserialize the transaction
18481813
PartiallySignedTransaction psbtx;
18491814
std::string error;

src/rpc/util.cpp

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,6 @@ std::string GetAllOutputTypes()
3030
return Join(ret, ", ");
3131
}
3232

33-
void RPCTypeCheck(const UniValue& params,
34-
const std::list<UniValueType>& typesExpected,
35-
bool fAllowNull)
36-
{
37-
unsigned int i = 0;
38-
for (const UniValueType& t : typesExpected) {
39-
if (params.size() <= i)
40-
break;
41-
42-
const UniValue& v = params[i];
43-
if (!(fAllowNull && v.isNull())) {
44-
RPCTypeCheckArgument(v, t);
45-
}
46-
i++;
47-
}
48-
}
49-
5033
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
5134
{
5235
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
@@ -579,6 +562,9 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
579562
if (request.mode == JSONRPCRequest::GET_HELP || !IsValidNumArgs(request.params.size())) {
580563
throw std::runtime_error(ToString());
581564
}
565+
for (size_t i{0}; i < m_args.size(); ++i) {
566+
m_args.at(i).MatchesType(request.params[i]);
567+
}
582568
UniValue ret = m_fun(*this, request);
583569
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
584570
CHECK_NONFATAL(std::any_of(m_results.m_results.begin(), m_results.m_results.end(), [&ret](const RPCResult& res) { return res.MatchesType(ret); }));
@@ -677,6 +663,44 @@ UniValue RPCHelpMan::GetArgMap() const
677663
return arr;
678664
}
679665

666+
void RPCArg::MatchesType(const UniValue& request) const
667+
{
668+
if (m_opts.skip_type_check) return;
669+
if (IsOptional() && request.isNull()) return;
670+
switch (m_type) {
671+
case Type::STR_HEX:
672+
case Type::STR: {
673+
RPCTypeCheckArgument(request, UniValue::VSTR);
674+
return;
675+
}
676+
case Type::NUM: {
677+
RPCTypeCheckArgument(request, UniValue::VNUM);
678+
return;
679+
}
680+
case Type::AMOUNT: {
681+
// VNUM or VSTR, checked inside AmountFromValue()
682+
return;
683+
}
684+
case Type::RANGE: {
685+
// VNUM or VARR, checked inside ParseRange()
686+
return;
687+
}
688+
case Type::BOOL: {
689+
RPCTypeCheckArgument(request, UniValue::VBOOL);
690+
return;
691+
}
692+
case Type::OBJ:
693+
case Type::OBJ_USER_KEYS: {
694+
RPCTypeCheckArgument(request, UniValue::VOBJ);
695+
return;
696+
}
697+
case Type::ARR: {
698+
RPCTypeCheckArgument(request, UniValue::VARR);
699+
return;
700+
}
701+
} // no default case, so the compiler can warn about missing cases
702+
}
703+
680704
std::string RPCArg::GetFirstName() const
681705
{
682706
return m_names.substr(0, m_names.find("|"));

0 commit comments

Comments
 (0)