mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-09 03:18:09 -03:00
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: ACK04249682e3
ryanofsky: Code review ACK04249682e3
, 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: ACK04249682e3
tdb3: ACK04249682e3
Tree-SHA512: 2761cb7555d759670e40d8f37b96a079f8e12a588ac43313b9e63c69afd478321515873a8896ea56784f0100dac4476b0c0e0ef8b5418f8aea24d9965cace4d4
This commit is contained in:
commit
c506f2cee7
1 changed files with 118 additions and 77 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue