aboutsummaryrefslogtreecommitdiff
path: root/src/rest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rest.cpp')
-rw-r--r--src/rest.cpp118
1 files changed, 79 insertions, 39 deletions
diff --git a/src/rest.cpp b/src/rest.cpp
index 71426a4dc4..747c7aea19 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -8,6 +8,7 @@
#include <core_io.h>
#include <httpserver.h>
#include <index/txindex.h>
+#include <node/blockstorage.h>
#include <node/context.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
@@ -18,10 +19,12 @@
#include <sync.h>
#include <txmempool.h>
#include <util/check.h>
-#include <util/ref.h>
+#include <util/system.h>
#include <validation.h>
#include <version.h>
+#include <any>
+
#include <boost/algorithm/string.hpp>
#include <univalue.h>
@@ -73,10 +76,10 @@ static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string me
* context is not found.
* @returns Pointer to the node context or nullptr if not found.
*/
-static NodeContext* GetNodeContext(const util::Ref& context, HTTPRequest* req)
+static NodeContext* GetNodeContext(const std::any& context, HTTPRequest* req)
{
- NodeContext* node = context.Has<NodeContext>() ? &context.Get<NodeContext>() : nullptr;
- if (!node) {
+ auto node_context = util::AnyPtr<NodeContext>(context);
+ if (!node_context) {
RESTERR(req, HTTP_INTERNAL_SERVER_ERROR,
strprintf("%s:%d (%s)\n"
"Internal bug detected: Node context not found!\n"
@@ -84,7 +87,7 @@ static NodeContext* GetNodeContext(const util::Ref& context, HTTPRequest* req)
__FILE__, __LINE__, __func__, PACKAGE_BUGREPORT));
return nullptr;
}
- return node;
+ return node_context;
}
/**
@@ -94,14 +97,35 @@ static NodeContext* GetNodeContext(const util::Ref& context, HTTPRequest* req)
* context mempool is not found.
* @returns Pointer to the mempool or nullptr if no mempool found.
*/
-static CTxMemPool* GetMemPool(const util::Ref& context, HTTPRequest* req)
+static CTxMemPool* GetMemPool(const std::any& context, HTTPRequest* req)
{
- NodeContext* node = context.Has<NodeContext>() ? &context.Get<NodeContext>() : nullptr;
- if (!node || !node->mempool) {
+ auto node_context = util::AnyPtr<NodeContext>(context);
+ if (!node_context || !node_context->mempool) {
RESTERR(req, HTTP_NOT_FOUND, "Mempool disabled or instance not found");
return nullptr;
}
- return node->mempool.get();
+ return node_context->mempool.get();
+}
+
+/**
+ * Get the node context chainstatemanager.
+ *
+ * @param[in] req The HTTP request, whose status code will be set if node
+ * context chainstatemanager is not found.
+ * @returns Pointer to the chainstatemanager or nullptr if none found.
+ */
+static ChainstateManager* GetChainman(const std::any& context, HTTPRequest* req)
+{
+ auto node_context = util::AnyPtr<NodeContext>(context);
+ if (!node_context || !node_context->chainman) {
+ RESTERR(req, HTTP_INTERNAL_SERVER_ERROR,
+ strprintf("%s:%d (%s)\n"
+ "Internal bug detected: Chainman disabled or instance not found!\n"
+ "You may report this issue here: %s\n",
+ __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT));
+ return nullptr;
+ }
+ return node_context->chainman;
}
static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
@@ -151,7 +175,7 @@ static bool CheckWarmup(HTTPRequest* req)
return true;
}
-static bool rest_headers(const util::Ref& context,
+static bool rest_headers(const std::any& context,
HTTPRequest* req,
const std::string& strURIPart)
{
@@ -178,14 +202,18 @@ static bool rest_headers(const util::Ref& context,
std::vector<const CBlockIndex *> headers;
headers.reserve(count);
{
+ ChainstateManager* maybe_chainman = GetChainman(context, req);
+ if (!maybe_chainman) return false;
+ ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
- tip = ::ChainActive().Tip();
- const CBlockIndex* pindex = g_chainman.m_blockman.LookupBlockIndex(hash);
- while (pindex != nullptr && ::ChainActive().Contains(pindex)) {
+ CChain& active_chain = chainman.ActiveChain();
+ tip = active_chain.Tip();
+ const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash);
+ while (pindex != nullptr && active_chain.Contains(pindex)) {
headers.push_back(pindex);
if (headers.size() == (unsigned long)count)
break;
- pindex = ::ChainActive().Next(pindex);
+ pindex = active_chain.Next(pindex);
}
}
@@ -229,7 +257,8 @@ static bool rest_headers(const util::Ref& context,
}
}
-static bool rest_block(HTTPRequest* req,
+static bool rest_block(const std::any& context,
+ HTTPRequest* req,
const std::string& strURIPart,
bool showTxDetails)
{
@@ -246,9 +275,12 @@ static bool rest_block(HTTPRequest* req,
CBlockIndex* pblockindex = nullptr;
CBlockIndex* tip = nullptr;
{
+ ChainstateManager* maybe_chainman = GetChainman(context, req);
+ if (!maybe_chainman) return false;
+ ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
- tip = ::ChainActive().Tip();
- pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash);
+ tip = chainman.ActiveChain().Tip();
+ pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
if (!pblockindex) {
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
@@ -293,20 +325,20 @@ static bool rest_block(HTTPRequest* req,
}
}
-static bool rest_block_extended(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_block_extended(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
- return rest_block(req, strURIPart, true);
+ return rest_block(context, req, strURIPart, true);
}
-static bool rest_block_notxdetails(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_block_notxdetails(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
- return rest_block(req, strURIPart, false);
+ return rest_block(context, req, strURIPart, false);
}
// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp
RPCHelpMan getblockchaininfo();
-static bool rest_chaininfo(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -315,7 +347,8 @@ static bool rest_chaininfo(const util::Ref& context, HTTPRequest* req, const std
switch (rf) {
case RetFormat::JSON: {
- JSONRPCRequest jsonRequest(context);
+ JSONRPCRequest jsonRequest;
+ jsonRequest.context = context;
jsonRequest.params = UniValue(UniValue::VARR);
UniValue chainInfoObject = getblockchaininfo().HandleRequest(jsonRequest);
std::string strJSON = chainInfoObject.write() + "\n";
@@ -329,7 +362,7 @@ static bool rest_chaininfo(const util::Ref& context, HTTPRequest* req, const std
}
}
-static bool rest_mempool_info(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_mempool_info(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -353,7 +386,7 @@ static bool rest_mempool_info(const util::Ref& context, HTTPRequest* req, const
}
}
-static bool rest_mempool_contents(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_mempool_contents(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req)) return false;
const CTxMemPool* mempool = GetMemPool(context, req);
@@ -376,7 +409,7 @@ static bool rest_mempool_contents(const util::Ref& context, HTTPRequest* req, co
}
}
-static bool rest_tx(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -435,7 +468,7 @@ static bool rest_tx(const util::Ref& context, HTTPRequest* req, const std::strin
}
}
-static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
return false;
@@ -533,6 +566,9 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
std::string bitmapStringRepresentation;
std::vector<bool> hits;
bitmap.resize((vOutPoints.size() + 7) / 8);
+ ChainstateManager* maybe_chainman = GetChainman(context, req);
+ if (!maybe_chainman) return false;
+ ChainstateManager& chainman = *maybe_chainman;
{
auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
for (const COutPoint& vOutPoint : vOutPoints) {
@@ -548,12 +584,12 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
if (!mempool) return false;
// use db+mempool as cache backend in case user likes to query mempool
LOCK2(cs_main, mempool->cs);
- CCoinsViewCache& viewChain = ::ChainstateActive().CoinsTip();
+ CCoinsViewCache& viewChain = chainman.ActiveChainstate().CoinsTip();
CCoinsViewMemPool viewMempool(&viewChain, *mempool);
process_utxos(viewMempool, *mempool);
} else {
LOCK(cs_main); // no need to lock mempool!
- process_utxos(::ChainstateActive().CoinsTip(), CTxMemPool());
+ process_utxos(chainman.ActiveChainstate().CoinsTip(), CTxMemPool());
}
for (size_t i = 0; i < hits.size(); ++i) {
@@ -568,7 +604,7 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
req->WriteHeader("Content-Type", "application/octet-stream");
@@ -578,7 +614,7 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
case RetFormat::HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse) + "\n";
req->WriteHeader("Content-Type", "text/plain");
@@ -591,8 +627,8 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
// pack in some essentials
// use more or less the same output as mentioned in Bip64
- objGetUTXOResponse.pushKV("chainHeight", ::ChainActive().Height());
- objGetUTXOResponse.pushKV("chaintipHash", ::ChainActive().Tip()->GetBlockHash().GetHex());
+ objGetUTXOResponse.pushKV("chainHeight", chainman.ActiveChain().Height());
+ objGetUTXOResponse.pushKV("chaintipHash", chainman.ActiveChain().Tip()->GetBlockHash().GetHex());
objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);
UniValue utxos(UniValue::VARR);
@@ -621,7 +657,7 @@ static bool rest_getutxos(const util::Ref& context, HTTPRequest* req, const std:
}
}
-static bool rest_blockhash_by_height(const util::Ref& context, HTTPRequest* req,
+static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
const std::string& str_uri_part)
{
if (!CheckWarmup(req)) return false;
@@ -635,11 +671,15 @@ static bool rest_blockhash_by_height(const util::Ref& context, HTTPRequest* req,
CBlockIndex* pblockindex = nullptr;
{
+ ChainstateManager* maybe_chainman = GetChainman(context, req);
+ if (!maybe_chainman) return false;
+ ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
- if (blockheight > ::ChainActive().Height()) {
+ const CChain& active_chain = chainman.ActiveChain();
+ if (blockheight > active_chain.Height()) {
return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
}
- pblockindex = ::ChainActive()[blockheight];
+ pblockindex = active_chain[blockheight];
}
switch (rf) {
case RetFormat::BINARY: {
@@ -669,7 +709,7 @@ static bool rest_blockhash_by_height(const util::Ref& context, HTTPRequest* req,
static const struct {
const char* prefix;
- bool (*handler)(const util::Ref& context, HTTPRequest* req, const std::string& strReq);
+ bool (*handler)(const std::any& context, HTTPRequest* req, const std::string& strReq);
} uri_prefixes[] = {
{"/rest/tx/", rest_tx},
{"/rest/block/notxdetails/", rest_block_notxdetails},
@@ -682,10 +722,10 @@ static const struct {
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
};
-void StartREST(const util::Ref& context)
+void StartREST(const std::any& context)
{
for (const auto& up : uri_prefixes) {
- auto handler = [&context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };
+ auto handler = [context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };
RegisterHTTPHandler(up.prefix, false, handler);
}
}