diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -320,7 +320,7 @@ random.cpp randomenv.cpp rcu.cpp - rpc/protocol.cpp + rpc/request.cpp support/cleanse.cpp support/lockedpool.cpp sync.cpp @@ -528,7 +528,6 @@ rpc/misc.cpp rpc/net.cpp rpc/rawtransaction.cpp - rpc/request.cpp rpc/server.cpp script/scriptcache.cpp script/sigcache.cpp diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -209,9 +209,9 @@ rpc/mining.h \ rpc/protocol.h \ rpc/rawtransaction_util.h \ + rpc/register.h \ rpc/request.h \ rpc/server.h \ - rpc/register.h \ rpc/util.h \ rwcollection.h \ scheduler.h \ @@ -335,7 +335,6 @@ rpc/misc.cpp \ rpc/net.cpp \ rpc/rawtransaction.cpp \ - rpc/request.cpp \ rpc/server.cpp \ script/scriptcache.cpp \ script/sigcache.cpp \ @@ -542,7 +541,7 @@ random.cpp \ randomenv.cpp \ rcu.cpp \ - rpc/protocol.cpp \ + rpc/request.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rest.cpp b/src/rest.cpp --- a/src/rest.cpp +++ b/src/rest.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -6,15 +6,6 @@ #ifndef BITCOIN_RPC_PROTOCOL_H #define BITCOIN_RPC_PROTOCOL_H -#include - -#include -#include -#include -#include - -#include - //! HTTP status codes enum HTTPStatusCode { HTTP_OK = 200, @@ -125,21 +116,4 @@ RPC_FORBIDDEN_BY_SAFE_MODE = -2, }; -UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, - 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 JSONRPCProcessBatchReply(const UniValue &in, size_t num); - #endif // BITCOIN_RPC_PROTOCOL_H diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp deleted file mode 100644 --- a/src/rpc/protocol.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include - -#include -#include -#include -#include -#include - -#include - -/** - * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, but - * uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were - * unspecified (HTTP errors and contents of 'error'). - * - * 1.0 spec: http://json-rpc.org/wiki/specification - * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html - */ - -UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, - const UniValue &id) { - UniValue request(UniValue::VOBJ); - request.pushKV("method", strMethod); - request.pushKV("params", params); - request.pushKV("id", id); - return request; -} - -UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, - const UniValue &id) { - UniValue reply(UniValue::VOBJ); - if (!error.isNull()) { - reply.pushKV("result", NullUniValue); - } else { - reply.pushKV("result", result); - } - reply.pushKV("error", error); - reply.pushKV("id", id); - return reply; -} - -std::string JSONRPCReply(const UniValue &result, const UniValue &error, - const UniValue &id) { - UniValue reply = JSONRPCReplyObj(result, error, id); - return reply.write() + "\n"; -} - -UniValue JSONRPCError(int code, const std::string &message) { - UniValue error(UniValue::VOBJ); - error.pushKV("code", code); - error.pushKV("message", message); - return error; -} - -/** Username used when cookie authentication is in use (arbitrary, only for - * recognizability in debugging/logging purposes) - */ -static const std::string COOKIEAUTH_USER = "__cookie__"; -/** Default name for auth cookie file */ -static const std::string COOKIEAUTH_FILE = ".cookie"; - -/** Get name of RPC authentication cookie file */ -static fs::path GetAuthCookieFile(bool temp = false) { - std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE); - if (temp) { - arg += ".tmp"; - } - return AbsPathForConfigVal(fs::path(arg)); -} - -bool GenerateAuthCookie(std::string *cookie_out) { - const size_t COOKIE_SIZE = 32; - uint8_t rand_pwd[COOKIE_SIZE]; - GetRandBytes(rand_pwd, COOKIE_SIZE); - std::string cookie = - COOKIEAUTH_USER + ":" + HexStr(rand_pwd, rand_pwd + COOKIE_SIZE); - - /** the umask determines what permissions are used to create this file - - * these are set to 077 in init.cpp unless overridden with -sysperms. - */ - fsbridge::ofstream file; - fs::path filepath_tmp = GetAuthCookieFile(true); - file.open(filepath_tmp); - if (!file.is_open()) { - LogPrintf("Unable to open cookie authentication file %s for writing\n", - filepath_tmp.string()); - return false; - } - file << cookie; - file.close(); - - fs::path filepath = GetAuthCookieFile(false); - if (!RenameOver(filepath_tmp, filepath)) { - LogPrintf("Unable to rename cookie authentication file %s to %s\n", - filepath_tmp.string(), filepath.string()); - return false; - } - LogPrintf("Generated RPC authentication cookie %s\n", filepath.string()); - - if (cookie_out) { - *cookie_out = cookie; - } - return true; -} - -bool GetAuthCookie(std::string *cookie_out) { - fsbridge::ifstream file; - std::string cookie; - fs::path filepath = GetAuthCookieFile(); - file.open(filepath); - if (!file.is_open()) { - return false; - } - std::getline(file, cookie); - file.close(); - - if (cookie_out) { - *cookie_out = cookie; - } - return true; -} - -void DeleteAuthCookie() { - try { - fs::remove(GetAuthCookieFile()); - } catch (const fs::filesystem_error &e) { - LogPrintf("%s: Unable to remove random auth cookie file: %s\n", - __func__, fsbridge::get_filesystem_error_message(e)); - } -} - -std::vector JSONRPCProcessBatchReply(const UniValue &in, size_t num) { - if (!in.isArray()) { - throw std::runtime_error("Batch must be an array"); - } - std::vector batch(num); - for (size_t i = 0; i < in.size(); ++i) { - const UniValue &rec = in[i]; - if (!rec.isObject()) { - throw std::runtime_error("Batch member must be object"); - } - size_t id = rec["id"].get_int(); - if (id >= num) { - throw std::runtime_error("Batch member id larger than size"); - } - batch[id] = rec; - } - return batch; -} diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/rpc/request.h b/src/rpc/request.h --- a/src/rpc/request.h +++ b/src/rpc/request.h @@ -9,6 +9,23 @@ #include +UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, + 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 JSONRPCProcessBatchReply(const UniValue &in, size_t num); + class JSONRPCRequest { public: UniValue id; diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp --- a/src/rpc/request.cpp +++ b/src/rpc/request.cpp @@ -1,20 +1,167 @@ // Copyright (c) 2018-2019 The Bitcoin developers +// 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. +#include + +#include #include +#include #include -#include -#include #include +#include #include +/** + * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, but + * uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were + * unspecified (HTTP errors and contents of 'error'). + * + * 1.0 spec: http://json-rpc.org/wiki/specification + * 1.2 spec: http://jsonrpc.org/historical/json-rpc-over-http.html + */ + +UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue ¶ms, + const UniValue &id) { + UniValue request(UniValue::VOBJ); + request.pushKV("method", strMethod); + request.pushKV("params", params); + request.pushKV("id", id); + return request; +} + +UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, + const UniValue &id) { + UniValue reply(UniValue::VOBJ); + if (!error.isNull()) { + reply.pushKV("result", NullUniValue); + } else { + reply.pushKV("result", result); + } + reply.pushKV("error", error); + reply.pushKV("id", id); + return reply; +} + +std::string JSONRPCReply(const UniValue &result, const UniValue &error, + const UniValue &id) { + UniValue reply = JSONRPCReplyObj(result, error, id); + return reply.write() + "\n"; +} + +UniValue JSONRPCError(int code, const std::string &message) { + UniValue error(UniValue::VOBJ); + error.pushKV("code", code); + error.pushKV("message", message); + return error; +} + +/** + * Username used when cookie authentication is in use (arbitrary, only for + * recognizability in debugging/logging purposes) + */ +static const std::string COOKIEAUTH_USER = "__cookie__"; +/** Default name for auth cookie file */ +static const std::string COOKIEAUTH_FILE = ".cookie"; + +/** Get name of RPC authentication cookie file */ +static fs::path GetAuthCookieFile(bool temp = false) { + std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE); + if (temp) { + arg += ".tmp"; + } + return AbsPathForConfigVal(fs::path(arg)); +} + +bool GenerateAuthCookie(std::string *cookie_out) { + const size_t COOKIE_SIZE = 32; + uint8_t rand_pwd[COOKIE_SIZE]; + GetRandBytes(rand_pwd, COOKIE_SIZE); + std::string cookie = + COOKIEAUTH_USER + ":" + HexStr(rand_pwd, rand_pwd + COOKIE_SIZE); + + /** + * the umask determines what permissions are used to create this file - + * these are set to 077 in init.cpp unless overridden with -sysperms. + */ + fsbridge::ofstream file; + fs::path filepath_tmp = GetAuthCookieFile(true); + file.open(filepath_tmp); + if (!file.is_open()) { + LogPrintf("Unable to open cookie authentication file %s for writing\n", + filepath_tmp.string()); + return false; + } + file << cookie; + file.close(); + + fs::path filepath = GetAuthCookieFile(false); + if (!RenameOver(filepath_tmp, filepath)) { + LogPrintf("Unable to rename cookie authentication file %s to %s\n", + filepath_tmp.string(), filepath.string()); + return false; + } + LogPrintf("Generated RPC authentication cookie %s\n", filepath.string()); + + if (cookie_out) { + *cookie_out = cookie; + } + return true; +} + +bool GetAuthCookie(std::string *cookie_out) { + fsbridge::ifstream file; + std::string cookie; + fs::path filepath = GetAuthCookieFile(); + file.open(filepath); + if (!file.is_open()) { + return false; + } + std::getline(file, cookie); + file.close(); + + if (cookie_out) { + *cookie_out = cookie; + } + return true; +} + +void DeleteAuthCookie() { + try { + fs::remove(GetAuthCookieFile()); + } catch (const fs::filesystem_error &e) { + LogPrintf("%s: Unable to remove random auth cookie file: %s\n", + __func__, fsbridge::get_filesystem_error_message(e)); + } +} + +std::vector JSONRPCProcessBatchReply(const UniValue &in, size_t num) { + if (!in.isArray()) { + throw std::runtime_error("Batch must be an array"); + } + std::vector batch(num); + for (size_t i = 0; i < in.size(); ++i) { + const UniValue &rec = in[i]; + if (!rec.isObject()) { + throw std::runtime_error("Batch member must be object"); + } + size_t id = rec["id"].get_int(); + if (id >= num) { + throw std::runtime_error("Batch member id larger than size"); + } + batch[id] = rec; + } + 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 diff --git a/src/rpc/server.h b/src/rpc/server.h --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -9,21 +9,21 @@ #include #include -#include #include #include #include #include +#include + +#include + #include #include #include #include #include -#include -#include - static const unsigned int DEFAULT_RPC_SERIALIZE_VERSION = 1; class CRPCCommand; diff --git a/src/test/rpc_server_tests.cpp b/src/test/rpc_server_tests.cpp --- a/src/test/rpc_server_tests.cpp +++ b/src/test/rpc_server_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include #include #include