txpackage_tests.cpp
1 // Copyright (c) 2021-2022 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <consensus/validation.h> 6 #include <key_io.h> 7 #include <policy/packages.h> 8 #include <policy/policy.h> 9 #include <policy/rbf.h> 10 #include <primitives/transaction.h> 11 #include <script/script.h> 12 #include <serialize.h> 13 #include <streams.h> 14 #include <test/util/random.h> 15 #include <test/util/script.h> 16 #include <test/util/setup_common.h> 17 #include <util/strencodings.h> 18 #include <test/util/txmempool.h> 19 #include <validation.h> 20 21 #include <boost/test/unit_test.hpp> 22 23 using namespace util::hex_literals; 24 25 // A fee amount that is above 1sat/vB but below 5sat/vB for most transactions created within these 26 // unit tests. 27 static const CAmount low_fee_amt{200}; 28 29 struct TxPackageTest : TestChain100Setup { 30 // Create placeholder transactions that have no meaning. 31 inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs) 32 { 33 CMutableTransaction mtx = CMutableTransaction(); 34 mtx.vin.resize(num_inputs); 35 mtx.vout.resize(num_outputs); 36 auto random_script = CScript() << ToByteVector(m_rng.rand256()) << ToByteVector(m_rng.rand256()); 37 for (size_t i{0}; i < num_inputs; ++i) { 38 mtx.vin[i].prevout.hash = Txid::FromUint256(m_rng.rand256()); 39 mtx.vin[i].prevout.n = 0; 40 mtx.vin[i].scriptSig = random_script; 41 } 42 for (size_t o{0}; o < num_outputs; ++o) { 43 mtx.vout[o].nValue = 1 * CENT; 44 mtx.vout[o].scriptPubKey = random_script; 45 } 46 return MakeTransactionRef(mtx); 47 } 48 }; // struct TxPackageTest 49 50 BOOST_FIXTURE_TEST_SUITE(txpackage_tests, TxPackageTest) 51 52 BOOST_AUTO_TEST_CASE(package_hash_tests) 53 { 54 // Random real segwit transaction 55 DataStream stream_1{ 56 "02000000000101964b8aa63509579ca6086e6012eeaa4c2f4dd1e283da29b67c8eea38b3c6fd220000000000fdffffff0294c618000000000017a9145afbbb42f4e83312666d0697f9e66259912ecde38768fa2c0000000000160014897388a0889390fd0e153a22bb2cf9d8f019faf50247304402200547406380719f84d68cf4e96cc3e4a1688309ef475b150be2b471c70ea562aa02206d255f5acc40fd95981874d77201d2eb07883657ce1c796513f32b6079545cdf0121023ae77335cefcb5ab4c1dc1fb0d2acfece184e593727d7d5906c78e564c7c11d125cf0c00"_hex, 57 }; 58 CTransaction tx_1(deserialize, TX_WITH_WITNESS, stream_1); 59 CTransactionRef ptx_1{MakeTransactionRef(tx_1)}; 60 61 // Random real nonsegwit transaction 62 DataStream stream_2{ 63 "01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e2754dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d9032a7b9d64fa43188ac00000000"_hex, 64 }; 65 CTransaction tx_2(deserialize, TX_WITH_WITNESS, stream_2); 66 CTransactionRef ptx_2{MakeTransactionRef(tx_2)}; 67 68 // Random real segwit transaction 69 DataStream stream_3{ 70 "0200000000010177862801f77c2c068a70372b4c435ef8dd621291c36a64eb4dd491f02218f5324600000000fdffffff014a0100000000000022512035ea312034cfac01e956a269f3bf147f569c2fbb00180677421262da042290d803402be713325ff285e66b0380f53f2fae0d0fb4e16f378a440fed51ce835061437566729d4883bc917632f3cff474d6384bc8b989961a1d730d4a87ed38ad28bd337b20f1d658c6c138b1c312e072b4446f50f01ae0da03a42e6274f8788aae53416a7fac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800357b2270223a226272632d3230222c226f70223a226d696e74222c227469636b223a224342414c222c22616d74223a2236393639227d6821c1f1d658c6c138b1c312e072b4446f50f01ae0da03a42e6274f8788aae53416a7f00000000"_hex, 71 }; 72 CTransaction tx_3(deserialize, TX_WITH_WITNESS, stream_3); 73 CTransactionRef ptx_3{MakeTransactionRef(tx_3)}; 74 75 // It's easy to see that wtxids are sorted in lexicographical order: 76 Wtxid wtxid_1{Wtxid::FromHex("85cd1a31eb38f74ed5742ec9cb546712ab5aaf747de28a9168b53e846cbda17f").value()}; 77 Wtxid wtxid_2{Wtxid::FromHex("b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b").value()}; 78 Wtxid wtxid_3{Wtxid::FromHex("e065bac15f62bb4e761d761db928ddee65a47296b2b776785abb912cdec474e3").value()}; 79 BOOST_CHECK_EQUAL(tx_1.GetWitnessHash(), wtxid_1); 80 BOOST_CHECK_EQUAL(tx_2.GetWitnessHash(), wtxid_2); 81 BOOST_CHECK_EQUAL(tx_3.GetWitnessHash(), wtxid_3); 82 83 BOOST_CHECK(wtxid_1.GetHex() < wtxid_2.GetHex()); 84 BOOST_CHECK(wtxid_2.GetHex() < wtxid_3.GetHex()); 85 86 // The txids are not (we want to test that sorting and hashing use wtxid, not txid): 87 Txid txid_1{Txid::FromHex("bd0f71c1d5e50589063e134fad22053cdae5ab2320db5bf5e540198b0b5a4e69").value()}; 88 Txid txid_2{Txid::FromHex("b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b").value()}; 89 Txid txid_3{Txid::FromHex("ee707be5201160e32c4fc715bec227d1aeea5940fb4295605e7373edce3b1a93").value()}; 90 BOOST_CHECK_EQUAL(tx_1.GetHash(), txid_1); 91 BOOST_CHECK_EQUAL(tx_2.GetHash(), txid_2); 92 BOOST_CHECK_EQUAL(tx_3.GetHash(), txid_3); 93 94 BOOST_CHECK(txid_2.GetHex() < txid_1.GetHex()); 95 96 BOOST_CHECK(txid_1.ToUint256() != wtxid_1.ToUint256()); 97 BOOST_CHECK(txid_2.ToUint256() == wtxid_2.ToUint256()); 98 BOOST_CHECK(txid_3.ToUint256() != wtxid_3.ToUint256()); 99 100 // We are testing that both functions compare using GetHex() and not uint256. 101 // (in this pair of wtxids, hex string order != uint256 order) 102 BOOST_CHECK(wtxid_2 < wtxid_1); 103 // (in this pair of wtxids, hex string order == uint256 order) 104 BOOST_CHECK(wtxid_2 < wtxid_3); 105 106 // All permutations of the package containing ptx_1, ptx_2, ptx_3 have the same package hash 107 std::vector<CTransactionRef> package_123{ptx_1, ptx_2, ptx_3}; 108 std::vector<CTransactionRef> package_132{ptx_1, ptx_3, ptx_2}; 109 std::vector<CTransactionRef> package_231{ptx_2, ptx_3, ptx_1}; 110 std::vector<CTransactionRef> package_213{ptx_2, ptx_1, ptx_3}; 111 std::vector<CTransactionRef> package_312{ptx_3, ptx_1, ptx_2}; 112 std::vector<CTransactionRef> package_321{ptx_3, ptx_2, ptx_1}; 113 114 uint256 calculated_hash_123 = (HashWriter() << wtxid_1 << wtxid_2 << wtxid_3).GetSHA256(); 115 116 uint256 hash_if_by_txid = (HashWriter() << wtxid_2 << wtxid_1 << wtxid_3).GetSHA256(); 117 BOOST_CHECK(hash_if_by_txid != calculated_hash_123); 118 119 uint256 hash_if_use_txid = (HashWriter() << txid_2 << txid_1 << txid_3).GetSHA256(); 120 BOOST_CHECK(hash_if_use_txid != calculated_hash_123); 121 122 uint256 hash_if_use_int_order = (HashWriter() << wtxid_2 << wtxid_1 << wtxid_3).GetSHA256(); 123 BOOST_CHECK(hash_if_use_int_order != calculated_hash_123); 124 125 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_123)); 126 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_132)); 127 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_231)); 128 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_213)); 129 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_312)); 130 BOOST_CHECK_EQUAL(calculated_hash_123, GetPackageHash(package_321)); 131 } 132 133 BOOST_AUTO_TEST_CASE(package_sanitization_tests) 134 { 135 // Packages can't have more than 25 transactions. 136 Package package_too_many; 137 package_too_many.reserve(MAX_PACKAGE_COUNT + 1); 138 for (size_t i{0}; i < MAX_PACKAGE_COUNT + 1; ++i) { 139 package_too_many.emplace_back(create_placeholder_tx(1, 1)); 140 } 141 PackageValidationState state_too_many; 142 BOOST_CHECK(!IsWellFormedPackage(package_too_many, state_too_many, /*require_sorted=*/true)); 143 BOOST_CHECK_EQUAL(state_too_many.GetResult(), PackageValidationResult::PCKG_POLICY); 144 BOOST_CHECK_EQUAL(state_too_many.GetRejectReason(), "package-too-many-transactions"); 145 146 // Packages can't have a total weight of more than 404'000WU. 147 CTransactionRef large_ptx = create_placeholder_tx(150, 150); 148 Package package_too_large; 149 auto size_large = GetTransactionWeight(*large_ptx); 150 size_t total_weight{0}; 151 while (total_weight <= MAX_PACKAGE_WEIGHT) { 152 package_too_large.push_back(large_ptx); 153 total_weight += size_large; 154 } 155 BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT); 156 PackageValidationState state_too_large; 157 BOOST_CHECK(!IsWellFormedPackage(package_too_large, state_too_large, /*require_sorted=*/true)); 158 BOOST_CHECK_EQUAL(state_too_large.GetResult(), PackageValidationResult::PCKG_POLICY); 159 BOOST_CHECK_EQUAL(state_too_large.GetRejectReason(), "package-too-large"); 160 161 // Packages can't contain transactions with the same txid. 162 Package package_duplicate_txids_empty; 163 for (auto i{0}; i < 3; ++i) { 164 CMutableTransaction empty_tx; 165 package_duplicate_txids_empty.emplace_back(MakeTransactionRef(empty_tx)); 166 } 167 PackageValidationState state_duplicates; 168 BOOST_CHECK(!IsWellFormedPackage(package_duplicate_txids_empty, state_duplicates, /*require_sorted=*/true)); 169 BOOST_CHECK_EQUAL(state_duplicates.GetResult(), PackageValidationResult::PCKG_POLICY); 170 BOOST_CHECK_EQUAL(state_duplicates.GetRejectReason(), "package-contains-duplicates"); 171 BOOST_CHECK(!IsConsistentPackage(package_duplicate_txids_empty)); 172 173 // Packages can't have transactions spending the same prevout 174 CMutableTransaction tx_zero_1; 175 CMutableTransaction tx_zero_2; 176 COutPoint same_prevout{Txid::FromUint256(m_rng.rand256()), 0}; 177 tx_zero_1.vin.emplace_back(same_prevout); 178 tx_zero_2.vin.emplace_back(same_prevout); 179 // Different vouts (not the same tx) 180 tx_zero_1.vout.emplace_back(CENT, P2WSH_OP_TRUE); 181 tx_zero_2.vout.emplace_back(2 * CENT, P2WSH_OP_TRUE); 182 Package package_conflicts{MakeTransactionRef(tx_zero_1), MakeTransactionRef(tx_zero_2)}; 183 BOOST_CHECK(!IsConsistentPackage(package_conflicts)); 184 // Transactions are considered sorted when they have no dependencies. 185 BOOST_CHECK(IsTopoSortedPackage(package_conflicts)); 186 PackageValidationState state_conflicts; 187 BOOST_CHECK(!IsWellFormedPackage(package_conflicts, state_conflicts, /*require_sorted=*/true)); 188 BOOST_CHECK_EQUAL(state_conflicts.GetResult(), PackageValidationResult::PCKG_POLICY); 189 BOOST_CHECK_EQUAL(state_conflicts.GetRejectReason(), "conflict-in-package"); 190 191 // IsConsistentPackage only cares about conflicts between transactions, not about a transaction 192 // conflicting with itself (i.e. duplicate prevouts in vin). 193 CMutableTransaction dup_tx; 194 const COutPoint rand_prevout{Txid::FromUint256(m_rng.rand256()), 0}; 195 dup_tx.vin.emplace_back(rand_prevout); 196 dup_tx.vin.emplace_back(rand_prevout); 197 Package package_with_dup_tx{MakeTransactionRef(dup_tx)}; 198 BOOST_CHECK(IsConsistentPackage(package_with_dup_tx)); 199 package_with_dup_tx.emplace_back(create_placeholder_tx(1, 1)); 200 BOOST_CHECK(IsConsistentPackage(package_with_dup_tx)); 201 } 202 203 BOOST_AUTO_TEST_CASE(package_validation_tests) 204 { 205 LOCK(cs_main); 206 unsigned int initialPoolSize = m_node.mempool->size(); 207 208 // Parent and Child Package 209 CKey parent_key = GenerateRandomKey(); 210 CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey())); 211 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 212 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 213 /*output_destination=*/parent_locking_script, 214 /*output_amount=*/CAmount(49 * COIN), /*submit=*/false); 215 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 216 217 CKey child_key = GenerateRandomKey(); 218 CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey())); 219 auto mtx_child = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent, /*input_vout=*/0, 220 /*input_height=*/101, /*input_signing_key=*/parent_key, 221 /*output_destination=*/child_locking_script, 222 /*output_amount=*/CAmount(48 * COIN), /*submit=*/false); 223 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 224 Package package_parent_child{tx_parent, tx_child}; 225 const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_parent_child, /*test_accept=*/true, /*client_maxfeerate=*/{}); 226 if (auto err_parent_child{CheckPackageMempoolAcceptResult(package_parent_child, result_parent_child, /*expect_valid=*/true, nullptr)}) { 227 BOOST_ERROR(err_parent_child.value()); 228 } else { 229 auto it_parent = result_parent_child.m_tx_results.find(tx_parent->GetWitnessHash()); 230 auto it_child = result_parent_child.m_tx_results.find(tx_child->GetWitnessHash()); 231 232 BOOST_CHECK(it_parent->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent)) == COIN); 233 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1); 234 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash()); 235 236 BOOST_CHECK(it_child->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child)) == COIN); 237 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1); 238 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash()); 239 } 240 // A single, giant transaction submitted through ProcessNewPackage fails on single tx policy. 241 CTransactionRef giant_ptx = create_placeholder_tx(999, 999); 242 BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1000); 243 Package package_single_giant{giant_ptx}; 244 auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_single_giant, /*test_accept=*/true, /*client_maxfeerate=*/{}); 245 if (auto err_single_large{CheckPackageMempoolAcceptResult(package_single_giant, result_single_large, /*expect_valid=*/false, nullptr)}) { 246 BOOST_ERROR(err_single_large.value()); 247 } else { 248 BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX); 249 BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed"); 250 auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetWitnessHash()); 251 BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size"); 252 } 253 254 // Check that mempool size hasn't changed. 255 BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); 256 } 257 258 BOOST_AUTO_TEST_CASE(noncontextual_package_tests) 259 { 260 // The signatures won't be verified so we can just use a placeholder 261 CKey placeholder_key = GenerateRandomKey(); 262 CScript spk = GetScriptForDestination(PKHash(placeholder_key.GetPubKey())); 263 CKey placeholder_key_2 = GenerateRandomKey(); 264 CScript spk2 = GetScriptForDestination(PKHash(placeholder_key_2.GetPubKey())); 265 266 // Parent and Child Package 267 { 268 auto mtx_parent = CreateValidMempoolTransaction(m_coinbase_txns[0], 0, 0, coinbaseKey, spk, 269 CAmount(49 * COIN), /*submit=*/false); 270 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 271 272 auto mtx_child = CreateValidMempoolTransaction(tx_parent, 0, 101, placeholder_key, spk2, 273 CAmount(48 * COIN), /*submit=*/false); 274 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 275 276 PackageValidationState state; 277 BOOST_CHECK(IsWellFormedPackage({tx_parent, tx_child}, state, /*require_sorted=*/true)); 278 BOOST_CHECK(!IsWellFormedPackage({tx_child, tx_parent}, state, /*require_sorted=*/true)); 279 BOOST_CHECK_EQUAL(state.GetResult(), PackageValidationResult::PCKG_POLICY); 280 BOOST_CHECK_EQUAL(state.GetRejectReason(), "package-not-sorted"); 281 BOOST_CHECK(IsChildWithParents({tx_parent, tx_child})); 282 BOOST_CHECK(IsChildWithParentsTree({tx_parent, tx_child})); 283 BOOST_CHECK(GetPackageHash({tx_parent}) != GetPackageHash({tx_child})); 284 BOOST_CHECK(GetPackageHash({tx_child, tx_child}) != GetPackageHash({tx_child})); 285 BOOST_CHECK(GetPackageHash({tx_child, tx_parent}) != GetPackageHash({tx_child, tx_child})); 286 BOOST_CHECK(!IsChildWithParents({})); 287 BOOST_CHECK(!IsChildWithParentsTree({})); 288 } 289 290 // 24 Parents and 1 Child 291 { 292 Package package; 293 CMutableTransaction child; 294 for (int i{0}; i < 24; ++i) { 295 auto parent = MakeTransactionRef(CreateValidMempoolTransaction(m_coinbase_txns[i + 1], 296 0, 0, coinbaseKey, spk, CAmount(48 * COIN), false)); 297 package.emplace_back(parent); 298 child.vin.emplace_back(COutPoint(parent->GetHash(), 0)); 299 } 300 child.vout.emplace_back(47 * COIN, spk2); 301 302 // The child must be in the package. 303 BOOST_CHECK(!IsChildWithParents(package)); 304 305 // The parents can be in any order. 306 FastRandomContext rng; 307 std::shuffle(package.begin(), package.end(), rng); 308 package.push_back(MakeTransactionRef(child)); 309 310 PackageValidationState state; 311 BOOST_CHECK(IsWellFormedPackage(package, state, /*require_sorted=*/true)); 312 BOOST_CHECK(IsChildWithParents(package)); 313 BOOST_CHECK(IsChildWithParentsTree(package)); 314 315 package.erase(package.begin()); 316 BOOST_CHECK(IsChildWithParents(package)); 317 318 // The package cannot have unrelated transactions. 319 package.insert(package.begin(), m_coinbase_txns[0]); 320 BOOST_CHECK(!IsChildWithParents(package)); 321 } 322 323 // 2 Parents and 1 Child where one parent depends on the other. 324 { 325 CMutableTransaction mtx_parent; 326 mtx_parent.vin.emplace_back(COutPoint(m_coinbase_txns[0]->GetHash(), 0)); 327 mtx_parent.vout.emplace_back(20 * COIN, spk); 328 mtx_parent.vout.emplace_back(20 * COIN, spk2); 329 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 330 331 CMutableTransaction mtx_parent_also_child; 332 mtx_parent_also_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 0)); 333 mtx_parent_also_child.vout.emplace_back(20 * COIN, spk); 334 CTransactionRef tx_parent_also_child = MakeTransactionRef(mtx_parent_also_child); 335 336 CMutableTransaction mtx_child; 337 mtx_child.vin.emplace_back(COutPoint(tx_parent->GetHash(), 1)); 338 mtx_child.vin.emplace_back(COutPoint(tx_parent_also_child->GetHash(), 0)); 339 mtx_child.vout.emplace_back(39 * COIN, spk); 340 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 341 342 PackageValidationState state; 343 BOOST_CHECK(IsChildWithParents({tx_parent, tx_parent_also_child})); 344 BOOST_CHECK(IsChildWithParents({tx_parent, tx_child})); 345 BOOST_CHECK(IsChildWithParents({tx_parent, tx_parent_also_child, tx_child})); 346 BOOST_CHECK(!IsChildWithParentsTree({tx_parent, tx_parent_also_child, tx_child})); 347 // IsChildWithParents does not detect unsorted parents. 348 BOOST_CHECK(IsChildWithParents({tx_parent_also_child, tx_parent, tx_child})); 349 BOOST_CHECK(IsWellFormedPackage({tx_parent, tx_parent_also_child, tx_child}, state, /*require_sorted=*/true)); 350 BOOST_CHECK(!IsWellFormedPackage({tx_parent_also_child, tx_parent, tx_child}, state, /*require_sorted=*/true)); 351 BOOST_CHECK_EQUAL(state.GetResult(), PackageValidationResult::PCKG_POLICY); 352 BOOST_CHECK_EQUAL(state.GetRejectReason(), "package-not-sorted"); 353 } 354 } 355 356 BOOST_AUTO_TEST_CASE(package_submission_tests) 357 { 358 LOCK(cs_main); 359 unsigned int expected_pool_size = m_node.mempool->size(); 360 CKey parent_key = GenerateRandomKey(); 361 CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey())); 362 363 // Unrelated transactions are not allowed in package submission. 364 Package package_unrelated; 365 for (size_t i{0}; i < 10; ++i) { 366 auto mtx = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[i + 25], /*input_vout=*/0, 367 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 368 /*output_destination=*/parent_locking_script, 369 /*output_amount=*/CAmount(49 * COIN), /*submit=*/false); 370 package_unrelated.emplace_back(MakeTransactionRef(mtx)); 371 } 372 auto result_unrelated_submit = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 373 package_unrelated, /*test_accept=*/false, /*client_maxfeerate=*/{}); 374 // We don't expect m_tx_results for each transaction when basic sanity checks haven't passed. 375 BOOST_CHECK(result_unrelated_submit.m_state.IsInvalid()); 376 BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY); 377 BOOST_CHECK_EQUAL(result_unrelated_submit.m_state.GetRejectReason(), "package-not-child-with-parents"); 378 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 379 380 // Parent and Child (and Grandchild) Package 381 Package package_parent_child; 382 Package package_3gen; 383 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 384 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 385 /*output_destination=*/parent_locking_script, 386 /*output_amount=*/CAmount(49 * COIN), /*submit=*/false); 387 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 388 package_parent_child.push_back(tx_parent); 389 package_3gen.push_back(tx_parent); 390 391 CKey child_key = GenerateRandomKey(); 392 CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey())); 393 auto mtx_child = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent, /*input_vout=*/0, 394 /*input_height=*/101, /*input_signing_key=*/parent_key, 395 /*output_destination=*/child_locking_script, 396 /*output_amount=*/CAmount(48 * COIN), /*submit=*/false); 397 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 398 package_parent_child.push_back(tx_child); 399 package_3gen.push_back(tx_child); 400 401 CKey grandchild_key = GenerateRandomKey(); 402 CScript grandchild_locking_script = GetScriptForDestination(PKHash(grandchild_key.GetPubKey())); 403 auto mtx_grandchild = CreateValidMempoolTransaction(/*input_transaction=*/tx_child, /*input_vout=*/0, 404 /*input_height=*/101, /*input_signing_key=*/child_key, 405 /*output_destination=*/grandchild_locking_script, 406 /*output_amount=*/CAmount(47 * COIN), /*submit=*/false); 407 CTransactionRef tx_grandchild = MakeTransactionRef(mtx_grandchild); 408 package_3gen.push_back(tx_grandchild); 409 410 // 3 Generations is not allowed. 411 { 412 auto result_3gen_submit = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 413 package_3gen, /*test_accept=*/false, /*client_maxfeerate=*/{}); 414 BOOST_CHECK(result_3gen_submit.m_state.IsInvalid()); 415 BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetResult(), PackageValidationResult::PCKG_POLICY); 416 BOOST_CHECK_EQUAL(result_3gen_submit.m_state.GetRejectReason(), "package-not-child-with-parents"); 417 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 418 } 419 420 // Parent and child package where transactions are invalid for reasons other than fee and 421 // missing inputs, so the package validation isn't expected to happen. 422 { 423 CScriptWitness bad_witness; 424 bad_witness.stack.emplace_back(1); 425 CMutableTransaction mtx_parent_invalid{mtx_parent}; 426 mtx_parent_invalid.vin[0].scriptWitness = bad_witness; 427 CTransactionRef tx_parent_invalid = MakeTransactionRef(mtx_parent_invalid); 428 Package package_invalid_parent{tx_parent_invalid, tx_child}; 429 auto result_quit_early = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 430 package_invalid_parent, /*test_accept=*/ false, /*client_maxfeerate=*/{}); 431 if (auto err_parent_invalid{CheckPackageMempoolAcceptResult(package_invalid_parent, result_quit_early, /*expect_valid=*/false, m_node.mempool.get())}) { 432 BOOST_ERROR(err_parent_invalid.value()); 433 } else { 434 auto it_parent = result_quit_early.m_tx_results.find(tx_parent_invalid->GetWitnessHash()); 435 auto it_child = result_quit_early.m_tx_results.find(tx_child->GetWitnessHash()); 436 BOOST_CHECK_EQUAL(it_parent->second.m_state.GetResult(), TxValidationResult::TX_WITNESS_MUTATED); 437 BOOST_CHECK_EQUAL(it_parent->second.m_state.GetRejectReason(), "bad-witness-nonstandard"); 438 BOOST_CHECK_EQUAL(it_child->second.m_state.GetResult(), TxValidationResult::TX_MISSING_INPUTS); 439 BOOST_CHECK_EQUAL(it_child->second.m_state.GetRejectReason(), "bad-txns-inputs-missingorspent"); 440 } 441 BOOST_CHECK_EQUAL(result_quit_early.m_state.GetResult(), PackageValidationResult::PCKG_TX); 442 } 443 444 // Child with missing parent. 445 mtx_child.vin.emplace_back(COutPoint(package_unrelated[0]->GetHash(), 0)); 446 Package package_missing_parent; 447 package_missing_parent.push_back(tx_parent); 448 package_missing_parent.push_back(MakeTransactionRef(mtx_child)); 449 { 450 const auto result_missing_parent = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 451 package_missing_parent, /*test_accept=*/false, /*client_maxfeerate=*/{}); 452 BOOST_CHECK(result_missing_parent.m_state.IsInvalid()); 453 BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetResult(), PackageValidationResult::PCKG_POLICY); 454 BOOST_CHECK_EQUAL(result_missing_parent.m_state.GetRejectReason(), "package-not-child-with-unconfirmed-parents"); 455 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 456 } 457 458 // Submit package with parent + child. 459 { 460 const auto submit_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 461 package_parent_child, /*test_accept=*/false, /*client_maxfeerate=*/{}); 462 expected_pool_size += 2; 463 BOOST_CHECK_MESSAGE(submit_parent_child.m_state.IsValid(), 464 "Package validation unexpectedly failed: " << submit_parent_child.m_state.GetRejectReason()); 465 BOOST_CHECK_EQUAL(submit_parent_child.m_tx_results.size(), package_parent_child.size()); 466 auto it_parent = submit_parent_child.m_tx_results.find(tx_parent->GetWitnessHash()); 467 auto it_child = submit_parent_child.m_tx_results.find(tx_child->GetWitnessHash()); 468 BOOST_CHECK(it_parent != submit_parent_child.m_tx_results.end()); 469 BOOST_CHECK(it_parent->second.m_state.IsValid()); 470 BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_parent))); 471 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1); 472 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash()); 473 BOOST_CHECK(it_child->second.m_effective_feerate == CFeeRate(1 * COIN, GetVirtualTransactionSize(*tx_child))); 474 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1); 475 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash()); 476 477 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 478 } 479 480 // Already-in-mempool transactions should be detected and de-duplicated. 481 { 482 const auto submit_deduped = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 483 package_parent_child, /*test_accept=*/false, /*client_maxfeerate=*/{}); 484 if (auto err_deduped{CheckPackageMempoolAcceptResult(package_parent_child, submit_deduped, /*expect_valid=*/true, m_node.mempool.get())}) { 485 BOOST_ERROR(err_deduped.value()); 486 } else { 487 auto it_parent_deduped = submit_deduped.m_tx_results.find(tx_parent->GetWitnessHash()); 488 auto it_child_deduped = submit_deduped.m_tx_results.find(tx_child->GetWitnessHash()); 489 BOOST_CHECK(it_parent_deduped->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 490 BOOST_CHECK(it_child_deduped->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 491 } 492 493 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 494 } 495 } 496 497 // Tests for packages containing a single transaction 498 BOOST_AUTO_TEST_CASE(package_single_tx) 499 { 500 // Mine blocks to mature coinbases. 501 mineBlocks(3); 502 LOCK(cs_main); 503 auto expected_pool_size{m_node.mempool->size()}; 504 505 const CAmount high_fee{1000}; 506 507 // No unconfirmed parents 508 CKey single_key = GenerateRandomKey(); 509 CScript single_locking_script = GetScriptForDestination(PKHash(single_key.GetPubKey())); 510 auto mtx_single = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 511 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 512 /*output_destination=*/single_locking_script, 513 /*output_amount=*/CAmount(49 * COIN), /*submit=*/false); 514 CTransactionRef tx_single = MakeTransactionRef(mtx_single); 515 Package package_tx_single{tx_single}; 516 const auto result_single_tx = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 517 package_tx_single, /*test_accept=*/false, /*client_maxfeerate=*/{}); 518 expected_pool_size += 1; 519 BOOST_CHECK_MESSAGE(result_single_tx.m_state.IsValid(), 520 "Package validation unexpectedly failed: " << result_single_tx.m_state.ToString()); 521 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 522 523 // Parent and Child. Both submitted by themselves through the ProcessNewPackage interface. 524 CKey parent_key = GenerateRandomKey(); 525 CScript parent_locking_script = GetScriptForDestination(WitnessV0KeyHash(parent_key.GetPubKey())); 526 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[1], /*input_vout=*/0, 527 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 528 /*output_destination=*/parent_locking_script, 529 /*output_amount=*/CAmount(50 * COIN) - high_fee, /*submit=*/false); 530 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 531 Package package_just_parent{tx_parent}; 532 const auto result_just_parent = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_just_parent, /*test_accept=*/false, /*client_maxfeerate=*/{}); 533 if (auto err_parent_child{CheckPackageMempoolAcceptResult(package_just_parent, result_just_parent, /*expect_valid=*/true, nullptr)}) { 534 BOOST_ERROR(err_parent_child.value()); 535 } else { 536 auto it_parent = result_just_parent.m_tx_results.find(tx_parent->GetWitnessHash()); 537 BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(), it_parent->second.m_state.ToString()); 538 BOOST_CHECK(it_parent->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_parent)) == high_fee); 539 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().size(), 1); 540 BOOST_CHECK_EQUAL(it_parent->second.m_wtxids_fee_calculations.value().front(), tx_parent->GetWitnessHash()); 541 } 542 expected_pool_size += 1; 543 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 544 545 CKey child_key = GenerateRandomKey(); 546 CScript child_locking_script = GetScriptForDestination(WitnessV0KeyHash(child_key.GetPubKey())); 547 auto mtx_child = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent, /*input_vout=*/0, 548 /*input_height=*/101, /*input_signing_key=*/parent_key, 549 /*output_destination=*/child_locking_script, 550 /*output_amount=*/CAmount(50 * COIN) - 2 * high_fee, /*submit=*/false); 551 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 552 Package package_just_child{tx_child}; 553 const auto result_just_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_just_child, /*test_accept=*/false, /*client_maxfeerate=*/{}); 554 if (auto err_parent_child{CheckPackageMempoolAcceptResult(package_just_child, result_just_child, /*expect_valid=*/true, nullptr)}) { 555 BOOST_ERROR(err_parent_child.value()); 556 } else { 557 auto it_child = result_just_child.m_tx_results.find(tx_child->GetWitnessHash()); 558 BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(), it_child->second.m_state.ToString()); 559 BOOST_CHECK(it_child->second.m_effective_feerate.value().GetFee(GetVirtualTransactionSize(*tx_child)) == high_fee); 560 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().size(), 1); 561 BOOST_CHECK_EQUAL(it_child->second.m_wtxids_fee_calculations.value().front(), tx_child->GetWitnessHash()); 562 } 563 expected_pool_size += 1; 564 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 565 566 // Too-low fee to RBF tx_single 567 auto mtx_single_low_fee = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 568 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 569 /*output_destination=*/single_locking_script, 570 /*output_amount=*/CAmount(49 * COIN - 1), /*submit=*/false); 571 CTransactionRef tx_single_low_fee = MakeTransactionRef(mtx_single_low_fee); 572 Package package_tx_single_low_fee{tx_single_low_fee}; 573 const auto result_single_tx_low_fee = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 574 package_tx_single_low_fee, /*test_accept=*/false, /*client_maxfeerate=*/{}); 575 576 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 577 578 BOOST_CHECK(!result_single_tx_low_fee.m_state.IsValid()); 579 BOOST_CHECK_EQUAL(result_single_tx_low_fee.m_state.GetResult(), PackageValidationResult::PCKG_TX); 580 auto it_low_fee = result_single_tx_low_fee.m_tx_results.find(tx_single_low_fee->GetWitnessHash()); 581 BOOST_CHECK_EQUAL(it_low_fee->second.m_state.GetResult(), TxValidationResult::TX_RECONSIDERABLE); 582 if (auto err_single{CheckPackageMempoolAcceptResult(package_tx_single_low_fee, result_single_tx_low_fee, /*expect_valid=*/false, m_node.mempool.get())}) { 583 BOOST_ERROR(err_single.value()); 584 } 585 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 586 } 587 588 // Tests for packages containing transactions that have same-txid-different-witness equivalents in 589 // the mempool. 590 BOOST_AUTO_TEST_CASE(package_witness_swap_tests) 591 { 592 // Mine blocks to mature coinbases. 593 mineBlocks(5); 594 MockMempoolMinFee(CFeeRate(5000)); 595 LOCK(cs_main); 596 597 // Transactions with a same-txid-different-witness transaction in the mempool should be ignored, 598 // and the mempool entry's wtxid returned. 599 CScript witnessScript = CScript() << OP_DROP << OP_TRUE; 600 CScript scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); 601 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 602 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 603 /*output_destination=*/scriptPubKey, 604 /*output_amount=*/CAmount(49 * COIN), /*submit=*/false); 605 CTransactionRef ptx_parent = MakeTransactionRef(mtx_parent); 606 607 // Make two children with the same txid but different witnesses. 608 CScriptWitness witness1; 609 witness1.stack.emplace_back(1); 610 witness1.stack.emplace_back(witnessScript.begin(), witnessScript.end()); 611 612 CScriptWitness witness2(witness1); 613 witness2.stack.emplace_back(2); 614 witness2.stack.emplace_back(witnessScript.begin(), witnessScript.end()); 615 616 CKey child_key = GenerateRandomKey(); 617 CScript child_locking_script = GetScriptForDestination(WitnessV0KeyHash(child_key.GetPubKey())); 618 CMutableTransaction mtx_child1; 619 mtx_child1.version = 1; 620 mtx_child1.vin.resize(1); 621 mtx_child1.vin[0].prevout.hash = ptx_parent->GetHash(); 622 mtx_child1.vin[0].prevout.n = 0; 623 mtx_child1.vin[0].scriptSig = CScript(); 624 mtx_child1.vin[0].scriptWitness = witness1; 625 mtx_child1.vout.resize(1); 626 mtx_child1.vout[0].nValue = CAmount(48 * COIN); 627 mtx_child1.vout[0].scriptPubKey = child_locking_script; 628 629 CMutableTransaction mtx_child2{mtx_child1}; 630 mtx_child2.vin[0].scriptWitness = witness2; 631 632 CTransactionRef ptx_child1 = MakeTransactionRef(mtx_child1); 633 CTransactionRef ptx_child2 = MakeTransactionRef(mtx_child2); 634 635 // child1 and child2 have the same txid 636 BOOST_CHECK_EQUAL(ptx_child1->GetHash(), ptx_child2->GetHash()); 637 // child1 and child2 have different wtxids 638 BOOST_CHECK(ptx_child1->GetWitnessHash() != ptx_child2->GetWitnessHash()); 639 // Check that they have different package hashes 640 BOOST_CHECK(GetPackageHash({ptx_parent, ptx_child1}) != GetPackageHash({ptx_parent, ptx_child2})); 641 642 // Try submitting Package1{parent, child1} and Package2{parent, child2} where the children are 643 // same-txid-different-witness. 644 { 645 Package package_parent_child1{ptx_parent, ptx_child1}; 646 const auto submit_witness1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 647 package_parent_child1, /*test_accept=*/false, /*client_maxfeerate=*/{}); 648 if (auto err_witness1{CheckPackageMempoolAcceptResult(package_parent_child1, submit_witness1, /*expect_valid=*/true, m_node.mempool.get())}) { 649 BOOST_ERROR(err_witness1.value()); 650 } 651 652 // Child2 would have been validated individually. 653 Package package_parent_child2{ptx_parent, ptx_child2}; 654 const auto submit_witness2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 655 package_parent_child2, /*test_accept=*/false, /*client_maxfeerate=*/{}); 656 if (auto err_witness2{CheckPackageMempoolAcceptResult(package_parent_child2, submit_witness2, /*expect_valid=*/true, m_node.mempool.get())}) { 657 BOOST_ERROR(err_witness2.value()); 658 } else { 659 auto it_parent2_deduped = submit_witness2.m_tx_results.find(ptx_parent->GetWitnessHash()); 660 auto it_child2 = submit_witness2.m_tx_results.find(ptx_child2->GetWitnessHash()); 661 BOOST_CHECK(it_parent2_deduped->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 662 BOOST_CHECK(it_child2->second.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS); 663 BOOST_CHECK_EQUAL(ptx_child1->GetWitnessHash(), it_child2->second.m_other_wtxid.value()); 664 } 665 666 // Deduplication should work when wtxid != txid. Submit package with the already-in-mempool 667 // transactions again, which should not fail. 668 const auto submit_segwit_dedup = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 669 package_parent_child1, /*test_accept=*/false, /*client_maxfeerate=*/{}); 670 if (auto err_segwit_dedup{CheckPackageMempoolAcceptResult(package_parent_child1, submit_segwit_dedup, /*expect_valid=*/true, m_node.mempool.get())}) { 671 BOOST_ERROR(err_segwit_dedup.value()); 672 } else { 673 auto it_parent_dup = submit_segwit_dedup.m_tx_results.find(ptx_parent->GetWitnessHash()); 674 auto it_child_dup = submit_segwit_dedup.m_tx_results.find(ptx_child1->GetWitnessHash()); 675 BOOST_CHECK(it_parent_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 676 BOOST_CHECK(it_child_dup->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 677 } 678 } 679 680 // Try submitting Package1{child2, grandchild} where child2 is same-txid-different-witness as 681 // the in-mempool transaction, child1. Since child1 exists in the mempool and its outputs are 682 // available, child2 should be ignored and grandchild should be accepted. 683 // 684 // This tests a potential censorship vector in which an attacker broadcasts a competing package 685 // where a parent's witness is mutated. The honest package should be accepted despite the fact 686 // that we don't allow witness replacement. 687 CKey grandchild_key = GenerateRandomKey(); 688 CScript grandchild_locking_script = GetScriptForDestination(WitnessV0KeyHash(grandchild_key.GetPubKey())); 689 auto mtx_grandchild = CreateValidMempoolTransaction(/*input_transaction=*/ptx_child2, /*input_vout=*/0, 690 /*input_height=*/0, /*input_signing_key=*/child_key, 691 /*output_destination=*/grandchild_locking_script, 692 /*output_amount=*/CAmount(47 * COIN), /*submit=*/false); 693 CTransactionRef ptx_grandchild = MakeTransactionRef(mtx_grandchild); 694 // Check that they have different package hashes 695 BOOST_CHECK(GetPackageHash({ptx_child1, ptx_grandchild}) != GetPackageHash({ptx_child2, ptx_grandchild})); 696 // We already submitted child1 above. 697 { 698 Package package_child2_grandchild{ptx_child2, ptx_grandchild}; 699 const auto submit_spend_ignored = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 700 package_child2_grandchild, /*test_accept=*/false, /*client_maxfeerate=*/{}); 701 if (auto err_spend_ignored{CheckPackageMempoolAcceptResult(package_child2_grandchild, submit_spend_ignored, /*expect_valid=*/true, m_node.mempool.get())}) { 702 BOOST_ERROR(err_spend_ignored.value()); 703 } else { 704 auto it_child2_ignored = submit_spend_ignored.m_tx_results.find(ptx_child2->GetWitnessHash()); 705 auto it_grandchild = submit_spend_ignored.m_tx_results.find(ptx_grandchild->GetWitnessHash()); 706 BOOST_CHECK(it_child2_ignored->second.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS); 707 BOOST_CHECK(it_grandchild->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 708 } 709 } 710 711 // A package Package{parent1, parent2, parent3, child} where the parents are a mixture of 712 // identical-tx-in-mempool, same-txid-different-witness-in-mempool, and new transactions. 713 Package package_mixed; 714 715 // Give all the parents anyone-can-spend scripts so we don't have to deal with signing the child. 716 CScript acs_script = CScript() << OP_TRUE; 717 CScript acs_spk = GetScriptForDestination(WitnessV0ScriptHash(acs_script)); 718 CScriptWitness acs_witness; 719 acs_witness.stack.emplace_back(acs_script.begin(), acs_script.end()); 720 721 // parent1 will already be in the mempool 722 auto mtx_parent1 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[1], /*input_vout=*/0, 723 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 724 /*output_destination=*/acs_spk, 725 /*output_amount=*/CAmount(49 * COIN), /*submit=*/true); 726 CTransactionRef ptx_parent1 = MakeTransactionRef(mtx_parent1); 727 package_mixed.push_back(ptx_parent1); 728 729 // parent2 will have a same-txid-different-witness tx already in the mempool 730 CScript grandparent2_script = CScript() << OP_DROP << OP_TRUE; 731 CScript grandparent2_spk = GetScriptForDestination(WitnessV0ScriptHash(grandparent2_script)); 732 CScriptWitness parent2_witness1; 733 parent2_witness1.stack.emplace_back(1); 734 parent2_witness1.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end()); 735 CScriptWitness parent2_witness2; 736 parent2_witness2.stack.emplace_back(2); 737 parent2_witness2.stack.emplace_back(grandparent2_script.begin(), grandparent2_script.end()); 738 739 // Create grandparent2 creating an output with multiple spending paths. Submit to mempool. 740 auto mtx_grandparent2 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[2], /*input_vout=*/0, 741 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 742 /*output_destination=*/grandparent2_spk, 743 /*output_amount=*/CAmount(49 * COIN), /*submit=*/true); 744 CTransactionRef ptx_grandparent2 = MakeTransactionRef(mtx_grandparent2); 745 746 CMutableTransaction mtx_parent2_v1; 747 mtx_parent2_v1.version = 1; 748 mtx_parent2_v1.vin.resize(1); 749 mtx_parent2_v1.vin[0].prevout.hash = ptx_grandparent2->GetHash(); 750 mtx_parent2_v1.vin[0].prevout.n = 0; 751 mtx_parent2_v1.vin[0].scriptSig = CScript(); 752 mtx_parent2_v1.vin[0].scriptWitness = parent2_witness1; 753 mtx_parent2_v1.vout.resize(1); 754 mtx_parent2_v1.vout[0].nValue = CAmount(48 * COIN); 755 mtx_parent2_v1.vout[0].scriptPubKey = acs_spk; 756 757 CMutableTransaction mtx_parent2_v2{mtx_parent2_v1}; 758 mtx_parent2_v2.vin[0].scriptWitness = parent2_witness2; 759 760 CTransactionRef ptx_parent2_v1 = MakeTransactionRef(mtx_parent2_v1); 761 CTransactionRef ptx_parent2_v2 = MakeTransactionRef(mtx_parent2_v2); 762 // Put parent2_v1 in the package, submit parent2_v2 to the mempool. 763 const MempoolAcceptResult parent2_v2_result = m_node.chainman->ProcessTransaction(ptx_parent2_v2); 764 BOOST_CHECK(parent2_v2_result.m_result_type == MempoolAcceptResult::ResultType::VALID); 765 package_mixed.push_back(ptx_parent2_v1); 766 767 // parent3 will be a new transaction. Put a low feerate to make it invalid on its own. 768 auto mtx_parent3 = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[3], /*input_vout=*/0, 769 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 770 /*output_destination=*/acs_spk, 771 /*output_amount=*/CAmount(50 * COIN - low_fee_amt), /*submit=*/false); 772 CTransactionRef ptx_parent3 = MakeTransactionRef(mtx_parent3); 773 package_mixed.push_back(ptx_parent3); 774 BOOST_CHECK(m_node.mempool->GetMinFee().GetFee(GetVirtualTransactionSize(*ptx_parent3)) > low_fee_amt); 775 BOOST_CHECK(m_node.mempool->m_opts.min_relay_feerate.GetFee(GetVirtualTransactionSize(*ptx_parent3)) <= low_fee_amt); 776 777 // child spends parent1, parent2, and parent3 778 CKey mixed_grandchild_key = GenerateRandomKey(); 779 CScript mixed_child_spk = GetScriptForDestination(WitnessV0KeyHash(mixed_grandchild_key.GetPubKey())); 780 781 CMutableTransaction mtx_mixed_child; 782 mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent1->GetHash(), 0)); 783 mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent2_v1->GetHash(), 0)); 784 mtx_mixed_child.vin.emplace_back(COutPoint(ptx_parent3->GetHash(), 0)); 785 mtx_mixed_child.vin[0].scriptWitness = acs_witness; 786 mtx_mixed_child.vin[1].scriptWitness = acs_witness; 787 mtx_mixed_child.vin[2].scriptWitness = acs_witness; 788 mtx_mixed_child.vout.emplace_back((48 + 49 + 50 - 1) * COIN, mixed_child_spk); 789 CTransactionRef ptx_mixed_child = MakeTransactionRef(mtx_mixed_child); 790 package_mixed.push_back(ptx_mixed_child); 791 792 // Submit package: 793 // parent1 should be ignored 794 // parent2_v1 should be ignored (and v2 wtxid returned) 795 // parent3 should be accepted 796 // child should be accepted 797 { 798 const auto mixed_result = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_mixed, false, /*client_maxfeerate=*/{}); 799 if (auto err_mixed{CheckPackageMempoolAcceptResult(package_mixed, mixed_result, /*expect_valid=*/true, m_node.mempool.get())}) { 800 BOOST_ERROR(err_mixed.value()); 801 } else { 802 auto it_parent1 = mixed_result.m_tx_results.find(ptx_parent1->GetWitnessHash()); 803 auto it_parent2 = mixed_result.m_tx_results.find(ptx_parent2_v1->GetWitnessHash()); 804 auto it_parent3 = mixed_result.m_tx_results.find(ptx_parent3->GetWitnessHash()); 805 auto it_child = mixed_result.m_tx_results.find(ptx_mixed_child->GetWitnessHash()); 806 807 BOOST_CHECK(it_parent1->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 808 BOOST_CHECK(it_parent2->second.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS); 809 BOOST_CHECK(it_parent3->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 810 BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 811 BOOST_CHECK_EQUAL(ptx_parent2_v2->GetWitnessHash(), it_parent2->second.m_other_wtxid.value()); 812 813 // package feerate should include parent3 and child. It should not include parent1 or parent2_v1. 814 const CFeeRate expected_feerate(1 * COIN, GetVirtualTransactionSize(*ptx_parent3) + GetVirtualTransactionSize(*ptx_mixed_child)); 815 BOOST_CHECK(it_parent3->second.m_effective_feerate.value() == expected_feerate); 816 BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate); 817 std::vector<Wtxid> expected_wtxids({ptx_parent3->GetWitnessHash(), ptx_mixed_child->GetWitnessHash()}); 818 BOOST_CHECK(it_parent3->second.m_wtxids_fee_calculations.value() == expected_wtxids); 819 BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids); 820 } 821 } 822 } 823 824 BOOST_AUTO_TEST_CASE(package_cpfp_tests) 825 { 826 mineBlocks(5); 827 MockMempoolMinFee(CFeeRate(5000)); 828 LOCK(::cs_main); 829 size_t expected_pool_size = m_node.mempool->size(); 830 CKey child_key = GenerateRandomKey(); 831 CScript parent_spk = GetScriptForDestination(WitnessV0KeyHash(child_key.GetPubKey())); 832 CKey grandchild_key = GenerateRandomKey(); 833 CScript child_spk = GetScriptForDestination(WitnessV0KeyHash(grandchild_key.GetPubKey())); 834 835 // low-fee parent and high-fee child package 836 const CAmount coinbase_value{50 * COIN}; 837 const CAmount parent_value{coinbase_value - low_fee_amt}; 838 const CAmount child_value{parent_value - COIN}; 839 840 Package package_cpfp; 841 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 842 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 843 /*output_destination=*/parent_spk, 844 /*output_amount=*/parent_value, /*submit=*/false); 845 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 846 package_cpfp.push_back(tx_parent); 847 848 auto mtx_child = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent, /*input_vout=*/0, 849 /*input_height=*/101, /*input_signing_key=*/child_key, 850 /*output_destination=*/child_spk, 851 /*output_amount=*/child_value, /*submit=*/false); 852 CTransactionRef tx_child = MakeTransactionRef(mtx_child); 853 package_cpfp.push_back(tx_child); 854 855 // Package feerate is calculated using modified fees, and prioritisetransaction accepts negative 856 // fee deltas. This should be taken into account. De-prioritise the parent transaction 857 // to bring the package feerate to 0. 858 m_node.mempool->PrioritiseTransaction(tx_parent->GetHash(), child_value - coinbase_value); 859 { 860 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 861 const auto submit_cpfp_deprio = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 862 package_cpfp, /*test_accept=*/ false, /*client_maxfeerate=*/{}); 863 if (auto err_cpfp_deprio{CheckPackageMempoolAcceptResult(package_cpfp, submit_cpfp_deprio, /*expect_valid=*/false, m_node.mempool.get())}) { 864 BOOST_ERROR(err_cpfp_deprio.value()); 865 } else { 866 BOOST_CHECK_EQUAL(submit_cpfp_deprio.m_state.GetResult(), PackageValidationResult::PCKG_TX); 867 BOOST_CHECK_EQUAL(submit_cpfp_deprio.m_tx_results.find(tx_parent->GetWitnessHash())->second.m_state.GetResult(), 868 TxValidationResult::TX_MEMPOOL_POLICY); 869 BOOST_CHECK_EQUAL(submit_cpfp_deprio.m_tx_results.find(tx_child->GetWitnessHash())->second.m_state.GetResult(), 870 TxValidationResult::TX_MISSING_INPUTS); 871 BOOST_CHECK(submit_cpfp_deprio.m_tx_results.find(tx_parent->GetWitnessHash())->second.m_state.GetRejectReason() == "min relay fee not met"); 872 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 873 } 874 } 875 876 // Clear the prioritisation of the parent transaction. 877 WITH_LOCK(m_node.mempool->cs, m_node.mempool->ClearPrioritisation(tx_parent->GetHash())); 878 879 // Package CPFP: Even though the parent's feerate is below the mempool minimum feerate, the 880 // child pays enough for the package feerate to meet the threshold. 881 { 882 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 883 const auto submit_cpfp = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 884 package_cpfp, /*test_accept=*/ false, /*client_maxfeerate=*/{}); 885 if (auto err_cpfp{CheckPackageMempoolAcceptResult(package_cpfp, submit_cpfp, /*expect_valid=*/true, m_node.mempool.get())}) { 886 BOOST_ERROR(err_cpfp.value()); 887 } else { 888 auto it_parent = submit_cpfp.m_tx_results.find(tx_parent->GetWitnessHash()); 889 auto it_child = submit_cpfp.m_tx_results.find(tx_child->GetWitnessHash()); 890 BOOST_CHECK(it_parent->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 891 BOOST_CHECK(it_parent->second.m_base_fees.value() == coinbase_value - parent_value); 892 BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 893 BOOST_CHECK(it_child->second.m_base_fees.value() == COIN); 894 895 const CFeeRate expected_feerate(coinbase_value - child_value, 896 GetVirtualTransactionSize(*tx_parent) + GetVirtualTransactionSize(*tx_child)); 897 BOOST_CHECK(it_parent->second.m_effective_feerate.value() == expected_feerate); 898 BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate); 899 std::vector<Wtxid> expected_wtxids({tx_parent->GetWitnessHash(), tx_child->GetWitnessHash()}); 900 BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids); 901 BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids); 902 BOOST_CHECK(expected_feerate.GetFeePerK() > 1000); 903 } 904 expected_pool_size += 2; 905 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 906 } 907 908 // Just because we allow low-fee parents doesn't mean we allow low-feerate packages. 909 // The mempool minimum feerate is 5sat/vB, but this package just pays 800 satoshis total. 910 // The child fees would be able to pay for itself, but isn't enough for the entire package. 911 Package package_still_too_low; 912 const CAmount parent_fee{200}; 913 const CAmount child_fee{600}; 914 auto mtx_parent_cheap = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[1], /*input_vout=*/0, 915 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 916 /*output_destination=*/parent_spk, 917 /*output_amount=*/coinbase_value - parent_fee, /*submit=*/false); 918 CTransactionRef tx_parent_cheap = MakeTransactionRef(mtx_parent_cheap); 919 package_still_too_low.push_back(tx_parent_cheap); 920 BOOST_CHECK(m_node.mempool->GetMinFee().GetFee(GetVirtualTransactionSize(*tx_parent_cheap)) > parent_fee); 921 BOOST_CHECK(m_node.mempool->m_opts.min_relay_feerate.GetFee(GetVirtualTransactionSize(*tx_parent_cheap)) <= parent_fee); 922 923 auto mtx_child_cheap = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent_cheap, /*input_vout=*/0, 924 /*input_height=*/101, /*input_signing_key=*/child_key, 925 /*output_destination=*/child_spk, 926 /*output_amount=*/coinbase_value - parent_fee - child_fee, /*submit=*/false); 927 CTransactionRef tx_child_cheap = MakeTransactionRef(mtx_child_cheap); 928 package_still_too_low.push_back(tx_child_cheap); 929 BOOST_CHECK(m_node.mempool->GetMinFee().GetFee(GetVirtualTransactionSize(*tx_child_cheap)) <= child_fee); 930 BOOST_CHECK(m_node.mempool->GetMinFee().GetFee(GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap)) > parent_fee + child_fee); 931 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 932 933 // Cheap package should fail for being too low fee. 934 { 935 const auto submit_package_too_low = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 936 package_still_too_low, /*test_accept=*/false, /*client_maxfeerate=*/{}); 937 if (auto err_package_too_low{CheckPackageMempoolAcceptResult(package_still_too_low, submit_package_too_low, /*expect_valid=*/false, m_node.mempool.get())}) { 938 BOOST_ERROR(err_package_too_low.value()); 939 } else { 940 // Individual feerate of parent is too low. 941 BOOST_CHECK_EQUAL(submit_package_too_low.m_tx_results.at(tx_parent_cheap->GetWitnessHash()).m_state.GetResult(), 942 TxValidationResult::TX_RECONSIDERABLE); 943 BOOST_CHECK(submit_package_too_low.m_tx_results.at(tx_parent_cheap->GetWitnessHash()).m_effective_feerate.value() == 944 CFeeRate(parent_fee, GetVirtualTransactionSize(*tx_parent_cheap))); 945 // Package feerate of parent + child is too low. 946 BOOST_CHECK_EQUAL(submit_package_too_low.m_tx_results.at(tx_child_cheap->GetWitnessHash()).m_state.GetResult(), 947 TxValidationResult::TX_RECONSIDERABLE); 948 BOOST_CHECK(submit_package_too_low.m_tx_results.at(tx_child_cheap->GetWitnessHash()).m_effective_feerate.value() == 949 CFeeRate(parent_fee + child_fee, GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap))); 950 } 951 BOOST_CHECK_EQUAL(submit_package_too_low.m_state.GetResult(), PackageValidationResult::PCKG_TX); 952 BOOST_CHECK_EQUAL(submit_package_too_low.m_state.GetRejectReason(), "transaction failed"); 953 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 954 } 955 956 // Package feerate includes the modified fees of the transactions. 957 // This means a child with its fee delta from prioritisetransaction can pay for a parent. 958 m_node.mempool->PrioritiseTransaction(tx_child_cheap->GetHash(), 1 * COIN); 959 // Now that the child's fees have "increased" by 1 BTC, the cheap package should succeed. 960 { 961 const auto submit_prioritised_package = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 962 package_still_too_low, /*test_accept=*/false, /*client_maxfeerate=*/{}); 963 if (auto err_prioritised{CheckPackageMempoolAcceptResult(package_still_too_low, submit_prioritised_package, /*expect_valid=*/true, m_node.mempool.get())}) { 964 BOOST_ERROR(err_prioritised.value()); 965 } else { 966 const CFeeRate expected_feerate(1 * COIN + parent_fee + child_fee, 967 GetVirtualTransactionSize(*tx_parent_cheap) + GetVirtualTransactionSize(*tx_child_cheap)); 968 BOOST_CHECK_EQUAL(submit_prioritised_package.m_tx_results.size(), package_still_too_low.size()); 969 auto it_parent = submit_prioritised_package.m_tx_results.find(tx_parent_cheap->GetWitnessHash()); 970 auto it_child = submit_prioritised_package.m_tx_results.find(tx_child_cheap->GetWitnessHash()); 971 BOOST_CHECK(it_parent->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 972 BOOST_CHECK(it_parent->second.m_base_fees.value() == parent_fee); 973 BOOST_CHECK(it_parent->second.m_effective_feerate.value() == expected_feerate); 974 BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 975 BOOST_CHECK(it_child->second.m_base_fees.value() == child_fee); 976 BOOST_CHECK(it_child->second.m_effective_feerate.value() == expected_feerate); 977 std::vector<Wtxid> expected_wtxids({tx_parent_cheap->GetWitnessHash(), tx_child_cheap->GetWitnessHash()}); 978 BOOST_CHECK(it_parent->second.m_wtxids_fee_calculations.value() == expected_wtxids); 979 BOOST_CHECK(it_child->second.m_wtxids_fee_calculations.value() == expected_wtxids); 980 } 981 expected_pool_size += 2; 982 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 983 } 984 985 // Package feerate is calculated without topology in mind; it's just aggregating fees and sizes. 986 // However, this should not allow parents to pay for children. Each transaction should be 987 // validated individually first, eliminating sufficient-feerate parents before they are unfairly 988 // included in the package feerate. It's also important that the low-fee child doesn't prevent 989 // the parent from being accepted. 990 Package package_rich_parent; 991 const CAmount high_parent_fee{1 * COIN}; 992 auto mtx_parent_rich = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[2], /*input_vout=*/0, 993 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 994 /*output_destination=*/parent_spk, 995 /*output_amount=*/coinbase_value - high_parent_fee, /*submit=*/false); 996 CTransactionRef tx_parent_rich = MakeTransactionRef(mtx_parent_rich); 997 package_rich_parent.push_back(tx_parent_rich); 998 999 auto mtx_child_poor = CreateValidMempoolTransaction(/*input_transaction=*/tx_parent_rich, /*input_vout=*/0, 1000 /*input_height=*/101, /*input_signing_key=*/child_key, 1001 /*output_destination=*/child_spk, 1002 /*output_amount=*/coinbase_value - high_parent_fee, /*submit=*/false); 1003 CTransactionRef tx_child_poor = MakeTransactionRef(mtx_child_poor); 1004 package_rich_parent.push_back(tx_child_poor); 1005 1006 // Parent pays 1 BTC and child pays none. The parent should be accepted without the child. 1007 { 1008 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1009 const auto submit_rich_parent = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, 1010 package_rich_parent, /*test_accept=*/false, /*client_maxfeerate=*/{}); 1011 if (auto err_rich_parent{CheckPackageMempoolAcceptResult(package_rich_parent, submit_rich_parent, /*expect_valid=*/false, m_node.mempool.get())}) { 1012 BOOST_ERROR(err_rich_parent.value()); 1013 } else { 1014 // The child would have been validated on its own and failed. 1015 BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetResult(), PackageValidationResult::PCKG_TX); 1016 BOOST_CHECK_EQUAL(submit_rich_parent.m_state.GetRejectReason(), "transaction failed"); 1017 1018 auto it_parent = submit_rich_parent.m_tx_results.find(tx_parent_rich->GetWitnessHash()); 1019 auto it_child = submit_rich_parent.m_tx_results.find(tx_child_poor->GetWitnessHash()); 1020 BOOST_CHECK(it_parent->second.m_result_type == MempoolAcceptResult::ResultType::VALID); 1021 BOOST_CHECK(it_child->second.m_result_type == MempoolAcceptResult::ResultType::INVALID); 1022 BOOST_CHECK(it_parent->second.m_state.GetRejectReason() == ""); 1023 BOOST_CHECK_MESSAGE(it_parent->second.m_base_fees.value() == high_parent_fee, 1024 strprintf("rich parent: expected fee %s, got %s", high_parent_fee, it_parent->second.m_base_fees.value())); 1025 BOOST_CHECK(it_parent->second.m_effective_feerate == CFeeRate(high_parent_fee, GetVirtualTransactionSize(*tx_parent_rich))); 1026 BOOST_CHECK_EQUAL(it_child->second.m_result_type, MempoolAcceptResult::ResultType::INVALID); 1027 BOOST_CHECK_EQUAL(it_child->second.m_state.GetResult(), TxValidationResult::TX_MEMPOOL_POLICY); 1028 BOOST_CHECK(it_child->second.m_state.GetRejectReason() == "min relay fee not met"); 1029 } 1030 expected_pool_size += 1; 1031 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1032 } 1033 } 1034 1035 BOOST_AUTO_TEST_CASE(package_rbf_tests) 1036 { 1037 mineBlocks(5); 1038 LOCK(::cs_main); 1039 size_t expected_pool_size = m_node.mempool->size(); 1040 CKey child_key{GenerateRandomKey()}; 1041 CScript parent_spk = GetScriptForDestination(WitnessV0KeyHash(child_key.GetPubKey())); 1042 CKey grandchild_key{GenerateRandomKey()}; 1043 CScript child_spk = GetScriptForDestination(WitnessV0KeyHash(grandchild_key.GetPubKey())); 1044 1045 const CAmount coinbase_value{50 * COIN}; 1046 // Test that de-duplication works. This is not actually package rbf. 1047 { 1048 // 1 parent paying 200sat, 1 child paying 300sat 1049 Package package1; 1050 // 1 parent paying 200sat, 1 child paying 500sat 1051 Package package2; 1052 // Package1 and package2 have the same parent. The children conflict. 1053 auto mtx_parent = CreateValidMempoolTransaction(/*input_transaction=*/m_coinbase_txns[0], /*input_vout=*/0, 1054 /*input_height=*/0, /*input_signing_key=*/coinbaseKey, 1055 /*output_destination=*/parent_spk, 1056 /*output_amount=*/coinbase_value - low_fee_amt, /*submit=*/false); 1057 CTransactionRef tx_parent = MakeTransactionRef(mtx_parent); 1058 package1.push_back(tx_parent); 1059 package2.push_back(tx_parent); 1060 1061 CTransactionRef tx_child_1 = MakeTransactionRef(CreateValidMempoolTransaction(tx_parent, 0, 101, child_key, child_spk, coinbase_value - low_fee_amt - 300, false)); 1062 package1.push_back(tx_child_1); 1063 CTransactionRef tx_child_2 = MakeTransactionRef(CreateValidMempoolTransaction(tx_parent, 0, 101, child_key, child_spk, coinbase_value - low_fee_amt - 500, false)); 1064 package2.push_back(tx_child_2); 1065 1066 LOCK(m_node.mempool->cs); 1067 const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, /*test_accept=*/false, std::nullopt); 1068 if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) { 1069 BOOST_ERROR(err_1.value()); 1070 } 1071 1072 // Check precise ResultTypes and mempool size. We know it_parent_1 and it_child_1 exist from above call 1073 auto it_parent_1 = submit1.m_tx_results.find(tx_parent->GetWitnessHash()); 1074 auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash()); 1075 BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1076 BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1077 expected_pool_size += 2; 1078 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1079 1080 const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, /*test_accept=*/false, std::nullopt); 1081 if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) { 1082 BOOST_ERROR(err_2.value()); 1083 } 1084 1085 // Check precise ResultTypes and mempool size. We know it_parent_2 and it_child_2 exist from above call 1086 auto it_parent_2 = submit2.m_tx_results.find(tx_parent->GetWitnessHash()); 1087 auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash()); 1088 BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::MEMPOOL_ENTRY); 1089 BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1090 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1091 1092 // child1 has been replaced 1093 BOOST_CHECK(!m_node.mempool->exists(GenTxid::Txid(tx_child_1->GetHash()))); 1094 } 1095 1096 // Test package rbf. 1097 { 1098 CTransactionRef tx_parent_1 = MakeTransactionRef(CreateValidMempoolTransaction( 1099 m_coinbase_txns[1], /*input_vout=*/0, /*input_height=*/0, 1100 coinbaseKey, parent_spk, coinbase_value - 200, /*submit=*/false)); 1101 CTransactionRef tx_child_1 = MakeTransactionRef(CreateValidMempoolTransaction( 1102 tx_parent_1, /*input_vout=*/0, /*input_height=*/101, 1103 child_key, child_spk, coinbase_value - 400, /*submit=*/false)); 1104 1105 CTransactionRef tx_parent_2 = MakeTransactionRef(CreateValidMempoolTransaction( 1106 m_coinbase_txns[1], /*input_vout=*/0, /*input_height=*/0, 1107 coinbaseKey, parent_spk, coinbase_value - 800, /*submit=*/false)); 1108 CTransactionRef tx_child_2 = MakeTransactionRef(CreateValidMempoolTransaction( 1109 tx_parent_2, /*input_vout=*/0, /*input_height=*/101, 1110 child_key, child_spk, coinbase_value - 800 - 200, /*submit=*/false)); 1111 1112 CTransactionRef tx_parent_3 = MakeTransactionRef(CreateValidMempoolTransaction( 1113 m_coinbase_txns[1], /*input_vout=*/0, /*input_height=*/0, 1114 coinbaseKey, parent_spk, coinbase_value - 199, /*submit=*/false)); 1115 CTransactionRef tx_child_3 = MakeTransactionRef(CreateValidMempoolTransaction( 1116 tx_parent_3, /*input_vout=*/0, /*input_height=*/101, 1117 child_key, child_spk, coinbase_value - 199 - 1300, /*submit=*/false)); 1118 1119 // In all packages, the parents conflict with each other 1120 BOOST_CHECK(tx_parent_1->GetHash() != tx_parent_2->GetHash() && tx_parent_2->GetHash() != tx_parent_3->GetHash()); 1121 1122 // 1 parent paying 200sat, 1 child paying 200sat. 1123 Package package1{tx_parent_1, tx_child_1}; 1124 // 1 parent paying 800sat, 1 child paying 200sat. 1125 Package package2{tx_parent_2, tx_child_2}; 1126 // 1 parent paying 199sat, 1 child paying 1300sat. 1127 Package package3{tx_parent_3, tx_child_3}; 1128 1129 const auto submit1 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, false, std::nullopt); 1130 if (auto err_1{CheckPackageMempoolAcceptResult(package1, submit1, /*expect_valid=*/true, m_node.mempool.get())}) { 1131 BOOST_ERROR(err_1.value()); 1132 } 1133 auto it_parent_1 = submit1.m_tx_results.find(tx_parent_1->GetWitnessHash()); 1134 auto it_child_1 = submit1.m_tx_results.find(tx_child_1->GetWitnessHash()); 1135 BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1136 BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1137 expected_pool_size += 2; 1138 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1139 1140 // This replacement is actually not package rbf; the parent carries enough fees 1141 // to replace the entire package on its own. 1142 const auto submit2 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package2, false, std::nullopt); 1143 if (auto err_2{CheckPackageMempoolAcceptResult(package2, submit2, /*expect_valid=*/true, m_node.mempool.get())}) { 1144 BOOST_ERROR(err_2.value()); 1145 } 1146 auto it_parent_2 = submit2.m_tx_results.find(tx_parent_2->GetWitnessHash()); 1147 auto it_child_2 = submit2.m_tx_results.find(tx_child_2->GetWitnessHash()); 1148 BOOST_CHECK_EQUAL(it_parent_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1149 BOOST_CHECK_EQUAL(it_child_2->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1150 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1151 1152 // Package RBF, in which the replacement transaction's child sponsors the fees to meet RBF feerate rules 1153 const auto submit3 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package3, false, std::nullopt); 1154 if (auto err_3{CheckPackageMempoolAcceptResult(package3, submit3, /*expect_valid=*/true, m_node.mempool.get())}) { 1155 BOOST_ERROR(err_3.value()); 1156 } 1157 auto it_parent_3 = submit3.m_tx_results.find(tx_parent_3->GetWitnessHash()); 1158 auto it_child_3 = submit3.m_tx_results.find(tx_child_3->GetWitnessHash()); 1159 BOOST_CHECK_EQUAL(it_parent_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1160 BOOST_CHECK_EQUAL(it_child_3->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1161 1162 // package3 was considered as a package to replace both package2 transactions 1163 BOOST_CHECK(it_parent_3->second.m_replaced_transactions.size() == 2); 1164 BOOST_CHECK(it_child_3->second.m_replaced_transactions.empty()); 1165 1166 std::vector<Wtxid> expected_package3_wtxids({tx_parent_3->GetWitnessHash(), tx_child_3->GetWitnessHash()}); 1167 const auto package3_total_vsize{GetVirtualTransactionSize(*tx_parent_3) + GetVirtualTransactionSize(*tx_child_3)}; 1168 BOOST_CHECK(it_parent_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids); 1169 BOOST_CHECK(it_child_3->second.m_wtxids_fee_calculations.value() == expected_package3_wtxids); 1170 BOOST_CHECK_EQUAL(it_parent_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 199 + 1300); 1171 BOOST_CHECK_EQUAL(it_child_3->second.m_effective_feerate.value().GetFee(package3_total_vsize), 199 + 1300); 1172 1173 BOOST_CHECK_EQUAL(m_node.mempool->size(), expected_pool_size); 1174 1175 // Finally, check that we can prioritise tx_child_1 to get package1 into the mempool. 1176 // It should not be possible to resubmit package1 and get it in without prioritisation. 1177 const auto submit4 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, false, std::nullopt); 1178 if (auto err_4{CheckPackageMempoolAcceptResult(package1, submit4, /*expect_valid=*/false, m_node.mempool.get())}) { 1179 BOOST_ERROR(err_4.value()); 1180 } 1181 m_node.mempool->PrioritiseTransaction(tx_child_1->GetHash(), 1363); 1182 const auto submit5 = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package1, false, std::nullopt); 1183 if (auto err_5{CheckPackageMempoolAcceptResult(package1, submit5, /*expect_valid=*/true, m_node.mempool.get())}) { 1184 BOOST_ERROR(err_5.value()); 1185 } 1186 it_parent_1 = submit5.m_tx_results.find(tx_parent_1->GetWitnessHash()); 1187 it_child_1 = submit5.m_tx_results.find(tx_child_1->GetWitnessHash()); 1188 BOOST_CHECK_EQUAL(it_parent_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1189 BOOST_CHECK_EQUAL(it_child_1->second.m_result_type, MempoolAcceptResult::ResultType::VALID); 1190 LOCK(m_node.mempool->cs); 1191 BOOST_CHECK(m_node.mempool->GetIter(tx_parent_1->GetHash()).has_value()); 1192 BOOST_CHECK(m_node.mempool->GetIter(tx_child_1->GetHash()).has_value()); 1193 } 1194 } 1195 BOOST_AUTO_TEST_SUITE_END()