19 #include <boost/algorithm/string.hpp>
23 static const size_t MAX_GETUTXOS_OUTPOINTS = 15;
49 template <
typename Stream,
typename Operation>
72 static enum RetFormat ParseDataFormat(std::string& param,
const std::string& strReq)
74 const std::string::size_type pos = strReq.rfind(
'.');
75 if (pos == std::string::npos)
78 return rf_names[0].rf;
81 param = strReq.substr(0, pos);
82 const std::string suff(strReq, pos + 1);
84 for (
unsigned int i = 0; i <
ARRAYLEN(rf_names); i++)
85 if (suff == rf_names[i].name)
86 return rf_names[i].rf;
90 return rf_names[0].rf;
93 static std::string AvailableDataFormatsString()
95 std::string formats =
"";
96 for (
unsigned int i = 0; i <
ARRAYLEN(rf_names); i++)
97 if (strlen(rf_names[i].name) > 0) {
99 formats.append(rf_names[i].name);
100 formats.append(
", ");
103 if (formats.length() > 0)
104 return formats.substr(0, formats.length() - 2);
111 if (!
IsHex(strReq) || (strReq.size() != 64))
120 std::string statusmessage;
127 const std::string& strURIPart)
129 if (!CheckWarmup(req))
132 const RetFormat rf = ParseDataFormat(param, strURIPart);
133 std::vector<std::string> path;
134 boost::split(path, param, boost::is_any_of(
"/"));
136 if (path.size() != 2)
137 return RESTERR(req,
HTTP_BAD_REQUEST,
"No header count specified. Use /rest/headers/<count>/<hash>.<ext>.");
139 long count = strtol(path[0].c_str(), NULL, 10);
140 if (count < 1 || count > 2000)
141 return RESTERR(req,
HTTP_BAD_REQUEST,
"Header count out of range: " + path[0]);
143 std::string hashStr = path[1];
148 std::vector<const CBlockIndex *> headers;
149 headers.reserve(count);
155 headers.push_back(pindex);
156 if (headers.size() == (
unsigned long)count)
164 BOOST_FOREACH(
const CBlockIndex *pindex, headers) {
170 std::string binaryHeader = ssHeader.str();
171 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
177 std::string strHex =
HexStr(ssHeader.begin(), ssHeader.end()) +
"\n";
184 BOOST_FOREACH(
const CBlockIndex *pindex, headers) {
187 std::string strJSON = jsonHeaders.write() +
"\n";
188 req->
WriteHeader(
"Content-Type",
"application/json");
193 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: .bin, .hex)");
202 const std::string& strURIPart,
205 if (!CheckWarmup(req))
208 const RetFormat rf = ParseDataFormat(hashStr, strURIPart);
223 return RESTERR(req,
HTTP_NOT_FOUND, hashStr +
" not available (pruned data)");
234 std::string binaryBlock = ssBlock.str();
235 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
241 std::string strHex =
HexStr(ssBlock.begin(), ssBlock.end()) +
"\n";
249 std::string strJSON = objBlock.
write() +
"\n";
250 req->
WriteHeader(
"Content-Type",
"application/json");
256 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
264 static bool rest_block_extended(
HTTPRequest* req,
const std::string& strURIPart)
266 return rest_block(req, strURIPart,
true);
269 static bool rest_block_notxdetails(
HTTPRequest* req,
const std::string& strURIPart)
271 return rest_block(req, strURIPart,
false);
277 static bool rest_chaininfo(
HTTPRequest* req,
const std::string& strURIPart)
279 if (!CheckWarmup(req))
282 const RetFormat rf = ParseDataFormat(param, strURIPart);
289 std::string strJSON = chainInfoObject.
write() +
"\n";
290 req->
WriteHeader(
"Content-Type",
"application/json");
295 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
303 static bool rest_mempool_info(
HTTPRequest* req,
const std::string& strURIPart)
305 if (!CheckWarmup(req))
308 const RetFormat rf = ParseDataFormat(param, strURIPart);
314 std::string strJSON = mempoolInfoObject.
write() +
"\n";
315 req->
WriteHeader(
"Content-Type",
"application/json");
320 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
328 static bool rest_mempool_contents(
HTTPRequest* req,
const std::string& strURIPart)
330 if (!CheckWarmup(req))
333 const RetFormat rf = ParseDataFormat(param, strURIPart);
339 std::string strJSON = mempoolObject.
write() +
"\n";
340 req->
WriteHeader(
"Content-Type",
"application/json");
345 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: json)");
353 static bool rest_tx(
HTTPRequest* req,
const std::string& strURIPart)
355 if (!CheckWarmup(req))
358 const RetFormat rf = ParseDataFormat(hashStr, strURIPart);
374 std::string binaryTx = ssTx.str();
375 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
381 std::string strHex =
HexStr(ssTx.begin(), ssTx.end()) +
"\n";
390 std::string strJSON = objTx.write() +
"\n";
391 req->
WriteHeader(
"Content-Type",
"application/json");
397 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
405 static bool rest_getutxos(
HTTPRequest* req,
const std::string& strURIPart)
407 if (!CheckWarmup(req))
410 const RetFormat rf = ParseDataFormat(param, strURIPart);
412 std::vector<std::string> uriParts;
413 if (param.length() > 1)
415 std::string strUriParams = param.substr(1);
416 boost::split(uriParts, strUriParams, boost::is_any_of(
"/"));
420 std::string strRequestMutable = req->
ReadBody();
421 if (strRequestMutable.length() == 0 && uriParts.size() == 0)
424 bool fInputParsed =
false;
425 bool fCheckMemPool =
false;
426 std::vector<COutPoint> vOutPoints;
431 if (uriParts.size() > 0)
435 if (uriParts.size() > 0 && uriParts[0] ==
"checkmempool")
436 fCheckMemPool =
true;
438 for (
size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
442 std::string strTxid = uriParts[i].substr(0, uriParts[i].find(
"-"));
443 std::string strOutput = uriParts[i].substr(uriParts[i].find(
"-")+1);
449 vOutPoints.push_back(
COutPoint(txid, (uint32_t)nOutput));
452 if (vOutPoints.size() > 0)
461 std::vector<unsigned char> strRequestV =
ParseHex(strRequestMutable);
462 strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
468 if (strRequestMutable.size() > 0)
471 return RESTERR(req,
HTTP_BAD_REQUEST,
"Combination of URI scheme inputs and raw post data is not allowed");
474 oss << strRequestMutable;
475 oss >> fCheckMemPool;
478 }
catch (
const std::ios_base::failure& e) {
491 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
496 if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS)
497 return RESTERR(req,
HTTP_BAD_REQUEST,
strprintf(
"Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size()));
500 std::vector<unsigned char> bitmap;
501 std::vector<CCoin> outs;
502 std::string bitmapStringRepresentation;
503 std::vector<bool> hits;
504 bitmap.resize((vOutPoints.size() + 7) / 8);
515 view.SetBackend(viewMempool);
517 for (
size_t i = 0; i < vOutPoints.size(); i++) {
519 uint256 hash = vOutPoints[i].hash;
521 if (view.GetCoins(hash, coins)) {
530 coin.
out = coins.
vout.at(vOutPoints[i].n);
532 outs.push_back(coin);
537 bitmapStringRepresentation.append(hit ?
"1" :
"0");
538 bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
548 std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
550 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
558 std::string strHex =
HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) +
"\n";
572 objGetUTXOResponse.push_back(Pair(
"bitmap", bitmapStringRepresentation));
575 BOOST_FOREACH (
const CCoin& coin, outs) {
577 utxo.push_back(Pair(
"txvers", (int32_t)coin.
nTxVer));
578 utxo.push_back(Pair(
"height", (int32_t)coin.
nHeight));
584 utxo.push_back(Pair(
"scriptPubKey", o));
585 utxos.push_back(utxo);
587 objGetUTXOResponse.push_back(Pair(
"utxos", utxos));
590 std::string strJSON = objGetUTXOResponse.write() +
"\n";
591 req->
WriteHeader(
"Content-Type",
"application/json");
596 return RESTERR(req,
HTTP_NOT_FOUND,
"output format not found (available: " + AvailableDataFormatsString() +
")");
604 static const struct {
608 {
"/rest/tx/", rest_tx},
609 {
"/rest/block/notxdetails/", rest_block_notxdetails},
610 {
"/rest/block/", rest_block_extended},
611 {
"/rest/chaininfo", rest_chaininfo},
612 {
"/rest/mempool/info", rest_mempool_info},
613 {
"/rest/mempool/contents", rest_mempool_contents},
614 {
"/rest/headers/", rest_headers},
615 {
"/rest/getutxos", rest_getutxos},
620 for (
unsigned int i = 0; i <
ARRAYLEN(uri_prefixes); i++)
631 for (
unsigned int i = 0; i <
ARRAYLEN(uri_prefixes); i++)
@ BLOCK_HAVE_DATA
full block available in blk*.dat
const CChainParams & Params()
Return the currently selected parameters.
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockHeader GetBlockHeader(const Consensus::Params &consensusParams, bool fCheckPOW=true) const
uint256 GetBlockHash() const
unsigned int nStatus
Verification status of this block. See enum BlockStatus.
unsigned int nTx
Number of transactions in this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or NULL if the given index is not found or is the tip.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or NULL if none.
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const Consensus::Params & GetConsensus(uint32_t nTargetHeight) const
Pruned version of CTransaction: only retains metadata and unspent transaction outputs.
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
int nVersion
version of the CTransaction; accesses to this value should probably check for nHeight as well,...
bool IsAvailable(unsigned int nPos) const
check whether a particular output is still available
int nHeight
at which height this transaction was included in the active block chain
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Abstract view on the open txout dataset.
CCoinsView that brings transactions from a memorypool into view.
Double ended buffer combining vector and stream-like interfaces.
An outpoint - a combination of a transaction hash and an index n into its vout.
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
void pruneSpent(const uint256 &hash, CCoins &coins)
An output of a transaction.
void WriteReply(int nStatus, const std::string &strReply="")
Write HTTP reply.
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
std::string ReadBody()
Read request body.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
void SetHex(const char *psz)
std::string GetHex() const
uint256 ParseHashStr(const std::string &, const std::string &strName)
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
UniValue mempoolToJSON(bool fVerbose=false)
UniValue getblockchaininfo(const JSONRPCRequest &request)
UniValue blockToJSON(const CBlock &block, const CBlockIndex *blockindex, bool txDetails=false)
void ScriptPubKeyToJSON(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
void TxToJSON(const CTransaction &tx, const uint256 hashBlock, UniValue &entry)
UniValue mempoolInfoToJSON()
void StopREST()
Stop HTTP REST subsystem.
bool StartREST()
Start HTTP REST subsystem.
UniValue blockheaderToJSON(const CBlockIndex *blockindex)
void InterruptREST()
Interrupt RPC REST subsystem.
bool(* handler)(HTTPRequest *req, const std::string &strReq)
HTTPStatusCode
HTTP status codes.
@ HTTP_SERVICE_UNAVAILABLE
bool RPCIsInWarmup(std::string *outStatus)
UniValue ValueFromAmount(const CAmount &amount)
int RPCSerializationFlags()
void SerializationOp(Stream &s, Operation ser_action)
std::shared_ptr< const CTransaction > CTransactionRef
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
bool IsHex(const string &str)
vector< unsigned char > ParseHex(const char *psz)
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
CCoinsViewCache * pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
CCriticalSection cs_main
Global state.
bool fHavePruned
Pruning-related variables and constants.
CTxMemPool mempool(::minRelayTxFee)
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.
bool ReadBlockFromDisk(CBlock &block, const CDiskBlockPos &pos, const Consensus::Params &consensusParams, bool fCheckPOW)
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).