Bitcoin full node and query server

Apr 19, 2024

View in context in the libbitcoin Slack #general mirror.

evoskuil02:13
code query::unspent_duplicates(const tx_link& link,
    const context& ctx) const noexcept
{
    if (!ctx.is_enabled(system::chain::flags::bip30_rule))
        return error::success;

    // Self is not a spender in this case.
    constexpr auto self = tx_link::terminal;
    const auto coinbases = to_strongs(get_tx_key(link));

    // self should be strong but was not found (fault).
    if (coinbases.empty())
        return error::integrity;

    // assuming it is strong only self was found (optimization).
    if (is_one(coinbases.size()))
        return error::success;

    // All that are found must be confirmed spent except self.
    size_t strong_unspent_coinbase_count{};
    for (const auto& coinbase: coinbases)
    {
        // All outputs must be spent or the coinbase is unspent.
        for (size_t out = zero; out < output_count(coinbase.tx); ++out)
        {
            if (!spent_prevout(table::spend::compose(coinbase.tx, out), self))
            {
                // Could stop at two but very rare so condition is more costly.
                ++strong_unspent_coinbase_count;
                continue;
            }
        }
    }

    switch (strong_unspent_coinbase_count)
    {
        // self should be unspent.
        case zero: return error::integrity;

        // only self is unspent.
        case one: return error::success;

        // at least one instance other than self is unspent.
        default: return error::unspent_coinbase_collision;
    }
}
(edited)