Merge #18740: Remove g_rpc_node global

b3f7f375ef refactor: Remove g_rpc_node global (Russell Yanofsky)
ccb5059ee8 scripted-diff: Remove g_rpc_node references (Russell Yanofsky)
6fca33b2ed refactor: Pass NodeContext to RPC and REST methods through util::Ref (Russell Yanofsky)
691c817b34 Add util::Ref class as temporary alternative for c++17 std::any (Russell Yanofsky)

Pull request description:

  This PR removes the `g_rpc_node` global, to get same benefits we see removing other globals and make RPC code more testable, modular, and reusable.

  This uses a hybrid of the approaches suggested in #17548. Instead of using `std::any`, which isn't available in c++11, or `void*`, which isn't type safe, it uses a small new `util::Ref` helper class, which acts like a simplified `std::any` that only holds references, not values.

  Motivation for writing this was to provide an simpler alternative to #18647 by Harris Brakmić (brakmic) which avoids some shortcomings of that PR (https://github.com/bitcoin/bitcoin/pull/18647#issuecomment-617878826)

ACKs for top commit:
  MarcoFalke:
    re-ACK b3f7f375ef, only change is adding back const and more tests 🚾
  ajtowns:
    ACK b3f7f375ef

Tree-SHA512: 56292268a001bdbe34d641db1180c215351503966ff451e55cc96c9137f1d262225d7d7733de9c9da7ce7d7a4b34213a98c2476266b58c89dbbb0f3cb5aa5d70
This commit is contained in:
MarcoFalke
2020-05-21 06:53:30 -04:00
22 changed files with 262 additions and 131 deletions

View File

@@ -18,6 +18,7 @@
#include <sync.h>
#include <txmempool.h>
#include <util/check.h>
#include <util/ref.h>
#include <util/strencodings.h>
#include <validation.h>
#include <version.h>
@@ -75,13 +76,14 @@ static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string me
* @param[in] req the HTTP request
* return pointer to the mempool or nullptr if no mempool found
*/
static CTxMemPool* GetMemPool(HTTPRequest* req)
static CTxMemPool* GetMemPool(const util::Ref& context, HTTPRequest* req)
{
if (!g_rpc_node || !g_rpc_node->mempool) {
NodeContext* node = context.Has<NodeContext>() ? &context.Get<NodeContext>() : nullptr;
if (!node || !node->mempool) {
RESTERR(req, HTTP_NOT_FOUND, "Mempool disabled or instance not found");
return nullptr;
}
return g_rpc_node->mempool;
return node->mempool;
}
static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
@@ -129,7 +131,8 @@ static bool CheckWarmup(HTTPRequest* req)
return true;
}
static bool rest_headers(HTTPRequest* req,
static bool rest_headers(const util::Ref& context,
HTTPRequest* req,
const std::string& strURIPart)
{
if (!CheckWarmup(req))
@@ -270,12 +273,12 @@ static bool rest_block(HTTPRequest* req,
}
}
static bool rest_block_extended(HTTPRequest* req, const std::string& strURIPart)
static bool rest_block_extended(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
return rest_block(req, strURIPart, true);
}
static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPart)
static bool rest_block_notxdetails(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
return rest_block(req, strURIPart, false);
}
@@ -283,7 +286,7 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa
// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp
UniValue getblockchaininfo(const JSONRPCRequest& request);
static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
static bool rest_chaininfo(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -292,7 +295,7 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
switch (rf) {
case RetFormat::JSON: {
JSONRPCRequest jsonRequest;
JSONRPCRequest jsonRequest(context);
jsonRequest.params = UniValue(UniValue::VARR);
UniValue chainInfoObject = getblockchaininfo(jsonRequest);
std::string strJSON = chainInfoObject.write() + "\n";
@@ -306,11 +309,11 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
}
}
static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
static bool rest_mempool_info(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
const CTxMemPool* mempool = GetMemPool(req);
const CTxMemPool* mempool = GetMemPool(context, req);
if (!mempool) return false;
std::string param;
const RetFormat rf = ParseDataFormat(param, strURIPart);
@@ -330,10 +333,10 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
}
}
static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPart)
static bool rest_mempool_contents(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req)) return false;
const CTxMemPool* mempool = GetMemPool(req);
const CTxMemPool* mempool = GetMemPool(context, req);
if (!mempool) return false;
std::string param;
const RetFormat rf = ParseDataFormat(param, strURIPart);
@@ -353,7 +356,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar
}
}
static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
static bool rest_tx(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -409,7 +412,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
}
}
static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -518,7 +521,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
};
if (fCheckMemPool) {
const CTxMemPool* mempool = GetMemPool(req);
const CTxMemPool* mempool = GetMemPool(context, req);
if (!mempool) return false;
// use db+mempool as cache backend in case user likes to query mempool
LOCK2(cs_main, mempool->cs);
@@ -595,7 +598,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
}
}
static bool rest_blockhash_by_height(HTTPRequest* req,
static bool rest_blockhash_by_height(const util::Ref& context, HTTPRequest* req,
const std::string& str_uri_part)
{
if (!CheckWarmup(req)) return false;
@@ -643,7 +646,7 @@ static bool rest_blockhash_by_height(HTTPRequest* req,
static const struct {
const char* prefix;
bool (*handler)(HTTPRequest* req, const std::string& strReq);
bool (*handler)(const util::Ref& context, HTTPRequest* req, const std::string& strReq);
} uri_prefixes[] = {
{"/rest/tx/", rest_tx},
{"/rest/block/notxdetails/", rest_block_notxdetails},
@@ -656,10 +659,12 @@ static const struct {
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
};
void StartREST()
void StartREST(const util::Ref& context)
{
for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++)
RegisterHTTPHandler(uri_prefixes[i].prefix, false, uri_prefixes[i].handler);
for (const auto& up : uri_prefixes) {
auto handler = [&context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };
RegisterHTTPHandler(up.prefix, false, handler);
}
}
void InterruptREST()