Merge 81f4a3e84d into merged_master (Bitcoin PR bitcoin/bitcoin#22796)

This commit is contained in:
Byron Hambly 2023-04-11 09:13:05 +00:00
commit 162e1f24bd
5 changed files with 86 additions and 51 deletions

View file

@ -27,6 +27,7 @@
#include <node/ui_interface.h>
#include <pegins.h>
#include <policy/policy.h>
#include <policy/rbf.h>
#include <policy/settings.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
@ -491,8 +492,10 @@ private:
bool m_replacement_transaction;
CAmount m_base_fees;
CAmount m_modified_fees;
CAmount m_conflicting_fees;
size_t m_conflicting_size;
/** Total modified fees of all transactions being replaced. */
CAmount m_conflicting_fees{0};
/** Total virtual size of all transactions being replaced. */
size_t m_conflicting_size{0};
const CTransactionRef& m_ptx;
const uint256& m_hash;
@ -628,14 +631,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
}
if (!setConflicts.count(ptxConflicting->GetHash()))
{
// Allow opt-out of transaction replacement by setting
// nSequence > MAX_BIP125_RBF_SEQUENCE (SEQUENCE_FINAL-2) on all inputs.
//
// SEQUENCE_FINAL-1 is picked to still allow use of nLockTime by
// non-replaceable transactions. All inputs rather than just one
// is for the sake of multi-party protocols, where we don't
// want a single party to be able to disable replacement.
//
// Transactions that don't explicitly signal replaceability are
// *not* replaceable with the current logic, even if one of their
// unconfirmed ancestors signals replaceability. This diverges
@ -643,16 +638,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Applications relying on first-seen mempool behavior should
// check all unconfirmed ancestors; otherwise an opt-in ancestor
// might be replaced, causing removal of this descendant.
bool fReplacementOptOut = true;
for (const CTxIn &_txin : ptxConflicting->vin)
{
if (_txin.nSequence <= MAX_BIP125_RBF_SEQUENCE)
{
fReplacementOptOut = false;
break;
}
}
if (fReplacementOptOut) {
if (!SignalsOptInRBF(*ptxConflicting)) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "txn-mempool-conflict");
}
@ -879,11 +865,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
}
}
// Check if it's economically rational to mine this transaction rather
// than the ones it replaces.
nConflictingFees = 0;
nConflictingSize = 0;
uint64_t nConflictingCount = 0;
// If we don't hold the lock allConflicting might be incomplete; the
// subsequent RemoveStaged() and addUnchecked() calls don't guarantee
@ -891,9 +872,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
fReplacementTransaction = setConflicts.size();
if (fReplacementTransaction)
{
std::string err_string;
CFeeRate newFeeRate(nModifiedFees, nSize);
std::set<uint256> setConflictsParents;
const int maxDescendantsToVisit = 100;
for (const auto& mi : setIterConflicting) {
// Don't allow the replacement to reduce the feerate of the
// mempool.
@ -918,33 +898,26 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
newFeeRate.ToString(),
oldFeeRate.ToString()));
}
}
// Calculate all conflicting entries and enforce Rule #5.
if (!GetEntriesForConflicts(tx, m_pool, setIterConflicting, allConflicting, err_string)) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too many potential replacements", err_string);
}
// Check if it's economically rational to mine this transaction rather
// than the ones it replaces.
for (CTxMemPool::txiter it : allConflicting) {
nConflictingFees += it->GetModifiedFee();
nConflictingSize += it->GetTxSize();
}
std::set<uint256> setConflictsParents;
for (const auto& mi : setIterConflicting) {
for (const CTxIn &txin : mi->GetTx().vin)
{
setConflictsParents.insert(txin.prevout.hash);
}
nConflictingCount += mi->GetCountWithDescendants();
}
// This potentially overestimates the number of actual descendants
// but we just want to be conservative to avoid doing too much
// work.
if (nConflictingCount <= maxDescendantsToVisit) {
// If not too many to replace, then calculate the set of
// transactions that would have to be evicted
for (CTxMemPool::txiter it : setIterConflicting) {
m_pool.CalculateDescendants(it, allConflicting);
}
for (CTxMemPool::txiter it : allConflicting) {
nConflictingFees += it->GetModifiedFee();
nConflictingSize += it->GetTxSize();
}
} else {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too many potential replacements",
strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
hash.ToString(),
nConflictingCount,
maxDescendantsToVisit));
}
for (unsigned int j = 0; j < tx.vin.size(); j++)