Changeset View
Changeset View
Standalone View
Standalone View
src/test/txvalidation_tests.cpp
// Copyright (c) 2017-2019 The Bitcoin Core developers | // Copyright (c) 2017-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <policy/packages.h> | |||||
#include <policy/policy.h> | |||||
#include <primitives/transaction.h> | #include <primitives/transaction.h> | ||||
#include <script/script.h> | #include <script/script.h> | ||||
#include <script/standard.h> | #include <script/standard.h> | ||||
#include <txmempool.h> | #include <txmempool.h> | ||||
#include <validation.h> | #include <validation.h> | ||||
#include <test/util/setup_common.h> | #include <test/util/setup_common.h> | ||||
Show All 32 Lines | BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup) { | ||||
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); | BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); | ||||
// Check that the validation state reflects the unsuccesful attempt. | // Check that the validation state reflects the unsuccesful attempt. | ||||
BOOST_CHECK(result.m_state.IsInvalid()); | BOOST_CHECK(result.m_state.IsInvalid()); | ||||
BOOST_CHECK_EQUAL(result.m_state.GetRejectReason(), "bad-tx-coinbase"); | BOOST_CHECK_EQUAL(result.m_state.GetRejectReason(), "bad-tx-coinbase"); | ||||
BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS); | BOOST_CHECK(result.m_state.GetResult() == TxValidationResult::TX_CONSENSUS); | ||||
} | } | ||||
// 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 = COutPoint(TxId{InsecureRand256()}, 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_tests, TestChain100Setup) { | BOOST_FIXTURE_TEST_CASE(package_tests, TestChain100Setup) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
unsigned int initialPoolSize = m_node.mempool->size(); | unsigned int initialPoolSize = m_node.mempool->size(); | ||||
// Parent and Child Package | // Parent and Child Package | ||||
CKey parent_key; | CKey parent_key; | ||||
parent_key.MakeNewKey(true); | parent_key.MakeNewKey(true); | ||||
CScript parent_locking_script = | CScript parent_locking_script = | ||||
Show All 27 Lines | BOOST_FIXTURE_TEST_CASE(package_tests, TestChain100Setup) { | ||||
BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(), | BOOST_CHECK_MESSAGE(it_parent->second.m_state.IsValid(), | ||||
"Package validation unexpectedly failed: " | "Package validation unexpectedly failed: " | ||||
<< it_parent->second.m_state.GetRejectReason()); | << it_parent->second.m_state.GetRejectReason()); | ||||
BOOST_CHECK(it_child != result_parent_child.m_tx_results.end()); | BOOST_CHECK(it_child != result_parent_child.m_tx_results.end()); | ||||
BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(), | BOOST_CHECK_MESSAGE(it_child->second.m_state.IsValid(), | ||||
"Package validation unexpectedly failed: " | "Package validation unexpectedly failed: " | ||||
<< it_child->second.m_state.GetRejectReason()); | << it_child->second.m_state.GetRejectReason()); | ||||
// Packages can't have more than 50 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)); | |||||
} | |||||
auto result_too_many = ProcessNewPackage( | |||||
GetConfig(), m_node.chainman->ActiveChainstate(), *m_node.mempool, | |||||
package_too_many, /* test_accept */ true); | |||||
BOOST_CHECK(result_too_many.m_state.IsInvalid()); | |||||
BOOST_CHECK_EQUAL(result_too_many.m_state.GetResult(), | |||||
PackageValidationResult::PCKG_POLICY); | |||||
BOOST_CHECK_EQUAL(result_too_many.m_state.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); | |||||
auto result_too_large = ProcessNewPackage( | |||||
GetConfig(), m_node.chainman->ActiveChainstate(), *m_node.mempool, | |||||
package_too_large, /* test_accept */ true); | |||||
BOOST_CHECK(result_too_large.m_state.IsInvalid()); | |||||
BOOST_CHECK_EQUAL(result_too_large.m_state.GetResult(), | |||||
PackageValidationResult::PCKG_POLICY); | |||||
BOOST_CHECK_EQUAL(result_too_large.m_state.GetRejectReason(), | |||||
"package-too-large"); | |||||
// 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(GetConfig(), 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->GetId()); | |||||
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. | // Check that mempool size hasn't changed. | ||||
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); | BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize); | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |