View in context in the libbitcoin Slack #general mirror.
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)