aboutsummaryrefslogtreecommitdiff
path: root/src/test/miner_tests.cpp
diff options
context:
space:
mode:
authorglozow <gloriajzhao@gmail.com>2022-03-11 15:41:51 +0000
committerglozow <gloriajzhao@gmail.com>2022-03-14 16:03:10 +0000
commite4303c337c8423f21c2c72ee1bcca3aaf46fa1cb (patch)
tree1aa8faf51aa8e009417cd4bfe4d8b773c0b9ed62 /src/test/miner_tests.cpp
parent7a8d60676bc0eec289687b2dfd5d2b00b83c0eaa (diff)
downloadbitcoin-e4303c337c8423f21c2c72ee1bcca3aaf46fa1cb.tar.xz
[unit test] prioritisation in mining
Diffstat (limited to 'src/test/miner_tests.cpp')
-rw-r--r--src/test/miner_tests.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index b2c8a1f3aa..7e26e732f5 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -31,6 +31,7 @@ namespace miner_tests {
struct MinerTestingSetup : public TestingSetup {
void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
void TestBasicMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
+ void TestPrioritisedMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs);
bool TestSequenceLocks(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_node.mempool->cs)
{
CCoinsViewMemPool view_mempool(&m_node.chainman->ActiveChainstate().CoinsTip(), *m_node.mempool);
@@ -468,6 +469,81 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
}
+void MinerTestingSetup::TestPrioritisedMining(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
+{
+ TestMemPoolEntryHelper entry;
+
+ // Test that a tx below min fee but prioritised is included
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 5000000000LL; // 0 fee
+ uint256 hashFreePrioritisedTx = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(0).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ m_node.mempool->PrioritiseTransaction(hashFreePrioritisedTx, 5 * COIN);
+
+ tx.vin[0].prevout.hash = txFirst[1]->GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vout[0].nValue = 5000000000LL - 1000;
+ // This tx has a low fee: 1000 satoshis
+ uint256 hashParentTx = tx.GetHash(); // save this txid for later use
+ m_node.mempool->addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+
+ // This tx has a medium fee: 10000 satoshis
+ tx.vin[0].prevout.hash = txFirst[2]->GetHash();
+ tx.vout[0].nValue = 5000000000LL - 10000;
+ uint256 hashMediumFeeTx = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ m_node.mempool->PrioritiseTransaction(hashMediumFeeTx, -5 * COIN);
+
+ // This tx also has a low fee, but is prioritised
+ tx.vin[0].prevout.hash = hashParentTx;
+ tx.vout[0].nValue = 5000000000LL - 1000 - 1000; // 1000 satoshi fee
+ uint256 hashPrioritsedChild = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(1000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ m_node.mempool->PrioritiseTransaction(hashPrioritsedChild, 2 * COIN);
+
+ // Test that transaction selection properly updates ancestor fee calculations as prioritised
+ // parents get included in a block. Create a transaction with two prioritised ancestors, each
+ // included by itself: FreeParent <- FreeChild <- FreeGrandchild.
+ // When FreeParent is added, a modified entry will be created for FreeChild + FreeGrandchild
+ // FreeParent's prioritisation should not be included in that entry.
+ // When FreeChild is included, FreeChild's prioritisation should also not be included.
+ tx.vin[0].prevout.hash = txFirst[3]->GetHash();
+ tx.vout[0].nValue = 5000000000LL; // 0 fee
+ uint256 hashFreeParent = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
+ m_node.mempool->PrioritiseTransaction(hashFreeParent, 10 * COIN);
+
+ tx.vin[0].prevout.hash = hashFreeParent;
+ tx.vout[0].nValue = 5000000000LL; // 0 fee
+ uint256 hashFreeChild = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
+ m_node.mempool->PrioritiseTransaction(hashFreeChild, 1 * COIN);
+
+ tx.vin[0].prevout.hash = hashFreeChild;
+ tx.vout[0].nValue = 5000000000LL; // 0 fee
+ uint256 hashFreeGrandchild = tx.GetHash();
+ m_node.mempool->addUnchecked(entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
+
+ auto pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+ 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) {
+ // The FreeParent and FreeChild's prioritisations should not impact the child.
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeGrandchild);
+ // De-prioritised transaction should not be included.
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashMediumFeeTx);
+ }
+}
+
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
@@ -522,6 +598,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
TestPackageSelection(chainparams, scriptPubKey, txFirst);
+ m_node.chainman->ActiveChain().Tip()->nHeight--;
+ SetMockTime(0);
+ m_node.mempool->clear();
+
+ TestPrioritisedMining(chainparams, scriptPubKey, txFirst);
+
fCheckpointsEnabled = true;
}