Repository: bitcoin/bitcoin
File: src/rest.cpp (C++)

Code before:
    if (!parsed_count.has_value() || *parsed_count < 1 || *parsed_count > MAX_REST_HEADERS_RESULTS) {
        return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, raw_count));
    }

    auto block_hash{uint256::FromHex(raw_blockhash)};
    if (!block_hash) {
        return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + raw_blockhash);
    }

    BlockFilterType filtertype;
    if (!BlockFilterTypeByName(uri_parts[0], filtertype)) {
        return RESTERR(req, HTTP_BAD_REQUEST, "Unknown filtertype " + uri_parts[0]);
    }

    BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
    if (!index) {
        return RESTERR(req, HTTP_BAD_REQUEST, "Index is not enabled for filtertype " + uri_parts[0]);
    }

    std::vector<const CBlockIndex*> headers;
    headers.reserve(*parsed_count);
    {
        ChainstateManager* maybe_chainman = GetChainman(context, req);
        if (!maybe_chainman) return false;
        ChainstateManager& chainman = *maybe_chainman;
        LOCK(cs_main);
        CChain& active_chain = chainman.ActiveChain();
        const CBlockIndex* pindex{chainman.m_blockman.LookupBlockIndex(*block_hash)};
        while (pindex != nullptr && active_chain.Contains(pindex)) {
            headers.push_back(pindex);
            if (headers.size() == *parsed_count)
                break;
            pindex = active_chain.Next(pindex);
        }
    }

    bool index_ready = index->BlockUntilSyncedToCurrentChain();

    std::vector<uint256> filter_headers;
    filter_headers.reserve(*parsed_count);
    for (const CBlockIndex* pindex : headers) {
        uint256 filter_header;
        if (!index->LookupFilterHeader(pindex, filter_header)) {
            std::string errmsg = "Filter not found.";

            if (!index_ready) {
                errmsg += " Block filters are still in the process of being indexed.";
            } else {
                errmsg += " This error is unexpected and indicates index corruption.";
            }


Review comment (refactor):
The idiomatic way to use the `std::optional` is to guard in the if condition for its existence.
`.value()` only really makes sense over `*` when we need it to throw - which it can't if we're already guarding.
Also, the first condition has an if-exists-assign-else-return format, while the second checks for non-existence and assigns to external.
We could also just return from the `try` for the happy case, narrowing the scopes of the related variables.

And what is the expected behavior when `part_size_str` is `nullopt`, I don't think we should try to dereference it in case of an error.
We could likely simplify this by only assigning the pair optional when both are present and use `value_or("")` for simpler validation:
```suggestion
static bool rest_block_part(const std::any& context, HTTPRequest* req, const std::string& uri_part)
{
    try {
        std::optional<std::pair<size_t, size_t>> block_part{};
        if (const auto opt_offset{ToIntegral<size_t>(req->GetQueryParameter("offset").value_or(""))}) {
            if (const auto opt_size{ToIntegral<size_t>(req->GetQueryParameter("size").value_or(""))}) {
                block_part = {*opt_offset, *opt_size};
            } else {
                return RESTERR(req, HTTP_BAD_REQUEST, "Block part size missing or invalid");
            }
        } else {
            return RESTERR(req, HTTP_BAD_REQUEST, "Block part offset missing or invalid");
        }
        return rest_block(context, req, uri_part, /*tx_verbosity=*/std::nullopt, block_part);
    } catch (const std::runtime_error& e) {
        return RESTERR(req, HTTP_BAD_REQUEST, e.what());
    }
}
```

Code after:
        } else {
            return RESTERR(req, HTTP_BAD_REQUEST, "Block part offset missing or invalid");
        }
    } catch (const std::runtime_error& e) {
        return RESTERR(req, HTTP_BAD_REQUEST, e.what());
    }
}

static bool rest_filter_header(const std::any& context, HTTPRequest* req, const std::string& uri_part)
{
    if (!CheckWarmup(req)) return false;

    std::string param;
    const RESTResponseFormat rf = ParseDataFormat(param, uri_part);

    std::vector<std::string> uri_parts = SplitString(param, '/');
    std::string raw_count;
    std::string raw_blockhash;
    if (uri_parts.size() == 3) {
        // deprecated path: /rest/blockfilterheaders/<filtertype>/<count>/<blockhash>
        raw_blockhash = uri_parts[2];
        raw_count = uri_parts[1];
    } else if (uri_parts.size() == 2) {
        // new path with query parameter: /rest/blockfilterheaders/<filtertype>/<blockhash>?count=<count>
        raw_blockhash = uri_parts[1];
        try {
            raw_count = req->GetQueryParameter("count").value_or("5");
        } catch (const std::runtime_error& e) {
            return RESTERR(req, HTTP_BAD_REQUEST, e.what());
        }
    } else {
        return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/blockfilterheaders/<filtertype>/<blockhash>.<ext>?count=<count>");
    }

    const auto parsed_count{ToIntegral<size_t>(raw_count)};
    if (!parsed_count.has_value() || *parsed_count < 1 || *parsed_count > MAX_REST_HEADERS_RESULTS) {
        return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Header count is invalid or out of acceptable range (1-%u): %s", MAX_REST_HEADERS_RESULTS, raw_count));
    }

    auto block_hash{uint256::FromHex(raw_blockhash)};
    if (!block_hash) {
        return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + raw_blockhash);
    }

    BlockFilterType filtertype;
    if (!BlockFilterTypeByName(uri_parts[0], filtertype)) {
        return RESTERR(req, HTTP_BAD_REQUEST, "Unknown filtertype " + uri_parts[0]);
    }

    BlockFilterIndex* index = GetBlockFilterIndex(filtertype);
    if (!index) {