From 8e49477e86b3089ea70d1f2659b9fd3a8a1f7db4 Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Tue, 3 Oct 2023 15:00:00 -0400 Subject: [PATCH] wallet: Replace max descendant count with cluster_count With the descendant size limits removed, replace the concept of "max number of descendants of any ancestor of a given tx" with the cluster count of the cluster that the transaction belongs to. --- src/node/interfaces.cpp | 6 +- src/test/mempool_tests.cpp | 124 ++++++++++++++++++------------------- src/txmempool.cpp | 6 +- src/txmempool.h | 4 +- 4 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index c3e57291794..65997267652 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -678,11 +678,11 @@ public: // that Chain clients do not need to know about. return TransactionError::OK == err; } - void getTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize, CAmount* ancestorfees) override + void getTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& cluster_count, size_t* ancestorsize, CAmount* ancestorfees) override { - ancestors = descendants = 0; + ancestors = cluster_count = 0; if (!m_node.mempool) return; - m_node.mempool->GetTransactionAncestry(txid, ancestors, descendants, ancestorsize, ancestorfees); + m_node.mempool->GetTransactionAncestry(txid, ancestors, cluster_count, ancestorsize, ancestorfees); } std::map calculateIndividualBumpFees(const std::vector& outpoints, const CFeeRate& target_feerate) override diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 2271e7b88db..d0cbdea717e 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -296,7 +296,7 @@ inline CTransactionRef make_tx(std::vector&& output_values, std::vector BOOST_AUTO_TEST_CASE(MempoolAncestryTests) { - size_t ancestors, descendants; + size_t ancestors, clustersize; CTxMemPool& pool = *Assert(m_node.mempool); LOCK2(cs_main, pool.cs); @@ -309,10 +309,10 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) CTransactionRef tx1 = make_tx(/*output_values=*/{10 * COIN}); AddToMempool(pool, entry.Fee(10000LL).FromTx(tx1)); - // Ancestors / descendants should be 1 / 1 (itself / itself) - pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); + // Ancestors / clustersize should be 1 / 1 (itself / itself) + pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 1ULL); + BOOST_CHECK_EQUAL(clustersize, 1ULL); /* Child transaction */ // @@ -321,17 +321,17 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) CTransactionRef tx2 = make_tx(/*output_values=*/{495 * CENT, 5 * COIN}, /*inputs=*/{tx1}); AddToMempool(pool, entry.Fee(10000LL).FromTx(tx2)); - // Ancestors / descendants should be: - // transaction ancestors descendants + // Ancestors / clustersize should be: + // transaction ancestors clustersize // ============ =========== =========== // tx1 1 (tx1) 2 (tx1,2) // tx2 2 (tx1,2) 2 (tx1,2) - pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); + pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 2ULL); - pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 2ULL); + pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 2ULL); - BOOST_CHECK_EQUAL(descendants, 2ULL); + BOOST_CHECK_EQUAL(clustersize, 2ULL); /* Grand-child 1 */ // @@ -340,21 +340,21 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) CTransactionRef tx3 = make_tx(/*output_values=*/{290 * CENT, 200 * CENT}, /*inputs=*/{tx2}); AddToMempool(pool, entry.Fee(10000LL).FromTx(tx3)); - // Ancestors / descendants should be: - // transaction ancestors descendants + // Ancestors / clustersize should be: + // transaction ancestors clustersize // ============ =========== =========== // tx1 1 (tx1) 3 (tx1,2,3) // tx2 2 (tx1,2) 3 (tx1,2,3) // tx3 3 (tx1,2,3) 3 (tx1,2,3) - pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); + pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 3ULL); - pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 3ULL); + pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 2ULL); - BOOST_CHECK_EQUAL(descendants, 3ULL); - pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 3ULL); + pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 3ULL); + BOOST_CHECK_EQUAL(clustersize, 3ULL); /* Grand-child 2 */ // @@ -365,25 +365,25 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) CTransactionRef tx4 = make_tx(/*output_values=*/{290 * CENT, 250 * CENT}, /*inputs=*/{tx2}, /*input_indices=*/{1}); AddToMempool(pool, entry.Fee(10000LL).FromTx(tx4)); - // Ancestors / descendants should be: - // transaction ancestors descendants + // Ancestors / clustersize should be: + // transaction ancestors clustersize // ============ =========== =========== // tx1 1 (tx1) 4 (tx1,2,3,4) // tx2 2 (tx1,2) 4 (tx1,2,3,4) // tx3 3 (tx1,2,3) 4 (tx1,2,3,4) // tx4 3 (tx1,2,4) 4 (tx1,2,3,4) - pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); + pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 4ULL); - pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 4ULL); + pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 2ULL); - BOOST_CHECK_EQUAL(descendants, 4ULL); - pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 4ULL); + pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 4ULL); - pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 4ULL); + pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 4ULL); + BOOST_CHECK_EQUAL(clustersize, 4ULL); /* Make an alternate branch that is longer and connect it to tx3 */ // @@ -401,56 +401,56 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests) tyi = make_tx(/*output_values=*/{v}, /*inputs=*/i > 0 ? std::vector{*ty[i - 1]} : std::vector{}); v -= 50 * CENT; AddToMempool(pool, entry.Fee(10000LL).FromTx(tyi)); - pool.GetTransactionAncestry(tyi->GetHash(), ancestors, descendants); + pool.GetTransactionAncestry(tyi->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, i+1); - BOOST_CHECK_EQUAL(descendants, i+1); + BOOST_CHECK_EQUAL(clustersize, i+1); } CTransactionRef ty6 = make_tx(/*output_values=*/{5 * COIN}, /*inputs=*/{tx3, ty5}); AddToMempool(pool, entry.Fee(10000LL).FromTx(ty6)); - // Ancestors / descendants should be: - // transaction ancestors descendants + // Ancestors / clustersize should be: + // transaction ancestors clustersize // ============ =================== =========== - // tx1 1 (tx1) 5 (tx1,2,3,4, ty6) - // tx2 2 (tx1,2) 5 (tx1,2,3,4, ty6) - // tx3 3 (tx1,2,3) 5 (tx1,2,3,4, ty6) - // tx4 3 (tx1,2,4) 5 (tx1,2,3,4, ty6) - // ty1 1 (ty1) 6 (ty1,2,3,4,5,6) - // ty2 2 (ty1,2) 6 (ty1,2,3,4,5,6) - // ty3 3 (ty1,2,3) 6 (ty1,2,3,4,5,6) - // ty4 4 (y1234) 6 (ty1,2,3,4,5,6) - // ty5 5 (y12345) 6 (ty1,2,3,4,5,6) - // ty6 9 (tx123, ty123456) 6 (ty1,2,3,4,5,6) - pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants); + // tx1 1 (tx1) 10 (tx1-5, ty1-5) + // tx2 2 (tx1,2) 10 + // tx3 3 (tx1,2,3) 10 + // tx4 3 (tx1,2,4) 10 + // ty1 1 (ty1) 10 + // ty2 2 (ty1,2) 10 + // ty3 3 (ty1,2,3) 10 + // ty4 4 (y1234) 10 + // ty5 5 (y12345) 10 + // ty6 9 (tx123, ty123456) 10 + pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 5ULL); - pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 2ULL); - BOOST_CHECK_EQUAL(descendants, 5ULL); - pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 5ULL); - pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 5ULL); - pool.GetTransactionAncestry(ty1->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty1->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 1ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); - pool.GetTransactionAncestry(ty2->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty2->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 2ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); - pool.GetTransactionAncestry(ty3->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty3->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 3ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); - pool.GetTransactionAncestry(ty4->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty4->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 4ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); - pool.GetTransactionAncestry(ty5->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty5->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 5ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); - pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants); + BOOST_CHECK_EQUAL(clustersize, 10ULL); + pool.GetTransactionAncestry(ty6->GetHash(), ancestors, clustersize); BOOST_CHECK_EQUAL(ancestors, 9ULL); - BOOST_CHECK_EQUAL(descendants, 6ULL); + BOOST_CHECK_EQUAL(clustersize, 10ULL); } BOOST_AUTO_TEST_CASE(MempoolAncestryTestsDiamond) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index ab6d3ed229f..e268fd61e79 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1217,16 +1217,16 @@ std::tuple CTxMemPool::CalculateDescendantData(const CT return {descendant_count, descendant_size, descendant_fees}; } -void CTxMemPool::GetTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& descendants, size_t* const ancestorsize, CAmount* const ancestorfees) const { +void CTxMemPool::GetTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& cluster_count, size_t* const ancestorsize, CAmount* const ancestorfees) const { LOCK(cs); auto it = mapTx.find(txid); - ancestors = descendants = 0; + ancestors = cluster_count = 0; if (it != mapTx.end()) { auto [ancestor_count, ancestor_size, ancestor_fees] = CalculateAncestorData(*it); - descendants = CalculateDescendantMaximum(it); ancestors = ancestor_count; if (ancestorsize) *ancestorsize = ancestor_size; if (ancestorfees) *ancestorfees = ancestor_fees; + cluster_count = m_txgraph->GetCluster(*it, TxGraph::Level::MAIN).size(); } } diff --git a/src/txmempool.h b/src/txmempool.h index 49ee510a4f0..520410b6849 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -516,12 +516,12 @@ public: int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs); /** - * Calculate the ancestor and descendant count for the given transaction. + * Calculate the ancestor and cluster count for the given transaction. * The counts include the transaction itself. * When ancestors is non-zero (ie, the transaction itself is in the mempool), * ancestorsize and ancestorfees will also be set to the appropriate values. */ - void GetTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize = nullptr, CAmount* ancestorfees = nullptr) const; + void GetTransactionAncestry(const Txid& txid, size_t& ancestors, size_t& cluster_count, size_t* ancestorsize = nullptr, CAmount* ancestorfees = nullptr) const; /** * @returns true if an initial attempt to load the persisted mempool was made, regardless of