rest: Add GetChainman function and use it

This is not the cleanest change but:

1. It fixes the erroneous use of RPC's Ensure*() in rest.cpp, which
   cause crashes in REST contexts.

   RPC code wraps all calls in a try/except, REST code does not.
   Ensure*(), being part of RPC, expects that its throw's will get
   caught by a try/except. But if you use Ensure*() in REST code, since
   it doesn't have a try/except wrap, a crash will happen.

2. It is consistent with other functions like GetMemPool.

Someone can probably make this a bit prettier.
This commit is contained in:
Carl Dong 2021-04-23 15:18:04 -04:00
parent fc1c282845
commit 9ecade1425

View file

@ -107,6 +107,27 @@ static CTxMemPool* GetMemPool(const std::any& context, HTTPRequest* req)
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)
{
const std::string::size_type pos = strReq.rfind('.');
@ -181,7 +202,9 @@ static bool rest_headers(const std::any& context,
std::vector<const CBlockIndex *> headers;
headers.reserve(count);
{
ChainstateManager& chainman = EnsureAnyChainman(context);
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
CChain& active_chain = chainman.ActiveChain();
tip = active_chain.Tip();
@ -252,7 +275,9 @@ static bool rest_block(const std::any& context,
CBlockIndex* pblockindex = nullptr;
CBlockIndex* tip = nullptr;
{
ChainstateManager& chainman = EnsureAnyChainman(context);
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
tip = chainman.ActiveChain().Tip();
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
@ -541,7 +566,9 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
std::string bitmapStringRepresentation;
std::vector<bool> hits;
bitmap.resize((vOutPoints.size() + 7) / 8);
ChainstateManager& chainman = EnsureAnyChainman(context);
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) {
@ -644,7 +671,9 @@ static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,
CBlockIndex* pblockindex = nullptr;
{
ChainstateManager& chainman = EnsureAnyChainman(context);
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
const CChain& active_chain = chainman.ActiveChain();
if (blockheight > active_chain.Height()) {