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.
1001[[fallthrough]];1002}1004case RESTResponseFormat::BINARY: {1005try {1006//deserialize only if user sent a request1007if (strRequestMutable.size() > 0)1008{1009if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA1010return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and raw post data is not allowed");1012DataStream oss{};1013oss << strRequestMutable;1014oss >> fCheckMemPool;1015oss >> vOutPoints;1016}1017} catch (const std::ios_base::failure&) {1018// abort in case of unreadable binary data1019return RESTERR(req, HTTP_BAD_REQUEST, "Parse error");1020}1021break;1022}1024case RESTResponseFormat::JSON: {1025if (!fInputParsed)1026return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request");1027break;1028}1029default: {1030return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");1031}1032}1034// limit max outpoints1035if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS)1036return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size()));1038// check spentness and form a bitmap (as well as a JSON capable human-readable string representation)1039std::vector<unsigned char> bitmap;1040std::vector<CCoin> outs;1041std::string bitmapStringRepresentation;1042std::vector<bool> hits;1043bitmap.resize(CeilDiv(vOutPoints.size(), 8u));1044ChainstateManager* maybe_chainman = GetChainman(context, req);1045if (!maybe_chainman) return false;1046ChainstateManager& chainman = *maybe_chainman;1047decltype(chainman.ActiveHeight()) active_height;1048uint256 active_hash;1049{1050auto process_utxos = [&vOutPoints, &outs, &hits, &active_height, &active_hash, &chainman](const CCoinsView& view, const CTxMemPool* mempool) EXCLUSIVE_LOCKS_REQUIRED(chainman.GetMutex()) {1051for (const COutPoint& vOutPoint : vOutPoints) {1052auto coin = !mempool || !mempool->isSpent(vOutPoint) ? view.GetCoin(vOutPoint) : std::nullopt;1053hits.push_back(coin.has_value());1054if (coin) outs.emplace_back(std::move(*coin));1055}1056active_height = chainman.ActiveHeight();1057active_hash = chainman.ActiveTip()->GetBlockHash();1058};1060if (fCheckMemPool) {1061const CTxMemPool* mempool = GetMemPool(context, req);1062if (!mempool) return false;1063// use db+mempool as cache backend in case user likes to query mempool1064LOCK2(cs_main, mempool->cs);1065CCoinsViewCache& viewChain = chainman.ActiveChainstate().CoinsTip();1066CCoinsViewMemPool viewMempool(&viewChain, *mempool);1067process_utxos(viewMempool, mempool);1068} else {1069LOCK(cs_main);1070process_utxos(chainman.ActiveChainstate().CoinsTip(), nullptr);1071}1073for (size_t i = 0; i < hits.size(); ++i) {1074const bool hit = hits[i];1075bitmapStringRepresentation.append(hit ? "1" : "0"); // form a binary string representation (human-readable for json output)1076bitmap[i / 8] |= ((uint8_t)hit) << (i % 8);1077}1078}1080switch (rf) {1081case RESTResponseFormat::BINARY: {1082// serialize data1083// use exact same output as mentioned in Bip641084DataStream ssGetUTXOResponse{};1085ssGetUTXOResponse << active_height << active_hash << bitmap << outs;1087req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1088req->WriteHeader("Content-Type", "application/octet-stream");1089req->WriteReply(HTTP_OK, ssGetUTXOResponse);1090return true;1091}1093case RESTResponseFormat::HEX: {1094DataStream ssGetUTXOResponse{};1095ssGetUTXOResponse << active_height << active_hash << bitmap << outs;1096std::string strHex = HexStr(ssGetUTXOResponse) + "\n";1098req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1099req->WriteHeader("Content-Type", "text/plain");1100req->WriteReply(HTTP_OK, strHex);1101return true;1102}1104case RESTResponseFormat::JSON: {1105UniValue objGetUTXOResponse(UniValue::VOBJ);1107// pack in some essentials1108// use more or less the same output as mentioned in Bip641109objGetUTXOResponse.pushKV("chainHeight", active_height);1110objGetUTXOResponse.pushKV("chaintipHash", active_hash.GetHex());1111objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);1113UniValue utxos(UniValue::VARR);1114for (const CCoin& coin : outs) {1115UniValue utxo(UniValue::VOBJ);1116utxo.pushKV("height", coin.nHeight);1117utxo.pushKV("value", ValueFromAmount(coin.out.nValue));1119// include the script in a json output1120UniValue o(UniValue::VOBJ);1121ScriptToUniv(coin.out.scriptPubKey, /*out=*/o, /*include_hex=*/true, /*include_address=*/true);1122utxo.pushKV("scriptPubKey", std::move(o));1123utxos.push_back(std::move(utxo));1124}1125objGetUTXOResponse.pushKV("utxos", std::move(utxos));1127// return json string1128std::string strJSON = objGetUTXOResponse.write() + "\n";1129req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1130req->WriteHeader("Content-Type", "application/json");1131req->WriteReply(HTTP_OK, strJSON);1132return true;1133}1134default: {1135return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");1136}1137}1138}1140static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req,1141const std::string& str_uri_part)1142{1143if (!CheckWarmup(req)) return false;1144std::string height_str;1145const RESTResponseFormat rf = ParseDataFormat(height_str, str_uri_part);1147const auto blockheight{ToIntegral<int32_t>(height_str)};1148if (!blockheight || *blockheight < 0) {1149return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str, SAFE_CHARS_URI));1150}1152CBlockIndex* pblockindex = nullptr;1153{1154ChainstateManager* maybe_chainman = GetChainman(context, req);1155if (!maybe_chainman) return false;1156ChainstateManager& chainman = *maybe_chainman;1157LOCK(cs_main);1158const CChain& active_chain = chainman.ActiveChain();1159if (*blockheight > active_chain.Height()) {1160return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range");1161}1162pblockindex = active_chain[*blockheight];1163}1164switch (rf) {1165case RESTResponseFormat::BINARY: {1166DataStream ss_blockhash{};1167ss_blockhash << pblockindex->GetBlockHash();1168// Do not cache because reorgs can change the response.1169req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1170req->WriteHeader("Content-Type", "application/octet-stream");1171req->WriteReply(HTTP_OK, ss_blockhash);1172return true;1173}1174case RESTResponseFormat::HEX: {1175req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1176req->WriteHeader("Content-Type", "text/plain");1177req->WriteReply(HTTP_OK, pblockindex->GetBlockHash().GetHex() + "\n");1178return true;1179}1180case RESTResponseFormat::JSON: {1181req->WriteHeader("Cache-Control", REST_CACHE_NO_STORE);1182req->WriteHeader("Content-Type", "application/json");1183UniValue resp = UniValue(UniValue::VOBJ);1184resp.pushKV("blockhash", pblockindex->GetBlockHash().GetHex());1185req->WriteReply(HTTP_OK, resp.write() + "\n");1186return true;1187}1188default: {1189return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")");1190}1191}1192}1194static const struct {1195const char* prefix;1196bool (*handler)(const std::any& context, HTTPRequest* req, const std::string& strReq);1197} uri_prefixes[] = {1198{"/rest/tx/", rest_tx},1199{"/rest/block/notxdetails/", rest_block_notxdetails},1200{"/rest/block/", rest_block_extended},1201{"/rest/blockpart/", rest_block_part},1202{"/rest/blockfilter/", rest_block_filter},1203{"/rest/blockfilterheaders/", rest_filter_header},1204{"/rest/chaininfo", rest_chaininfo},1205{"/rest/mempool/", rest_mempool},1206{"/rest/headers/", rest_headers},1207{"/rest/getutxos", rest_getutxos},1208{"/rest/deploymentinfo/", rest_deploymentinfo},1209{"/rest/deploymentinfo", rest_deploymentinfo},1210{"/rest/blockhashbyheight/", rest_blockhash_by_height},1211{"/rest/spenttxouts/", rest_spent_txouts},1212};1214void StartREST(const std::any& context)1215{1216for (const auto& up : uri_prefixes) {1217auto handler = [context, up](HTTPRequest* req, const std::string& prefix) { return up.handler(context, req, prefix); };1218RegisterHTTPHandler(up.prefix, false, handler);1219}1220}1222void InterruptREST()1223{1224}1226void StopREST()1227{1228for (const auto& up : uri_prefixes) {1229UnregisterHTTPHandler(up.prefix, false);1230}1231}
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.