Repository: bitcoin/bitcoin
File: src/test/fuzz/mini_miner.cpp (C++)

Code before:
            COutPoint coin{tx->GetHash(), n};
            if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
        }
    }
    const CFeeRate target_feerate{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};

    node::BlockAssembler::Options miner_options;
    miner_options.blockMinFeeRate = target_feerate;
    miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
    miner_options.test_block_validity = false;

    node::BlockAssembler miner{g_setup->m_node.chainman->ActiveChainstate(), &pool, miner_options};
    node::MiniMiner mini_miner{pool, outpoints};
    assert(mini_miner.IsReadyToCalculate());

    CScript spk_placeholder = CScript() << OP_0;
    // Use BlockAssembler as oracle. BlockAssembler and MiniMiner should select the same
    // transactions, stopping once packages do not meet target_feerate.
    const auto blocktemplate{miner.CreateNewBlock(spk_placeholder)};
    mini_miner.BuildMockTemplate(target_feerate);
    assert(!mini_miner.IsReadyToCalculate());
    auto mock_template_txids = mini_miner.GetMockTemplateTxids();
    // MiniMiner doesn't add a coinbase tx.
    assert(mock_template_txids.count(blocktemplate->block.vtx[0]->GetHash()) == 0);
    mock_template_txids.emplace(blocktemplate->block.vtx[0]->GetHash());
    assert(mock_template_txids.size() <= blocktemplate->block.vtx.size());
    assert(mock_template_txids.size() >= blocktemplate->block.vtx.size());
    assert(mock_template_txids.size() == blocktemplate->block.vtx.size());
    for (const auto& tx : blocktemplate->block.vtx) {
        assert(mock_template_txids.count(tx->GetHash()));
    }
}
} // namespace


Review comment (suggestion):
In 'fuzz: mini_miner_selection fixups':

The comment in L189 threw me off. I assume that it’s meant to indicate that we are able to add the coinbase transaction to `mock_template_txids` because MiniMiner did not add it, but I first understood it to indicate that we should not be able to add a coinbase transaction to `mock_template_txids` and therefore the assert was inverse to my expectation.

Also, TIL that the return values of `emplace(…)` differ between `set` and `vector`.

Code after:
            COutPoint coin{tx->GetHash(), n};
            if (!pool.GetConflictTx(coin)) outpoints.push_back(coin);
        }
    }
    const CFeeRate target_feerate{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};

    node::BlockAssembler::Options miner_options;
    miner_options.blockMinFeeRate = target_feerate;
    miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
    miner_options.test_block_validity = false;

    node::BlockAssembler miner{g_setup->m_node.chainman->ActiveChainstate(), &pool, miner_options};
    node::MiniMiner mini_miner{pool, outpoints};
    assert(mini_miner.IsReadyToCalculate());

    CScript spk_placeholder = CScript() << OP_0;
    // Use BlockAssembler as oracle. BlockAssembler and MiniMiner should select the same
    // transactions, stopping once packages do not meet target_feerate.
    const auto blocktemplate{miner.CreateNewBlock(spk_placeholder)};
    mini_miner.BuildMockTemplate(target_feerate);
    assert(!mini_miner.IsReadyToCalculate());
    auto mock_template_txids = mini_miner.GetMockTemplateTxids();
    // MiniMiner doesn't add a coinbase tx.
    assert(mock_template_txids.count(blocktemplate->block.vtx[0]->GetHash()) == 0);
    auto [iter, new_entry] = mock_template_txids.emplace(blocktemplate->block.vtx[0]->GetHash());
    assert(new_entry);

    assert(mock_template_txids.size() == blocktemplate->block.vtx.size());
    for (const auto& tx : blocktemplate->block.vtx) {
        assert(mock_template_txids.count(tx->GetHash()));
    }
}
} // namespace