Skip to content

Commit 8392d23

Browse files
committed
merge bitcoin#23381: refactoring for package submission
changes involving RBF have been excluded as RBF isn't implemented in Dash Core excluded: - 8fa2936 - 3d3e459
1 parent d3c0059 commit 8392d23

File tree

6 files changed

+219
-144
lines changed

6 files changed

+219
-144
lines changed

src/Makefile.test.include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ BITCOIN_TESTS =\
174174
test/torcontrol_tests.cpp \
175175
test/transaction_tests.cpp \
176176
test/txindex_tests.cpp \
177+
test/txpackage_tests.cpp \
177178
test/txreconciliation_tests.cpp \
178179
test/txvalidation_tests.cpp \
179180
test/txvalidationcache_tests.cpp \

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ static RPCHelpMan testmempoolaccept()
12821282
if (tx_result.m_result_type == MempoolAcceptResult::ResultType::VALID) {
12831283
const CAmount fee = tx_result.m_base_fees.value();
12841284
// Check that fee does not exceed maximum fee
1285-
const int64_t virtual_size = GetVirtualTransactionSize(*tx);
1285+
const int64_t virtual_size = tx_result.m_vsize.value();
12861286
const CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
12871287
if (max_raw_tx_fee && fee > max_raw_tx_fee) {
12881288
result_inner.pushKV("allowed", false);

src/test/txpackage_tests.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright (c) 2021 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 <primitives/transaction.h>
10+
#include <script/script.h>
11+
#include <script/standard.h>
12+
#include <test/util/setup_common.h>
13+
#include <validation.h>
14+
15+
#include <boost/test/unit_test.hpp>
16+
17+
struct TestChain100NoDIP0001Setup : public TestChain100Setup {
18+
TestChain100NoDIP0001Setup()
19+
: TestChain100Setup{{"-testactivationheight=dip0001@2000"}} {}
20+
};
21+
22+
BOOST_AUTO_TEST_SUITE(txpackage_tests)
23+
24+
// Create placeholder transactions that have no meaning.
25+
inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs)
26+
{
27+
CMutableTransaction mtx = CMutableTransaction();
28+
mtx.vin.resize(num_inputs);
29+
mtx.vout.resize(num_outputs);
30+
auto random_script = CScript() << ToByteVector(InsecureRand256()) << ToByteVector(InsecureRand256());
31+
for (size_t i{0}; i < num_inputs; ++i) {
32+
mtx.vin[i].prevout.hash = InsecureRand256();
33+
mtx.vin[i].prevout.n = 0;
34+
mtx.vin[i].scriptSig = random_script;
35+
}
36+
for (size_t o{0}; o < num_outputs; ++o) {
37+
mtx.vout[o].nValue = 1 * CENT;
38+
mtx.vout[o].scriptPubKey = random_script;
39+
}
40+
return MakeTransactionRef(mtx);
41+
}
42+
43+
BOOST_FIXTURE_TEST_CASE(package_sanitization_tests, TestChain100NoDIP0001Setup)
44+
{
45+
// Packages can't have more than 25 transactions.
46+
Package package_too_many;
47+
package_too_many.reserve(MAX_PACKAGE_COUNT + 1);
48+
for (size_t i{0}; i < MAX_PACKAGE_COUNT + 1; ++i) {
49+
package_too_many.emplace_back(create_placeholder_tx(1, 1));
50+
}
51+
PackageValidationState state_too_many;
52+
BOOST_CHECK(!CheckPackage(package_too_many, state_too_many));
53+
BOOST_CHECK_EQUAL(state_too_many.GetResult(), PackageValidationResult::PCKG_POLICY);
54+
BOOST_CHECK_EQUAL(state_too_many.GetRejectReason(), "package-too-many-transactions");
55+
56+
// Packages can't have a total size of more than 101KvB.
57+
CTransactionRef large_ptx = create_placeholder_tx(150, 150);
58+
Package package_too_large;
59+
auto size_large = GetVirtualTransactionSize(*large_ptx);
60+
size_t total_size{0};
61+
while (total_size <= MAX_PACKAGE_SIZE * 1000) {
62+
package_too_large.push_back(large_ptx);
63+
total_size += size_large;
64+
}
65+
BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT);
66+
PackageValidationState state_too_large;
67+
BOOST_CHECK(!CheckPackage(package_too_large, state_too_large));
68+
BOOST_CHECK_EQUAL(state_too_large.GetResult(), PackageValidationResult::PCKG_POLICY);
69+
BOOST_CHECK_EQUAL(state_too_large.GetRejectReason(), "package-too-large");
70+
}
71+
72+
BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100NoDIP0001Setup)
73+
{
74+
LOCK(cs_main);
75+
unsigned int initialPoolSize = m_node.mempool->size();
76+
77+
// Parent and Child Package
78+
CKey parent_key;
79+
parent_key.MakeNewKey(true);
80+
CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey()));
81+
auto mtx_parent = CreateValidMempoolTransaction(/* input_transaction */ m_coinbase_txns[0], /* vout */ 0,
82+
/* input_height */ 0, /* input_signing_key */ coinbaseKey,
83+
/* output_destination */ parent_locking_script,
84+
/* output_amount */ CAmount(49 * COIN), /* submit */ false);
85+
CTransactionRef tx_parent = MakeTransactionRef(mtx_parent);
86+
87+
CKey child_key;
88+
child_key.MakeNewKey(true);
89+
CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey()));
90+
auto mtx_child = CreateValidMempoolTransaction(/* input_transaction */ tx_parent, /* vout */ 0,
91+
/* input_height */ 101, /* input_signing_key */ parent_key,
92+
/* output_destination */ child_locking_script,
93+
/* output_amount */ CAmount(48 * COIN), /* submit */ false);
94+
CTransactionRef tx_child = MakeTransactionRef(mtx_child);
95+
const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {tx_parent, tx_child}, /* test_accept */ true);
96+
BOOST_CHECK_MESSAGE(result_parent_child.m_state.IsValid(),
97+
"Package validation unexpectedly failed: " << result_parent_child.m_state.GetRejectReason());
98+
auto it_parent = result_parent_child.m_tx_results.find(tx_parent->GetHash());
99+
auto it_child = result_parent_child.m_tx_results.find(tx_child->GetHash());
100+
BOOST_CHECK(it_parent != result_parent_child.m_tx_results.end());
101+
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(),
102+
"Package validation unexpectedly failed: " << it_parent->second.m_state.GetRejectReason());
103+
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
104+
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
105+
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
106+
107+
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
108+
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
109+
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > MAX_PACKAGE_SIZE * 1000);
110+
auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {giant_ptx}, /* test_accept */ true);
111+
BOOST_CHECK(result_single_large.m_state.IsInvalid());
112+
BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX);
113+
BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed");
114+
auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetHash());
115+
BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end());
116+
BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size");
117+
118+
// Check that mempool size hasn't changed.
119+
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
120+
}
121+
BOOST_AUTO_TEST_SUITE_END()

