Changeset View
Changeset View
Standalone View
Standalone View
src/rest.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <blockdb.h> | #include <blockdb.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <core_io.h> | #include <core_io.h> | ||||
#include <httpserver.h> | #include <httpserver.h> | ||||
#include <index/txindex.h> | #include <index/txindex.h> | ||||
#include <node/context.h> | |||||
#include <primitives/block.h> | #include <primitives/block.h> | ||||
#include <primitives/transaction.h> | #include <primitives/transaction.h> | ||||
#include <rpc/blockchain.h> | #include <rpc/blockchain.h> | ||||
#include <rpc/protocol.h> | #include <rpc/protocol.h> | ||||
#include <rpc/server.h> | #include <rpc/server.h> | ||||
#include <streams.h> | #include <streams.h> | ||||
#include <sync.h> | #include <sync.h> | ||||
#include <txmempool.h> | #include <txmempool.h> | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, | static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, | ||||
std::string message) { | std::string message) { | ||||
req->WriteHeader("Content-Type", "text/plain"); | req->WriteHeader("Content-Type", "text/plain"); | ||||
req->WriteReply(status, message + "\r\n"); | req->WriteReply(status, message + "\r\n"); | ||||
return false; | return false; | ||||
} | } | ||||
/** | |||||
* Get the node context mempool. | |||||
* | |||||
* Set the HTTP error and return nullptr if node context | |||||
* mempool is not found. | |||||
* | |||||
* @param[in] req the HTTP request | |||||
* return pointer to the mempool or nullptr if no mempool found | |||||
*/ | |||||
static CTxMemPool *GetMemPool(HTTPRequest *req) { | |||||
if (!g_rpc_node || !g_rpc_node->mempool) { | |||||
RESTERR(req, HTTP_NOT_FOUND, "Mempool disabled or instance not found"); | |||||
return nullptr; | |||||
} | |||||
return g_rpc_node->mempool; | |||||
} | |||||
static RetFormat ParseDataFormat(std::string ¶m, | static RetFormat ParseDataFormat(std::string ¶m, | ||||
const std::string &strReq) { | const std::string &strReq) { | ||||
const std::string::size_type pos = strReq.rfind('.'); | const std::string::size_type pos = strReq.rfind('.'); | ||||
if (pos == std::string::npos) { | if (pos == std::string::npos) { | ||||
param = strReq; | param = strReq; | ||||
return rf_names[0].rf; | return rf_names[0].rf; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 240 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static bool rest_mempool_info(Config &config, HTTPRequest *req, | static bool rest_mempool_info(Config &config, HTTPRequest *req, | ||||
const std::string &strURIPart) { | const std::string &strURIPart) { | ||||
if (!CheckWarmup(req)) { | if (!CheckWarmup(req)) { | ||||
return false; | return false; | ||||
} | } | ||||
const CTxMemPool *mempool = GetMemPool(req); | |||||
if (!mempool) { | |||||
return false; | |||||
} | |||||
std::string param; | std::string param; | ||||
const RetFormat rf = ParseDataFormat(param, strURIPart); | const RetFormat rf = ParseDataFormat(param, strURIPart); | ||||
switch (rf) { | switch (rf) { | ||||
case RetFormat::JSON: { | case RetFormat::JSON: { | ||||
UniValue mempoolInfoObject = MempoolInfoToJSON(::g_mempool); | UniValue mempoolInfoObject = MempoolInfoToJSON(*mempool); | ||||
std::string strJSON = mempoolInfoObject.write() + "\n"; | std::string strJSON = mempoolInfoObject.write() + "\n"; | ||||
req->WriteHeader("Content-Type", "application/json"); | req->WriteHeader("Content-Type", "application/json"); | ||||
req->WriteReply(HTTP_OK, strJSON); | req->WriteReply(HTTP_OK, strJSON); | ||||
return true; | return true; | ||||
} | } | ||||
default: { | default: { | ||||
return RESTERR(req, HTTP_NOT_FOUND, | return RESTERR(req, HTTP_NOT_FOUND, | ||||
"output format not found (available: json)"); | "output format not found (available: json)"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static bool rest_mempool_contents(Config &config, HTTPRequest *req, | static bool rest_mempool_contents(Config &config, HTTPRequest *req, | ||||
const std::string &strURIPart) { | const std::string &strURIPart) { | ||||
if (!CheckWarmup(req)) { | if (!CheckWarmup(req)) { | ||||
return false; | return false; | ||||
} | } | ||||
const CTxMemPool *mempool = GetMemPool(req); | |||||
if (!mempool) { | |||||
return false; | |||||
} | |||||
std::string param; | std::string param; | ||||
const RetFormat rf = ParseDataFormat(param, strURIPart); | const RetFormat rf = ParseDataFormat(param, strURIPart); | ||||
switch (rf) { | switch (rf) { | ||||
case RetFormat::JSON: { | case RetFormat::JSON: { | ||||
UniValue mempoolObject = MempoolToJSON(::g_mempool, true); | UniValue mempoolObject = MempoolToJSON(*mempool, true); | ||||
std::string strJSON = mempoolObject.write() + "\n"; | std::string strJSON = mempoolObject.write() + "\n"; | ||||
req->WriteHeader("Content-Type", "application/json"); | req->WriteHeader("Content-Type", "application/json"); | ||||
req->WriteReply(HTTP_OK, strJSON); | req->WriteReply(HTTP_OK, strJSON); | ||||
return true; | return true; | ||||
} | } | ||||
default: { | default: { | ||||
return RESTERR(req, HTTP_NOT_FOUND, | return RESTERR(req, HTTP_NOT_FOUND, | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | bitmap.resize((vOutPoints.size() + 7) / 8); | ||||
hits.push_back(hit); | hits.push_back(hit); | ||||
if (hit) { | if (hit) { | ||||
outs.emplace_back(std::move(coin)); | outs.emplace_back(std::move(coin)); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
if (fCheckMemPool) { | if (fCheckMemPool) { | ||||
const CTxMemPool *mempool = GetMemPool(req); | |||||
if (!mempool) { | |||||
return false; | |||||
} | |||||
// use db+mempool as cache backend in case user likes to query | // use db+mempool as cache backend in case user likes to query | ||||
// mempool | // mempool | ||||
LOCK2(cs_main, g_mempool.cs); | LOCK2(cs_main, mempool->cs); | ||||
CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip(); | CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip(); | ||||
CCoinsViewMemPool viewMempool(&viewChain, g_mempool); | CCoinsViewMemPool viewMempool(&viewChain, *mempool); | ||||
process_utxos(viewMempool, g_mempool); | process_utxos(viewMempool, *mempool); | ||||
} else { | } else { | ||||
// no need to lock mempool! | // no need to lock mempool! | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
process_utxos(::ChainstateActive().CoinsTip(), CTxMemPool()); | process_utxos(::ChainstateActive().CoinsTip(), CTxMemPool()); | ||||
} | } | ||||
for (size_t i = 0; i < hits.size(); ++i) { | for (size_t i = 0; i < hits.size(); ++i) { | ||||
const bool hit = hits[i]; | const bool hit = hits[i]; | ||||
▲ Show 20 Lines • Show All 155 Lines • Show Last 20 Lines |