Skip to content

Commit 7b60c02

Browse files
committed
MOVEONLY: BIP125 Rule 2 to policy/rbf
1 parent f8ad2a5 commit 7b60c02

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

src/policy/rbf.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,40 @@ std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
7575
return std::nullopt;
7676
}
7777

78+
std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
79+
const CTxMemPool& m_pool,
80+
const CTxMemPool::setEntries& setIterConflicting)
81+
{
82+
AssertLockHeld(m_pool.cs);
83+
std::set<uint256> setConflictsParents;
84+
for (const auto& mi : setIterConflicting) {
85+
for (const CTxIn &txin : mi->GetTx().vin)
86+
{
87+
setConflictsParents.insert(txin.prevout.hash);
88+
}
89+
}
90+
91+
for (unsigned int j = 0; j < tx.vin.size(); j++)
92+
{
93+
// We don't want to accept replacements that require low
94+
// feerate junk to be mined first. Ideally we'd keep track of
95+
// the ancestor feerates and make the decision based on that,
96+
// but for now requiring all new inputs to be confirmed works.
97+
//
98+
// Note that if you relax this to make RBF a little more useful,
99+
// this may break the CalculateMempoolAncestors RBF relaxation,
100+
// above. See the comment above the first CalculateMempoolAncestors
101+
// call for more info.
102+
if (!setConflictsParents.count(tx.vin[j].prevout.hash))
103+
{
104+
// Rather than check the UTXO set - potentially expensive -
105+
// it's cheaper to just check if the new input refers to a
106+
// tx that's in the mempool.
107+
if (m_pool.exists(tx.vin[j].prevout.hash)) {
108+
return strprintf("replacement %s adds unconfirmed input, idx %d",
109+
tx.GetHash().ToString(), j);
110+
}
111+
}
112+
}
113+
return std::nullopt;
114+
}

src/policy/rbf.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,11 @@ std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx, CTxMem
4949
const CTxMemPool::setEntries& setIterConflicting,
5050
CTxMemPool::setEntries& allConflicting)
5151
EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs);
52+
53+
/** BIP125 Rule #2: "The replacement transaction may only include an unconfirmed input if that input
54+
* was included in one of the original transactions."
55+
* @returns error message if Rule #2 is broken, otherwise std::nullopt. */
56+
std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx, const CTxMemPool& m_pool,
57+
const CTxMemPool::setEntries& setIterConflicting)
58+
EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs);
5259
#endif // BITCOIN_POLICY_RBF_H

src/validation.cpp

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,11 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
821821
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
822822
"too many potential replacements", *err_string);
823823
}
824+
// Enforce Rule #2.
825+
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, setIterConflicting)}) {
826+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
827+
"replacement-adds-unconfirmed", *err_string);
828+
}
824829

825830
// Check if it's economically rational to mine this transaction rather
826831
// than the ones it replaces.
@@ -829,38 +834,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
829834
nConflictingSize += it->GetTxSize();
830835
}
831836

832-
std::set<uint256> setConflictsParents;
833-
for (const auto& mi : setIterConflicting) {
834-
for (const CTxIn &txin : mi->GetTx().vin)
835-
{
836-
setConflictsParents.insert(txin.prevout.hash);
837-
}
838-
}
839-
840-
for (unsigned int j = 0; j < tx.vin.size(); j++)
841-
{
842-
// We don't want to accept replacements that require low
843-
// feerate junk to be mined first. Ideally we'd keep track of
844-
// the ancestor feerates and make the decision based on that,
845-
// but for now requiring all new inputs to be confirmed works.
846-
//
847-
// Note that if you relax this to make RBF a little more useful,
848-
// this may break the CalculateMempoolAncestors RBF relaxation,
849-
// above. See the comment above the first CalculateMempoolAncestors
850-
// call for more info.
851-
if (!setConflictsParents.count(tx.vin[j].prevout.hash))
852-
{
853-
// Rather than check the UTXO set - potentially expensive -
854-
// it's cheaper to just check if the new input refers to a
855-
// tx that's in the mempool.
856-
if (m_pool.exists(tx.vin[j].prevout.hash)) {
857-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "replacement-adds-unconfirmed",
858-
strprintf("replacement %s adds unconfirmed input, idx %d",
859-
hash.ToString(), j));
860-
}
861-
}
862-
}
863-
864837
// The replacement must pay greater fees than the transactions it
865838
// replaces - if we did the bandwidth used by those conflicting
866839
// transactions would not be paid for.

0 commit comments

Comments
 (0)