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