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.
This commit is contained in:
1 parent
e031085fd4
commit
8e49477e86
4 files changed
+70
-70
No files matched your search
@@ -678,11 +678,11 @@ public:
|
|||||||
// that Chain clients do not need to know about.
|
// that Chain clients do not need to know about.
|
||||||
return TransactionError::OK == err;
|
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;
|
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<COutPoint, CAmount> calculateIndividualBumpFees(const std::vector<COutPoint>& outpoints, const CFeeRate& target_feerate) override
|
std::map<COutPoint, CAmount> calculateIndividualBumpFees(const std::vector<COutPoint>& outpoints, const CFeeRate& target_feerate) override
|
||||||
|
|||||||
+62
-62
@@ -296,7 +296,7 @@ inline CTransactionRef make_tx(std::vector<CAmount>&& output_values, std::vector
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||||
{
|
{
|
||||||
size_t ancestors, descendants;
|
size_t ancestors, clustersize;
|
||||||
|
|
||||||
CTxMemPool& pool = *Assert(m_node.mempool);
|
CTxMemPool& pool = *Assert(m_node.mempool);
|
||||||
LOCK2(cs_main, pool.cs);
|
LOCK2(cs_main, pool.cs);
|
||||||
@@ -309,10 +309,10 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
|||||||
CTransactionRef tx1 = make_tx(/*output_values=*/{10 * COIN});
|
CTransactionRef tx1 = make_tx(/*output_values=*/{10 * COIN});
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx1));
|
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx1));
|
||||||
|
|
||||||
// Ancestors / descendants should be 1 / 1 (itself / itself)
|
// Ancestors / clustersize should be 1 / 1 (itself / itself)
|
||||||
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 1ULL);
|
BOOST_CHECK_EQUAL(clustersize, 1ULL);
|
||||||
|
|
||||||
/* Child transaction */
|
/* Child transaction */
|
||||||
//
|
//
|
||||||
@@ -321,17 +321,17 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
|||||||
CTransactionRef tx2 = make_tx(/*output_values=*/{495 * CENT, 5 * COIN}, /*inputs=*/{tx1});
|
CTransactionRef tx2 = make_tx(/*output_values=*/{495 * CENT, 5 * COIN}, /*inputs=*/{tx1});
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx2));
|
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx2));
|
||||||
|
|
||||||
// Ancestors / descendants should be:
|
// Ancestors / clustersize should be:
|
||||||
// transaction ancestors descendants
|
// transaction ancestors clustersize
|
||||||
// ============ =========== ===========
|
// ============ =========== ===========
|
||||||
// tx1 1 (tx1) 2 (tx1,2)
|
// tx1 1 (tx1) 2 (tx1,2)
|
||||||
// tx2 2 (tx1,2) 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(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 2ULL);
|
BOOST_CHECK_EQUAL(clustersize, 2ULL);
|
||||||
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 2ULL);
|
BOOST_CHECK_EQUAL(clustersize, 2ULL);
|
||||||
|
|
||||||
/* Grand-child 1 */
|
/* Grand-child 1 */
|
||||||
//
|
//
|
||||||
@@ -340,21 +340,21 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
|||||||
CTransactionRef tx3 = make_tx(/*output_values=*/{290 * CENT, 200 * CENT}, /*inputs=*/{tx2});
|
CTransactionRef tx3 = make_tx(/*output_values=*/{290 * CENT, 200 * CENT}, /*inputs=*/{tx2});
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx3));
|
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx3));
|
||||||
|
|
||||||
// Ancestors / descendants should be:
|
// Ancestors / clustersize should be:
|
||||||
// transaction ancestors descendants
|
// transaction ancestors clustersize
|
||||||
// ============ =========== ===========
|
// ============ =========== ===========
|
||||||
// tx1 1 (tx1) 3 (tx1,2,3)
|
// tx1 1 (tx1) 3 (tx1,2,3)
|
||||||
// tx2 2 (tx1,2) 3 (tx1,2,3)
|
// tx2 2 (tx1,2) 3 (tx1,2,3)
|
||||||
// tx3 3 (tx1,2,3) 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(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 3ULL);
|
BOOST_CHECK_EQUAL(clustersize, 3ULL);
|
||||||
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 3ULL);
|
BOOST_CHECK_EQUAL(clustersize, 3ULL);
|
||||||
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 3ULL);
|
BOOST_CHECK_EQUAL(clustersize, 3ULL);
|
||||||
|
|
||||||
/* Grand-child 2 */
|
/* 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});
|
CTransactionRef tx4 = make_tx(/*output_values=*/{290 * CENT, 250 * CENT}, /*inputs=*/{tx2}, /*input_indices=*/{1});
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx4));
|
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx4));
|
||||||
|
|
||||||
// Ancestors / descendants should be:
|
// Ancestors / clustersize should be:
|
||||||
// transaction ancestors descendants
|
// transaction ancestors clustersize
|
||||||
// ============ =========== ===========
|
// ============ =========== ===========
|
||||||
// tx1 1 (tx1) 4 (tx1,2,3,4)
|
// tx1 1 (tx1) 4 (tx1,2,3,4)
|
||||||
// tx2 2 (tx1,2) 4 (tx1,2,3,4)
|
// tx2 2 (tx1,2) 4 (tx1,2,3,4)
|
||||||
// tx3 3 (tx1,2,3) 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)
|
// 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(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 4ULL);
|
BOOST_CHECK_EQUAL(clustersize, 4ULL);
|
||||||
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 4ULL);
|
BOOST_CHECK_EQUAL(clustersize, 4ULL);
|
||||||
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 4ULL);
|
BOOST_CHECK_EQUAL(clustersize, 4ULL);
|
||||||
pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
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 */
|
/* 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<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
|
tyi = make_tx(/*output_values=*/{v}, /*inputs=*/i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
|
||||||
v -= 50 * CENT;
|
v -= 50 * CENT;
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(tyi));
|
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(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});
|
CTransactionRef ty6 = make_tx(/*output_values=*/{5 * COIN}, /*inputs=*/{tx3, ty5});
|
||||||
AddToMempool(pool, entry.Fee(10000LL).FromTx(ty6));
|
AddToMempool(pool, entry.Fee(10000LL).FromTx(ty6));
|
||||||
|
|
||||||
// Ancestors / descendants should be:
|
// Ancestors / clustersize should be:
|
||||||
// transaction ancestors descendants
|
// transaction ancestors clustersize
|
||||||
// ============ =================== ===========
|
// ============ =================== ===========
|
||||||
// tx1 1 (tx1) 5 (tx1,2,3,4, ty6)
|
// tx1 1 (tx1) 10 (tx1-5, ty1-5)
|
||||||
// tx2 2 (tx1,2) 5 (tx1,2,3,4, ty6)
|
// tx2 2 (tx1,2) 10
|
||||||
// tx3 3 (tx1,2,3) 5 (tx1,2,3,4, ty6)
|
// tx3 3 (tx1,2,3) 10
|
||||||
// tx4 3 (tx1,2,4) 5 (tx1,2,3,4, ty6)
|
// tx4 3 (tx1,2,4) 10
|
||||||
// ty1 1 (ty1) 6 (ty1,2,3,4,5,6)
|
// ty1 1 (ty1) 10
|
||||||
// ty2 2 (ty1,2) 6 (ty1,2,3,4,5,6)
|
// ty2 2 (ty1,2) 10
|
||||||
// ty3 3 (ty1,2,3) 6 (ty1,2,3,4,5,6)
|
// ty3 3 (ty1,2,3) 10
|
||||||
// ty4 4 (y1234) 6 (ty1,2,3,4,5,6)
|
// ty4 4 (y1234) 10
|
||||||
// ty5 5 (y12345) 6 (ty1,2,3,4,5,6)
|
// ty5 5 (y12345) 10
|
||||||
// ty6 9 (tx123, ty123456) 6 (ty1,2,3,4,5,6)
|
// ty6 9 (tx123, ty123456) 10
|
||||||
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx1->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 5ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx2->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 5ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx3->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 5ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(tx4->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 5ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty1->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty1->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
BOOST_CHECK_EQUAL(ancestors, 1ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty2->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty2->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
BOOST_CHECK_EQUAL(ancestors, 2ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty3->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty3->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
BOOST_CHECK_EQUAL(ancestors, 3ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty4->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty4->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 4ULL);
|
BOOST_CHECK_EQUAL(ancestors, 4ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty5->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty5->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 5ULL);
|
BOOST_CHECK_EQUAL(ancestors, 5ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants);
|
pool.GetTransactionAncestry(ty6->GetHash(), ancestors, clustersize);
|
||||||
BOOST_CHECK_EQUAL(ancestors, 9ULL);
|
BOOST_CHECK_EQUAL(ancestors, 9ULL);
|
||||||
BOOST_CHECK_EQUAL(descendants, 6ULL);
|
BOOST_CHECK_EQUAL(clustersize, 10ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(MempoolAncestryTestsDiamond)
|
BOOST_AUTO_TEST_CASE(MempoolAncestryTestsDiamond)
|
||||||
|
|||||||
+3
-3
@@ -1217,16 +1217,16 @@ std::tuple<size_t, size_t, CAmount> CTxMemPool::CalculateDescendantData(const CT
|
|||||||
return {descendant_count, descendant_size, descendant_fees};
|
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);
|
LOCK(cs);
|
||||||
auto it = mapTx.find(txid);
|
auto it = mapTx.find(txid);
|
||||||
ancestors = descendants = 0;
|
ancestors = cluster_count = 0;
|
||||||
if (it != mapTx.end()) {
|
if (it != mapTx.end()) {
|
||||||
auto [ancestor_count, ancestor_size, ancestor_fees] = CalculateAncestorData(*it);
|
auto [ancestor_count, ancestor_size, ancestor_fees] = CalculateAncestorData(*it);
|
||||||
descendants = CalculateDescendantMaximum(it);
|
|
||||||
ancestors = ancestor_count;
|
ancestors = ancestor_count;
|
||||||
if (ancestorsize) *ancestorsize = ancestor_size;
|
if (ancestorsize) *ancestorsize = ancestor_size;
|
||||||
if (ancestorfees) *ancestorfees = ancestor_fees;
|
if (ancestorfees) *ancestorfees = ancestor_fees;
|
||||||
|
cluster_count = m_txgraph->GetCluster(*it, TxGraph::Level::MAIN).size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -516,12 +516,12 @@ public:
|
|||||||
int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
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.
|
* The counts include the transaction itself.
|
||||||
* When ancestors is non-zero (ie, the transaction itself is in the mempool),
|
* When ancestors is non-zero (ie, the transaction itself is in the mempool),
|
||||||
* ancestorsize and ancestorfees will also be set to the appropriate values.
|
* 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
|
* @returns true if an initial attempt to load the persisted mempool was made, regardless of
|
||||||
|
|||||||
Reference in new issue
Block a user