Skip to content

Commit 533660c

Browse files
committed
Replace MAX_PACKAGE_SIZE with MAX_PACKAGE_WEIGHT to avoid vbyte confusion
While allowing submitted packages to be slightly larger than what may be allowed in the mempool to allow simpler reasoning about contextual-less checks vs chain limits.
1 parent 3966b0a commit 533660c

File tree

4 files changed

+29
-22
lines changed

4 files changed

+29
-22
lines changed

doc/policy/packages.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,19 @@ tip or some preceding transaction in the package.
1818

1919
The following rules are enforced for all packages:
2020

21-
* Packages cannot exceed `MAX_PACKAGE_COUNT=25` count and `MAX_PACKAGE_SIZE=101KvB` total size
21+
* Packages cannot exceed `MAX_PACKAGE_COUNT=25` count and `MAX_PACKAGE_WEIGHT=404000` total weight
2222
(#20833)
2323

24-
- *Rationale*: This is already enforced as mempool ancestor/descendant limits. If
25-
transactions in a package are all related, exceeding this limit would mean that the package
26-
can either be split up or it wouldn't pass individual mempool policy.
24+
- *Rationale*: We want package size to be as small as possible to mitigate DoS via package
25+
validation. However, we want to make sure that the limit does not restrict ancestor
26+
packages that would be allowed if submitted individually.
2727

2828
- Note that, if these mempool limits change, package limits should be reconsidered. Users may
2929
also configure their mempool limits differently.
3030

31+
- Note that the this is transaction weight, not "virtual" size as with other limits to allow
32+
simpler context-less checks.
33+
3134
* Packages must be topologically sorted. (#20833)
3235

3336
* Packages cannot have conflicting transactions, i.e. no two transactions in a package can spend

src/policy/packages.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ bool CheckPackage(const Package& txns, PackageValidationState& state)
2323
return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-many-transactions");
2424
}
2525

26-
const int64_t total_size = std::accumulate(txns.cbegin(), txns.cend(), 0,
27-
[](int64_t sum, const auto& tx) { return sum + GetVirtualTransactionSize(*tx); });
28-
// If the package only contains 1 tx, it's better to report the policy violation on individual tx size.
29-
if (package_count > 1 && total_size > MAX_PACKAGE_SIZE * 1000) {
26+
const int64_t total_weight = std::accumulate(txns.cbegin(), txns.cend(), 0,
27+
[](int64_t sum, const auto& tx) { return sum + GetTransactionWeight(*tx); });
28+
// If the package only contains 1 tx, it's better to report the policy violation on individual tx weight.
29+
if (package_count > 1 && total_weight > MAX_PACKAGE_WEIGHT) {
3030
return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-large");
3131
}
3232

src/policy/packages.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,22 @@
1515

1616
/** Default maximum number of transactions in a package. */
1717
static constexpr uint32_t MAX_PACKAGE_COUNT{25};
18-
/** Default maximum total virtual size of transactions in a package in KvB. */
19-
static constexpr uint32_t MAX_PACKAGE_SIZE{101};
20-
static_assert(MAX_PACKAGE_SIZE * WITNESS_SCALE_FACTOR * 1000 >= MAX_STANDARD_TX_WEIGHT);
18+
/** Default maximum total weight of transactions in a package in weight
19+
to allow for context-less checks. This must allow a superset of sigops
20+
weighted vsize limited transactions to not disallow transactions we would
21+
have otherwise accepted individually. */
22+
static constexpr uint32_t MAX_PACKAGE_WEIGHT = 404'000;
23+
static_assert(MAX_PACKAGE_WEIGHT >= MAX_STANDARD_TX_WEIGHT);
2124

22-
// If a package is submitted, it must be within the mempool's ancestor/descendant limits. Since a
23-
// submitted package must be child-with-unconfirmed-parents (all of the transactions are an ancestor
25+
// If a package is to be evaluated, it must be at least as large as the mempool's ancestor/descendant limits,
26+
// otherwise transactions that would be individually accepted may be rejected in a package erroneously.
27+
// Since a submitted package must be child-with-unconfirmed-parents (all of the transactions are an ancestor
2428
// of the child), package limits are ultimately bounded by mempool package limits. Ensure that the
2529
// defaults reflect this constraint.
2630
static_assert(DEFAULT_DESCENDANT_LIMIT >= MAX_PACKAGE_COUNT);
2731
static_assert(DEFAULT_ANCESTOR_LIMIT >= MAX_PACKAGE_COUNT);
28-
static_assert(DEFAULT_ANCESTOR_SIZE_LIMIT_KVB >= MAX_PACKAGE_SIZE);
29-
static_assert(DEFAULT_DESCENDANT_SIZE_LIMIT_KVB >= MAX_PACKAGE_SIZE);
32+
static_assert(MAX_PACKAGE_WEIGHT >= DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * WITNESS_SCALE_FACTOR * 1000);
33+
static_assert(MAX_PACKAGE_WEIGHT >= DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * WITNESS_SCALE_FACTOR * 1000);
3034

3135
/** A "reason" why a package was invalid. It may be that one or more of the included
3236
* transactions is invalid or the package itself violates our rules.
@@ -47,7 +51,7 @@ class PackageValidationState : public ValidationState<PackageValidationResult> {
4751

4852
/** Context-free package policy checks:
4953
* 1. The number of transactions cannot exceed MAX_PACKAGE_COUNT.
50-
* 2. The total virtual size cannot exceed MAX_PACKAGE_SIZE.
54+
* 2. The total weight cannot exceed MAX_PACKAGE_WEIGHT.
5155
* 3. If any dependencies exist between transactions, parents must appear before children.
5256
* 4. Transactions cannot conflict, i.e., spend the same inputs.
5357
*/

src/test/txpackage_tests.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ BOOST_FIXTURE_TEST_CASE(package_sanitization_tests, TestChain100Setup)
5151
BOOST_CHECK_EQUAL(state_too_many.GetResult(), PackageValidationResult::PCKG_POLICY);
5252
BOOST_CHECK_EQUAL(state_too_many.GetRejectReason(), "package-too-many-transactions");
5353

54-
// Packages can't have a total size of more than 101KvB.
54+
// Packages can't have a total weight of more than 404'000WU.
5555
CTransactionRef large_ptx = create_placeholder_tx(150, 150);
5656
Package package_too_large;
57-
auto size_large = GetVirtualTransactionSize(*large_ptx);
58-
size_t total_size{0};
59-
while (total_size <= MAX_PACKAGE_SIZE * 1000) {
57+
auto size_large = GetTransactionWeight(*large_ptx);
58+
size_t total_weight{0};
59+
while (total_weight <= MAX_PACKAGE_WEIGHT) {
6060
package_too_large.push_back(large_ptx);
61-
total_size += size_large;
61+
total_weight += size_large;
6262
}
6363
BOOST_CHECK(package_too_large.size() <= MAX_PACKAGE_COUNT);
6464
PackageValidationState state_too_large;
@@ -122,7 +122,7 @@ BOOST_FIXTURE_TEST_CASE(package_validation_tests, TestChain100Setup)
122122

123123
// A single, giant transaction submitted through ProcessNewPackage fails on single tx policy.
124124
CTransactionRef giant_ptx = create_placeholder_tx(999, 999);
125-
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > MAX_PACKAGE_SIZE * 1000);
125+
BOOST_CHECK(GetVirtualTransactionSize(*giant_ptx) > DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1000);
126126
auto result_single_large = ProcessNewPackage(m_node.chainman->ActiveChainstate(), *m_node.mempool, {giant_ptx}, /*test_accept=*/true);
127127
BOOST_CHECK(result_single_large.m_state.IsInvalid());
128128
BOOST_CHECK_EQUAL(result_single_large.m_state.GetResult(), PackageValidationResult::PCKG_TX);

0 commit comments

Comments
 (0)