aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp9
-rw-r--r--src/rpc/mining.cpp8
-rw-r--r--src/rpc/net.cpp6
-rw-r--r--src/rpc/node.cpp7
-rw-r--r--src/rpc/signmessage.cpp6
-rw-r--r--src/rpc/util.cpp12
-rw-r--r--src/rpc/util.h62
7 files changed, 84 insertions, 26 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index a1135c27d4..eed004806a 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -2174,7 +2174,8 @@ static RPCHelpMan scantxoutset()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
UniValue result(UniValue::VOBJ);
- if (request.params[0].get_str() == "status") {
+ const auto action{self.Arg<std::string>("action")};
+ if (action == "status") {
CoinsViewScanReserver reserver;
if (reserver.reserve()) {
// no scan in progress
@@ -2182,7 +2183,7 @@ static RPCHelpMan scantxoutset()
}
result.pushKV("progress", g_scan_progress.load());
return result;
- } else if (request.params[0].get_str() == "abort") {
+ } else if (action == "abort") {
CoinsViewScanReserver reserver;
if (reserver.reserve()) {
// reserve was possible which means no scan was running
@@ -2191,7 +2192,7 @@ static RPCHelpMan scantxoutset()
// set the abort flag
g_should_abort_scan = true;
return true;
- } else if (request.params[0].get_str() == "start") {
+ } else if (action == "start") {
CoinsViewScanReserver reserver;
if (!reserver.reserve()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
@@ -2260,7 +2261,7 @@ static RPCHelpMan scantxoutset()
result.pushKV("unspents", unspents);
result.pushKV("total_amount", ValueFromAmount(total_in));
} else {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", action));
}
return result;
},
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index f7cdbf52dd..454c262803 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -122,7 +122,7 @@ static RPCHelpMan getnetworkhashps()
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- return GetNetworkHashPS(self.Arg<int>(0), self.Arg<int>(1), chainman.ActiveChain());
+ return GetNetworkHashPS(self.Arg<int>("nblocks"), self.Arg<int>("height"), chainman.ActiveChain());
},
};
}
@@ -229,12 +229,12 @@ static RPCHelpMan generatetodescriptor()
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- const auto num_blocks{self.Arg<int>(0)};
- const auto max_tries{self.Arg<uint64_t>(2)};
+ const auto num_blocks{self.Arg<int>("num_blocks")};
+ const auto max_tries{self.Arg<uint64_t>("maxtries")};
CScript coinbase_script;
std::string error;
- if (!getScriptFromDescriptor(self.Arg<std::string>(1), coinbase_script, error)) {
+ if (!getScriptFromDescriptor(self.Arg<std::string>("descriptor"), coinbase_script, error)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index f935a3b08f..49789f538b 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -322,7 +322,7 @@ static RPCHelpMan addnode()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- const std::string command{request.params[1].get_str()};
+ const auto command{self.Arg<std::string>("command")};
if (command != "onetry" && command != "add" && command != "remove") {
throw std::runtime_error(
self.ToString());
@@ -331,9 +331,9 @@ static RPCHelpMan addnode()
NodeContext& node = EnsureAnyNodeContext(request.context);
CConnman& connman = EnsureConnman(node);
- const std::string node_arg{request.params[0].get_str()};
+ const auto node_arg{self.Arg<std::string>("node")};
bool node_v2transport = connman.GetLocalServices() & NODE_P2P_V2;
- bool use_v2transport = self.MaybeArg<bool>(2).value_or(node_v2transport);
+ bool use_v2transport = self.MaybeArg<bool>("v2transport").value_or(node_v2transport);
if (use_v2transport && !node_v2transport) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Error: v2transport requested but not enabled (see -v2transport)");
diff --git a/src/rpc/node.cpp b/src/rpc/node.cpp
index b8c0080aef..ffc2ee5ab0 100644
--- a/src/rpc/node.cpp
+++ b/src/rpc/node.cpp
@@ -26,6 +26,7 @@
#include <univalue.h>
#include <util/any.h>
#include <util/check.h>
+#include <util/time.h>
#include <stdint.h>
#ifdef HAVE_MALLOC_INFO
@@ -58,9 +59,11 @@ static RPCHelpMan setmocktime()
LOCK(cs_main);
const int64_t time{request.params[0].getInt<int64_t>()};
- if (time < 0) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime cannot be negative: %s.", time));
+ constexpr int64_t max_time{Ticks<std::chrono::seconds>(std::chrono::nanoseconds::max())};
+ if (time < 0 || time > max_time) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime must be in the range [0, %s], not %s.", max_time, time));
}
+
SetMockTime(time);
const NodeContext& node_context{EnsureAnyNodeContext(request.context)};
for (const auto& chain_client : node_context.chain_clients) {
diff --git a/src/rpc/signmessage.cpp b/src/rpc/signmessage.cpp
index 8c752ba1fd..9f3c24efcf 100644
--- a/src/rpc/signmessage.cpp
+++ b/src/rpc/signmessage.cpp
@@ -38,9 +38,9 @@ static RPCHelpMan verifymessage()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- std::string strAddress = request.params[0].get_str();
- std::string strSign = request.params[1].get_str();
- std::string strMessage = request.params[2].get_str();
+ std::string strAddress = self.Arg<std::string>("address");
+ std::string strSign = self.Arg<std::string>("signature");
+ std::string strMessage = self.Arg<std::string>("message");
switch (MessageVerify(strAddress, strSign, strMessage)) {
case MessageVerificationResult::ERR_INVALID_ADDRESS:
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 6e332e3855..f683878054 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -24,6 +24,8 @@
#include <util/string.h>
#include <util/translation.h>
+#include <algorithm>
+#include <iterator>
#include <string_view>
#include <tuple>
@@ -729,6 +731,16 @@ std::vector<std::pair<std::string, bool>> RPCHelpMan::GetArgNames() const
return ret;
}
+size_t RPCHelpMan::GetParamIndex(std::string_view key) const
+{
+ auto it{std::find_if(
+ m_args.begin(), m_args.end(), [&key](const auto& arg) { return arg.GetName() == key;}
+ )};
+
+ CHECK_NONFATAL(it != m_args.end()); // TODO: ideally this is checked at compile time
+ return std::distance(m_args.begin(), it);
+}
+
std::string RPCHelpMan::ToString() const
{
std::string ret;
diff --git a/src/rpc/util.h b/src/rpc/util.h
index f6ee6a317a..177af90c05 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -404,18 +404,25 @@ public:
UniValue HandleRequest(const JSONRPCRequest& request) const;
/**
- * Helper to get a request argument.
- * This function only works during m_fun(), i.e. it should only be used in
- * RPC method implementations. The helper internally checks whether the
- * user-passed argument isNull() and parses (from JSON) and returns the
- * user-passed argument, or the default value derived from the RPCArg
- * documentation, or a falsy value if no default was given.
+ * @brief Helper to get a required or default-valued request argument.
*
- * Use Arg<Type>(i) to get the argument or its default value. Otherwise,
- * use MaybeArg<Type>(i) to get the optional argument or a falsy value.
+ * Use this function when the argument is required or when it has a default value. If the
+ * argument is optional and may not be provided, use MaybeArg instead.
*
- * The Type passed to this helper must match the corresponding
- * RPCArg::Type.
+ * This function only works during m_fun(), i.e., it should only be used in
+ * RPC method implementations. It internally checks whether the user-passed
+ * 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<Type>(size_t i) to get the argument (or the default value) by index.
+ * - Use Arg<Type>(const std::string& key) to get the argument (or the default value) by key.
+ *
+ * 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.
+ *
+ * @see MaybeArg for handling optional arguments without default values.
*/
template <typename R>
auto Arg(size_t i) const
@@ -429,6 +436,34 @@ public:
return ArgValue<const R&>(i);
}
}
+ template<typename R>
+ auto Arg(std::string_view key) const
+ {
+ return Arg<R>(GetParamIndex(key));
+ }
+ /**
+ * @brief Helper to get an optional request argument.
+ *
+ * Use this function when the argument is optional and does not have a default value. If the
+ * argument is required or has a default value, use Arg instead.
+ *
+ * This function only works during m_fun(), i.e., it should only be used in
+ * RPC method implementations. It internally checks whether the user-passed
+ * 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<Type>(size_t i) to get the optional argument by index.
+ * - Use MaybeArg<Type>(const std::string& key) to get the optional argument by key.
+ *
+ * The Type passed to this helper must match the corresponding RPCArg::Type.
+ *
+ * @return For integral and floating-point types, a std::optional<Type> 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 <typename R>
auto MaybeArg(size_t i) const
{
@@ -441,6 +476,11 @@ public:
return ArgValue<const R*>(i);
}
}
+ template<typename R>
+ auto MaybeArg(std::string_view key) const
+ {
+ return MaybeArg<R>(GetParamIndex(key));
+ }
std::string ToString() const;
/** Return the named args that need to be converted from string to another JSON type */
UniValue GetArgMap() const;
@@ -460,6 +500,8 @@ private:
mutable const JSONRPCRequest* m_req{nullptr}; // A pointer to the request for the duration of m_fun()
template <typename R>
R ArgValue(size_t i) const;
+ //! Return positional index of a parameter using its name as key.
+ size_t GetParamIndex(std::string_view key) const;
};
/**