From de669a883bf65c576cc596b20a576d7bb1618182 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 17 Jun 2024 13:49:01 -0400 Subject: [PATCH 1/4] doc: replace mention of V3 with TRUC --- doc/policy/packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/policy/packages.md b/doc/policy/packages.md index a220bdd17fa2f..e8295ed4d7da1 100644 --- a/doc/policy/packages.md +++ b/doc/policy/packages.md @@ -56,7 +56,7 @@ The following rules are enforced for all packages: - *Rationale*: Basic support for package RBF can be used by wallets by making chains of no longer than two, then directly conflicting - those chains when needed. Combined with V3 transactions this can + those chains when needed. Combined with TRUC transactions this can result in more robust fee bumping. More general package RBF may be enabled in the future. From ff4558d441f377a372647972d35b5476b94579c9 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 17 Jun 2024 13:50:23 -0400 Subject: [PATCH 2/4] doc: reword package RBF documentation --- doc/policy/packages.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/policy/packages.md b/doc/policy/packages.md index e8295ed4d7da1..9b321799f1595 100644 --- a/doc/policy/packages.md +++ b/doc/policy/packages.md @@ -38,11 +38,11 @@ The following rules are enforced for all packages: * Only limited package replacements are currently considered. (#28984) - - All direct conflicts must signal replacement (or have `-mempoolfullrbf=1` set). + - All direct conflicts must signal replacement (or the node must have `-mempoolfullrbf=1` set). - Packages are 1-parent-1-child, with no in-mempool ancestors of the package. - - All conflicting clusters(connected components of mempool transactions) must be clusters of up to size 2. + - All conflicting clusters (connected components of mempool transactions) must be clusters of up to size 2. - No more than MAX_REPLACEMENT_CANDIDATES transactions can be replaced, analogous to regular [replacement rule](./mempool-replacements.md) 5). From ad7f1f697f01845470f8df0944a94012fabcba09 Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 17 Jun 2024 14:32:28 -0400 Subject: [PATCH 3/4] test package rbf boundary conditions more closely --- test/functional/mempool_package_rbf.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/functional/mempool_package_rbf.py b/test/functional/mempool_package_rbf.py index ceb9530394129..bf3066f1ebc42 100755 --- a/test/functional/mempool_package_rbf.py +++ b/test/functional/mempool_package_rbf.py @@ -168,11 +168,20 @@ def test_package_rbf_additional_fees(self): self.assert_mempool_contents(expected=package_txns1) self.log.info("Check replacement pays for incremental bandwidth") - package_hex3, package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE) - pkg_results3 = node.submitpackage(package_hex3) - assert_equal(f"package RBF failed: insufficient anti-DoS fees, rejecting replacement {package_txns3[1].rehash()}, not enough additional fees to relay; 0.00 < 0.00000{sum([tx.get_vsize() for tx in package_txns3])}", pkg_results3["package_msg"]) - + _, placeholder_txns3 = self.create_simple_package(coin) + package_3_size = sum([tx.get_vsize() for tx in placeholder_txns3]) + incremental_sats_required = Decimal(package_3_size) / COIN + incremental_sats_short = incremental_sats_required - Decimal("0.00000001") + # Recreate the package with slightly higher fee once we know the size of the new package, but still short of required fee + failure_package_hex3, failure_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_short) + assert_equal(package_3_size, sum([tx.get_vsize() for tx in failure_package_txns3])) + pkg_results3 = node.submitpackage(failure_package_hex3) + assert_equal(f"package RBF failed: insufficient anti-DoS fees, rejecting replacement {failure_package_txns3[1].rehash()}, not enough additional fees to relay; {incremental_sats_short} < {incremental_sats_required}", pkg_results3["package_msg"]) self.assert_mempool_contents(expected=package_txns1) + + success_package_hex3, success_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_required) + node.submitpackage(success_package_hex3) + self.assert_mempool_contents(expected=success_package_txns3) self.generate(node, 1) self.log.info("Check Package RBF must have strict cpfp structure") @@ -180,11 +189,14 @@ def test_package_rbf_additional_fees(self): package_hex4, package_txns4 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE) node.submitpackage(package_hex4) self.assert_mempool_contents(expected=package_txns4) - package_hex5, package_txns5 = self.create_simple_package(coin, parent_fee=DEFAULT_CHILD_FEE, child_fee=DEFAULT_CHILD_FEE - Decimal("0.00000001")) + package_hex5, package_txns5 = self.create_simple_package(coin, parent_fee=DEFAULT_CHILD_FEE, child_fee=DEFAULT_CHILD_FEE) pkg_results5 = node.submitpackage(package_hex5) assert 'package RBF failed: package feerate is less than parent feerate' in pkg_results5["package_msg"] - self.assert_mempool_contents(expected=package_txns4) + + package_hex5_1, package_txns5_1 = self.create_simple_package(coin, parent_fee=DEFAULT_CHILD_FEE, child_fee=DEFAULT_CHILD_FEE + Decimal("0.00000001")) + node.submitpackage(package_hex5_1) + self.assert_mempool_contents(expected=package_txns5_1) self.generate(node, 1) def test_package_rbf_max_conflicts(self): From 3f00aae14092ca076cff7f9ddf6155c601979fcd Mon Sep 17 00:00:00 2001 From: Greg Sanders Date: Mon, 17 Jun 2024 14:35:22 -0400 Subject: [PATCH 4/4] package rbf: cpfp structure requires package > parent feerate --- src/validation.cpp | 2 +- test/functional/mempool_package_rbf.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index c34d60f137246..b38b47bdc772e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1201,7 +1201,7 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector& txn const CFeeRate package_feerate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize); if (package_feerate <= parent_feerate) { return package_state.Invalid(PackageValidationResult::PCKG_POLICY, - "package RBF failed: package feerate is less than parent feerate", + "package RBF failed: package feerate is less than or equal to parent feerate", strprintf("package feerate %s <= parent feerate is %s", package_feerate.ToString(), parent_feerate.ToString())); } diff --git a/test/functional/mempool_package_rbf.py b/test/functional/mempool_package_rbf.py index bf3066f1ebc42..e9658aa8d02c0 100755 --- a/test/functional/mempool_package_rbf.py +++ b/test/functional/mempool_package_rbf.py @@ -191,7 +191,7 @@ def test_package_rbf_additional_fees(self): self.assert_mempool_contents(expected=package_txns4) package_hex5, package_txns5 = self.create_simple_package(coin, parent_fee=DEFAULT_CHILD_FEE, child_fee=DEFAULT_CHILD_FEE) pkg_results5 = node.submitpackage(package_hex5) - assert 'package RBF failed: package feerate is less than parent feerate' in pkg_results5["package_msg"] + assert 'package RBF failed: package feerate is less than or equal to parent feerate' in pkg_results5["package_msg"] self.assert_mempool_contents(expected=package_txns4) package_hex5_1, package_txns5_1 = self.create_simple_package(coin, parent_fee=DEFAULT_CHILD_FEE, child_fee=DEFAULT_CHILD_FEE + Decimal("0.00000001"))