21 #include <boost/algorithm/string.hpp> 25 static const size_t MAX_GETUTXOS_OUTPOINTS = 15;
53 template <
typename Stream,
typename Operation>
56 uint32_t nTxVerDummy = 0;
66 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
71 static enum RetFormat ParseDataFormat(std::string& param,
const std::string& strReq)
73 const std::string::size_type pos = strReq.rfind(
'.');
74 if (pos == std::string::npos)
77 return rf_names[0].rf;
80 param = strReq.substr(0, pos);
81 const std::string suff(strReq, pos + 1);
83 for (
unsigned int i = 0; i <
ARRAYLEN(rf_names); i++)
84 if (suff == rf_names[i].
name)
85 return rf_names[i].rf;
89 return rf_names[0].rf;
92 static std::string AvailableDataFormatsString()
94 std::string formats =
"";
95 for (
unsigned int i = 0; i <
ARRAYLEN(rf_names); i++)
96 if (strlen(rf_names[i].
name) > 0) {
98 formats.append(rf_names[i].name);
102 if (formats.length() > 0)
103 return formats.substr(0, formats.length() - 2);
110 if (!
IsHex(strReq) || (strReq.size() != 64))
119 std::string statusmessage;
126 const std::string& strURIPart)
128 if (!CheckWarmup(req))
131 const RetFormat rf = ParseDataFormat(param, strURIPart);
132 std::vector<std::string> path;
133 boost::split(path, param, boost::is_any_of(
"/"));
135 if (path.size() != 2 && (path.size() != 3 || path[0] !=
"legacy")) {
136 return RESTERR(req,
HTTP_BAD_REQUEST,
"No header count specified. Use /rest/headers/<count>/<hash>.<ext> or /rest/headers/legacy/<count>/<hash>.<ext>.");
138 std::string headerCount,hashStr;
139 if (path.size() == 2) {
140 headerCount = path[0];
144 headerCount = path[1];
147 long count = strtol(headerCount.c_str(),
nullptr, 10);
148 if (count < 1 || count > 2000)
149 return RESTERR(req,
HTTP_BAD_REQUEST,
"Header count out of range: " + path[0]);
156 std::vector<const CBlockIndex *> headers;
157 headers.reserve(count);
163 headers.push_back(pindex);
164 if (headers.size() == (
unsigned long)count)
172 ssHeader << pindex->GetBlockHeader();
177 std::string binaryHeader = ssHeader.
str();
178 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
179 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
185 std::string strHex =
HexStr(ssHeader.
begin(), ssHeader.
end()) +
"\n";
187 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
196 std::string strJSON = jsonHeaders.
write() +
"\n";
197 req->
WriteHeader(
"Content-Type",
"application/json");
198 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
203 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: .bin, .hex)");
212 const std::string& strURIPart,
215 if (!CheckWarmup(req))
217 std::string param, hashStr;
218 const RetFormat rf = ParseDataFormat(param, strURIPart);
219 std::vector<std::string> path;
220 boost::split(path, param, boost::is_any_of(
"/"));
222 if (path.size() == 1) {
242 return RESTERR(req,
HTTP_NOT_FOUND, hashStr +
" not available (pruned data)");
252 std::string binaryBlock = ssBlock.
str();
253 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
254 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
260 std::string strHex =
HexStr(ssBlock.
begin(), ssBlock.
end()) +
"\n";
262 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
269 std::string strJSON = objBlock.
write() +
"\n";
270 req->
WriteHeader(
"Content-Type",
"application/json");
271 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
277 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
285 static bool rest_block_extended(
HTTPRequest* req,
const std::string& strURIPart)
287 return rest_block(req, strURIPart,
true);
290 static bool rest_block_notxdetails(
HTTPRequest* req,
const std::string& strURIPart)
292 return rest_block(req, strURIPart,
false);
298 static bool rest_chaininfo(
HTTPRequest* req,
const std::string& strURIPart)
300 if (!CheckWarmup(req))
303 const RetFormat rf = ParseDataFormat(param, strURIPart);
310 std::string strJSON = chainInfoObject.
write() +
"\n";
311 req->
WriteHeader(
"Content-Type",
"application/json");
312 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
317 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
325 static bool rest_mempool_info(
HTTPRequest* req,
const std::string& strURIPart)
327 if (!CheckWarmup(req))
330 const RetFormat rf = ParseDataFormat(param, strURIPart);
336 std::string strJSON = mempoolInfoObject.
write() +
"\n";
337 req->
WriteHeader(
"Content-Type",
"application/json");
338 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
343 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
351 static bool rest_mempool_contents(
HTTPRequest* req,
const std::string& strURIPart)
353 if (!CheckWarmup(req))
356 const RetFormat rf = ParseDataFormat(param, strURIPart);
362 std::string strJSON = mempoolObject.
write() +
"\n";
363 req->
WriteHeader(
"Content-Type",
"application/json");
364 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
369 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
377 static bool rest_tx(
HTTPRequest* req,
const std::string& strURIPart)
379 if (!CheckWarmup(req))
382 const RetFormat rf = ParseDataFormat(hashStr, strURIPart);
398 std::string binaryTx = ssTx.
str();
399 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
400 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
408 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
416 std::string strJSON = objTx.
write() +
"\n";
417 req->
WriteHeader(
"Content-Type",
"application/json");
418 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
424 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
432 static bool rest_getutxos(
HTTPRequest* req,
const std::string& strURIPart)
434 if (!CheckWarmup(req))
437 const RetFormat rf = ParseDataFormat(param, strURIPart);
439 std::vector<std::string> uriParts;
440 if (param.length() > 1)
442 std::string strUriParams = param.substr(1);
443 boost::split(uriParts, strUriParams, boost::is_any_of(
"/"));
447 std::string strRequestMutable = req->
ReadBody();
448 if (strRequestMutable.length() == 0 && uriParts.size() == 0)
451 bool fInputParsed =
false;
452 bool fCheckMemPool =
false;
453 std::vector<COutPoint> vOutPoints;
458 if (uriParts.size() > 0)
462 if (uriParts.size() > 0 && uriParts[0] ==
"checkmempool")
463 fCheckMemPool =
true;
465 for (
size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
469 std::string strTxid = uriParts[i].substr(0, uriParts[i].find(
"-"));
470 std::string strOutput = uriParts[i].substr(uriParts[i].find(
"-")+1);
476 vOutPoints.push_back(
COutPoint(txid, (uint32_t)nOutput));
479 if (vOutPoints.size() > 0)
488 std::vector<unsigned char> strRequestV =
ParseHex(strRequestMutable);
489 strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
495 if (strRequestMutable.size() > 0)
498 return RESTERR(req,
HTTP_BAD_REQUEST,
"Combination of URI scheme inputs and raw post data is not allowed");
501 oss << strRequestMutable;
502 oss >> fCheckMemPool;
505 }
catch (
const std::ios_base::failure&
e) {
518 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
523 if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS)
524 return RESTERR(req,
HTTP_BAD_REQUEST,
strprintf(
"Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size()));
527 std::vector<unsigned char> bitmap;
528 std::vector<CCoin> outs;
529 std::string bitmapStringRepresentation;
530 std::vector<bool> hits;
531 bitmap.resize((vOutPoints.size() + 7) / 8);
544 for (
size_t i = 0; i < vOutPoints.size(); i++) {
549 outs.emplace_back(std::move(coin));
553 bitmapStringRepresentation.append(hit ?
"1" :
"0");
554 bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
564 std::string ssGetUTXOResponseString = ssGetUTXOResponse.
str();
566 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
567 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
575 std::string strHex =
HexStr(ssGetUTXOResponse.
begin(), ssGetUTXOResponse.
end()) +
"\n";
578 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
590 objGetUTXOResponse.
push_back(
Pair(
"bitmap", bitmapStringRepresentation));
593 for (
const CCoin& coin : outs) {
607 std::string strJSON = objGetUTXOResponse.
write() +
"\n";
608 req->
WriteHeader(
"Content-Type",
"application/json");
609 req->
WriteHeader(
"Access-Control-Allow-Origin",
"*");
614 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
622 static const struct {
626 {
"/rest/tx/", rest_tx},
627 {
"/rest/block/notxdetails/", rest_block_notxdetails},
628 {
"/rest/block/", rest_block_extended},
629 {
"/rest/chaininfo", rest_chaininfo},
630 {
"/rest/mempool/info", rest_mempool_info},
631 {
"/rest/mempool/contents", rest_mempool_contents},
632 {
"/rest/headers/", rest_headers},
633 {
"/rest/getutxos", rest_getutxos},
638 for (
unsigned int i = 0; i <
ARRAYLEN(uri_prefixes); i++)
649 for (
unsigned int i = 0; i <
ARRAYLEN(uri_prefixes); i++)
bool(* handler)(HTTPRequest *req, const std::string &strReq)
const_iterator begin() const
void SetBackend(CCoinsView &viewIn)
bool fHavePruned
Pruning-related variables and constants.
bool isSpent(const COutPoint &outpoint)
UniValue mempoolInfoToJSON()
Mempool information to JSON.
std::string GetHex() const
UniValue ValueFromAmount(const CAmount &amount)
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
HTTPStatusCode
HTTP status codes.
UniValue blockheaderToJSON(const CBlockIndex *blockindex)
Block header to JSON.
std::hash for asio::adress
Double ended buffer combining vector and stream-like interfaces.
std::shared_ptr< const CTransaction > CTransactionRef
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
bool ReadBlockFromDisk(Block &block, const CDiskBlockPos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CCoinsViewCache * pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
int Height() const
Return the maximal height in the chain.
bool push_back(const UniValue &val)
unsigned int nStatus
Verification status of this block. See enum BlockStatus.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
Abstract view on the open txout dataset.
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
void WriteReply(int nStatus, const std::string &strReply="")
Write HTTP reply.
UniValue getblockchaininfo(const JSONRPCRequest &request)
bool IsHex(const std::string &str)
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
An output of a transaction.
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
An outpoint - a combination of a transaction hash and an index n into its vout.
UniValue mempoolToJSON(bool fVerbose)
Mempool to JSON.
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params &consensusParams, uint256 &hashBlock, bool fAllowSlow)
Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock...
uint256 ParseHashStr(const std::string &, const std::string &strName)
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
void StopREST()
Stop HTTP REST subsystem.
The block chain is a tree shaped structure starting with the genesis block at the root...
const CChainParams & Params()
Return the currently selected parameters.
int RPCSerializationFlags()
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
bool RPCIsInWarmup(std::string *outStatus)
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
std::string ReadBody()
Read request body.
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
void SerializationOp(Stream &s, Operation ser_action)
void InterruptREST()
Interrupt RPC REST subsystem.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
full block available in blk*.dat
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
UniValue blockToJSON(const CBlock &block, const CBlockIndex *blockindex, bool txDetails)
Block description to JSON.
void SetHex(const char *psz)
CCoinsView that brings transactions from a memorypool into view.
unsigned int nTx
Number of transactions in this block.
bool StartREST()
Start HTTP REST subsystem.
uint256 GetBlockHash() const
const_iterator end() const
std::vector< unsigned char > ParseHex(const char *psz)