| 185 | } |
| 186 | |
| 187 | static bool rest_headers(const std::any& context, |
| 188 | HTTPRequest* req, |
| 189 | const std::string& strURIPart) |
| 190 | { |
| 191 | if (!CheckWarmup(req)) |
| 192 | return false; |
| 193 | std::string param; |
| 194 | const RetFormat rf = ParseDataFormat(param, strURIPart); |
| 195 | std::vector<std::string> path; |
| 196 | boost::split(path, param, boost::is_any_of("/")); |
| 197 | |
| 198 | if (path.size() != 2) |
| 199 | return RESTERR(req, HTTP_BAD_REQUEST, "No header count specified. Use /rest/headers/<count>/<hash>.<ext>."); |
| 200 | |
| 201 | const auto parsed_count{ToIntegral<size_t>(path[0])}; |
| 202 | if (!parsed_count.has_value() || *parsed_count < 1 || *parsed_count > MAX_REST_HEADERS_RESULTS) { |
| 203 | return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, path[0])); |
| 204 | } |
| 205 | |
| 206 | std::string hashStr = path[1]; |
| 207 | uint256 hash; |
| 208 | if (!ParseHashStr(hashStr, hash)) |
| 209 | return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); |
| 210 | |
| 211 | const CBlockIndex* tip = nullptr; |
| 212 | std::vector<const CBlockIndex*> headers; |
| 213 | headers.reserve(*parsed_count); |
| 214 | { |
| 215 | ChainstateManager* maybe_chainman = GetChainman(context, req); |
| 216 | if (!maybe_chainman) return false; |
| 217 | ChainstateManager& chainman = *maybe_chainman; |
| 218 | LOCK(cs_main); |
| 219 | CChain& active_chain = chainman.ActiveChain(); |
| 220 | tip = active_chain.Tip(); |
| 221 | const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(hash); |
| 222 | while (pindex != nullptr && active_chain.Contains(pindex)) { |
| 223 | headers.push_back(pindex); |
| 224 | if (headers.size() == *parsed_count) { |
| 225 | break; |
| 226 | } |
| 227 | pindex = active_chain.Next(pindex); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | switch (rf) { |
| 232 | case RetFormat::BINARY: { |
| 233 | CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); |
| 234 | for (const CBlockIndex *pindex : headers) { |
| 235 | LOCK(cs_main); |
| 236 | CBlockIndex tmpBlockIndexFull; |
| 237 | const CBlockIndex* pindexfull=pindex->untrim_to(&tmpBlockIndexFull); |
| 238 | ssHeader << pindexfull->GetBlockHeader(); |
| 239 | } |
| 240 | |
| 241 | std::string binaryHeader = ssHeader.str(); |
| 242 | req->WriteHeader("Content-Type", "application/octet-stream"); |
| 243 | req->WriteReply(HTTP_OK, binaryHeader); |
| 244 | return true; |
nothing calls this directly
no test coverage detected