Needed for both #31283 and #31564.
By using the Mining interface in miner_tests.cpp
we increase its coverage in unit tests.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31581.
See the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
143- BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
144- BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
145- BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
146- BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
147+ std::unique_ptr<BlockTemplate> block_template = miner->createNewBlock(options);
148+ CBlock block{block_template->getBlock()};
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
Other tests seem to add BOOST_REQUIRE(block_template); before this.
A failing BOOST_REQUIRE
produces an easier to debug failure than dereferencing nullptr, so it’s always a good one to add.
I updated the test to do this after every miner->createNewBlock()
call.
Similarly BOOST_REQUIRE
stops the test immedidately, so I replaced a few BOOST_CHECK
calls with it.
620- BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashParentTx);
621- BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashPrioritsedChild);
622- BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashFreeChild);
623- for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
624+ auto block_template = miner->createNewBlock(options);
625+ CBlock block{block_template->getBlock()};
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
Other tests seem to add BOOST_REQUIRE(block_template); before this.
103@@ -106,6 +104,10 @@ static std::unique_ptr<CBlockIndex> CreateBlockIndex(int nHeight, CBlockIndex* a
104 void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
105 {
106 CTxMemPool& tx_mempool{MakeMempool()};
107+ auto miner{MakeMining()};
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
In other tests below this is followed by BOOST_REQUIRE(miner);
. Seems fine to keep or drop, but would be good to be consistent.
Also I think it might be a little clearer if variable was called mining
instead of miner
since it’s not a miner and can’t mine blocks, it’s just a pointer to the interface used for mining. But feel free to ignore this if you prefer the current name.
697+ block.hashMerkleRoot = BlockMerkleRoot(block);
698+ block.nNonce = bi.nonce;
699+ }
700+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
701+ // Alternate calls between Chainman's ProcessNewBlock and submitSolution
702+ // via the Mining interface.
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
Can this comment be updated to say the reason for alternating between these? (e.g. to provide test coverage for net_processing code)
I think it would also be clearer to drop the comments about this in the PR and commit descriptions:
Those comments were confusing to me without seeing context here. They also seem unrelated to all the other changes in this PR (unless I am not seeing a bigger connection). If those comments are just supposed to describe this if
statement, it would be better to move them here.
707 }
708- std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
709- BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr));
710- pblock->hashPrevBlock = pblock->GetHash();
711+ // ProcessNewBlock and submitSolution do not check if the new block is
712+ // valid. If it is, they will wait for the tip to update. Therefore the
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
Unless I’m misunderstanding something it doesn’t seem accurate to say that these don’t check if the new block is valid. Would seem more accurate to say they return true even if the block is invalid. Also it would seem be more accurate to say that they update the tip, rather than that they wait for the tip to update.
710- pblock->hashPrevBlock = pblock->GetHash();
711+ // ProcessNewBlock and submitSolution do not check if the new block is
712+ // valid. If it is, they will wait for the tip to update. Therefore the
713+ // following check will either return immediately, or be stuck indefinately.
714+ // It's mainly there to increase test coverage.
715+ miner->waitTipChanged(block.hashPrevBlock);
In commit “test: use Mining interface in miner_tests” (e4e76f27d73646d887ed8b660c67da4b4b785d8e)
Seems fine to call waitTipChange if idea is to add more test coverage for it, but wouldn’t it be more direct to just check that the new tip matches the block hash if the idea is to check that the block was connected? This way if the block was not connected the test would fail instead of hanging indefinitely.
waitTipChanged()
call.
704+ // via the Mining interface. The former is used by net_processing as well
705+ // as the submitblock RPC.
706+ if (current_height % 2 == 0) {
707+ BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr));
708+ } else {
709+ BOOST_REQUIRE(block_template->submitSolution(block.nVersion, block.nTime, block.nNonce, MakeTransactionRef(txCoinbase)));
Feel free to ignore: could use block.vtx[0]
here instead of MakeTransactionRef(txCoinbase)
:
0 BOOST_REQUIRE(block_template->submitSolution(block.nVersion, block.nTime, block.nNonce, block.vtx[0]));
and reduce the scope of txCoinbase
to only inside the above {
}
block.
txCoinbase
is more clear than block.vtx[0]
and limiting the scope isn’t that important.
ACK 04249682e381f976de6ba56bb4fb2996dfa194ab
Not in this PR, just an observation: given that we have two concepts: “block” and “block template”, I find the below pattern a bit confusing:
0block_template = mining->createNewBlock()
1block = block_template->getBlock()
because I would expect createNewBlock()
to create a new block, but apparently it creates a new block template.
because I would expect
createNewBlock()
to create a new block, but apparently it creates a new block template.
Indeed, I could rename the interface method (different PR) to e.g. newBlockTemplate()
. Though I’d rather avoid the code churn in my pile of PRs :-)
159@@ -158,11 +160,13 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
160 tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
161 Txid hashLowFeeTx = tx.GetHash();
162 AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
163- pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
164+ block_template = mining->createNewBlock(options);
165+ BOOST_REQUIRE(block_template);
166+ block = block_template->getBlock();
This pattern is repeated throughout the file. Unless I’m missing something, seems like a good opportunity to de-duplicate with something like:
0CBlock CreateAndGetBlock(const node::BlockCreateOptions& options)
1{
2 auto mining{MakeMining()};
3 BOOST_REQUIRE(mining);
4 std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options);
5 BOOST_REQUIRE(block_template);
6 return block_template->getBlock();
7}
ACK 04249682e381f976de6ba56bb4fb2996dfa194ab
Nice updates. Left a minor non-blocking comment.
709+ BOOST_REQUIRE(block_template->submitSolution(block.nVersion, block.nTime, block.nNonce, MakeTransactionRef(txCoinbase)));
710+ }
711+ {
712+ LOCK(cs_main);
713+ // The above calls don't guarantee the tip is actually updated, so
714+ // we explictly check this.
nit:
0src/test/miner_tests.cpp:704: explictly ==> explicitly