| 881 | } |
| 882 | |
| 883 | static bool rest_blockhash_by_height(const std::any& context, HTTPRequest* req, |
| 884 | const std::string& str_uri_part) |
| 885 | { |
| 886 | if (!CheckWarmup(req)) return false; |
| 887 | std::string height_str; |
| 888 | const RetFormat rf = ParseDataFormat(height_str, str_uri_part); |
| 889 | |
| 890 | int32_t blockheight = -1; // Initialization done only to prevent valgrind false positive, see https://github.com/bitcoin/bitcoin/pull/18785 |
| 891 | if (!ParseInt32(height_str, &blockheight) || blockheight < 0) { |
| 892 | return RESTERR(req, HTTP_BAD_REQUEST, "Invalid height: " + SanitizeString(height_str)); |
| 893 | } |
| 894 | |
| 895 | CBlockIndex* pblockindex = nullptr; |
| 896 | { |
| 897 | ChainstateManager* maybe_chainman = GetChainman(context, req); |
| 898 | if (!maybe_chainman) return false; |
| 899 | ChainstateManager& chainman = *maybe_chainman; |
| 900 | LOCK(cs_main); |
| 901 | const CChain& active_chain = chainman.ActiveChain(); |
| 902 | if (blockheight > active_chain.Height()) { |
| 903 | return RESTERR(req, HTTP_NOT_FOUND, "Block height out of range"); |
| 904 | } |
| 905 | pblockindex = active_chain[blockheight]; |
| 906 | } |
| 907 | switch (rf) { |
| 908 | case RetFormat::BINARY: { |
| 909 | CDataStream ss_blockhash(SER_NETWORK, PROTOCOL_VERSION); |
| 910 | ss_blockhash << pblockindex->GetBlockHash(); |
| 911 | req->WriteHeader("Content-Type", "application/octet-stream"); |
| 912 | req->WriteReply(HTTP_OK, ss_blockhash.str()); |
| 913 | return true; |
| 914 | } |
| 915 | case RetFormat::HEX: { |
| 916 | req->WriteHeader("Content-Type", "text/plain"); |
| 917 | req->WriteReply(HTTP_OK, pblockindex->GetBlockHash().GetHex() + "\n"); |
| 918 | return true; |
| 919 | } |
| 920 | case RetFormat::JSON: { |
| 921 | req->WriteHeader("Content-Type", "application/json"); |
| 922 | UniValue resp = UniValue(UniValue::VOBJ); |
| 923 | resp.pushKV("blockhash", pblockindex->GetBlockHash().GetHex()); |
| 924 | req->WriteReply(HTTP_OK, resp.write() + "\n"); |
| 925 | return true; |
| 926 | } |
| 927 | default: { |
| 928 | return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: " + AvailableDataFormatsString() + ")"); |
| 929 | } |
| 930 | } |
| 931 | } |
| 932 | |
| 933 | static const struct { |
| 934 | const char* prefix; |
nothing calls this directly
no test coverage detected