diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index edd45d9731a..4a0e96fd750 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -82,7 +82,7 @@ static RPCHelpMan sendrawtransaction() CTransactionRef tx(MakeTransactionRef(std::move(mtx))); - const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg(1))}; + const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg("maxfeerate"))}; int64_t virtual_size = GetVirtualTransactionSize(*tx); CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size); @@ -162,7 +162,7 @@ static RPCHelpMan testmempoolaccept() "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions."); } - const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg(1))}; + const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg("maxfeerate"))}; std::vector txns; txns.reserve(raw_transactions.size()); @@ -873,7 +873,7 @@ static RPCHelpMan submitpackage() } // Fee check needs to be run with chainstate and package context - const CFeeRate max_raw_tx_fee_rate = ParseFeeRate(self.Arg(1)); + const CFeeRate max_raw_tx_fee_rate{ParseFeeRate(self.Arg("maxfeerate"))}; std::optional client_maxfeerate{max_raw_tx_fee_rate}; // 0-value is special; it's mapped to no sanity check if (max_raw_tx_fee_rate == CFeeRate(0)) { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 606fc62dbe9..63daa3da3a1 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -485,7 +485,7 @@ static RPCHelpMan prioritisetransaction() LOCK(cs_main); uint256 hash(ParseHashV(request.params[0], "txid")); - const auto dummy{self.MaybeArg(1)}; + const auto dummy{self.MaybeArg("dummy")}; CAmount nAmount = request.params[2].getInt(); if (dummy && *dummy != 0) { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4fc93291f5b..034dbdc914f 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -401,7 +401,7 @@ static RPCHelpMan addconnection() } else { throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString()); } - bool use_v2transport = self.Arg(2); + bool use_v2transport{self.Arg("v2transport")}; NodeContext& node = EnsureAnyNodeContext(request.context); CConnman& connman = EnsureConnman(node); diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 486c4215184..fe829ae9a47 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -677,7 +677,7 @@ static const UniValue* DetailMaybeArg(CheckFn* check, const std::vector& static void CheckRequiredOrDefault(const RPCArg& param) { - // Must use `Arg(i)` to get the argument or its default value. + // Must use `Arg(key)` to get the argument or its default value. const bool required{ std::holds_alternative(param.m_fallback) && RPCArg::Optional::NO == std::get(param.m_fallback), }; diff --git a/src/rpc/util.h b/src/rpc/util.h index 0e4dcc27b5e..394a429a29a 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -414,19 +414,16 @@ public: * argument isNull() and parses (from JSON) and returns the user-passed argument, * or the default value derived from the RPCArg documentation. * - * There are two overloads of this function: - * - Use Arg(size_t i) to get the argument (or the default value) by index. - * - Use Arg(const std::string& key) to get the argument (or the default value) by key. + * The instantiation of this helper for type R must match the corresponding RPCArg::Type. * - * The Type passed to this helper must match the corresponding RPCArg::Type. - * - * @return The value of the RPC argument (or the default value) cast to type Type. + * @return The value of the RPC argument (or the default value) cast to type R. * * @see MaybeArg for handling optional arguments without default values. */ template - auto Arg(size_t i) const + auto Arg(std::string_view key) const { + auto i{GetParamIndex(key)}; // Return argument (required or with default value). if constexpr (std::is_integral_v || std::is_floating_point_v) { // Return numbers by value. @@ -436,11 +433,6 @@ public: return ArgValue(i); } } - template - auto Arg(std::string_view key) const - { - return Arg(GetParamIndex(key)); - } /** * @brief Helper to get an optional request argument. * @@ -452,21 +444,18 @@ public: * argument isNull() and parses (from JSON) and returns the user-passed argument, * or a falsy value if no argument was passed. * - * There are two overloads of this function: - * - Use MaybeArg(size_t i) to get the optional argument by index. - * - Use MaybeArg(const std::string& key) to get the optional argument by key. + * The instantiation of this helper for type R must match the corresponding RPCArg::Type. * - * The Type passed to this helper must match the corresponding RPCArg::Type. + * @return For integral and floating-point types, a std::optional is returned. + * For other types, a R* pointer to the argument is returned. If the + * argument is not provided, std::nullopt or a null pointer is returned. * - * @return For integral and floating-point types, a std::optional is returned. - * For other types, a Type* pointer to the argument is returned. If the - * argument is not provided, std::nullopt or a null pointer is returned. - * * @see Arg for handling arguments that are required or have a default value. */ template - auto MaybeArg(size_t i) const + auto MaybeArg(std::string_view key) const { + auto i{GetParamIndex(key)}; // Return optional argument (without default). if constexpr (std::is_integral_v || std::is_floating_point_v) { // Return numbers by value, wrapped in optional. @@ -476,11 +465,6 @@ public: return ArgValue(i); } } - template - auto MaybeArg(std::string_view key) const - { - return MaybeArg(GetParamIndex(key)); - } std::string ToString() const; /** Return the named args that need to be converted from string to another JSON type */ UniValue GetArgMap() const; diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 3de4cd17942..efa078ca74c 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -614,40 +614,26 @@ BOOST_AUTO_TEST_CASE(rpc_arg_helper) //! Check that `self.Arg` returns the same value as the `request.params` accessors RPCHelpMan::RPCMethodImpl check_positional = [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - BOOST_CHECK_EQUAL(self.Arg(0), request.params[0].getInt()); - BOOST_CHECK_EQUAL(self.Arg(1), request.params[1].get_str()); - BOOST_CHECK_EQUAL(self.Arg(2), request.params[2].isNull() ? DEFAULT_UINT64_T : request.params[2].getInt()); - BOOST_CHECK_EQUAL(self.Arg(3), request.params[3].isNull() ? DEFAULT_STRING : request.params[3].get_str()); - BOOST_CHECK_EQUAL(self.Arg(4), request.params[4].isNull() ? DEFAULT_BOOL : request.params[4].get_bool()); + BOOST_CHECK_EQUAL(self.Arg("req_int"), request.params[0].getInt()); + BOOST_CHECK_EQUAL(self.Arg("req_str"), request.params[1].get_str()); + BOOST_CHECK_EQUAL(self.Arg("def_uint64_t"), request.params[2].isNull() ? DEFAULT_UINT64_T : request.params[2].getInt()); + BOOST_CHECK_EQUAL(self.Arg("def_string"), request.params[3].isNull() ? DEFAULT_STRING : request.params[3].get_str()); + BOOST_CHECK_EQUAL(self.Arg("def_bool"), request.params[4].isNull() ? DEFAULT_BOOL : request.params[4].get_bool()); if (!request.params[5].isNull()) { - BOOST_CHECK_EQUAL(self.MaybeArg(5).value(), request.params[5].get_real()); + BOOST_CHECK_EQUAL(self.MaybeArg("opt_double").value(), request.params[5].get_real()); } else { - BOOST_CHECK(!self.MaybeArg(5)); + BOOST_CHECK(!self.MaybeArg("opt_double")); } if (!request.params[6].isNull()) { - BOOST_CHECK(self.MaybeArg(6)); - BOOST_CHECK_EQUAL(*self.MaybeArg(6), request.params[6].get_str()); + BOOST_CHECK(self.MaybeArg("opt_string")); + BOOST_CHECK_EQUAL(*self.MaybeArg("opt_string"), request.params[6].get_str()); } else { - BOOST_CHECK(!self.MaybeArg(6)); + BOOST_CHECK(!self.MaybeArg("opt_string")); } return UniValue{}; }; CheckRpc(params, UniValue{JSON(R"([5, "hello", null, null, null, null, null])")}, check_positional); CheckRpc(params, UniValue{JSON(R"([5, "hello", 4, "test", true, 1.23, "world"])")}, check_positional); - - //! Check that `self.Arg` returns the same value when using index and key - RPCHelpMan::RPCMethodImpl check_named = [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - BOOST_CHECK_EQUAL(self.Arg(0), self.Arg("req_int")); - BOOST_CHECK_EQUAL(self.Arg(1), self.Arg("req_str")); - BOOST_CHECK_EQUAL(self.Arg(2), self.Arg("def_uint64_t")); - BOOST_CHECK_EQUAL(self.Arg(3), self.Arg("def_string")); - BOOST_CHECK_EQUAL(self.Arg(4), self.Arg("def_bool")); - BOOST_CHECK(self.MaybeArg(5) == self.MaybeArg("opt_double")); - BOOST_CHECK(self.MaybeArg(6) == self.MaybeArg("opt_string")); - return UniValue{}; - }; - CheckRpc(params, UniValue{JSON(R"([5, "hello", null, null, null, null, null])")}, check_named); - CheckRpc(params, UniValue{JSON(R"([5, "hello", 4, "test", true, 1.23, "world"])")}, check_named); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 68331bf85f9..8c218ad7661 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -395,7 +395,7 @@ static RPCHelpMan createwallet() if (!request.params[4].isNull() && request.params[4].get_bool()) { flags |= WALLET_FLAG_AVOID_REUSE; } - if (self.Arg(5)) { + if (self.Arg("descriptors")) { #ifndef USE_SQLITE throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)"); #endif @@ -489,7 +489,7 @@ static RPCHelpMan unloadwallet() // Release the "main" shared pointer and prevent further notifications. // Note that any attempt to load the same wallet would fail until the wallet // is destroyed (see CheckUniqueFileid). - std::optional load_on_start{self.MaybeArg(1)}; + std::optional load_on_start{self.MaybeArg("load_on_startup")}; if (!RemoveWallet(context, wallet, load_on_start, warnings)) { throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded"); }