Skip to content

Commit f293c68

Browse files
committed
MOVEONLY: getting mempool conflicts to policy/rbf
1 parent 8d71796 commit f293c68

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

src/policy/rbf.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <policy/rbf.h>
6+
7+
#include <policy/settings.h>
8+
#include <tinyformat.h>
9+
#include <util/moneystr.h>
610
#include <util/rbf.h>
711

812
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
@@ -42,3 +46,34 @@ RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
4246
// If we don't have a local mempool we can only check the transaction itself.
4347
return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
4448
}
49+
50+
bool GetEntriesForConflicts(const CTransaction& tx,
51+
CTxMemPool& m_pool,
52+
const CTxMemPool::setEntries& setIterConflicting,
53+
CTxMemPool::setEntries& allConflicting,
54+
std::string& err_string)
55+
{
56+
AssertLockHeld(m_pool.cs);
57+
const uint256 hash = tx.GetHash();
58+
uint64_t nConflictingCount = 0;
59+
for (const auto& mi : setIterConflicting) {
60+
nConflictingCount += mi->GetCountWithDescendants();
61+
// This potentially overestimates the number of actual descendants
62+
// but we just want to be conservative to avoid doing too much
63+
// work.
64+
if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
65+
err_string = strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
66+
hash.ToString(),
67+
nConflictingCount,
68+
MAX_BIP125_REPLACEMENT_CANDIDATES);
69+
return false;
70+
}
71+
}
72+
// If not too many to replace, then calculate the set of
73+
// transactions that would have to be evicted
74+
for (CTxMemPool::txiter it : setIterConflicting) {
75+
m_pool.CalculateDescendants(it, allConflicting);
76+
}
77+
return true;
78+
}
79+

src/policy/rbf.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,19 @@ enum class RBFTransactionState {
3535
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
3636
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx);
3737

38+
/** Get all descendants of setIterConflicting. Also enforce BIP125 Rule #5, "The number of original
39+
* transactions to be replaced and their descendant transactions which will be evicted from the
40+
* mempool must not exceed a total of 100 transactions." Quit as early as possible. There cannot be
41+
* more than MAX_BIP125_REPLACEMENT_CANDIDATES potential entries.
42+
* @param[in] setIterConflicting The set of iterators to mempool entries.
43+
* @param[out] err_string Used to return errors, if any.
44+
* @param[out] allConflicting Populated with all the mempool entries that would be replaced,
45+
* which includes descendants of setIterConflicting. Not cleared at
46+
* the start; any existing mempool entries will remain in the set.
47+
* @returns false if Rule 5 is broken.
48+
*/
49+
bool GetEntriesForConflicts(const CTransaction& tx, CTxMemPool& m_pool,
50+
const CTxMemPool::setEntries& setIterConflicting,
51+
CTxMemPool::setEntries& allConflicting,
52+
std::string& err_string) EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs);
3853
#endif // BITCOIN_POLICY_RBF_H

src/validation.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
789789
fReplacementTransaction = setConflicts.size();
790790
if (fReplacementTransaction)
791791
{
792+
std::string err_string;
792793
CFeeRate newFeeRate(nModifiedFees, nSize);
793794
for (const auto& mi : setIterConflicting) {
794795
// Don't allow the replacement to reduce the feerate of the
@@ -816,25 +817,11 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
816817
}
817818
}
818819

819-
uint64_t nConflictingCount = 0;
820-
for (const auto& mi : setIterConflicting) {
821-
nConflictingCount += mi->GetCountWithDescendants();
822-
// This potentially overestimates the number of actual descendants
823-
// but we just want to be conservative to avoid doing too much
824-
// work.
825-
if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
826-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too many potential replacements",
827-
strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
828-
hash.ToString(),
829-
nConflictingCount,
830-
MAX_BIP125_REPLACEMENT_CANDIDATES));
831-
}
832-
}
833-
// If not too many to replace, then calculate the set of
834-
// transactions that would have to be evicted
835-
for (CTxMemPool::txiter it : setIterConflicting) {
836-
m_pool.CalculateDescendants(it, allConflicting);
820+
// Calculate all conflicting entries and enforce Rule #5.
821+
if (!GetEntriesForConflicts(tx, m_pool, setIterConflicting, allConflicting, err_string)) {
822+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too many potential replacements", err_string);
837823
}
824+
838825
// Check if it's economically rational to mine this transaction rather
839826
// than the ones it replaces.
840827
for (CTxMemPool::txiter it : allConflicting) {

0 commit comments

Comments
 (0)