Bitcoin Core  29.1.0
P2P Digital Currency
txpackage_tests.cpp
Go to the documentation of this file.
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 
30 // Create placeholder transactions that have no meaning.
31 inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs)
32 {
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 
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);
60 
61  // Random real nonsegwit transaction
62  DataStream stream_2{
63  "01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e2754dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d9032a7b9d64fa43188ac00000000"_hex,
64  };
65  CTransaction tx_2(deserialize, TX_WITH_WITNESS, stream_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);
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));
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));
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));
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);
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 
277  BOOST_CHECK(IsWellFormedPackage({tx_parent, tx_child}, state, /*require_sorted=*/true));
278  BOOST_CHECK(!IsWellFormedPackage({tx_child, tx_parent}, state, /*require_sorted=*/true));
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}));
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 
311  BOOST_CHECK(IsWellFormedPackage(package, state, /*require_sorted=*/true));
314 
315  package.erase(package.begin());
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 
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));
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);
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(),
869  BOOST_CHECK_EQUAL(submit_cpfp_deprio.m_tx_results.find(tx_child->GetWitnessHash())->second.m_state.GetResult(),
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(),
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(),
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 }
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:423
uint256 GetPackageHash(const std::vector< CTransactionRef > &transactions)
Get the hash of the concatenated wtxids of transactions, with wtxids treated as a little-endian numbe...
Definition: packages.cpp:151
The package itself is invalid (e.g. too many transactions).
Valid, transaction was already in the mempool.
bool IsChildWithParents(const Package &package)
Context-free check that a package is exactly one child and its parents; not all parents need to be pr...
Definition: packages.cpp:119
bool IsTopoSortedPackage(const Package &txns, std::unordered_set< uint256, SaltedTxidHasher > &later_txids)
IsTopoSortedPackage where a set of txids has been pre-populated.
Definition: packages.cpp:19
node::NodeContext m_node
Definition: bitcoin-gui.cpp:42
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:182
std::vector< CTxIn > vin
Definition: transaction.h:379
static const CScript P2WSH_OP_TRUE
Definition: script.h:12
std::vector< CTransactionRef > Package
A package is an ordered list of transactions.
Definition: packages.h:50
transaction was missing some of its inputs
constexpr deserialize_type deserialize
Definition: serialize.h:49
std::vector< std::vector< unsigned char > > stack
Definition: script.h:588
bool IsChildWithParentsTree(const Package &package)
Context-free check that a package IsChildWithParents() and none of the parents depend on each other (...
Definition: packages.cpp:136
violated mempool&#39;s fee/size/descendant/RBF/etc limits
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
Compute the virtual transaction size (weight reinterpreted as bytes).
Definition: policy.cpp:347
const ResultType m_result_type
Result type.
Definition: validation.h:132
std::map< Wtxid, MempoolAcceptResult > m_tx_results
Map from wtxid to finished MempoolAcceptResults.
Definition: validation.h:237
static int32_t GetTransactionWeight(const CTransaction &tx)
Definition: validation.h:133
std::unique_ptr< CTxMemPool > mempool
Definition: context.h:68
static constexpr unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT_KVB
Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors.
Definition: policy.h:70
CKey GenerateRandomKey(bool compressed) noexcept
Definition: key.cpp:352
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
iterator end()
Definition: prevector.h:304
Definition: script.h:84
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
#define LOCK(cs)
Definition: sync.h:257
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:100
Fast randomness source.
Definition: random.h:376
BOOST_AUTO_TEST_SUITE_END()
Result GetResult() const
Definition: validation.h:109
""_hex is a compile-time user-defined literal returning a std::array<std::byte>, equivalent to ParseH...
Definition: strencodings.h:427
std::optional< std::string > CheckPackageMempoolAcceptResult(const Package &txns, const PackageMempoolAcceptResult &result, bool expect_valid, const CTxMemPool *mempool)
Check expected properties for every PackageMempoolAcceptResult, regardless of value.
Definition: txmempool.cpp:43
At least one tx is invalid.
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
Definition: setup_common.h:140
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:28
std::vector< CTxOut > vout
Definition: transaction.h:380
fails some policy, but might be acceptable if submitted in a (different) package
Validation result for a transaction evaluated by MemPoolAccept (single or package).
Definition: validation.h:123
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:424
std::vector< unsigned char > ToByteVector(const T &in)
Definition: script.h:67
256-bit opaque blob.
Definition: uint256.h:201
bool IsWellFormedPackage(const Package &txns, PackageValidationState &state, bool require_sorted)
Context-free package policy checks:
Definition: packages.cpp:79
BOOST_AUTO_TEST_CASE(package_hash_tests)
const CAmount high_fee
static const CAmount low_fee_amt
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:414
static transaction_identifier FromUint256(const uint256 &id)
PackageMempoolAcceptResult ProcessNewPackage(Chainstate &active_chainstate, CTxMemPool &pool, const Package &package, bool test_accept, const std::optional< CFeeRate > &client_maxfeerate)
Validate (and maybe submit) a package to the mempool.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
Definition: feerate.h:32
iterator begin()
Definition: prevector.h:302
A mutable version of CTransaction.
Definition: transaction.h:377
static constexpr CAmount CENT
Definition: setup_common.h:47
static constexpr uint32_t MAX_PACKAGE_COUNT
Default maximum number of transactions in a package.
Definition: packages.h:19
An encapsulated private key.
Definition: key.h:34
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:295
std::string GetRejectReason() const
Definition: validation.h:110
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: cs_main.cpp:8
bool IsConsistentPackage(const Package &txns)
Checks that these transactions don&#39;t conflict, i.e., spend the same prevout.
Definition: packages.cpp:52
CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs)
static std::optional< transaction_identifier > FromHex(std::string_view hex)
std::unique_ptr< ChainstateManager > chainman
Definition: context.h:72
static GenTxid Txid(const uint256 &hash)
Definition: transaction.h:434
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
Definition: transaction.h:344
const Txid & GetHash() const LIFETIMEBOUND
Definition: transaction.h:343
static constexpr TransactionSerParams TX_WITH_WITNESS
Definition: transaction.h:195
#define BOOST_CHECK(expr)
Definition: object.cpp:17
static constexpr uint32_t MAX_PACKAGE_WEIGHT
Default maximum total weight of transactions in a package in weight to allow for context-less checks...
Definition: packages.h:24
transaction_identifier represents the two canonical transaction identifier types (txid, wtxid).
static constexpr CAmount COIN
The amount of satoshis in one BTC.
Definition: amount.h:15