Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711346
D12124.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Subscribers
None
D12124.id.diff
View Options
diff --git a/src/policy/packages.h b/src/policy/packages.h
--- a/src/policy/packages.h
+++ b/src/policy/packages.h
@@ -6,10 +6,17 @@
#define BITCOIN_POLICY_PACKAGES_H
#include <consensus/validation.h>
+#include <policy/policy.h>
#include <primitives/transaction.h>
#include <vector>
+/** Default maximum number of transactions in a package. */
+static constexpr uint32_t MAX_PACKAGE_COUNT{50};
+/** Default maximum total size of transactions in a package in KB. */
+static constexpr uint32_t MAX_PACKAGE_SIZE{101};
+static_assert(MAX_PACKAGE_SIZE * 1000 >= MAX_STANDARD_TX_SIZE);
+
/**
* A "reason" why a package was invalid. It may be that one or more of the
* included transactions is invalid or the package itself violates our rules.
diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
--- a/src/test/txvalidation_tests.cpp
+++ b/src/test/txvalidation_tests.cpp
@@ -5,6 +5,8 @@
#include <config.h>
#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>
@@ -53,6 +55,25 @@
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) {
LOCK(cs_main);
unsigned int initialPoolSize = m_node.mempool->size();
@@ -96,6 +117,58 @@
"Package validation unexpectedly failed: "
<< 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.
BOOST_CHECK_EQUAL(m_node.mempool->size(), initialPoolSize);
}
diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -737,6 +737,26 @@
PackageValidationState package_state;
const size_t package_count = txns.size();
+ // These context-free package limits can be checked before taking the
+ // mempool lock.
+ if (package_count > MAX_PACKAGE_COUNT) {
+ package_state.Invalid(PackageValidationResult::PCKG_POLICY,
+ "package-too-many-transactions");
+ return PackageMempoolAcceptResult(package_state, {});
+ }
+
+ const int64_t total_size = std::accumulate(
+ txns.cbegin(), txns.cend(), 0, [](int64_t sum, const auto &tx) {
+ return sum + GetVirtualTransactionSize(*tx);
+ });
+ // If the package only contains 1 tx, it's better to report the policy
+ // violation on individual tx size.
+ if (package_count > 1 && total_size > MAX_PACKAGE_SIZE * 1000) {
+ package_state.Invalid(PackageValidationResult::PCKG_POLICY,
+ "package-too-large");
+ return PackageMempoolAcceptResult(package_state, {});
+ }
+
std::vector<Workspace> workspaces{};
workspaces.reserve(package_count);
std::transform(txns.cbegin(), txns.cend(), std::back_inserter(workspaces),
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 26, 11:45 (16 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5564808
Default Alt Text
D12124.id.diff (6 KB)
Attached To
D12124: [policy] limit package sizes
Event Timeline
Log In to Comment