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