aboutsummaryrefslogtreecommitdiff
path: root/src/rest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rest.cpp')
-rw-r--r--src/rest.cpp103
1 files changed, 55 insertions, 48 deletions
diff --git a/src/rest.cpp b/src/rest.cpp
index f47b40343b..a5f164497d 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -6,6 +6,7 @@
#include <chain.h>
#include <chainparams.h>
#include <core_io.h>
+#include <index/txindex.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <validation.h>
@@ -24,21 +25,21 @@
static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
-enum RetFormat {
- RF_UNDEF,
- RF_BINARY,
- RF_HEX,
- RF_JSON,
+enum class RetFormat {
+ UNDEF,
+ BINARY,
+ HEX,
+ JSON,
};
static const struct {
- enum RetFormat rf;
+ RetFormat rf;
const char* name;
} rf_names[] = {
- {RF_UNDEF, ""},
- {RF_BINARY, "bin"},
- {RF_HEX, "hex"},
- {RF_JSON, "json"},
+ {RetFormat::UNDEF, ""},
+ {RetFormat::BINARY, "bin"},
+ {RetFormat::HEX, "hex"},
+ {RetFormat::JSON, "json"},
};
struct CCoin {
@@ -67,7 +68,7 @@ static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string me
return false;
}
-static enum RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
+static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
{
const std::string::size_type pos = strReq.rfind('.');
if (pos == std::string::npos)
@@ -162,20 +163,20 @@ static bool rest_headers(HTTPRequest* req,
}
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryHeader = ssHeader.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryHeader);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue jsonHeaders(UniValue::VARR);
{
LOCK(cs_main);
@@ -216,7 +217,7 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
- if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
+ if (IsBlockPruned(pblockindex))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
@@ -227,21 +228,21 @@ static bool rest_block(HTTPRequest* req,
ssBlock << block;
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryBlock = ssBlock.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryBlock);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objBlock;
{
LOCK(cs_main);
@@ -280,7 +281,7 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
JSONRPCRequest jsonRequest;
jsonRequest.params = UniValue(UniValue::VARR);
UniValue chainInfoObject = getblockchaininfo(jsonRequest);
@@ -303,7 +304,7 @@ static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue mempoolInfoObject = mempoolInfoToJSON();
std::string strJSON = mempoolInfoObject.write() + "\n";
@@ -325,7 +326,7 @@ static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPar
const RetFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue mempoolObject = mempoolToJSON(true);
std::string strJSON = mempoolObject.write() + "\n";
@@ -350,6 +351,10 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
if (!ParseHashStr(hashStr, hash))
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
+ if (g_txindex) {
+ g_txindex->BlockUntilSyncedToCurrentChain();
+ }
+
CTransactionRef tx;
uint256 hashBlock = uint256();
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
@@ -359,21 +364,21 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
ssTx << tx;
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
std::string binaryTx = ssTx.str();
req->WriteHeader("Content-Type", "application/octet-stream");
req->WriteReply(HTTP_OK, binaryTx);
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
req->WriteHeader("Content-Type", "text/plain");
req->WriteReply(HTTP_OK, strHex);
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objTx(UniValue::VOBJ);
TxToUniv(*tx, hashBlock, objTx);
std::string strJSON = objTx.write() + "\n";
@@ -440,13 +445,13 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
}
switch (rf) {
- case RF_HEX: {
+ case RetFormat::HEX: {
// convert hex to bin, continue then with bin part
std::vector<unsigned char> strRequestV = ParseHex(strRequestMutable);
strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
}
- case RF_BINARY: {
+ case RetFormat::BINARY: {
try {
//deserialize only if user sent a request
if (strRequestMutable.size() > 0)
@@ -466,7 +471,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
break;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
if (!fInputParsed)
return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");
break;
@@ -487,33 +492,35 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
std::vector<bool> hits;
bitmap.resize((vOutPoints.size() + 7) / 8);
{
- LOCK2(cs_main, mempool.cs);
-
- CCoinsView viewDummy;
- CCoinsViewCache view(&viewDummy);
-
- CCoinsViewCache& viewChain = *pcoinsTip;
- CCoinsViewMemPool viewMempool(&viewChain, mempool);
-
- if (fCheckMemPool)
- view.SetBackend(viewMempool); // switch cache backend to db+mempool in case user likes to query mempool
-
- for (size_t i = 0; i < vOutPoints.size(); i++) {
- bool hit = false;
- Coin coin;
- if (view.GetCoin(vOutPoints[i], coin) && !mempool.isSpent(vOutPoints[i])) {
- hit = true;
- outs.emplace_back(std::move(coin));
+ auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
+ for (const COutPoint& vOutPoint : vOutPoints) {
+ Coin coin;
+ bool hit = !mempool.isSpent(vOutPoint) && view.GetCoin(vOutPoint, coin);
+ hits.push_back(hit);
+ if (hit) outs.emplace_back(std::move(coin));
}
+ };
+
+ if (fCheckMemPool) {
+ // use db+mempool as cache backend in case user likes to query mempool
+ LOCK2(cs_main, mempool.cs);
+ CCoinsViewCache& viewChain = *pcoinsTip;
+ CCoinsViewMemPool viewMempool(&viewChain, mempool);
+ process_utxos(viewMempool, mempool);
+ } else {
+ LOCK(cs_main); // no need to lock mempool!
+ process_utxos(*pcoinsTip, CTxMemPool());
+ }
- hits.push_back(hit);
+ for (size_t i = 0; i < hits.size(); ++i) {
+ const bool hit = hits[i];
bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)
bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
}
}
switch (rf) {
- case RF_BINARY: {
+ case RetFormat::BINARY: {
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
@@ -525,7 +532,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
return true;
}
- case RF_HEX: {
+ case RetFormat::HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
ssGetUTXOResponse << chainActive.Height() << chainActive.Tip()->GetBlockHash() << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n";
@@ -535,7 +542,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
return true;
}
- case RF_JSON: {
+ case RetFormat::JSON: {
UniValue objGetUTXOResponse(UniValue::VOBJ);
// pack in some essentials