Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501}502}504static bool rest_block_extended(const std::any& context, HTTPRequest* req, const std::string& uri_part)505{506return rest_block(context, req, uri_part, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);507}509static bool rest_block_notxdetails(const std::any& context, HTTPRequest* req, const std::string& uri_part)510{511return rest_block(context, req, uri_part, TxVerbosity::SHOW_TXID);512}514static bool rest_block_part(const std::any& context, HTTPRequest* req, const std::string& uri_part)515{516try {517if (const auto opt_offset{ToIntegral<size_t>(req->GetQueryParameter("offset").value_or(""))}) {518if (const auto opt_size{ToIntegral<size_t>(req->GetQueryParameter("size").value_or(""))}) {519return rest_block(context, req, uri_part,520/*tx_verbosity=*/std::nullopt,521/*block_part=*/{{*opt_offset, *opt_size}});522} else {523return RESTERR(req, HTTP_BAD_REQUEST, "Block part size missing or invalid");524}525} else {526return RESTERR(req, HTTP_BAD_REQUEST, "Block part offset missing or invalid");527}528} catch (const std::runtime_error& e) {529return RESTERR(req, HTTP_BAD_REQUEST, e.what());530}531}533static bool rest_filter_header(const std::any& context, HTTPRequest* req, const std::string& uri_part)534{535if (!CheckWarmup(req)) return false;537std::string param;538const RESTResponseFormat rf = ParseDataFormat(param, uri_part);540std::vector<std::string> uri_parts = SplitString(param, '/');541std::string raw_count;542std::string raw_blockhash;543if (uri_parts.size() == 3) {544// deprecated path: /rest/blockfilterheaders/<filtertype>/<count>/<blockhash>545raw_blockhash = uri_parts[2];546raw_count = uri_parts[1];547} else if (uri_parts.size() == 2) {548// new path with query parameter: /rest/blockfilterheaders/<filtertype>/<blockhash>?count=<count>549raw_blockhash = uri_parts[1];550try {551raw_count = req->GetQueryParameter("count").value_or("5");552} catch (const std::runtime_error& e) {553return RESTERR(req, HTTP_BAD_REQUEST, e.what());554}555} else {556return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/blockfilterheaders/<filtertype>/<blockhash>.<ext>?count=<count>");557}559const auto parsed_count{ToIntegral<size_t>(raw_count)};560if (!parsed_count.has_value() || *parsed_count < 1 || *parsed_count > MAX_REST_HEADERS_RESULTS) {561return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, raw_count));562}564auto block_hash{uint256::FromHex(raw_blockhash)};565if (!block_hash) {566return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + raw_blockhash);567}569BlockFilterType filtertype;570if (!BlockFilterTypeByName(uri_parts[0], filtertype)) {571return RESTERR(req, HTTP_BAD_REQUEST, "Unknown filtertype " + uri_parts[0]);572}574BlockFilterIndex* index = GetBlockFilterIndex(filtertype);575if (!index) {576return RESTERR(req, HTTP_BAD_REQUEST, "Index is not enabled for filtertype " + uri_parts[0]);577}579std::vector<const CBlockIndex*> headers;580headers.reserve(*parsed_count);581{582ChainstateManager* maybe_chainman = GetChainman(context, req);583if (!maybe_chainman) return false;584ChainstateManager& chainman = *maybe_chainman;585LOCK(cs_main);586CChain& active_chain = chainman.ActiveChain();587const CBlockIndex* pindex{chainman.m_blockman.LookupBlockIndex(*block_hash)};588while (pindex != nullptr && active_chain.Contains(*pindex)) {589headers.push_back(pindex);590if (headers.size() == *parsed_count)591break;592pindex = active_chain.Next(*pindex);593}594}596bool index_ready = index->BlockUntilSyncedToCurrentChain();598std::vector<uint256> filter_headers;599filter_headers.reserve(*parsed_count);600for (const CBlockIndex* pindex : headers) {601uint256 filter_header;602if (!index->LookupFilterHeader(pindex, filter_header)) {603std::string errmsg = "Filter not found.";605if (!index_ready) {606errmsg += " Block filters are still in the process of being indexed.";607} else {608errmsg += " This error is unexpected and indicates index corruption.";609}611return RESTERR(req, HTTP_NOT_FOUND, errmsg);612}613filter_headers.push_back(filter_header);614}616switch (rf) {617case RESTResponseFormat::BINARY: {618DataStream ssHeader{};619for (const uint256& header : filter_headers) {620ssHeader << header;621}623// Do not cache because chain extensions and reorgs can affect the response.624req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);625req->WriteHeader("Content-Type", "application/octet-stream");626req->WriteReply(HTTP_OK, ssHeader);627return true;628}629case RESTResponseFormat::HEX: {630DataStream ssHeader{};631for (const uint256& header : filter_headers) {632ssHeader << header;633}635std::string strHex = HexStr(ssHeader) + "\n";636req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);637req->WriteHeader("Content-Type", "text/plain");638req->WriteReply(HTTP_OK, strHex);639return true;640}641case RESTResponseFormat::JSON: {642UniValue jsonHeaders(UniValue::VARR);643for (const uint256& header : filter_headers) {644jsonHeaders.push_back(header.GetHex());645}647std::string strJSON = jsonHeaders.write() + "\n";648req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);649req->WriteHeader("Content-Type", "application/json");650req->WriteReply(HTTP_OK, strJSON);651return true;652}653default: {654return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");655}656}657}659static bool rest_block_filter(const std::any& context, HTTPRequest* req, const std::string& uri_part)660{661if (!CheckWarmup(req)) return false;663std::string param;664const RESTResponseFormat rf = ParseDataFormat(param, uri_part);666// request is sent over URI scheme /rest/blockfilter/filtertype/blockhash667std::vector<std::string> uri_parts = SplitString(param, '/');668if (uri_parts.size() != 2) {669return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/blockfilter/<filtertype>/<blockhash>");670}672auto block_hash{uint256::FromHex(uri_parts[1])};673if (!block_hash) {674return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + uri_parts[1]);675}677BlockFilterType filtertype;678if (!BlockFilterTypeByName(uri_parts[0], filtertype)) {679return RESTERR(req, HTTP_BAD_REQUEST, "Unknown filtertype " + uri_parts[0]);680}682BlockFilterIndex* index = GetBlockFilterIndex(filtertype);683if (!index) {684return RESTERR(req, HTTP_BAD_REQUEST, "Index is not enabled for filtertype " + uri_parts[0]);685}687const CBlockIndex* block_index;688bool block_was_connected;689{690ChainstateManager* maybe_chainman = GetChainman(context, req);691if (!maybe_chainman) return false;692ChainstateManager& chainman = *maybe_chainman;693LOCK(cs_main);694block_index = chainman.m_blockman.LookupBlockIndex(*block_hash);695if (!block_index) {696return RESTERR(req, HTTP_NOT_FOUND, uri_parts[1] + " not found");697}698block_was_connected = block_index->IsValid(BLOCK_VALID_SCRIPTS);699}701bool index_ready = index->BlockUntilSyncedToCurrentChain();703BlockFilter filter;704if (!index->LookupFilter(block_index, filter)) {705std::string errmsg = "Filter not found.";707if (!block_was_connected) {708errmsg += " Block was not connected to active chain.";709} else if (!index_ready) {710errmsg += " Block filters are still in the process of being indexed.";711} else {712errmsg += " This error is unexpected and indicates index corruption.";713}715return RESTERR(req, HTTP_NOT_FOUND, errmsg);716}718switch (rf) {719case RESTResponseFormat::BINARY: {720DataStream ssResp{};721ssResp << filter;723req->WriteHeader("Cache-Control", REST_CACHE_IMMUTABLE);724req->WriteHeader("Content-Type", "application/octet-stream");725req->WriteReply(HTTP_OK, ssResp);726return true;727}728case RESTResponseFormat::HEX: {729DataStream ssResp{};730ssResp << filter;732std::string strHex = HexStr(ssResp) + "\n";733req->WriteHeader("Cache-Control", REST_CACHE_IMMUTABLE);734req->WriteHeader("Content-Type", "text/plain");735req->WriteReply(HTTP_OK, strHex);736return true;737}738case RESTResponseFormat::JSON: {739UniValue ret(UniValue::VOBJ);740ret.pushKV("filter", HexStr(filter.GetEncodedFilter()));741std::string strJSON = ret.write() + "\n";742req->WriteHeader("Cache-Control", REST_CACHE_IMMUTABLE);743req->WriteHeader("Content-Type", "application/json");744req->WriteReply(HTTP_OK, strJSON);745return true;746}747default: {748return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");749}750}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.