Merge bitcoin/bitcoin#31581: test: have miner_tests use Mining interface

04249682e3 test: use Mining interface in miner_tests (Sjors Provoost)

Pull request description:

  Needed for both #31283 and #31564.

  By using the Mining interface in `miner_tests.cpp` we increase its coverage in unit tests.

ACKs for top commit:
  achow101:
    ACK 04249682e3
  ryanofsky:
    Code review ACK 04249682e3, just minor suggested changes (renames, comments, BOOST_REQUIREs) since last review and some more extra clarifications and checks added to the CreateNewBlock_validity test. The CreateNewBlock_validity changes seem clear and easy to understand now.
  vasild:
    ACK 04249682e3
  tdb3:
    ACK 04249682e3

Tree-SHA512: 2761cb7555d759670e40d8f37b96a079f8e12a588ac43313b9e63c69afd478321515873a8896ea56784f0100dac4476b0c0e0ef8b5418f8aea24d9965cace4d4
This commit is contained in:
Ava Chow 2025-01-06 18:28:33 -05:00
commit c506f2cee7
No known key found for this signature in database
GPG key ID: 17565732E08E5E41

View file

@ -8,6 +8,7 @@
#include <consensus/consensus.h>
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <interfaces/mining.h>
#include <node/miner.h>
#include <policy/policy.h>
#include <test/util/random.h>
@ -28,8 +29,9 @@
#include <boost/test/unit_test.hpp>
using namespace util::hex_literals;
using interfaces::BlockTemplate;
using interfaces::Mining;
using node::BlockAssembler;
using node::CBlockTemplate;
namespace miner_tests {
struct MinerTestingSetup : public TestingSetup {
@ -54,7 +56,10 @@ struct MinerTestingSetup : public TestingSetup {
Assert(error.empty());
return *m_node.mempool;
}
BlockAssembler AssemblerForTest(CTxMemPool& tx_mempool, BlockAssembler::Options options);
std::unique_ptr<Mining> MakeMining()
{
return interfaces::MakeMining(m_node);
}
};
} // namespace miner_tests
@ -62,13 +67,6 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup)
static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
BlockAssembler MinerTestingSetup::AssemblerForTest(CTxMemPool& tx_mempool, BlockAssembler::Options options)
{
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
options.blockMinFeeRate = blockMinFeeRate;
return BlockAssembler{m_node.chainman->ActiveChainstate(), &tx_mempool, options};
}
constexpr static struct {
unsigned char extranonce;
unsigned int nonce;
@ -106,6 +104,10 @@ static std::unique_ptr<CBlockIndex> CreateBlockIndex(int nHeight, CBlockIndex* a
void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
{
CTxMemPool& tx_mempool{MakeMempool()};
auto mining{MakeMining()};
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
LOCK(tx_mempool.cs);
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry;
@ -135,13 +137,13 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
Txid hashHighFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
BOOST_REQUIRE_EQUAL(block.vtx.size(), 4U);
BOOST_CHECK(block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(block.vtx[2]->GetHash() == hashHighFeeTx);
BOOST_CHECK(block.vtx[3]->GetHash() == hashMediumFeeTx);
// Test that a package below the block min tx fee doesn't get included
tx.vin[0].prevout.hash = hashHighFeeTx;
@ -158,11 +160,13 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
Txid hashLowFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
block = block_template->getBlock();
// Verify that the free tx and the low fee tx didn't get selected
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
for (size_t i=0; i<block.vtx.size(); ++i) {
BOOST_CHECK(block.vtx[i]->GetHash() != hashFreeTx);
BOOST_CHECK(block.vtx[i]->GetHash() != hashLowFeeTx);
}
// Test that packages above the min relay fee do get included, even if one
@ -172,10 +176,12 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
hashLowFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse + 2).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
block = block_template->getBlock();
BOOST_REQUIRE_EQUAL(block.vtx.size(), 6U);
BOOST_CHECK(block.vtx[4]->GetHash() == hashFreeTx);
BOOST_CHECK(block.vtx[5]->GetHash() == hashLowFeeTx);
// Test that transaction selection properly updates ancestor fee
// calculations as ancestor transactions get included in a block.
@ -194,12 +200,14 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
Txid hashLowFeeTx2 = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
block = block_template->getBlock();
// Verify that this tx isn't selected.
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
for (size_t i=0; i<block.vtx.size(); ++i) {
BOOST_CHECK(block.vtx[i]->GetHash() != hashFreeTx2);
BOOST_CHECK(block.vtx[i]->GetHash() != hashLowFeeTx2);
}
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected
@ -207,9 +215,11 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vin[0].prevout.n = 1;
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
AddToMempool(tx_mempool, entry.Fee(10000).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U);
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
block = block_template->getBlock();
BOOST_REQUIRE_EQUAL(block.vtx.size(), 9U);
BOOST_CHECK(block.vtx[8]->GetHash() == hashLowFeeTx2);
}
void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight)
@ -225,6 +235,9 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
const CAmount HIGHFEE = COIN;
const CAmount HIGHERFEE = 4 * COIN;
auto mining{MakeMining()};
BOOST_REQUIRE(mining);
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
@ -233,8 +246,9 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
LOCK(tx_mempool.cs);
// Just to make sure we can still make simple blocks
auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_CHECK(pblocktemplate);
auto block_template{mining->createNewBlock(options)};
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
// block sigops > limit: 1000 CHECKMULTISIG + 1
tx.vin.resize(1);
@ -253,7 +267,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-blk-sigops"));
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-blk-sigops"));
}
{
@ -270,7 +284,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_REQUIRE(mining->createNewBlock(options));
}
{
@ -294,7 +308,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_REQUIRE(mining->createNewBlock(options));
}
{
@ -304,7 +318,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
// orphan in tx_mempool, template creation fails
hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
}
{
@ -325,7 +339,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].nValue = tx.vout[0].nValue + BLOCKSUBSIDY - HIGHERFEE; // First txn output + fresh coinbase - new txn fee
hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_REQUIRE(mining->createNewBlock(options));
}
{
@ -341,7 +355,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
// give it a fee so it'll get mined
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
// Should throw bad-cb-multiple
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-cb-multiple"));
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-cb-multiple"));
}
{
@ -358,7 +372,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
}
{
@ -378,7 +392,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
next->BuildSkip();
m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_REQUIRE(mining->createNewBlock(options));
// Extend to a 210000-long block chain.
while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) {
CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
@ -390,7 +404,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
next->BuildSkip();
m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_REQUIRE(mining->createNewBlock(options));
// invalid p2sh txn in tx_mempool, template creation fails
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
@ -406,7 +420,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("mandatory-script-verify-flag-failed"));
BOOST_CHECK_EXCEPTION(mining->createNewBlock(options), std::runtime_error, HasReason("mandatory-script-verify-flag-failed"));
// Delete the dummy blocks again.
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
@ -508,14 +522,15 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail
auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_CHECK(pblocktemplate);
auto block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
// None of the of the absolute height/time locked tx should have made
// it into the template because we still check IsFinalTx in CreateNewBlock,
// but relative locked txs will if inconsistently added to mempool.
// For now these will still generate a valid template until BIP68 soft fork
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
CBlock block{block_template->getBlock()};
BOOST_CHECK_EQUAL(block.vtx.size(), 3U);
// However if we advance height by 1 and time by SEQUENCE_LOCK_TIME, all of them should be mined
for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {
CBlockIndex* ancestor{Assert(m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i))};
@ -524,12 +539,17 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
m_node.chainman->ActiveChain().Tip()->nHeight++;
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
block = block_template->getBlock();
BOOST_CHECK_EQUAL(block.vtx.size(), 5U);
}
void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
{
auto mining{MakeMining()};
BOOST_REQUIRE(mining);
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
@ -594,34 +614,34 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
Txid hashFreeGrandchild = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashFreeParent);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashFreePrioritisedTx);
BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashPrioritsedChild);
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashFreeChild);
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
auto block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
BOOST_REQUIRE_EQUAL(block.vtx.size(), 6U);
BOOST_CHECK(block.vtx[1]->GetHash() == hashFreeParent);
BOOST_CHECK(block.vtx[2]->GetHash() == hashFreePrioritisedTx);
BOOST_CHECK(block.vtx[3]->GetHash() == hashParentTx);
BOOST_CHECK(block.vtx[4]->GetHash() == hashPrioritsedChild);
BOOST_CHECK(block.vtx[5]->GetHash() == hashFreeChild);
for (size_t i=0; i<block.vtx.size(); ++i) {
// The FreeParent and FreeChild's prioritisations should not impact the child.
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeGrandchild);
BOOST_CHECK(block.vtx[i]->GetHash() != hashFreeGrandchild);
// De-prioritised transaction should not be included.
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashMediumFeeTx);
BOOST_CHECK(block.vtx[i]->GetHash() != hashMediumFeeTx);
}
}
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
auto mining{MakeMining()};
BOOST_REQUIRE(mining);
// Note that by default, these tests run with size accounting enabled.
CScript scriptPubKey = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG;
std::unique_ptr<CBlockTemplate> pblocktemplate;
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
CTxMemPool& tx_mempool{*m_node.mempool};
// Simple block creation, nothing special yet:
BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock());
std::unique_ptr<BlockTemplate> block_template;
// We can't make transactions until we have inputs
// Therefore, load 110 blocks :)
@ -629,27 +649,48 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
int baseheight = 0;
std::vector<CTransactionRef> txFirst;
for (const auto& bi : BLOCKINFO) {
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
const int current_height{mining->getTip()->height};
// Simple block creation, nothing special yet:
block_template = mining->createNewBlock(options);
BOOST_REQUIRE(block_template);
CBlock block{block_template->getBlock()};
CMutableTransaction txCoinbase(*block.vtx[0]);
{
LOCK(cs_main);
pblock->nVersion = VERSIONBITS_TOP_BITS;
pblock->nTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1;
CMutableTransaction txCoinbase(*pblock->vtx[0]);
block.nVersion = VERSIONBITS_TOP_BITS;
block.nTime = Assert(m_node.chainman)->ActiveChain().Tip()->GetMedianTimePast()+1;
txCoinbase.version = 1;
txCoinbase.vin[0].scriptSig = CScript{} << (m_node.chainman->ActiveChain().Height() + 1) << bi.extranonce;
txCoinbase.vin[0].scriptSig = CScript{} << (current_height + 1) << bi.extranonce;
txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
txCoinbase.vout[0].scriptPubKey = CScript();
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
block.vtx[0] = MakeTransactionRef(txCoinbase);
if (txFirst.size() == 0)
baseheight = m_node.chainman->ActiveChain().Height();
baseheight = current_height;
if (txFirst.size() < 4)
txFirst.push_back(pblock->vtx[0]);
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = bi.nonce;
txFirst.push_back(block.vtx[0]);
block.hashMerkleRoot = BlockMerkleRoot(block);
block.nNonce = bi.nonce;
}
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr));
pblock->hashPrevBlock = pblock->GetHash();
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
// Alternate calls between Chainman's ProcessNewBlock and submitSolution
// via the Mining interface. The former is used by net_processing as well
// as the submitblock RPC.
if (current_height % 2 == 0) {
BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
} else {
BOOST_REQUIRE(block_template->submitSolution(block.nVersion, block.nTime, block.nNonce, MakeTransactionRef(txCoinbase)));
}
{
LOCK(cs_main);
// The above calls don't guarantee the tip is actually updated, so
// we explictly check this.
auto maybe_new_tip{Assert(m_node.chainman)->ActiveChain().Tip()};
BOOST_REQUIRE_EQUAL(maybe_new_tip->GetBlockHash(), block.GetHash());
}
// This just adds coverage
mining->waitTipChanged(block.hashPrevBlock);
}
LOCK(cs_main);