partial bitcoin#16240: JSONRPCRequest-aware RPCHelpMan

This commit is contained in:
Kittywhiskers Van Gogh 2022-02-27 13:16:53 +05:30
parent cbbe801a3c
commit eda7bb09e4
10 changed files with 100 additions and 81 deletions

View File

@ -257,9 +257,10 @@ BITCOIN_CORE_H = \
rpc/client.h \
rpc/mining.h \
rpc/protocol.h \
rpc/server.h \
rpc/rawtransaction_util.h \
rpc/register.h \
rpc/request.h \
rpc/server.h \
rpc/util.h \
saltedhasher.h \
scheduler.h \
@ -678,7 +679,7 @@ libdash_util_a_SOURCES = \
interfaces/handler.cpp \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
rpc/request.cpp \
stacktraces.cpp \
support/cleanse.cpp \
sync.cpp \

View File

@ -12,6 +12,7 @@
#include <clientversion.h>
#include <rpc/client.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <stacktraces.h>
#include <util/system.h>
#include <util/strencodings.h>

View File

@ -11,6 +11,7 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <rpc/blockchain.h>
#include <rpc/protocol.h>
#include <rpc/server.h>
#include <streams.h>
#include <sync.h>

View File

@ -6,15 +6,6 @@
#ifndef BITCOIN_RPC_PROTOCOL_H
#define BITCOIN_RPC_PROTOCOL_H
#include <fs.h>
#include <list>
#include <map>
#include <stdint.h>
#include <string>
#include <univalue.h>
//! HTTP status codes
enum HTTPStatusCode
{
@ -93,18 +84,4 @@ enum RPCErrorCode
RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode
};
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
UniValue JSONRPCError(int code, const std::string& message);
/** Generate a new RPC authentication cookie and write it to disk */
bool GenerateAuthCookie(std::string *cookie_out);
/** Read the RPC authentication cookie from disk */
bool GetAuthCookie(std::string *cookie_out);
/** Delete RPC authentication cookie from disk */
void DeleteAuthCookie();
/** Parse JSON-RPC batch reply into a vector */
std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num);
#endif // BITCOIN_RPC_PROTOCOL_H

View File

@ -12,7 +12,7 @@
#include <keystore.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <rpc/util.h>
#include <univalue.h>
#include <util/strencodings.h>

View File

@ -1,15 +1,16 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2014-2020 The Dash Core developers
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Copyright (c) 2014-2022 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <fs.h>
#include <random.h>
#include <rpc/protocol.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/time.h>
/**
* JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
@ -148,3 +149,38 @@ std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num)
}
return batch;
}
void JSONRPCRequest::parse(const UniValue& valRequest)
{
// Parse request
if (!valRequest.isObject())
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
id = find_value(request, "id");
// Parse method
UniValue valMethod = find_value(request, "method");
if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate") {
if (fLogIPs)
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
this->authUser, this->peerAddr);
else
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
}
// Parse params
UniValue valParams = find_value(request, "params");
if (valParams.isArray() || valParams.isObject())
params = valParams;
else if (valParams.isNull())
params = UniValue(UniValue::VARR);
else
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
}

42
src/rpc/request.h Normal file
View File

@ -0,0 +1,42 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_RPC_REQUEST_H
#define BITCOIN_RPC_REQUEST_H
#include <string>
#include <univalue.h>
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
UniValue JSONRPCError(int code, const std::string& message);
/** Generate a new RPC authentication cookie and write it to disk */
bool GenerateAuthCookie(std::string *cookie_out);
/** Read the RPC authentication cookie from disk */
bool GetAuthCookie(std::string *cookie_out);
/** Delete RPC authentication cookie from disk */
void DeleteAuthCookie();
/** Parse JSON-RPC batch reply into a vector */
std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num);
class JSONRPCRequest
{
public:
UniValue id;
std::string strMethod;
UniValue params;
bool fHelp;
std::string URI;
std::string authUser;
std::string peerAddr;
JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
void parse(const UniValue& valRequest);
};
#endif // BITCOIN_RPC_REQUEST_H

View File

@ -341,41 +341,6 @@ bool RPCIsInWarmup(std::string *outStatus)
return fRPCInWarmup;
}
void JSONRPCRequest::parse(const UniValue& valRequest)
{
// Parse request
if (!valRequest.isObject())
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
id = find_value(request, "id");
// Parse method
UniValue valMethod = find_value(request, "method");
if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
if (!valMethod.isStr())
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
strMethod = valMethod.get_str();
if (strMethod != "getblocktemplate") {
if (fLogIPs)
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
this->authUser, this->peerAddr);
else
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
}
// Parse params
UniValue valParams = find_value(request, "params");
if (valParams.isArray() || valParams.isObject())
params = valParams;
else if (valParams.isNull())
params = UniValue(UniValue::VARR);
else
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
}
bool IsDeprecatedRPCEnabled(const std::string& method)
{
const std::vector<std::string> enabled_methods = gArgs.GetArgs("-deprecatedrpc");

View File

@ -7,11 +7,12 @@
#define BITCOIN_RPC_SERVER_H
#include <amount.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <map>
#include <stdint.h>
#include <string>
#include <functional>
#include <univalue.h>
@ -23,21 +24,6 @@ namespace RPCServer
void OnStopped(std::function<void ()> slot);
}
class JSONRPCRequest
{
public:
UniValue id;
std::string strMethod;
UniValue params;
bool fHelp;
std::string URI;
std::string authUser;
std::string peerAddr;
JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
void parse(const UniValue& valRequest);
};
/** Query whether RPC is running */
bool IsRPCRunning();

View File

@ -9,6 +9,7 @@
#include <pubkey.h>
#include <protocol.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <script/standard.h>
#include <univalue.h>
#include <util/strencodings.h>
@ -243,6 +244,15 @@ public:
std::string ToString() const;
/** If the supplied number of args is neither too small nor too high */
bool IsValidNumArgs(size_t num_args) const;
/**
* Check if the given request is valid according to this command or if
* the user is asking for help information, and throw help when appropriate.
*/
inline void Check(const JSONRPCRequest& request) const {
if (request.fHelp || !IsValidNumArgs(request.params.size())) {
throw std::runtime_error(ToString());
}
}
private:
const std::string m_name;