65 uint32_t nTxVerDummy = 0;
66 READWRITE(nTxVerDummy, obj.nHeight, obj.out);
86 auto node_context = util::AnyPtr<NodeContext>(context);
103 auto node_context = util::AnyPtr<NodeContext>(context);
104 if (!node_context || !node_context->mempool) {
108 return node_context->mempool.get();
120 auto node_context = util::AnyPtr<NodeContext>(context);
121 if (!node_context || !node_context->chainman) {
125 return node_context->chainman.get();
132 param = strReq.substr(0, strReq.rfind(
'?'));
133 const std::string::size_type pos_format{param.rfind(
'.')};
136 if (pos_format == std::string::npos) {
141 const std::string suffix(param, pos_format + 1);
142 for (
const auto& rf_name :
rf_names) {
143 if (suffix == rf_name.name) {
144 param.erase(pos_format);
156 for (
const auto& rf_name :
rf_names) {
157 if (strlen(rf_name.name) > 0) {
159 formats.append(rf_name.name);
160 formats.append(
", ");
164 if (formats.length() > 0)
165 return formats.substr(0, formats.length() - 2);
172 std::string statusmessage;
180 const std::string& uri_part)
186 std::vector<std::string> path =
SplitString(param,
'/');
188 std::string raw_count;
190 if (path.size() == 2) {
194 }
else if (path.size() == 1) {
199 }
catch (
const std::runtime_error& e) {
203 return RESTERR(req,
HTTP_BAD_REQUEST,
"Invalid URI format. Expected /rest/headers/<hash>.<ext>?count=<count>");
206 const auto parsed_count{ToIntegral<size_t>(raw_count)};
217 std::vector<const CBlockIndex*> headers;
218 headers.reserve(*parsed_count);
220 if (!maybe_chainman)
return false;
225 tip = active_chain.
Tip();
227 while (pindex !=
nullptr && active_chain.
Contains(pindex)) {
228 headers.push_back(pindex);
229 if (headers.size() == *parsed_count) {
232 pindex = active_chain.
Next(pindex);
240 ssHeader << pindex->GetBlockHeader();
243 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
251 ssHeader << pindex->GetBlockHeader();
254 std::string strHex =
HexStr(ssHeader) +
"\n";
264 std::string strJSON = jsonHeaders.
write() +
"\n";
265 req->
WriteHeader(
"Content-Type",
"application/json");
285 coin.
out.Serialize(stream);
304 prevout.
pushKV(
"scriptPubKey", std::move(script_pub_key));
306 tx_prevouts.
push_back(std::move(prevout));
308 result.push_back(std::move(tx_prevouts));
319 std::vector<std::string> path =
SplitString(param,
'/');
322 if (path.size() == 1) {
353 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
361 const std::string strHex{
HexStr(ssSpentResponse) +
"\n"};
370 std::string strJSON =
result.write() +
"\n";
371 req->
WriteHeader(
"Content-Type",
"application/json");
390 const std::string& uri_part,
391 std::optional<TxVerbosity> tx_verbosity,
392 std::optional<std::pair<size_t, size_t>> block_part = std::nullopt)
408 if (!maybe_chainman)
return false;
418 if (chainman.
m_blockman.IsBlockPruned(*pblockindex)) {
428 switch (block_data.error()) {
439 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
445 const std::string strHex{
HexStr(*block_data) +
"\n"};
456 std::string strJSON = objBlock.
write() +
"\n";
457 req->
WriteHeader(
"Content-Type",
"application/json");
483 if (
const auto opt_offset{ToIntegral<size_t>(req->
GetQueryParameter(
"offset").value_or(
""))}) {
484 if (
const auto opt_size{ToIntegral<size_t>(req->
GetQueryParameter(
"size").value_or(
""))}) {
487 {{*opt_offset, *opt_size}});
494 }
catch (
const std::runtime_error& e) {
506 std::vector<std::string> uri_parts =
SplitString(param,
'/');
507 std::string raw_count;
508 std::string raw_blockhash;
509 if (uri_parts.size() == 3) {
511 raw_blockhash = uri_parts[2];
512 raw_count = uri_parts[1];
513 }
else if (uri_parts.size() == 2) {
515 raw_blockhash = uri_parts[1];
518 }
catch (
const std::runtime_error& e) {
522 return RESTERR(req,
HTTP_BAD_REQUEST,
"Invalid URI format. Expected /rest/blockfilterheaders/<filtertype>/<blockhash>.<ext>?count=<count>");
525 const auto parsed_count{ToIntegral<size_t>(raw_count)};
545 std::vector<const CBlockIndex*> headers;
546 headers.reserve(*parsed_count);
549 if (!maybe_chainman)
return false;
554 while (pindex !=
nullptr && active_chain.
Contains(pindex)) {
555 headers.push_back(pindex);
556 if (headers.size() == *parsed_count)
558 pindex = active_chain.
Next(pindex);
562 bool index_ready = index->BlockUntilSyncedToCurrentChain();
564 std::vector<uint256> filter_headers;
565 filter_headers.reserve(*parsed_count);
569 std::string errmsg =
"Filter not found.";
572 errmsg +=
" Block filters are still in the process of being indexed.";
574 errmsg +=
" This error is unexpected and indicates index corruption.";
579 filter_headers.push_back(filter_header);
585 for (
const uint256& header : filter_headers) {
589 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
595 for (
const uint256& header : filter_headers) {
599 std::string strHex =
HexStr(ssHeader) +
"\n";
606 for (
const uint256& header : filter_headers) {
610 std::string strJSON = jsonHeaders.
write() +
"\n";
611 req->
WriteHeader(
"Content-Type",
"application/json");
629 std::vector<std::string> uri_parts =
SplitString(param,
'/');
630 if (uri_parts.size() != 2) {
631 return RESTERR(req,
HTTP_BAD_REQUEST,
"Invalid URI format. Expected /rest/blockfilter/<filtertype>/<blockhash>");
650 bool block_was_connected;
653 if (!maybe_chainman)
return false;
663 bool index_ready = index->BlockUntilSyncedToCurrentChain();
667 std::string errmsg =
"Filter not found.";
669 if (!block_was_connected) {
670 errmsg +=
" Block was not connected to active chain.";
671 }
else if (!index_ready) {
672 errmsg +=
" Block filters are still in the process of being indexed.";
674 errmsg +=
" This error is unexpected and indicates index corruption.";
685 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
693 std::string strHex =
HexStr(ssResp) +
"\n";
701 std::string strJSON =
ret.write() +
"\n";
702 req->
WriteHeader(
"Content-Type",
"application/json");
728 std::string strJSON = chainInfoObject.
write() +
"\n";
729 req->
WriteHeader(
"Content-Type",
"application/json");
746 std::string hash_str;
755 if (!hash_str.empty()) {
762 if (!chainman)
return false;
770 req->
WriteHeader(
"Content-Type",
"application/json");
788 if (param !=
"contents" && param !=
"info") {
793 if (!mempool)
return false;
797 std::string str_json;
798 if (param ==
"contents") {
799 std::string raw_verbose;
802 }
catch (
const std::runtime_error& e) {
805 if (raw_verbose !=
"true" && raw_verbose !=
"false") {
806 return RESTERR(req,
HTTP_BAD_REQUEST,
"The \"verbose\" query parameter must be either \"true\" or \"false\".");
808 std::string raw_mempool_sequence;
810 raw_mempool_sequence = req->
GetQueryParameter(
"mempool_sequence").value_or(
"false");
811 }
catch (
const std::runtime_error& e) {
814 if (raw_mempool_sequence !=
"true" && raw_mempool_sequence !=
"false") {
815 return RESTERR(req,
HTTP_BAD_REQUEST,
"The \"mempool_sequence\" query parameter must be either \"true\" or \"false\".");
817 const bool verbose{raw_verbose ==
"true"};
818 const bool mempool_sequence{raw_mempool_sequence ==
"true"};
819 if (verbose && mempool_sequence) {
820 return RESTERR(req,
HTTP_BAD_REQUEST,
"Verbose results cannot contain mempool sequence values. (hint: set \"verbose=false\")");
827 req->
WriteHeader(
"Content-Type",
"application/json");
850 g_txindex->BlockUntilSyncedToCurrentChain();
854 if (!
node)
return false;
866 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
875 std::string strHex =
HexStr(ssTx) +
"\n";
884 std::string strJSON = objTx.
write() +
"\n";
885 req->
WriteHeader(
"Content-Type",
"application/json");
903 std::vector<std::string> uriParts;
904 if (param.length() > 1)
906 std::string strUriParams = param.substr(1);
911 std::string strRequestMutable = req->
ReadBody();
912 if (strRequestMutable.length() == 0 && uriParts.size() == 0)
915 bool fInputParsed =
false;
916 bool fCheckMemPool =
false;
917 std::vector<COutPoint> vOutPoints;
922 if (uriParts.size() > 0)
925 if (uriParts[0] ==
"checkmempool") fCheckMemPool =
true;
927 for (
size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
929 const auto txid_out{util::Split<std::string_view>(uriParts[i],
'-')};
930 if (txid_out.size() != 2) {
934 auto output{ToIntegral<uint32_t>(txid_out.at(1))};
936 if (!txid || !output) {
940 vOutPoints.emplace_back(*txid, *output);
943 if (vOutPoints.size() > 0)
952 std::vector<unsigned char> strRequestV =
ParseHex(strRequestMutable);
953 strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
960 if (strRequestMutable.size() > 0)
966 oss << strRequestMutable;
967 oss >> fCheckMemPool;
970 }
catch (
const std::ios_base::failure&) {
992 std::vector<unsigned char> bitmap;
993 std::vector<CCoin> outs;
994 std::string bitmapStringRepresentation;
995 std::vector<bool> hits;
996 bitmap.resize((vOutPoints.size() + 7) / 8);
998 if (!maybe_chainman)
return false;
1004 for (
const COutPoint& vOutPoint : vOutPoints) {
1005 auto coin = !mempool || !mempool->isSpent(vOutPoint) ? view.GetCoin(vOutPoint) : std::nullopt;
1006 hits.push_back(coin.has_value());
1007 if (coin) outs.emplace_back(std::move(*coin));
1013 if (fCheckMemPool) {
1015 if (!mempool)
return false;
1020 process_utxos(viewMempool, mempool);
1026 for (
size_t i = 0; i < hits.size(); ++i) {
1027 const bool hit = hits[i];
1028 bitmapStringRepresentation.append(hit ?
"1" :
"0");
1029 bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
1038 ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
1040 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
1047 ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
1048 std::string strHex =
HexStr(ssGetUTXOResponse) +
"\n";
1060 objGetUTXOResponse.
pushKV(
"chainHeight", active_height);
1061 objGetUTXOResponse.
pushKV(
"chaintipHash", active_hash.GetHex());
1062 objGetUTXOResponse.
pushKV(
"bitmap", bitmapStringRepresentation);
1065 for (
const CCoin& coin : outs) {
1067 utxo.
pushKV(
"height", coin.nHeight);
1073 utxo.
pushKV(
"scriptPubKey", std::move(o));
1076 objGetUTXOResponse.
pushKV(
"utxos", std::move(utxos));
1079 std::string strJSON = objGetUTXOResponse.
write() +
"\n";
1080 req->
WriteHeader(
"Content-Type",
"application/json");
1091 const std::string& str_uri_part)
1094 std::string height_str;
1097 const auto blockheight{ToIntegral<int32_t>(height_str)};
1098 if (!blockheight || *blockheight < 0) {
1105 if (!maybe_chainman)
return false;
1109 if (*blockheight > active_chain.
Height()) {
1112 pblockindex = active_chain[*blockheight];
1118 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
1128 req->
WriteHeader(
"Content-Type",
"application/json");
1140 static const struct {
std::shared_ptr< const CTransaction > CTransactionRef
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
static ChainstateManager * GetChainman(const std::any &context, HTTPRequest *req)
Get the node context chainstatemanager.
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
Interval between compact filter checkpoints.
void push_back(UniValue val)
std::vector< Coin > vprevout
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose, bool include_mempool_sequence)
Mempool to JSON.
static bool CheckWarmup(HTTPRequest *req)
std::vector< std::string > SplitString(std::string_view str, char sep)
The same as previous option with information about prevouts if available.
bool BlockFilterTypeByName(std::string_view name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
void WriteReply(int nStatus, std::string_view reply="")
Write HTTP reply.
UniValue ValueFromAmount(const CAmount amount)
static bool rest_block_part(const std::any &context, HTTPRequest *req, const std::string &uri_part)
static bool rest_tx(const std::any &context, HTTPRequest *req, const std::string &uri_part)
UniValue blockToJSON(BlockManager &blockman, const CBlock &block, const CBlockIndex &tip, const CBlockIndex &blockindex, TxVerbosity verbosity, const uint256 pow_limit)
Block description to JSON.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
An in-memory indexed chain of blocks.
static std::string AvailableDataFormatsString()
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static bool rest_headers(const std::any &context, HTTPRequest *req, const std::string &uri_part)
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
RESTResponseFormat ParseDataFormat(std::string ¶m, const std::string &strReq)
Parse a URI to get the data format and URI without data format and query string.
int Height() const
Return the maximal height in the chain.
CTxOut out
unspent transaction output
HTTPStatusCode
HTTP status codes.
static bool rest_block_filter(const std::any &context, HTTPRequest *req, const std::string &uri_part)
static bool rest_spent_txouts(const std::any &context, HTTPRequest *req, const std::string &uri_part)
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
static const struct @10 uri_prefixes[]
std::optional< std::string > GetQueryParameter(const std::string &key) const
Get the query parameter value from request uri for a specified key, or std::nullopt if the key is not...
static bool rest_filter_header(const std::any &context, HTTPRequest *req, const std::string &uri_part)
static bool rest_chaininfo(const std::any &context, HTTPRequest *req, const std::string &uri_part)
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex, const CTxUndo *txundo, TxVerbosity verbosity, std::function< bool(const CTxOut &)> is_change_func)
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
Minimal stream for reading from an existing byte array by std::span.
SERIALIZE_METHODS(CCoin, obj)
static bool rest_block_extended(const std::any &context, HTTPRequest *req, const std::string &uri_part)
uint256 GetBlockHash() const
static bool rest_mempool(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
NodeContext struct containing references to chain state and connection state.
uint256 powLimit
Proof of work parameters.
static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, std::string message)
static void BlockUndoToJSON(const CBlockUndo &block_undo, UniValue &result)
Serialize spent outputs as a list of per-transaction CTxOut lists using JSON format.
Abstract view on the open txout dataset.
UniValue blockheaderToJSON(const CBlockIndex &tip, const CBlockIndex &blockindex, const uint256 pow_limit)
Block header to JSON.
Double ended buffer combining vector and stream-like interfaces.
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
Complete block filter struct as defined in BIP 157.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
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...
static std::optional< uint256 > FromHex(std::string_view str)
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
const Consensus::Params & GetConsensus() const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
ReadRawBlockResult ReadRawBlock(const FlatFilePos &pos, std::optional< std::pair< size_t, size_t >> block_part=std::nullopt) const
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
An output of a transaction.
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
An outpoint - a combination of a transaction hash and an index n into its vout.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
static const struct @9 rf_names[]
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
CTransactionRef GetTransaction(const CBlockIndex *const block_index, const CTxMemPool *const mempool, const Txid &hash, const BlockManager &blockman, uint256 &hashBlock)
Return transaction with a given hash.
void ScriptToUniv(const CScript &script, UniValue &out, bool include_hex, bool include_address, const SigningProvider *provider)
static bool rest_blockhash_by_height(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
static void SerializeBlockUndo(DataStream &stream, const CBlockUndo &block_undo)
Serialize spent outputs as a list of per-transaction CTxOut lists using binary format.
static CTxMemPool * GetMemPool(const std::any &context, HTTPRequest *req)
Get the node context mempool.
static const size_t MAX_GETUTXOS_OUTPOINTS
RPCHelpMan getblockchaininfo()
#define EXCLUSIVE_LOCKS_REQUIRED(...)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
Only TXID for each block's transaction.
RPCHelpMan getdeploymentinfo()
void StopREST()
Stop HTTP REST subsystem.
The block chain is a tree shaped structure starting with the genesis block at the root...
void pushKV(std::string key, UniValue val)
Undo information for a CBlock.
Undo information for a CTransaction.
static NodeContext * GetNodeContext(const std::any &context, HTTPRequest *req)
Get the node context.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
std::string GetHex() const
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
static bool rest_block_notxdetails(const std::any &context, HTTPRequest *req, const std::string &uri_part)
bool RPCIsInWarmup(std::string *outStatus)
static bool rest_getutxos(const std::any &context, HTTPRequest *req, const std::string &uri_part)
std::string ReadBody()
Read request body.
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
#define STR_INTERNAL_BUG(msg)
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
const std::vector< unsigned char > & GetEncodedFilter() const LIFETIMEBOUND
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
void InterruptREST()
Interrupt RPC REST subsystem.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
full block available in blk*.dat
Chars allowed in URIs (RFC 3986)
UniValue HandleRequest(const JSONRPCRequest &request) const
std::vector< CTxUndo > vtxundo
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
CCoinsView that brings transactions from a mempool into view.
static bool rest_deploymentinfo(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
static std::optional< transaction_identifier > FromHex(std::string_view hex)
static constexpr unsigned int MAX_REST_HEADERS_RESULTS
static bool rest_block(const std::any &context, HTTPRequest *req, const std::string &uri_part, std::optional< TxVerbosity > tx_verbosity, std::optional< std::pair< size_t, size_t >> block_part=std::nullopt)
This handler is used by multiple HTTP endpoints:
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
static constexpr TransactionSerParams TX_WITH_WITNESS
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
void StartREST(const std::any &context)
Start HTTP REST subsystem.