src/test/txvalidation_tests.cpp

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -55,99 +55,4 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
5555
BOOST_CHECK_EQUAL(result.m_state.GetRejectReason(), "coinbase");
5656
BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS);
5757
}
58-
59-
// Create placeholder transactions that have no meaning.
60-
inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs)
61-
{
62-
CMutableTransaction mtx = CMutableTransaction();
63-
mtx.vin.resize(num_inputs);
64-
mtx.vout.resize(num_outputs);
65-
auto random_script = CScript() << ToByteVector(InsecureRand256()) << ToByteVector(InsecureRand256());
66-
for (size_t i{0}; i < num_inputs; ++i) {
67-
mtx.vin[i].prevout.hash = InsecureRand256();
68-
mtx.vin[i].prevout.n = 0;
69-
mtx.vin[i].scriptSig = random_script;
70-
}
71-
for (size_t o{0}; o < num_outputs; ++o) {
72-
mtx.vout[o].nValue = 1 * CENT;
73-
mtx.vout[o].scriptPubKey = random_script;
74-
}
75-
return MakeTransactionRef(mtx);
76-
}
77-
78-
BOOST_FIXTURE_TEST_CASE(package_tests, TestChain100NoDIP0001Setup)
79-
{
80-
LOCK(cs_main);
81-
unsigned int initialPoolSize = m_node.mempool->size();
82-
83-
// Parent and Child Package
84-
CKey parent_key;
85-
parent_key.MakeNewKey(true);
86-
CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey()));
87-
auto mtx_parent = CreateValidMempoolTransaction(/* input_transaction */ m_coinbase_txns[0], /* vout */ 0,
88-
/* input_height */ 0, /* input_signing_key */ coinbaseKey,
89-
/* output_destination */ parent_locking_script,
90-
/* output_amount */ CAmount(49 * COIN), /* submit */ false);
91-
CTransactionRef tx_parent = MakeTransactionRef(mtx_parent);
92-
93-
CKey child_key;
94-
child_key.MakeNewKey(true);
95-
CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey()));
96-
auto mtx_child = CreateValidMempoolTransaction(/* input_transaction */ tx_parent, /* vout */ 0,
97-
/* input_height */ 101, /* input_signing_key */ parent_key,
98-
/* output_destination */ child_locking_script,
99-
/* output_amount */ CAmount(48 * COIN), /* submit */ false);
100-
CTransactionRef tx_child = MakeTransactionRef(mtx_child);
101-
const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {tx_parent, tx_child}, /* test_accept */ true);
102-
BOOST_CHECK_MESSAGE(result_parent_child.m_state.IsValid(),
103-
"Package validation unexpectedly failed: " << result_parent_child.m_state.GetRejectReason());
104-
auto it_parent = result_parent_child.m_tx_results.find(tx_parent->GetHash());
105-
auto it_child = result_parent_child.m_tx_results.find(tx_child->GetHash());
106-
BOOST_CHECK(it_parent != result_parent_child.m_tx_results.end());
107-
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(),
108-
"Package validation unexpectedly failed: " << it_parent->second.m_state.GetRejectReason());
109-
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
110-
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
111-
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
112-
113-
// Packages can't have more than 25 transactions.
114-
Package package_too_many;
115-
package_too_many.reserve(MAX_PACKAGE_COUNT + 1);
116-
for (size_t i{0}; i < MAX_PACKAGE_COUNT + 1; ++i) {
117-
package_too_many.emplace_back(create_placeholder_tx(1, 1));
118-
}
119-
auto result_too_many = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_too_many, /* test_accept */ true);
120-
BOOST_CHECK(result_too_many.m_state.IsInvalid());
121-
BOOST_CHECK_EQUAL(result_too_many.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
122-
BOOST_CHECK_EQUAL(result_too_many.m_state.GetRejectReason(), "package-too-many-transactions");
123-
124-
// Packages can't have a total size of more than 101KvB.
125-
CTransactionRef large_ptx = create_placeholder_tx(150, 150);
126-
Package package_too_large;
127-
auto size_large = GetVirtualTransactionSize(*large_ptx);
128-
size_t total_size{0};
129-
while (total_size <= MAX_PACKAGE_SIZE * 1000) {
130-
package_too_large.push_back(large_ptx);
131-
total_size += size_large;
132-
}
133-
BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT);
134-
auto result_too_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, package_too_large, /* test_accept */ true);
135-
BOOST_CHECK(result_too_large.m_state.IsInvalid());
136-
BOOST_CHECK_EQUAL(result_too_large.m_state.GetResult(), PackageValidationResult::PCKG_POLICY);
137-
BOOST_CHECK_EQUAL(result_too_large.m_state.GetRejectReason(), "package-too-large");
138-
139-
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
140-
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
141-
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > MAX_PACKAGE_SIZE * 1000);
142-
auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {giant_ptx}, /* test_accept */ true);
143-
BOOST_CHECK(result_single_large.m_state.IsInvalid());
144-
BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX);
145-
BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed");
146-
auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetHash());
147-
BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end());
148-
BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size");
149-
150-
// Check that mempool size hasn't changed.
151-
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
152-
}
15358
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)