coins: filter coinbase txid from parallel input fetching

A non-segwit invalid block could spend its own coinbase output. In that case we would want to skip fetching the coinbase prevout since it would already be in the CoinsViewOverlay's cache and would cause block validation to revert to synchronous fetching.

Co-authored-by: Pieter Wuille <pieter@wuille.net>
This commit is contained in:
Andrew Toth
2026-07-15 13:23:51 -04:00
parent 70d9ec7f3d
commit 330022993f

View File

@@ -372,12 +372,13 @@ CCoinsViewCache::ResetGuard CoinsViewOverlay::StartFetching(const CBlock& block
Assert(m_inputs.empty());
Assert(m_input_head.load(std::memory_order_relaxed) == 0);
Assert(m_input_tail == 0);
if (const auto workers_count{m_thread_pool->WorkersCount()}; workers_count > 0) {
if (const auto workers_count{m_thread_pool->WorkersCount()}; workers_count > 0 && block.vtx.size() > 1) {
// Loop through the block inputs and set their prevouts in the queue.
// Filter inputs that spend outputs created earlier in the same block. These outputs will be created
// directly in the cache from the tx that creates them, so they will not be requested from a base view.
std::unordered_set<Txid, SaltedTxidHasher> earlier_txids;
earlier_txids.reserve(block.vtx.size());
earlier_txids.emplace(block.vtx[0]->GetHash());
for (const auto& tx : block.vtx | std::views::drop(1)) {
for (const auto& input : tx->vin) {
if (!earlier_txids.contains(input.prevout.hash)) m_inputs.emplace_back(input.prevout);