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");
384 const std::string& uri_part,
401 if (!maybe_chainman)
return false;
411 if (chainman.
m_blockman.IsBlockPruned(*pblockindex)) {
419 std::vector<std::byte> block_data{};
426 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
432 const std::string strHex{
HexStr(block_data) +
"\n"};
443 std::string strJSON = objBlock.
write() +
"\n";
444 req->
WriteHeader(
"Content-Type",
"application/json");
472 std::vector<std::string> uri_parts =
SplitString(param,
'/');
473 std::string raw_count;
474 std::string raw_blockhash;
475 if (uri_parts.size() == 3) {
477 raw_blockhash = uri_parts[2];
478 raw_count = uri_parts[1];
479 }
else if (uri_parts.size() == 2) {
481 raw_blockhash = uri_parts[1];
484 }
catch (
const std::runtime_error& e) {
488 return RESTERR(req,
HTTP_BAD_REQUEST,
"Invalid URI format. Expected /rest/blockfilterheaders/<filtertype>/<blockhash>.<ext>?count=<count>");
491 const auto parsed_count{ToIntegral<size_t>(raw_count)};
511 std::vector<const CBlockIndex*> headers;
512 headers.reserve(*parsed_count);
515 if (!maybe_chainman)
return false;
520 while (pindex !=
nullptr && active_chain.
Contains(pindex)) {
521 headers.push_back(pindex);
522 if (headers.size() == *parsed_count)
524 pindex = active_chain.
Next(pindex);
528 bool index_ready = index->BlockUntilSyncedToCurrentChain();
530 std::vector<uint256> filter_headers;
531 filter_headers.reserve(*parsed_count);
535 std::string errmsg =
"Filter not found.";
538 errmsg +=
" Block filters are still in the process of being indexed.";
540 errmsg +=
" This error is unexpected and indicates index corruption.";
545 filter_headers.push_back(filter_header);
551 for (
const uint256& header : filter_headers) {
555 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
561 for (
const uint256& header : filter_headers) {
565 std::string strHex =
HexStr(ssHeader) +
"\n";
572 for (
const uint256& header : filter_headers) {
576 std::string strJSON = jsonHeaders.
write() +
"\n";
577 req->
WriteHeader(
"Content-Type",
"application/json");
595 std::vector<std::string> uri_parts =
SplitString(param,
'/');
596 if (uri_parts.size() != 2) {
597 return RESTERR(req,
HTTP_BAD_REQUEST,
"Invalid URI format. Expected /rest/blockfilter/<filtertype>/<blockhash>");
616 bool block_was_connected;
619 if (!maybe_chainman)
return false;
629 bool index_ready = index->BlockUntilSyncedToCurrentChain();
633 std::string errmsg =
"Filter not found.";
635 if (!block_was_connected) {
636 errmsg +=
" Block was not connected to active chain.";
637 }
else if (!index_ready) {
638 errmsg +=
" Block filters are still in the process of being indexed.";
640 errmsg +=
" This error is unexpected and indicates index corruption.";
651 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
659 std::string strHex =
HexStr(ssResp) +
"\n";
667 std::string strJSON =
ret.write() +
"\n";
668 req->
WriteHeader(
"Content-Type",
"application/json");
694 std::string strJSON = chainInfoObject.
write() +
"\n";
695 req->
WriteHeader(
"Content-Type",
"application/json");
712 std::string hash_str;
721 if (!hash_str.empty()) {
728 if (!chainman)
return false;
736 req->
WriteHeader(
"Content-Type",
"application/json");
754 if (param !=
"contents" && param !=
"info") {
759 if (!mempool)
return false;
763 std::string str_json;
764 if (param ==
"contents") {
765 std::string raw_verbose;
768 }
catch (
const std::runtime_error& e) {
771 if (raw_verbose !=
"true" && raw_verbose !=
"false") {
772 return RESTERR(req,
HTTP_BAD_REQUEST,
"The \"verbose\" query parameter must be either \"true\" or \"false\".");
774 std::string raw_mempool_sequence;
776 raw_mempool_sequence = req->
GetQueryParameter(
"mempool_sequence").value_or(
"false");
777 }
catch (
const std::runtime_error& e) {
780 if (raw_mempool_sequence !=
"true" && raw_mempool_sequence !=
"false") {
781 return RESTERR(req,
HTTP_BAD_REQUEST,
"The \"mempool_sequence\" query parameter must be either \"true\" or \"false\".");
783 const bool verbose{raw_verbose ==
"true"};
784 const bool mempool_sequence{raw_mempool_sequence ==
"true"};
785 if (verbose && mempool_sequence) {
786 return RESTERR(req,
HTTP_BAD_REQUEST,
"Verbose results cannot contain mempool sequence values. (hint: set \"verbose=false\")");
793 req->
WriteHeader(
"Content-Type",
"application/json");
816 g_txindex->BlockUntilSyncedToCurrentChain();
820 if (!
node)
return false;
832 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
841 std::string strHex =
HexStr(ssTx) +
"\n";
850 std::string strJSON = objTx.
write() +
"\n";
851 req->
WriteHeader(
"Content-Type",
"application/json");
869 std::vector<std::string> uriParts;
870 if (param.length() > 1)
872 std::string strUriParams = param.substr(1);
877 std::string strRequestMutable = req->
ReadBody();
878 if (strRequestMutable.length() == 0 && uriParts.size() == 0)
881 bool fInputParsed =
false;
882 bool fCheckMemPool =
false;
883 std::vector<COutPoint> vOutPoints;
888 if (uriParts.size() > 0)
891 if (uriParts[0] ==
"checkmempool") fCheckMemPool =
true;
893 for (
size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
895 const auto txid_out{util::Split<std::string_view>(uriParts[i],
'-')};
896 if (txid_out.size() != 2) {
900 auto output{ToIntegral<uint32_t>(txid_out.at(1))};
902 if (!txid || !output) {
906 vOutPoints.emplace_back(*txid, *output);
909 if (vOutPoints.size() > 0)
918 std::vector<unsigned char> strRequestV =
ParseHex(strRequestMutable);
919 strRequestMutable.assign(strRequestV.begin(), strRequestV.end());
926 if (strRequestMutable.size() > 0)
932 oss << strRequestMutable;
933 oss >> fCheckMemPool;
936 }
catch (
const std::ios_base::failure&) {
958 std::vector<unsigned char> bitmap;
959 std::vector<CCoin> outs;
960 std::string bitmapStringRepresentation;
961 std::vector<bool> hits;
962 bitmap.resize((vOutPoints.size() + 7) / 8);
964 if (!maybe_chainman)
return false;
970 for (
const COutPoint& vOutPoint : vOutPoints) {
971 auto coin = !mempool || !mempool->isSpent(vOutPoint) ? view.GetCoin(vOutPoint) : std::nullopt;
972 hits.push_back(coin.has_value());
973 if (coin) outs.emplace_back(std::move(*coin));
981 if (!mempool)
return false;
986 process_utxos(viewMempool, mempool);
992 for (
size_t i = 0; i < hits.size(); ++i) {
993 const bool hit = hits[i];
994 bitmapStringRepresentation.append(hit ?
"1" :
"0");
995 bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);
1004 ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
1006 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
1013 ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
1014 std::string strHex =
HexStr(ssGetUTXOResponse) +
"\n";
1026 objGetUTXOResponse.
pushKV(
"chainHeight", active_height);
1027 objGetUTXOResponse.
pushKV(
"chaintipHash", active_hash.
GetHex());
1028 objGetUTXOResponse.
pushKV(
"bitmap", bitmapStringRepresentation);
1031 for (
const CCoin& coin : outs) {
1033 utxo.
pushKV(
"height", (int32_t)coin.nHeight);
1039 utxo.
pushKV(
"scriptPubKey", std::move(o));
1042 objGetUTXOResponse.
pushKV(
"utxos", std::move(utxos));
1045 std::string strJSON = objGetUTXOResponse.
write() +
"\n";
1046 req->
WriteHeader(
"Content-Type",
"application/json");
1057 const std::string& str_uri_part)
1060 std::string height_str;
1063 const auto blockheight{ToIntegral<int32_t>(height_str)};
1064 if (!blockheight || *blockheight < 0) {
1071 if (!maybe_chainman)
return false;
1075 if (*blockheight > active_chain.
Height()) {
1078 pblockindex = active_chain[*blockheight];
1084 req->
WriteHeader(
"Content-Type",
"application/octet-stream");
1094 req->
WriteHeader(
"Content-Type",
"application/json");
1106static const struct {
UniValue blockToJSON(BlockManager &blockman, const CBlock &block, const CBlockIndex &tip, const CBlockIndex &blockindex, TxVerbosity verbosity, const uint256 pow_limit)
Block description to JSON.
UniValue blockheaderToJSON(const CBlockIndex &tip, const CBlockIndex &blockindex, const uint256 pow_limit)
Block header to JSON.
bool BlockFilterTypeByName(std::string_view name, BlockFilterType &filter_type)
Find a filter type by its human-readable name.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
#define STR_INTERNAL_BUG(msg)
Complete block filter struct as defined in BIP 157.
const std::vector< unsigned char > & GetEncodedFilter() const LIFETIMEBOUND
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilter(const CBlockIndex *block_index, BlockFilter &filter_out) const
Get a single filter by block.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
The block chain is a tree shaped structure starting with the genesis block at the root,...
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
uint256 GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Undo information for a CBlock.
std::vector< CTxUndo > vtxundo
An in-memory indexed chain of blocks.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
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...
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Abstract view on the open txout dataset.
CCoinsView that brings transactions from a mempool into view.
An outpoint - a combination of a transaction hash and an index n into its vout.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
An output of a transaction.
Undo information for a CTransaction.
std::vector< Coin > vprevout
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
const Consensus::Params & GetConsensus() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
CTxOut out
unspent transaction output
Double ended buffer combining vector and stream-like interfaces.
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...
void WriteReply(int nStatus, std::string_view reply="")
Write HTTP reply.
void WriteHeader(const std::string &hdr, const std::string &value)
Write output header.
std::string ReadBody()
Read request body.
UniValue HandleRequest(const JSONRPCRequest &request) const
void push_back(UniValue val)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
void pushKV(std::string key, UniValue val)
std::string GetHex() const
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadBlockUndo(CBlockUndo &blockundo, const CBlockIndex &index) const
bool ReadRawBlock(std::vector< std::byte > &block, const FlatFilePos &pos) const
static std::optional< transaction_identifier > FromHex(std::string_view hex)
static std::optional< uint256 > FromHex(std::string_view str)
void TxToUniv(const CTransaction &tx, const uint256 &block_hash, UniValue &entry, bool include_hex=true, const CTxUndo *txundo=nullptr, TxVerbosity verbosity=TxVerbosity::SHOW_DETAILS, std::function< bool(const CTxOut &)> is_change_func={})
TxVerbosity
Verbose level for block's transaction.
@ SHOW_DETAILS_AND_PREVOUT
The same as previous option with information about prevouts if available.
@ SHOW_TXID
Only TXID for each block's transaction.
void ScriptToUniv(const CScript &script, UniValue &out, bool include_hex=true, bool include_address=false, const SigningProvider *provider=nullptr)
UniValue ValueFromAmount(const CAmount amount)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
Unregister handler for prefix.
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
Register handler for prefix.
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.
std::vector< std::string > SplitString(std::string_view str, char sep)
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr unsigned int MAX_REST_HEADERS_RESULTS
static bool rest_headers(const std::any &context, HTTPRequest *req, const std::string &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 bool rest_block_extended(const std::any &context, HTTPRequest *req, const std::string &uri_part)
static bool rest_blockhash_by_height(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
static bool rest_block_filter(const std::any &context, HTTPRequest *req, const std::string &uri_part)
static bool rest_block(const std::any &context, HTTPRequest *req, const std::string &uri_part, TxVerbosity tx_verbosity)
static bool rest_block_notxdetails(const std::any &context, HTTPRequest *req, const std::string &uri_part)
void StartREST(const std::any &context)
Start HTTP REST subsystem.
static bool rest_filter_header(const std::any &context, HTTPRequest *req, const std::string &uri_part)
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
static bool rest_getutxos(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)
static const struct @10 uri_prefixes[]
void StopREST()
Stop HTTP REST subsystem.
RPCHelpMan getdeploymentinfo()
RPCHelpMan getblockchaininfo()
void InterruptREST()
Interrupt RPC REST subsystem.
static bool rest_deploymentinfo(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
static bool RESTERR(HTTPRequest *req, enum HTTPStatusCode status, std::string message)
static bool rest_mempool(const std::any &context, HTTPRequest *req, const std::string &str_uri_part)
static const struct @9 rf_names[]
static bool CheckWarmup(HTTPRequest *req)
static ChainstateManager * GetChainman(const std::any &context, HTTPRequest *req)
Get the node context chainstatemanager.
static void BlockUndoToJSON(const CBlockUndo &block_undo, UniValue &result)
Serialize spent outputs as a list of per-transaction CTxOut lists using JSON format.
static bool rest_chaininfo(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)
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.
static CTxMemPool * GetMemPool(const std::any &context, HTTPRequest *req)
Get the node context mempool.
static const size_t MAX_GETUTXOS_OUTPOINTS
static std::string AvailableDataFormatsString()
static NodeContext * GetNodeContext(const std::any &context, HTTPRequest *req)
Get the node context.
UniValue MempoolInfoToJSON(const CTxMemPool &pool)
Mempool information to JSON.
UniValue MempoolToJSON(const CTxMemPool &pool, bool verbose, bool include_mempool_sequence)
Mempool to JSON.
HTTPStatusCode
HTTP status codes.
@ HTTP_SERVICE_UNAVAILABLE
@ HTTP_INTERNAL_SERVER_ERROR
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
bool RPCIsInWarmup(std::string *outStatus)
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
@ SAFE_CHARS_URI
Chars allowed in URIs (RFC 3986)
SERIALIZE_METHODS(CCoin, obj)
uint256 powLimit
Proof of work parameters.
NodeContext struct containing references to chain state and connection state.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.