Bitcoin Core  0.18.99
P2P Digital Currency
rest.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <attributes.h>
7 #include <chain.h>
8 #include <chainparams.h>
9 #include <core_io.h>
10 #include <httpserver.h>
11 #include <index/txindex.h>
12 #include <primitives/block.h>
13 #include <primitives/transaction.h>
14 #include <rpc/blockchain.h>
15 #include <rpc/protocol.h>
16 #include <rpc/server.h>
17 #include <streams.h>
18 #include <sync.h>
19 #include <txmempool.h>
20 #include <util/strencodings.h>
21 #include <validation.h>
22 #include <version.h>
23 
24 #include <boost/algorithm/string.hpp>
25 
26 #include <univalue.h>
27 
28 static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
29 
30 enum class RetFormat {
31  UNDEF,
32  BINARY,
33  HEX,
34  JSON,
35 };
36 
37 static const struct {
39  const char* name;
40 } rf_names[] = {
41  {RetFormat::UNDEF, ""},
42  {RetFormat::BINARY, "bin"},
43  {RetFormat::HEX, "hex"},
44  {RetFormat::JSON, "json"},
45 };
46 
47 struct CCoin {
48  uint32_t nHeight;
50 
52 
53  CCoin() : nHeight(0) {}
54  explicit CCoin(Coin&& in) : nHeight(in.nHeight), out(std::move(in.out)) {}
55 
56  template <typename Stream, typename Operation>
57  inline void SerializationOp(Stream& s, Operation ser_action)
58  {
59  uint32_t nTxVerDummy = 0;
60  READWRITE(nTxVerDummy);
61  READWRITE(nHeight);
62  READWRITE(out);
63  }
64 };
65 
66 static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string message)
67 {
68  req->WriteHeader("Content-Type", "text/plain");
69  req->WriteReply(status, message + "\r\n");
70  return false;
71 }
72 
73 static RetFormat ParseDataFormat(std::string& param, const std::string& strReq)
74 {
75  const std::string::size_type pos = strReq.rfind('.');
76  if (pos == std::string::npos)
77  {
78  param = strReq;
79  return rf_names[0].rf;
80  }
81 
82  param = strReq.substr(0, pos);
83  const std::string suff(strReq, pos + 1);
84 
85  for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
86  if (suff == rf_names[i].name)
87  return rf_names[i].rf;
88 
89  /* If no suffix is found, return original string. */
90  param = strReq;
91  return rf_names[0].rf;
92 }
93 
94 static std::string AvailableDataFormatsString()
95 {
96  std::string formats;
97  for (unsigned int i = 0; i < ARRAYLEN(rf_names); i++)
98  if (strlen(rf_names[i].name) > 0) {
99  formats.append(".");
100  formats.append(rf_names[i].name);
101  formats.append(", ");
102  }
103 
104  if (formats.length() > 0)
105  return formats.substr(0, formats.length() - 2);
106 
107  return formats;
108 }
109 
110 static bool CheckWarmup(HTTPRequest* req)
111 {
112  std::string statusmessage;
113  if (RPCIsInWarmup(&statusmessage))
114  return RESTERR(req, HTTP_SERVICE_UNAVAILABLE, "Service temporarily unavailable: " + statusmessage);
115  return true;
116 }
117 
118 static bool rest_headers(HTTPRequest* req,
119  const std::string& strURIPart)
120 {
121  if (!CheckWarmup(req))
122  return false;
123  std::string param;
124  const RetFormat rf = ParseDataFormat(param, strURIPart);
125  std::vector<std::string> path;
126  boost::split(path, param, boost::is_any_of("/"));
127 
128  if (path.size() != 2)
129  return RESTERR(req, HTTP_BAD_REQUEST, "No header count specified. Use /rest/headers/<count>/<hash>.<ext>.");
130 
131  long count = strtol(path[0].c_str(), nullptr, 10);
132  if (count < 1 || count > 2000)
133  return RESTERR(req, HTTP_BAD_REQUEST, "Header count out of range: " + path[0]);
134 
135  std::string hashStr = path[1];
136  uint256 hash;
137  if (!ParseHashStr(hashStr, hash))
138  return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
139 
140  const CBlockIndex* tip = nullptr;
141  std::vector<const CBlockIndex *> headers;
142  headers.reserve(count);
143  {
144  LOCK(cs_main);
145  tip = ::ChainActive().Tip();
146  const CBlockIndex* pindex = LookupBlockIndex(hash);
147  while (pindex != nullptr && ::ChainActive().Contains(pindex)) {
148  headers.push_back(pindex);
149  if (headers.size() == (unsigned long)count)
150  break;
151  pindex = ::ChainActive().Next(pindex);
152  }
153  }
154 
155  switch (rf) {
156  case RetFormat::BINARY: {
158  for (const CBlockIndex *pindex : headers) {
159  ssHeader << pindex->GetBlockHeader();
160  }
161 
162  std::string binaryHeader = ssHeader.str();
163  req->WriteHeader("Content-Type", "application/octet-stream");
164  req->WriteReply(HTTP_OK, binaryHeader);
165  return true;
166  }
167 
168  case RetFormat::HEX: {
170  for (const CBlockIndex *pindex : headers) {
171  ssHeader << pindex->GetBlockHeader();
172  }
173 
174  std::string strHex = HexStr(ssHeader.begin(), ssHeader.end()) + "\n";
175  req->WriteHeader("Content-Type", "text/plain");
176  req->WriteReply(HTTP_OK, strHex);
177  return true;
178  }
179  case RetFormat::JSON: {
180  UniValue jsonHeaders(UniValue::VARR);
181  for (const CBlockIndex *pindex : headers) {
182  jsonHeaders.push_back(blockheaderToJSON(tip, pindex));
183  }
184  std::string strJSON = jsonHeaders.write() + "\n";
185  req->WriteHeader("Content-Type", "application/json");
186  req->WriteReply(HTTP_OK, strJSON);
187  return true;
188  }
189  default: {
190  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: .bin, .hex)");
191  }
192  }
193 }
194 
195 static bool rest_block(HTTPRequest* req,
196  const std::string& strURIPart,
197  bool showTxDetails)
198 {
199  if (!CheckWarmup(req))
200  return false;
201  std::string hashStr;
202  const RetFormat rf = ParseDataFormat(hashStr, strURIPart);
203 
204  uint256 hash;
205  if (!ParseHashStr(hashStr, hash))
206  return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
207 
208  CBlock block;
209  CBlockIndex* pblockindex = nullptr;
210  CBlockIndex* tip = nullptr;
211  {
212  LOCK(cs_main);
213  tip = ::ChainActive().Tip();
214  pblockindex = LookupBlockIndex(hash);
215  if (!pblockindex) {
216  return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
217  }
218 
219  if (IsBlockPruned(pblockindex))
220  return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
221 
222  if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
223  return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
224  }
225 
226  switch (rf) {
227  case RetFormat::BINARY: {
229  ssBlock << block;
230  std::string binaryBlock = ssBlock.str();
231  req->WriteHeader("Content-Type", "application/octet-stream");
232  req->WriteReply(HTTP_OK, binaryBlock);
233  return true;
234  }
235 
236  case RetFormat::HEX: {
238  ssBlock << block;
239  std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()) + "\n";
240  req->WriteHeader("Content-Type", "text/plain");
241  req->WriteReply(HTTP_OK, strHex);
242  return true;
243  }
244 
245  case RetFormat::JSON: {
246  UniValue objBlock = blockToJSON(block, tip, pblockindex, showTxDetails);
247  std::string strJSON = objBlock.write() + "\n";
248  req->WriteHeader("Content-Type", "application/json");
249  req->WriteReply(HTTP_OK, strJSON);
250  return true;
251  }
252 
253  default: {
254  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
255  }
256  }
257 }
258 
259 static bool rest_block_extended(HTTPRequest* req, const std::string& strURIPart)
260 {
261  return rest_block(req, strURIPart, true);
262 }
263 
264 static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPart)
265 {
266  return rest_block(req, strURIPart, false);
267 }
268 
269 // A bit of a hack - dependency on a function defined in rpc/blockchain.cpp
271 
272 static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
273 {
274  if (!CheckWarmup(req))
275  return false;
276  std::string param;
277  const RetFormat rf = ParseDataFormat(param, strURIPart);
278 
279  switch (rf) {
280  case RetFormat::JSON: {
281  JSONRPCRequest jsonRequest;
282  jsonRequest.params = UniValue(UniValue::VARR);
283  UniValue chainInfoObject = getblockchaininfo(jsonRequest);
284  std::string strJSON = chainInfoObject.write() + "\n";
285  req->WriteHeader("Content-Type", "application/json");
286  req->WriteReply(HTTP_OK, strJSON);
287  return true;
288  }
289  default: {
290  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
291  }
292  }
293 }
294 
295 static bool rest_mempool_info(HTTPRequest* req, const std::string& strURIPart)
296 {
297  if (!CheckWarmup(req))
298  return false;
299  std::string param;
300  const RetFormat rf = ParseDataFormat(param, strURIPart);
301 
302  switch (rf) {
303  case RetFormat::JSON: {
304  UniValue mempoolInfoObject = MempoolInfoToJSON(::mempool);
305 
306  std::string strJSON = mempoolInfoObject.write() + "\n";
307  req->WriteHeader("Content-Type", "application/json");
308  req->WriteReply(HTTP_OK, strJSON);
309  return true;
310  }
311  default: {
312  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
313  }
314  }
315 }
316 
317 static bool rest_mempool_contents(HTTPRequest* req, const std::string& strURIPart)
318 {
319  if (!CheckWarmup(req))
320  return false;
321  std::string param;
322  const RetFormat rf = ParseDataFormat(param, strURIPart);
323 
324  switch (rf) {
325  case RetFormat::JSON: {
326  UniValue mempoolObject = MempoolToJSON(::mempool, true);
327 
328  std::string strJSON = mempoolObject.write() + "\n";
329  req->WriteHeader("Content-Type", "application/json");
330  req->WriteReply(HTTP_OK, strJSON);
331  return true;
332  }
333  default: {
334  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
335  }
336  }
337 }
338 
339 static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
340 {
341  if (!CheckWarmup(req))
342  return false;
343  std::string hashStr;
344  const RetFormat rf = ParseDataFormat(hashStr, strURIPart);
345 
346  uint256 hash;
347  if (!ParseHashStr(hashStr, hash))
348  return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
349 
350  if (g_txindex) {
351  g_txindex->BlockUntilSyncedToCurrentChain();
352  }
353 
354  CTransactionRef tx;
355  uint256 hashBlock = uint256();
356  if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock))
357  return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
358 
359  switch (rf) {
360  case RetFormat::BINARY: {
362  ssTx << tx;
363 
364  std::string binaryTx = ssTx.str();
365  req->WriteHeader("Content-Type", "application/octet-stream");
366  req->WriteReply(HTTP_OK, binaryTx);
367  return true;
368  }
369 
370  case RetFormat::HEX: {
372  ssTx << tx;
373 
374  std::string strHex = HexStr(ssTx.begin(), ssTx.end()) + "\n";
375  req->WriteHeader("Content-Type", "text/plain");
376  req->WriteReply(HTTP_OK, strHex);
377  return true;
378  }
379 
380  case RetFormat::JSON: {
381  UniValue objTx(UniValue::VOBJ);
382  TxToUniv(*tx, hashBlock, objTx);
383  std::string strJSON = objTx.write() + "\n";
384  req->WriteHeader("Content-Type", "application/json");
385  req->WriteReply(HTTP_OK, strJSON);
386  return true;
387  }
388 
389  default: {
390  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
391  }
392  }
393 }
394 
395 static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart)
396 {
397  if (!CheckWarmup(req))
398  return false;
399  std::string param;
400  const RetFormat rf = ParseDataFormat(param, strURIPart);
401 
402  std::vector<std::string> uriParts;
403  if (param.length() > 1)
404  {
405  std::string strUriParams = param.substr(1);
406  boost::split(uriParts, strUriParams, boost::is_any_of("/"));
407  }
408 
409  // throw exception in case of an empty request
410  std::string strRequestMutable = req->ReadBody();
411  if (strRequestMutable.length() == 0 && uriParts.size() == 0)
412  return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");
413 
414  bool fInputParsed = false;
415  bool fCheckMemPool = false;
416  std::vector<COutPoint> vOutPoints;
417 
418  // parse/deserialize input
419  // input-format = output-format, rest/getutxos/bin requires binary input, gives binary output, ...
420 
421  if (uriParts.size() > 0)
422  {
423  //inputs is sent over URI scheme (/rest/getutxos/checkmempool/txid1-n/txid2-n/...)
424  if (uriParts[0] == "checkmempool") fCheckMemPool = true;
425 
426  for (size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
427  {
428  uint256 txid;
429  int32_t nOutput;
430  std::string strTxid = uriParts[i].substr(0, uriParts[i].find('-'));
431  std::string strOutput = uriParts[i].substr(uriParts[i].find('-')+1);
432 
433  if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid))
434  return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");
435 
436  txid.SetHex(strTxid);
437  vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput));
438  }
439 
440  if (vOutPoints.size() > 0)
441  fInputParsed = true;
442  else
443  return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");
444  }
445 
446  switch (rf) {
447  case RetFormat::HEX: {
448  // convert hex to bin, continue then with bin part
449  std::vector<unsigned char> strRequestV = ParseHex(strRequestMutable);
450  strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
451  }
452 
453  case RetFormat::BINARY: {
454  try {
455  //deserialize only if user sent a request
456  if (strRequestMutable.size() > 0)
457  {
458  if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA
459  return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and raw post data is not allowed");
460 
462  oss << strRequestMutable;
463  oss >> fCheckMemPool;
464  oss >> vOutPoints;
465  }
466  } catch (const std::ios_base::failure&) {
467  // abort in case of unreadable binary data
468  return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");
469  }
470  break;
471  }
472 
473  case RetFormat::JSON: {
474  if (!fInputParsed)
475  return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");
476  break;
477  }
478  default: {
479  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
480  }
481  }
482 
483  // limit max outpoints
484  if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS)
485  return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size()));
486 
487  // check spentness and form a bitmap (as well as a JSON capable human-readable string representation)
488  std::vector<unsigned char> bitmap;
489  std::vector<CCoin> outs;
490  std::string bitmapStringRepresentation;
491  std::vector<bool> hits;
492  bitmap.resize((vOutPoints.size() + 7) / 8);
493  {
494  auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool& mempool) {
495  for (const COutPoint& vOutPoint : vOutPoints) {
496  Coin coin;
497  bool hit = !mempool.isSpent(vOutPoint) && view.GetCoin(vOutPoint, coin);
498  hits.push_back(hit);
499  if (hit) outs.emplace_back(std::move(coin));
500  }
501  };
502 
503  if (fCheckMemPool) {
504  // use db+mempool as cache backend in case user likes to query mempool
507  CCoinsViewMemPool viewMempool(&viewChain, mempool);
508  process_utxos(viewMempool, mempool);
509  } else {
510  LOCK(cs_main); // no need to lock mempool!
511  process_utxos(::ChainstateActive().CoinsTip(), CTxMemPool());
512  }
513 
514  for (size_t i = 0; i < hits.size(); ++i) {
515  const bool hit = hits[i];
516  bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)
517  bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
518  }
519  }
520 
521  switch (rf) {
522  case RetFormat::BINARY: {
523  // serialize data
524  // use exact same output as mentioned in Bip64
525  CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
526  ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
527  std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
528 
529  req->WriteHeader("Content-Type", "application/octet-stream");
530  req->WriteReply(HTTP_OK, ssGetUTXOResponseString);
531  return true;
532  }
533 
534  case RetFormat::HEX: {
535  CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
536  ssGetUTXOResponse << ::ChainActive().Height() << ::ChainActive().Tip()->GetBlockHash() << bitmap << outs;
537  std::string strHex = HexStr(ssGetUTXOResponse.begin(), ssGetUTXOResponse.end()) + "\n";
538 
539  req->WriteHeader("Content-Type", "text/plain");
540  req->WriteReply(HTTP_OK, strHex);
541  return true;
542  }
543 
544  case RetFormat::JSON: {
545  UniValue objGetUTXOResponse(UniValue::VOBJ);
546 
547  // pack in some essentials
548  // use more or less the same output as mentioned in Bip64
549  objGetUTXOResponse.pushKV("chainHeight", ::ChainActive().Height());
550  objGetUTXOResponse.pushKV("chaintipHash", ::ChainActive().Tip()->GetBlockHash().GetHex());
551  objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);
552 
553  UniValue utxos(UniValue::VARR);
554  for (const CCoin& coin : outs) {
555  UniValue utxo(UniValue::VOBJ);
556  utxo.pushKV("height", (int32_t)coin.nHeight);
557  utxo.pushKV("value", ValueFromAmount(coin.out.nValue));
558 
559  // include the script in a json output
561  ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true);
562  utxo.pushKV("scriptPubKey", o);
563  utxos.push_back(utxo);
564  }
565  objGetUTXOResponse.pushKV("utxos", utxos);
566 
567  // return json string
568  std::string strJSON = objGetUTXOResponse.write() + "\n";
569  req->WriteHeader("Content-Type", "application/json");
570  req->WriteReply(HTTP_OK, strJSON);
571  return true;
572  }
573  default: {
574  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
575  }
576  }
577 }
578 
580  const std::string& str_uri_part)
581 {
582  if (!CheckWarmup(req)) return false;
583  std::string height_str;
584  const RetFormat rf = ParseDataFormat(height_str, str_uri_part);
585 
586  int32_t blockheight;
587  if (!ParseInt32(height_str, &blockheight) || blockheight < 0) {
588  return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str));
589  }
590 
591  CBlockIndex* pblockindex = nullptr;
592  {
593  LOCK(cs_main);
594  if (blockheight > ::ChainActive().Height()) {
595  return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");
596  }
597  pblockindex = ::ChainActive()[blockheight];
598  }
599  switch (rf) {
600  case RetFormat::BINARY: {
602  ss_blockhash << pblockindex->GetBlockHash();
603  req->WriteHeader("Content-Type", "application/octet-stream");
604  req->WriteReply(HTTP_OK, ss_blockhash.str());
605  return true;
606  }
607  case RetFormat::HEX: {
608  req->WriteHeader("Content-Type", "text/plain");
609  req->WriteReply(HTTP_OK, pblockindex->GetBlockHash().GetHex() + "\n");
610  return true;
611  }
612  case RetFormat::JSON: {
613  req->WriteHeader("Content-Type", "application/json");
615  resp.pushKV("blockhash", pblockindex->GetBlockHash().GetHex());
616  req->WriteReply(HTTP_OK, resp.write() + "\n");
617  return true;
618  }
619  default: {
620  return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");
621  }
622  }
623 }
624 
625 static const struct {
626  const char* prefix;
627  bool (*handler)(HTTPRequest* req, const std::string& strReq);
628 } uri_prefixes[] = {
629  {"/rest/tx/", rest_tx},
630  {"/rest/block/notxdetails/", rest_block_notxdetails},
631  {"/rest/block/", rest_block_extended},
632  {"/rest/chaininfo", rest_chaininfo},
633  {"/rest/mempool/info", rest_mempool_info},
634  {"/rest/mempool/contents", rest_mempool_contents},
635  {"/rest/headers/", rest_headers},
636  {"/rest/getutxos", rest_getutxos},
637  {"/rest/blockhashbyheight/", rest_blockhash_by_height},
638 };
639 
640 void StartREST()
641 {
642  for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++)
644 }
645 
647 {
648 }
649 
650 void StopREST()
651 {
652  for (unsigned int i = 0; i < ARRAYLEN(uri_prefixes); i++)
654 }
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:408
uint32_t nHeight
Definition: rest.cpp:48
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
CTxMemPool mempool
bool(* handler)(HTTPRequest *req, const std::string &strReq)
Definition: rest.cpp:627
static bool CheckWarmup(HTTPRequest *req)
Definition: rest.cpp:110
static bool rest_mempool_info(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:295
static bool rest_chaininfo(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:272
static RetFormat ParseDataFormat(std::string &param, const std::string &strReq)
Definition: rest.cpp:73
A UTXO entry.
Definition: coins.h:30
Definition: block.h:72
CChain & ChainActive()
Definition: validation.cpp:92
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1067
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos, const Consensus::Params &consensusParams)
Functions for disk access for blocks.
Definition: validation.cpp:950
static std::string AvailableDataFormatsString()
Definition: rest.cpp:94
std::string str() const
Definition: streams.h:281
const char * prefix
Definition: rest.cpp:626
#define ARRAYLEN(array)
Utilities for converting data from/to strings.
Definition: strencodings.h:19
std::vector< unsigned char > ParseHex(const char *psz)
int Height() const
Return the maximal height in the chain.
Definition: chain.h:455
UniValue ValueFromAmount(const CAmount &amount)
Definition: core_write.cpp:18
HTTPStatusCode
HTTP status codes.
Definition: protocol.h:10
UniValue blockheaderToJSON(const CBlockIndex *tip, const CBlockIndex *blockindex)
Block header to JSON.
Definition: blockchain.cpp:92
static const struct @10 uri_prefixes[]
static bool rest_tx(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:339
RetFormat
Definition: rest.cpp:30
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:203
bool isSpent(const COutPoint &outpoint) const
Definition: txmempool.cpp:336
static bool rest_headers(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:118
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
Definition: httpserver.cpp:640
uint256 GetBlockHash() const
Definition: chain.h:261
static bool rest_block(HTTPRequest *req, const std::string &strURIPart, bool showTxDetails)
Definition: rest.cpp:195
#define LOCK2(cs1, cs2)
Definition: sync.h:183
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, std::string message)
Definition: rest.cpp:66
CCriticalSection cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:107
static bool rest_getutxos(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:395
Abstract view on the open txout dataset.
Definition: coins.h:146
RetFormat rf
Definition: rest.cpp:38
void WriteReply(int nStatus, const std::string &strReply="")
Write HTTP reply.
Definition: httpserver.cpp:570
UniValue params
Definition: request.h:32
static bool rest_mempool_contents(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:317
#define LOCK(cs)
Definition: sync.h:182
const char * name
Definition: rest.cpp:39
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:18
UniValue getblockchaininfo(const JSONRPCRequest &request)
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...
Definition: chain.h:447
bool IsHex(const std::string &str)
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
Definition: httpserver.cpp:646
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
An output of a transaction.
Definition: transaction.h:133
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:18
static const struct @9 rf_names[]
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params &consensusParams, uint256 &hashBlock, const CBlockIndex *const block_index)
Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock...
Definition: validation.cpp:889
UniValue blockToJSON(const CBlock &block, const CBlockIndex *tip, const CBlockIndex *blockindex, bool txDetails)
Block description to JSON.
Definition: blockchain.cpp:121
CCoin()
Definition: rest.cpp:53
CTxOut out
Definition: rest.cpp:49
void StartREST()
Start HTTP REST subsystem.
Definition: rest.cpp:640
static const size_t MAX_GETUTXOS_OUTPOINTS
Definition: rest.cpp:28
CBlockIndex * LookupBlockIndex(const uint256 &hash)
Definition: validation.cpp:156
static bool rest_blockhash_by_height(HTTPRequest *req, const std::string &str_uri_part)
Definition: rest.cpp:579
256-bit opaque blob.
Definition: uint256.h:121
CChainState & ChainstateActive()
Definition: validation.cpp:87
const_iterator end() const
Definition: streams.h:292
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:442
const_iterator begin() const
Definition: streams.h:290
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
Definition: httpserver.cpp:558
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
void StopREST()
Stop HTTP REST subsystem.
Definition: rest.cpp:650
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:139
const CChainParams & Params()
Return the currently selected parameters.
bool IsBlockPruned(const CBlockIndex *pblockindex)
Check whether the block associated with this index entry is pruned or not.
Definition: validation.h:781
int RPCSerializationFlags()
Definition: server.cpp:493
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:424
std::string GetHex() const
Definition: uint256.cpp:21
std::string HexStr(const T itbegin, const T itend)
Definition: strencodings.h:125
bool RPCIsInWarmup(std::string *outStatus)
Definition: server.cpp:323
Definition: rest.cpp:47
static int count
Definition: tests.c:45
void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex)
Definition: core_write.cpp:152
ADD_SERIALIZE_METHODS
Definition: rest.cpp:51
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: validation.h:626
std::string ReadBody()
Read request body.
Definition: httpserver.cpp:538
void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry, bool include_hex=true, int serialize_flags=0)
Definition: core_write.cpp:178
In-flight HTTP request.
Definition: httpserver.h:57
bool ParseHashStr(const std::string &strHex, uint256 &result)
Parse a hex string into 256 bits.
Definition: core_read.cpp:178
void SerializationOp(Stream &s, Operation ser_action)
Definition: rest.cpp:57
void InterruptREST()
Interrupt RPC REST subsystem.
Definition: rest.cpp:646
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:202
CCoin(Coin &&in)
Definition: rest.cpp:54
#define READWRITE(...)
Definition: serialize.h:184
void SetHex(const char *psz)
Definition: uint256.cpp:27
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose)
Mempool to JSON.
Definition: blockchain.cpp:466
CCoinsView that brings transactions from a mempool into view.
Definition: txmempool.h:752
static bool rest_block_notxdetails(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:264
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
Definition: txmempool.h:517
static bool rest_block_extended(HTTPRequest *req, const std::string &strURIPart)
Definition: rest.cpp:259