mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-13 19:50:43 +02:00
rpc: Add MaybeArg() and Arg() default helper
This commit is contained in:
parent
cd5d2f5f09
commit
c00000df16
@ -110,7 +110,7 @@ static RPCHelpMan getnetworkhashps()
|
|||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].getInt<int>() : 120, !request.params[1].isNull() ? request.params[1].getInt<int>() : -1, chainman.ActiveChain());
|
return GetNetworkHashPS(self.Arg<int>(0), self.Arg<int>(1), chainman.ActiveChain());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -217,12 +217,12 @@ static RPCHelpMan generatetodescriptor()
|
|||||||
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
|
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
{
|
{
|
||||||
const int num_blocks{request.params[0].getInt<int>()};
|
const auto num_blocks{self.Arg<int>(0)};
|
||||||
const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
|
const auto max_tries{self.Arg<uint64_t>(2)};
|
||||||
|
|
||||||
CScript coinbase_script;
|
CScript coinbase_script;
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!getScriptFromDescriptor(request.params[1].get_str(), coinbase_script, error)) {
|
if (!getScriptFromDescriptor(self.Arg<std::string>(1), coinbase_script, error)) {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,9 +468,10 @@ static RPCHelpMan prioritisetransaction()
|
|||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
uint256 hash(ParseHashV(request.params[0], "txid"));
|
uint256 hash(ParseHashV(request.params[0], "txid"));
|
||||||
|
const auto dummy{self.MaybeArg<double>(1)};
|
||||||
CAmount nAmount = request.params[2].getInt<int64_t>();
|
CAmount nAmount = request.params[2].getInt<int64_t>();
|
||||||
|
|
||||||
if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) {
|
if (dummy && *dummy != 0) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,7 +609,10 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
|
|||||||
if (!arg_mismatch.empty()) {
|
if (!arg_mismatch.empty()) {
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Wrong type passed:\n%s", arg_mismatch.write(4)));
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Wrong type passed:\n%s", arg_mismatch.write(4)));
|
||||||
}
|
}
|
||||||
|
CHECK_NONFATAL(m_req == nullptr);
|
||||||
|
m_req = &request;
|
||||||
UniValue ret = m_fun(*this, request);
|
UniValue ret = m_fun(*this, request);
|
||||||
|
m_req = nullptr;
|
||||||
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
|
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
|
||||||
UniValue mismatch{UniValue::VARR};
|
UniValue mismatch{UniValue::VARR};
|
||||||
for (const auto& res : m_results.m_results) {
|
for (const auto& res : m_results.m_results) {
|
||||||
@ -635,6 +638,49 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using CheckFn = void(const RPCArg&);
|
||||||
|
static const UniValue* DetailMaybeArg(CheckFn* check, const std::vector<RPCArg>& params, const JSONRPCRequest* req, size_t i)
|
||||||
|
{
|
||||||
|
CHECK_NONFATAL(i < params.size());
|
||||||
|
const UniValue& arg{CHECK_NONFATAL(req)->params[i]};
|
||||||
|
const RPCArg& param{params.at(i)};
|
||||||
|
if (check) check(param);
|
||||||
|
|
||||||
|
if (!arg.isNull()) return &arg;
|
||||||
|
if (!std::holds_alternative<RPCArg::Default>(param.m_fallback)) return nullptr;
|
||||||
|
return &std::get<RPCArg::Default>(param.m_fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckRequiredOrDefault(const RPCArg& param)
|
||||||
|
{
|
||||||
|
// Must use `Arg<Type>(i)` to get the argument or its default value.
|
||||||
|
const bool required{
|
||||||
|
std::holds_alternative<RPCArg::Optional>(param.m_fallback) && RPCArg::Optional::NO == std::get<RPCArg::Optional>(param.m_fallback),
|
||||||
|
};
|
||||||
|
CHECK_NONFATAL(required || std::holds_alternative<RPCArg::Default>(param.m_fallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TMPL_INST(check_param, ret_type, return_code) \
|
||||||
|
template <> \
|
||||||
|
ret_type RPCHelpMan::ArgValue<ret_type>(size_t i) const \
|
||||||
|
{ \
|
||||||
|
const UniValue* maybe_arg{ \
|
||||||
|
DetailMaybeArg(check_param, m_args, m_req, i), \
|
||||||
|
}; \
|
||||||
|
return return_code \
|
||||||
|
} \
|
||||||
|
void force_semicolon(ret_type)
|
||||||
|
|
||||||
|
// Optional arg (without default). Can also be called on required args, if needed.
|
||||||
|
TMPL_INST(nullptr, std::optional<double>, maybe_arg ? std::optional{maybe_arg->get_real()} : std::nullopt;);
|
||||||
|
TMPL_INST(nullptr, std::optional<bool>, maybe_arg ? std::optional{maybe_arg->get_bool()} : std::nullopt;);
|
||||||
|
TMPL_INST(nullptr, const std::string*, maybe_arg ? &maybe_arg->get_str() : nullptr;);
|
||||||
|
|
||||||
|
// Required arg or optional arg with default value.
|
||||||
|
TMPL_INST(CheckRequiredOrDefault, int, CHECK_NONFATAL(maybe_arg)->getInt<int>(););
|
||||||
|
TMPL_INST(CheckRequiredOrDefault, uint64_t, CHECK_NONFATAL(maybe_arg)->getInt<uint64_t>(););
|
||||||
|
TMPL_INST(CheckRequiredOrDefault, const std::string&, CHECK_NONFATAL(maybe_arg)->get_str(););
|
||||||
|
|
||||||
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
|
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
|
||||||
{
|
{
|
||||||
size_t num_required_args = 0;
|
size_t num_required_args = 0;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define BITCOIN_RPC_UTIL_H
|
#define BITCOIN_RPC_UTIL_H
|
||||||
|
|
||||||
#include <addresstype.h>
|
#include <addresstype.h>
|
||||||
|
#include <consensus/amount.h>
|
||||||
#include <node/transaction.h>
|
#include <node/transaction.h>
|
||||||
#include <outputtype.h>
|
#include <outputtype.h>
|
||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
@ -14,13 +15,29 @@
|
|||||||
#include <rpc/request.h>
|
#include <rpc/request.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/sign.h>
|
#include <script/sign.h>
|
||||||
|
#include <uint256.h>
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class JSONRPCRequest;
|
||||||
|
enum ServiceFlags : uint64_t;
|
||||||
|
enum class OutputType;
|
||||||
|
enum class TransactionError;
|
||||||
|
struct FlatSigningProvider;
|
||||||
|
struct bilingual_str;
|
||||||
|
|
||||||
static constexpr bool DEFAULT_RPC_DOC_CHECK{
|
static constexpr bool DEFAULT_RPC_DOC_CHECK{
|
||||||
#ifdef RPC_DOC_CHECK
|
#ifdef RPC_DOC_CHECK
|
||||||
true
|
true
|
||||||
@ -383,6 +400,44 @@ public:
|
|||||||
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
|
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
|
||||||
|
|
||||||
UniValue HandleRequest(const JSONRPCRequest& request) const;
|
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
|
||||||
|
* documention, or a falsy value if no default was given.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The Type passed to this helper must match the corresponding
|
||||||
|
* RPCArg::Type.
|
||||||
|
*/
|
||||||
|
template <typename R>
|
||||||
|
auto Arg(size_t i) const
|
||||||
|
{
|
||||||
|
// Return argument (required or with default value).
|
||||||
|
if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
|
||||||
|
// Return numbers by value.
|
||||||
|
return ArgValue<R>(i);
|
||||||
|
} else {
|
||||||
|
// Return everything else by reference.
|
||||||
|
return ArgValue<const R&>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <typename R>
|
||||||
|
auto MaybeArg(size_t i) const
|
||||||
|
{
|
||||||
|
// Return optional argument (without default).
|
||||||
|
if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
|
||||||
|
// Return numbers by value, wrapped in optional.
|
||||||
|
return ArgValue<std::optional<R>>(i);
|
||||||
|
} else {
|
||||||
|
// Return other types by pointer.
|
||||||
|
return ArgValue<const R*>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
/** Return 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 */
|
||||||
UniValue GetArgMap() const;
|
UniValue GetArgMap() const;
|
||||||
@ -399,6 +454,9 @@ private:
|
|||||||
const std::vector<RPCArg> m_args;
|
const std::vector<RPCArg> m_args;
|
||||||
const RPCResults m_results;
|
const RPCResults m_results;
|
||||||
const RPCExamples m_examples;
|
const RPCExamples m_examples;
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,8 +194,8 @@ RPCHelpMan getbalance()
|
|||||||
|
|
||||||
LOCK(pwallet->cs_wallet);
|
LOCK(pwallet->cs_wallet);
|
||||||
|
|
||||||
const UniValue& dummy_value = request.params[0];
|
const auto dummy_value{self.MaybeArg<std::string>(0)};
|
||||||
if (!dummy_value.isNull() && dummy_value.get_str() != "*") {
|
if (dummy_value && *dummy_value != "*") {
|
||||||
throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
|
throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ static RPCHelpMan unloadwallet()
|
|||||||
// Release the "main" shared pointer and prevent further notifications.
|
// Release the "main" shared pointer and prevent further notifications.
|
||||||
// Note that any attempt to load the same wallet would fail until the wallet
|
// Note that any attempt to load the same wallet would fail until the wallet
|
||||||
// is destroyed (see CheckUniqueFileid).
|
// is destroyed (see CheckUniqueFileid).
|
||||||
std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
|
std::optional<bool> load_on_start{self.MaybeArg<bool>(1)};
|
||||||
if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
|
if (!RemoveWallet(context, wallet, load_on_start, warnings)) {
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
|
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user