|
4 | 4 |
|
5 | 5 | #include <consensus/validation.h>
|
6 | 6 | #include <key_io.h>
|
| 7 | +#include <policy/packages.h> |
| 8 | +#include <policy/policy.h> |
7 | 9 | #include <primitives/transaction.h>
|
8 | 10 | #include <script/script.h>
|
9 | 11 | #include <script/standard.h>
|
@@ -49,6 +51,25 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
49 | 51 | BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS);
|
50 | 52 | }
|
51 | 53 |
|
| 54 | +// Create placeholder transactions that have no meaning. |
| 55 | +inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs) |
| 56 | +{ |
| 57 | + CMutableTransaction mtx = CMutableTransaction(); |
| 58 | + mtx.vin.resize(num_inputs); |
| 59 | + mtx.vout.resize(num_outputs); |
| 60 | + auto random_script = CScript() << ToByteVector(InsecureRand256()) << ToByteVector(InsecureRand256()); |
| 61 | + for (size_t i{0}; i < num_inputs; ++i) { |
| 62 | + mtx.vin[i].prevout.hash = InsecureRand256(); |
| 63 | + mtx.vin[i].prevout.n = 0; |
| 64 | + mtx.vin[i].scriptSig = random_script; |
| 65 | + } |
| 66 | + for (size_t o{0}; o < num_outputs; ++o) { |
| 67 | + mtx.vout[o].nValue = 1 * CENT; |
| 68 | + mtx.vout[o].scriptPubKey = random_script; |
| 69 | + } |
| 70 | + return MakeTransactionRef(mtx); |
| 71 | +} |
| 72 | + |
52 | 73 | BOOST_FIXTURE_TEST_CASE(package_tests, TestChain100Setup)
|
53 | 74 | {
|
54 | 75 | LOCK(cs_main);
|
@@ -84,6 +105,43 @@ BOOST_FIXTURE_TEST_CASE(package_tests, TestChain100Setup)
|
84 | 105 | BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
|
85 | 106 | "Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
|
86 | 107 |
|
| 108 | + // Packages can't have more than 25 transactions. |
| 109 | + Package package_too_many; |
| 110 | + package_too_many.reserve(MAX_PACKAGE_COUNT + 1); |
| 111 | + for (size_t i{0}; i < MAX_PACKAGE_COUNT + 1; ++i) { |
| 112 | + package_too_many.emplace_back(create_placeholder_tx(1, 1)); |
| 113 | + } |
| 114 | + auto result_too_many = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_too_many, /* test_accept */ true); |
| 115 | + BOOST_CHECK(result_too_many.m_state.IsInvalid()); |
| 116 | + BOOST_CHECK_EQUAL(result_too_many.m_state.GetResult(), PackageValidationResult::PCKG_POLICY); |
| 117 | + BOOST_CHECK_EQUAL(result_too_many.m_state.GetRejectReason(), "package-too-many-transactions"); |
| 118 | + |
| 119 | + // Packages can't have a total size of more than 101KvB. |
| 120 | + CTransactionRef large_ptx = create_placeholder_tx(150, 150); |
| 121 | + Package package_too_large; |
| 122 | + auto size_large = GetVirtualTransactionSize(*large_ptx); |
| 123 | + size_t total_size{0}; |
| 124 | + while (total_size <= MAX_PACKAGE_SIZE * 1000) { |
| 125 | + package_too_large.push_back(large_ptx); |
| 126 | + total_size += size_large; |
| 127 | + } |
| 128 | + BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT); |
| 129 | + auto result_too_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_too_large, /* test_accept */ true); |
| 130 | + BOOST_CHECK(result_too_large.m_state.IsInvalid()); |
| 131 | + BOOST_CHECK_EQUAL(result_too_large.m_state.GetResult(), PackageValidationResult::PCKG_POLICY); |
| 132 | + BOOST_CHECK_EQUAL(result_too_large.m_state.GetRejectReason(), "package-too-large"); |
| 133 | + |
| 134 | + // A single, giant transaction submitted through ProcessNewPackage fails on single tx policy. |
| 135 | + CTransactionRef giant_ptx = create_placeholder_tx(999, 999); |
| 136 | + BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > MAX_PACKAGE_SIZE * 1000); |
| 137 | + auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {giant_ptx}, /* test_accept */ true); |
| 138 | + BOOST_CHECK(result_single_large.m_state.IsInvalid()); |
| 139 | + BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX); |
| 140 | + BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed"); |
| 141 | + auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetWitnessHash()); |
| 142 | + BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end()); |
| 143 | + BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size"); |
| 144 | + |
87 | 145 | // Check that mempool size hasn't changed.
|
88 | 146 | BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
|
89 | 147 | }
|
|
0 commit comments