[build] Move rpc utility methods to rpc/util
Moves the following utility methods to rpc/util and moves that unit to libbitcoin_common so they can be accessed by all libraries. - `RPCTypeCheck` - `RPCTypeCheckArgument` - `RPCTypeCheckObj` - `AmountFromValue` - `ParseHashV``ParseHashO` - `ParseHexV` - `ParseHexO` - `HelpExampleCli` - `HelpExampleRpc`
This commit is contained in:
parent
4a75c9d651
commit
1acc61f874
6 changed files with 148 additions and 148 deletions
|
@ -280,7 +280,6 @@ libbitcoin_server_a_SOURCES = \
|
||||||
rpc/net.cpp \
|
rpc/net.cpp \
|
||||||
rpc/rawtransaction.cpp \
|
rpc/rawtransaction.cpp \
|
||||||
rpc/server.cpp \
|
rpc/server.cpp \
|
||||||
rpc/util.cpp \
|
|
||||||
script/sigcache.cpp \
|
script/sigcache.cpp \
|
||||||
shutdown.cpp \
|
shutdown.cpp \
|
||||||
timedata.cpp \
|
timedata.cpp \
|
||||||
|
@ -440,6 +439,7 @@ libbitcoin_common_a_SOURCES = \
|
||||||
policy/policy.cpp \
|
policy/policy.cpp \
|
||||||
protocol.cpp \
|
protocol.cpp \
|
||||||
psbt.cpp \
|
psbt.cpp \
|
||||||
|
rpc/util.cpp \
|
||||||
scheduler.cpp \
|
scheduler.cpp \
|
||||||
script/descriptor.cpp \
|
script/descriptor.cpp \
|
||||||
script/ismine.cpp \
|
script/ismine.cpp \
|
||||||
|
|
|
@ -77,99 +77,6 @@ void RPCServer::OnStopped(std::function<void ()> slot)
|
||||||
g_rpcSignals.Stopped.connect(slot);
|
g_rpcSignals.Stopped.connect(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCTypeCheck(const UniValue& params,
|
|
||||||
const std::list<UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull)
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
for (const UniValueType& t : typesExpected) {
|
|
||||||
if (params.size() <= i)
|
|
||||||
break;
|
|
||||||
|
|
||||||
const UniValue& v = params[i];
|
|
||||||
if (!(fAllowNull && v.isNull())) {
|
|
||||||
RPCTypeCheckArgument(v, t);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
|
|
||||||
{
|
|
||||||
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCTypeCheckObj(const UniValue& o,
|
|
||||||
const std::map<std::string, UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull,
|
|
||||||
bool fStrict)
|
|
||||||
{
|
|
||||||
for (const auto& t : typesExpected) {
|
|
||||||
const UniValue& v = find_value(o, t.first);
|
|
||||||
if (!fAllowNull && v.isNull())
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
|
|
||||||
|
|
||||||
if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
|
|
||||||
std::string err = strprintf("Expected type %s for %s, got %s",
|
|
||||||
uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fStrict)
|
|
||||||
{
|
|
||||||
for (const std::string& k : o.getKeys())
|
|
||||||
{
|
|
||||||
if (typesExpected.count(k) == 0)
|
|
||||||
{
|
|
||||||
std::string err = strprintf("Unexpected key %s", k);
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CAmount AmountFromValue(const UniValue& value)
|
|
||||||
{
|
|
||||||
if (!value.isNum() && !value.isStr())
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
|
|
||||||
CAmount amount;
|
|
||||||
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
|
||||||
if (!MoneyRange(amount))
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 ParseHashV(const UniValue& v, std::string strName)
|
|
||||||
{
|
|
||||||
std::string strHex(v.get_str());
|
|
||||||
if (64 != strHex.length())
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", strName, 64, strHex.length(), strHex));
|
|
||||||
if (!IsHex(strHex)) // Note: IsHex("") is false
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
|
||||||
return uint256S(strHex);
|
|
||||||
}
|
|
||||||
uint256 ParseHashO(const UniValue& o, std::string strKey)
|
|
||||||
{
|
|
||||||
return ParseHashV(find_value(o, strKey), strKey);
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
|
|
||||||
{
|
|
||||||
std::string strHex;
|
|
||||||
if (v.isStr())
|
|
||||||
strHex = v.get_str();
|
|
||||||
if (!IsHex(strHex))
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
|
||||||
return ParseHex(strHex);
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
|
|
||||||
{
|
|
||||||
return ParseHexV(find_value(o, strKey), strKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
|
std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& helpreq) const
|
||||||
{
|
{
|
||||||
std::string strRet;
|
std::string strRet;
|
||||||
|
@ -581,17 +488,6 @@ std::vector<std::string> CRPCTable::listCommands() const
|
||||||
return commandList;
|
return commandList;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
|
||||||
{
|
|
||||||
return "> bitcoin-cli " + methodname + " " + args + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
|
||||||
{
|
|
||||||
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
|
||||||
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
||||||
{
|
{
|
||||||
if (!timerInterface)
|
if (!timerInterface)
|
||||||
|
|
|
@ -27,15 +27,6 @@ namespace RPCServer
|
||||||
void OnStopped(std::function<void ()> slot);
|
void OnStopped(std::function<void ()> slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Wrapper for UniValue::VType, which includes typeAny:
|
|
||||||
* Used to denote don't care type. */
|
|
||||||
struct UniValueType {
|
|
||||||
UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
|
|
||||||
UniValueType() : typeAny(true) {}
|
|
||||||
bool typeAny;
|
|
||||||
UniValue::VType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class JSONRPCRequest
|
class JSONRPCRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -65,26 +56,6 @@ void SetRPCWarmupFinished();
|
||||||
/* returns the current warmup state. */
|
/* returns the current warmup state. */
|
||||||
bool RPCIsInWarmup(std::string *outStatus);
|
bool RPCIsInWarmup(std::string *outStatus);
|
||||||
|
|
||||||
/**
|
|
||||||
* Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
|
|
||||||
* the right number of arguments are passed, just that any passed are the correct type.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheck(const UniValue& params,
|
|
||||||
const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type-check one argument; throws JSONRPCError if wrong type given.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for expected keys/value types in an Object.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheckObj(const UniValue& o,
|
|
||||||
const std::map<std::string, UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull = false,
|
|
||||||
bool fStrict = false);
|
|
||||||
|
|
||||||
/** Opaque base class for timers returned by NewTimerFunc.
|
/** Opaque base class for timers returned by NewTimerFunc.
|
||||||
* This provides no methods at the moment, but makes sure that delete
|
* This provides no methods at the moment, but makes sure that delete
|
||||||
* cleans up the whole state.
|
* cleans up the whole state.
|
||||||
|
@ -204,19 +175,6 @@ bool IsDeprecatedRPCEnabled(const std::string& method);
|
||||||
|
|
||||||
extern CRPCTable tableRPC;
|
extern CRPCTable tableRPC;
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities: convert hex-encoded Values
|
|
||||||
* (throws error if not hex).
|
|
||||||
*/
|
|
||||||
extern uint256 ParseHashV(const UniValue& v, std::string strName);
|
|
||||||
extern uint256 ParseHashO(const UniValue& o, std::string strKey);
|
|
||||||
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
|
|
||||||
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
|
|
||||||
|
|
||||||
extern CAmount AmountFromValue(const UniValue& value);
|
|
||||||
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
|
|
||||||
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
|
||||||
|
|
||||||
void StartRPC();
|
void StartRPC();
|
||||||
void InterruptRPC();
|
void InterruptRPC();
|
||||||
void StopRPC();
|
void StopRPC();
|
||||||
|
|
104
src/rpc/util.cpp
104
src/rpc/util.cpp
|
@ -10,6 +10,110 @@
|
||||||
|
|
||||||
InitInterfaces* g_rpc_interfaces = nullptr;
|
InitInterfaces* g_rpc_interfaces = nullptr;
|
||||||
|
|
||||||
|
void RPCTypeCheck(const UniValue& params,
|
||||||
|
const std::list<UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (const UniValueType& t : typesExpected) {
|
||||||
|
if (params.size() <= i)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const UniValue& v = params[i];
|
||||||
|
if (!(fAllowNull && v.isNull())) {
|
||||||
|
RPCTypeCheckArgument(v, t);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
|
||||||
|
{
|
||||||
|
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RPCTypeCheckObj(const UniValue& o,
|
||||||
|
const std::map<std::string, UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull,
|
||||||
|
bool fStrict)
|
||||||
|
{
|
||||||
|
for (const auto& t : typesExpected) {
|
||||||
|
const UniValue& v = find_value(o, t.first);
|
||||||
|
if (!fAllowNull && v.isNull())
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
|
||||||
|
|
||||||
|
if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
|
||||||
|
std::string err = strprintf("Expected type %s for %s, got %s",
|
||||||
|
uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fStrict)
|
||||||
|
{
|
||||||
|
for (const std::string& k : o.getKeys())
|
||||||
|
{
|
||||||
|
if (typesExpected.count(k) == 0)
|
||||||
|
{
|
||||||
|
std::string err = strprintf("Unexpected key %s", k);
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount AmountFromValue(const UniValue& value)
|
||||||
|
{
|
||||||
|
if (!value.isNum() && !value.isStr())
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
|
||||||
|
CAmount amount;
|
||||||
|
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
||||||
|
if (!MoneyRange(amount))
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 ParseHashV(const UniValue& v, std::string strName)
|
||||||
|
{
|
||||||
|
std::string strHex(v.get_str());
|
||||||
|
if (64 != strHex.length())
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", strName, 64, strHex.length(), strHex));
|
||||||
|
if (!IsHex(strHex)) // Note: IsHex("") is false
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||||
|
return uint256S(strHex);
|
||||||
|
}
|
||||||
|
uint256 ParseHashO(const UniValue& o, std::string strKey)
|
||||||
|
{
|
||||||
|
return ParseHashV(find_value(o, strKey), strKey);
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
|
||||||
|
{
|
||||||
|
std::string strHex;
|
||||||
|
if (v.isStr())
|
||||||
|
strHex = v.get_str();
|
||||||
|
if (!IsHex(strHex))
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||||
|
return ParseHex(strHex);
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
|
||||||
|
{
|
||||||
|
return ParseHexV(find_value(o, strKey), strKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
|
return "> bitcoin-cli " + methodname + " " + args + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
|
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
||||||
|
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a hex string to a public key if possible
|
// Converts a hex string to a public key if possible
|
||||||
CPubKey HexToPubKey(const std::string& hex_in)
|
CPubKey HexToPubKey(const std::string& hex_in)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,48 @@ struct InitInterfaces;
|
||||||
//! state to RPC method implementations.
|
//! state to RPC method implementations.
|
||||||
extern InitInterfaces* g_rpc_interfaces;
|
extern InitInterfaces* g_rpc_interfaces;
|
||||||
|
|
||||||
|
/** Wrapper for UniValue::VType, which includes typeAny:
|
||||||
|
* Used to denote don't care type. */
|
||||||
|
struct UniValueType {
|
||||||
|
UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
|
||||||
|
UniValueType() : typeAny(true) {}
|
||||||
|
bool typeAny;
|
||||||
|
UniValue::VType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
|
||||||
|
* the right number of arguments are passed, just that any passed are the correct type.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheck(const UniValue& params,
|
||||||
|
const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-check one argument; throws JSONRPCError if wrong type given.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check for expected keys/value types in an Object.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheckObj(const UniValue& o,
|
||||||
|
const std::map<std::string, UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull = false,
|
||||||
|
bool fStrict = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities: convert hex-encoded Values
|
||||||
|
* (throws error if not hex).
|
||||||
|
*/
|
||||||
|
extern uint256 ParseHashV(const UniValue& v, std::string strName);
|
||||||
|
extern uint256 ParseHashO(const UniValue& o, std::string strKey);
|
||||||
|
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
|
||||||
|
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
|
||||||
|
|
||||||
|
extern CAmount AmountFromValue(const UniValue& value);
|
||||||
|
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
|
||||||
|
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
||||||
|
|
||||||
CPubKey HexToPubKey(const std::string& hex_in);
|
CPubKey HexToPubKey(const std::string& hex_in);
|
||||||
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
|
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
|
||||||
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
|
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/util.h>
|
||||||
|
|
||||||
#if defined(HAVE_CONSENSUS_LIB)
|
#if defined(HAVE_CONSENSUS_LIB)
|
||||||
#include <script/bitcoinconsensus.h>
|
#include <script/bitcoinconsensus.h>
|
||||||
|
|
Loading…
Reference in a new issue