mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-02 11:41:18 +00:00
Makes the test more minimal. We're just trying to test that our package sanitization logic is correct. Now that this code lives in its own function (rather than inside of AcceptMultipleTransactions), there's no need to call ProcessNewPackage to test this.
118 lines
6.0 KiB
C++
118 lines
6.0 KiB
C++
// Copyright (c) 2021 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <consensus/validation.h>
|
|
#include <key_io.h>
|
|
#include <policy/packages.h>
|
|
#include <policy/policy.h>
|
|
#include <primitives/transaction.h>
|
|
#include <script/script.h>
|
|
#include <script/standard.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <validation.h>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
BOOST_AUTO_TEST_SUITE(txpackage_tests)
|
|
|
|
// Create placeholder transactions that have no meaning.
|
|
inline CTransactionRef create_placeholder_tx(size_t num_inputs, size_t num_outputs)
|
|
{
|
|
CMutableTransaction mtx = CMutableTransaction();
|
|
mtx.vin.resize(num_inputs);
|
|
mtx.vout.resize(num_outputs);
|
|
auto random_script = CScript() << ToByteVector(InsecureRand256()) << ToByteVector(InsecureRand256());
|
|
for (size_t i{0}; i < num_inputs; ++i) {
|
|
mtx.vin[i].prevout.hash = InsecureRand256();
|
|
mtx.vin[i].prevout.n = 0;
|
|
mtx.vin[i].scriptSig = random_script;
|
|
}
|
|
for (size_t o{0}; o < num_outputs; ++o) {
|
|
mtx.vout[o].nValue = 1 * CENT;
|
|
mtx.vout[o].scriptPubKey = random_script;
|
|
}
|
|
return MakeTransactionRef(mtx);
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_CASE(package_sanitization_tests, TestChain100Setup)
|
|
{
|
|
// Packages can't have more than 25 transactions.
|
|
Package package_too_many;
|
|
package_too_many.reserve(MAX_PACKAGE_COUNT + 1);
|
|
for (size_t i{0}; i < MAX_PACKAGE_COUNT + 1; ++i) {
|
|
package_too_many.emplace_back(create_placeholder_tx(1, 1));
|
|
}
|
|
PackageValidationState state_too_many;
|
|
BOOST_CHECK(!CheckPackage(package_too_many, state_too_many));
|
|
BOOST_CHECK_EQUAL(state_too_many.GetResult(), PackageValidationResult::PCKG_POLICY);
|
|
BOOST_CHECK_EQUAL(state_too_many.GetRejectReason(), "package-too-many-transactions");
|
|
|
|
// Packages can't have a total size of more than 101KvB.
|
|
CTransactionRef large_ptx = create_placeholder_tx(150, 150);
|
|
Package package_too_large;
|
|
auto size_large = GetVirtualTransactionSize(*large_ptx);
|
|
size_t total_size{0};
|
|
while (total_size <= MAX_PACKAGE_SIZE * 1000) {
|
|
package_too_large.push_back(large_ptx);
|
|
total_size += size_large;
|
|
}
|
|
BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT);
|
|
PackageValidationState state_too_large;
|
|
BOOST_CHECK(!CheckPackage(package_too_large, state_too_large));
|
|
BOOST_CHECK_EQUAL(state_too_large.GetResult(), PackageValidationResult::PCKG_POLICY);
|
|
BOOST_CHECK_EQUAL(state_too_large.GetRejectReason(), "package-too-large");
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
|
|
{
|
|
LOCK(cs_main);
|
|
unsigned int initialPoolSize = m_node.mempool->size();
|
|
|
|
// Parent and Child Package
|
|
CKey parent_key;
|
|
parent_key.MakeNewKey(true);
|
|
CScript parent_locking_script = GetScriptForDestination(PKHash(parent_key.GetPubKey()));
|
|
auto mtx_parent = CreateValidMempoolTransaction(/* input_transaction */ m_coinbase_txns[0], /* vout */ 0,
|
|
/* input_height */ 0, /* input_signing_key */ coinbaseKey,
|
|
/* output_destination */ parent_locking_script,
|
|
/* output_amount */ CAmount(49 * COIN), /* submit */ false);
|
|
CTransactionRef tx_parent = MakeTransactionRef(mtx_parent);
|
|
|
|
CKey child_key;
|
|
child_key.MakeNewKey(true);
|
|
CScript child_locking_script = GetScriptForDestination(PKHash(child_key.GetPubKey()));
|
|
auto mtx_child = CreateValidMempoolTransaction(/* input_transaction */ tx_parent, /* vout */ 0,
|
|
/* input_height */ 101, /* input_signing_key */ parent_key,
|
|
/* output_destination */ child_locking_script,
|
|
/* output_amount */ CAmount(48 * COIN), /* submit */ false);
|
|
CTransactionRef tx_child = MakeTransactionRef(mtx_child);
|
|
const auto result_parent_child = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {tx_parent, tx_child}, /* test_accept */ true);
|
|
BOOST_CHECK_MESSAGE(result_parent_child.m_state.IsValid(),
|
|
"Package validation unexpectedly failed: " << result_parent_child.m_state.GetRejectReason());
|
|
auto it_parent = result_parent_child.m_tx_results.find(tx_parent->GetWitnessHash());
|
|
auto it_child = result_parent_child.m_tx_results.find(tx_child->GetWitnessHash());
|
|
BOOST_CHECK(it_parent != result_parent_child.m_tx_results.end());
|
|
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(),
|
|
"Package validation unexpectedly failed: " << it_parent->second.m_state.GetRejectReason());
|
|
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end());
|
|
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(),
|
|
"Package validation unexpectedly failed: " << it_child->second.m_state.GetRejectReason());
|
|
|
|
|
|
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
|
|
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
|
|
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > MAX_PACKAGE_SIZE * 1000);
|
|
auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {giant_ptx}, /* test_accept */ true);
|
|
BOOST_CHECK(result_single_large.m_state.IsInvalid());
|
|
BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX);
|
|
BOOST_CHECK_EQUAL(result_single_large.m_state.GetRejectReason(), "transaction failed");
|
|
auto it_giant_tx = result_single_large.m_tx_results.find(giant_ptx->GetWitnessHash());
|
|
BOOST_CHECK(it_giant_tx != result_single_large.m_tx_results.end());
|
|
BOOST_CHECK_EQUAL(it_giant_tx->second.m_state.GetRejectReason(), "tx-size");
|
|
|
|
// Check that mempool size hasn't changed.
|
|
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
|
|
}
|
|
BOOST_AUTO_TEST_SUITE_END()
|