Skip to content

Commit ac761f0

Browse files
committed
MOVEONLY: fee checks (Rules 3 and 4) to policy/rbf
1 parent 9c2f9f8 commit ac761f0

File tree

3 files changed

+43
-22
lines changed

3 files changed

+43
-22
lines changed

src/policy/rbf.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,29 @@ std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& s
161161
return std::nullopt;
162162
}
163163

164+
std::optional<std::string> PaysForRBF(CAmount nConflictingFees,
165+
CAmount nModifiedFees,
166+
size_t nSize,
167+
const uint256& hash)
168+
{
169+
// The replacement must pay greater fees than the transactions it
170+
// replaces - if we did the bandwidth used by those conflicting
171+
// transactions would not be paid for.
172+
if (nModifiedFees < nConflictingFees)
173+
{
174+
return strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
175+
hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees));
176+
}
177+
178+
// Finally in addition to paying more fees than the conflicts the
179+
// new transaction must pay for its own bandwidth.
180+
CAmount nDeltaFees = nModifiedFees - nConflictingFees;
181+
if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize))
182+
{
183+
return strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
184+
hash.ToString(),
185+
FormatMoney(nDeltaFees),
186+
FormatMoney(::incrementalRelayFee.GetFee(nSize)));
187+
}
188+
return std::nullopt;
189+
}

src/policy/rbf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,18 @@ std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries&
7878
std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& setIterConflicting,
7979
CFeeRate newFeeRate, const uint256& hash);
8080

81+
/** Enforce BIP125 Rule #3 "The replacement transaction pays an absolute fee of at least the sum
82+
* paid by the original transactions." Enforce BIP125 Rule #4 "The replacement transaction must also
83+
* pay for its own bandwidth at or above the rate set by the node's minimum relay fee setting."
84+
* @param[in] nConflictingFees Total modified fees of original transaction(s).
85+
* @param[in] nModifiedFees Total modified fees of replacement transaction(s).
86+
* @param[in] nSize Total virtual size of replacement transaction(s).
87+
* @param[in] hash Transaction ID, included in the error message if violation occurs.
88+
* @returns error string if fees are insufficient, otherwise std::nullopt.
89+
*/
90+
std::optional<std::string> PaysForRBF(CAmount nConflictingFees,
91+
CAmount nModifiedFees,
92+
size_t nSize,
93+
const uint256& hash);
94+
8195
#endif // BITCOIN_POLICY_RBF_H

src/validation.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -798,32 +798,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
798798
}
799799

800800
// Check if it's economically rational to mine this transaction rather
801-
// than the ones it replaces.
801+
// than the ones it replaces. Enforce Rules #3 and #4.
802802
for (CTxMemPool::txiter it : allConflicting) {
803803
nConflictingFees += it->GetModifiedFee();
804804
nConflictingSize += it->GetTxSize();
805805
}
806-
807-
// The replacement must pay greater fees than the transactions it
808-
// replaces - if we did the bandwidth used by those conflicting
809-
// transactions would not be paid for.
810-
if (nModifiedFees < nConflictingFees)
811-
{
812-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee",
813-
strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
814-
hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)));
815-
}
816-
817-
// Finally in addition to paying more fees than the conflicts the
818-
// new transaction must pay for its own bandwidth.
819-
CAmount nDeltaFees = nModifiedFees - nConflictingFees;
820-
if (nDeltaFees < ::incrementalRelayFee.GetFee(nSize))
821-
{
822-
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee",
823-
strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
824-
hash.ToString(),
825-
FormatMoney(nDeltaFees),
826-
FormatMoney(::incrementalRelayFee.GetFee(nSize))));
806+
if (const auto err_string{PaysForRBF(nConflictingFees, nModifiedFees, nSize, hash)}) {
807+
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
827808
}
828809
}
829810
return true;

0 commit comments

Comments
 (0)