Test suite for ancestor feerate transaction selection. Implemented as an additional function, rather than a separate test case, to allow reusing the blockchain created in CreateNewBlock_validity.
| 130 | // Implemented as an additional function, rather than a separate test case, |
| 131 | // to allow reusing the blockchain created in CreateNewBlock_validity. |
| 132 | void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) |
| 133 | { |
| 134 | CTxMemPool& tx_mempool{MakeMempool()}; |
| 135 | auto mining{MakeMining()}; |
| 136 | BlockCreateOptions options{ |
| 137 | .coinbase_output_script = scriptPubKey, |
| 138 | }; |
| 139 | |
| 140 | LOCK(tx_mempool.cs); |
| 141 | BOOST_CHECK(tx_mempool.size() == 0); |
| 142 | |
| 143 | // Block template should only have a coinbase when there's nothing in the mempool |
| 144 | std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options, /*cooldown=*/false); |
| 145 | BOOST_REQUIRE(block_template); |
| 146 | CBlock block{block_template->getBlock()}; |
| 147 | BOOST_REQUIRE_EQUAL(block.vtx.size(), 1U); |
| 148 | |
| 149 | // waitNext() on an empty mempool should return nullptr because there is no better template |
| 150 | auto should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1}); |
| 151 | BOOST_REQUIRE(should_be_nullptr == nullptr); |
| 152 | |
| 153 | // Unless fee_threshold is 0 |
| 154 | block_template = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 0}); |
| 155 | BOOST_REQUIRE(block_template); |
| 156 | |
| 157 | // Test the ancestor feerate transaction selection. |
| 158 | TestMemPoolEntryHelper entry; |
| 159 | |
| 160 | // Test that a medium fee transaction will be selected after a higher fee |
| 161 | // rate package with a low fee rate parent. |
| 162 | CMutableTransaction tx; |
| 163 | tx.vin.resize(1); |
| 164 | tx.vin[0].scriptSig = CScript() << OP_1; |
| 165 | tx.vin[0].prevout.hash = txFirst[0]->GetHash(); |
| 166 | tx.vin[0].prevout.n = 0; |
| 167 | tx.vout.resize(1); |
| 168 | tx.vout[0].nValue = 5000000000LL - 1000; |
| 169 | // This tx has a low fee: 1000 satoshis |
| 170 | Txid hashParentTx = tx.GetHash(); // save this txid for later use |
| 171 | const auto parent_tx{entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)}; |
| 172 | TryAddToMempool(tx_mempool, parent_tx); |
| 173 | |
| 174 | // This tx has a medium fee: 10000 satoshis |
| 175 | tx.vin[0].prevout.hash = txFirst[1]->GetHash(); |
| 176 | tx.vout[0].nValue = 5000000000LL - 10000; |
| 177 | Txid hashMediumFeeTx = tx.GetHash(); |
| 178 | const auto medium_fee_tx{entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)}; |
| 179 | TryAddToMempool(tx_mempool, medium_fee_tx); |
| 180 | |
| 181 | // This tx has a high fee, but depends on the first transaction |
| 182 | tx.vin[0].prevout.hash = hashParentTx; |
| 183 | tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee |
| 184 | Txid hashHighFeeTx = tx.GetHash(); |
| 185 | const auto high_fee_tx{entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)}; |
| 186 | TryAddToMempool(tx_mempool, high_fee_tx); |
| 187 | |
| 188 | block_template = mining->createNewBlock(options, /*cooldown=*/false); |
| 189 | BOOST_REQUIRE(block_template); |
nothing calls this directly
no test coverage detected