@@ -1008,32 +1008,60 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
1008
1008
{
1009
1009
LOCK (pool.cs );
1010
1010
1011
- // For efficiency we simply sum up the pre-calculated
1012
- // fees/size-with-descendants values from the mempool package
1013
- // tracking; this does mean the pathological case of diamond tx
1014
- // graphs will be overcounted.
1011
+ CFeeRate newFeeRate (nFees, nSize);
1015
1012
BOOST_FOREACH (const uint256 hashConflicting, setConflicts)
1016
1013
{
1017
1014
CTxMemPool::txiter mi = pool.mapTx .find (hashConflicting);
1018
1015
if (mi == pool.mapTx .end ())
1019
1016
continue ;
1017
+
1018
+ // Don't allow the replacement to reduce the feerate of the
1019
+ // mempool.
1020
+ //
1021
+ // We usually don't want to accept replacements with lower
1022
+ // feerates than what they replaced as that would lower the
1023
+ // feerate of the next block. Requiring that the feerate always
1024
+ // be increased is also an easy-to-reason about way to prevent
1025
+ // DoS attacks via replacements.
1026
+ //
1027
+ // The mining code doesn't (currently) take children into
1028
+ // account (CPFP) so we only consider the feerates of
1029
+ // transactions being directly replaced, not their indirect
1030
+ // descendants. While that does mean high feerate children are
1031
+ // ignored when deciding whether or not to replace, we do
1032
+ // require the replacement to pay more overall fees too,
1033
+ // mitigating most cases.
1034
+ CFeeRate oldFeeRate (mi->GetFee (), mi->GetTxSize ());
1035
+ if (newFeeRate <= oldFeeRate)
1036
+ {
1037
+ return state.DoS (0 ,
1038
+ error (" AcceptToMemoryPool: rejecting replacement %s; new feerate %s <= old feerate %s" ,
1039
+ hash.ToString (),
1040
+ newFeeRate.ToString (),
1041
+ oldFeeRate.ToString ()),
1042
+ REJECT_INSUFFICIENTFEE, " insufficient fee" );
1043
+ }
1044
+
1045
+ // For efficiency we simply sum up the pre-calculated
1046
+ // fees/size-with-descendants values from the mempool package
1047
+ // tracking; this does mean the pathological case of diamond tx
1048
+ // graphs will be overcounted.
1020
1049
nConflictingFees += mi->GetFeesWithDescendants ();
1021
1050
nConflictingSize += mi->GetSizeWithDescendants ();
1022
1051
}
1023
1052
1024
- // First of all we can't allow a replacement unless it pays greater
1025
- // fees than the transactions it conflicts with - if we did the
1026
- // bandwidth used by those conflicting transactions would not be
1027
- // paid for
1053
+ // The replacement must pay greater fees than the transactions it
1054
+ // replaces - if we did the bandwidth used by those conflicting
1055
+ // transactions would not be paid for.
1028
1056
if (nFees < nConflictingFees)
1029
1057
{
1030
1058
return state.DoS (0 , error (" AcceptToMemoryPool: rejecting replacement %s, less fees than conflicting txs; %s < %s" ,
1031
1059
hash.ToString (), FormatMoney (nFees), FormatMoney (nConflictingFees)),
1032
1060
REJECT_INSUFFICIENTFEE, " insufficient fee" );
1033
1061
}
1034
1062
1035
- // Secondly in addition to paying more fees than the conflicts the
1036
- // new transaction must additionally pay for its own bandwidth.
1063
+ // Finally in addition to paying more fees than the conflicts the
1064
+ // new transaction must pay for its own bandwidth.
1037
1065
CAmount nDeltaFees = nFees - nConflictingFees;
1038
1066
if (nDeltaFees < ::minRelayTxFee.GetFee (nSize))
1039
1067
{
@@ -1044,20 +1072,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
1044
1072
FormatMoney (::minRelayTxFee.GetFee (nSize))),
1045
1073
REJECT_INSUFFICIENTFEE, " insufficient fee" );
1046
1074
}
1047
-
1048
- // Finally replace only if we end up with a larger fees-per-kb than
1049
- // the replacements.
1050
- CFeeRate oldFeeRate (nConflictingFees, nConflictingSize);
1051
- CFeeRate newFeeRate (nFees, nSize);
1052
- if (newFeeRate <= oldFeeRate)
1053
- {
1054
- return state.DoS (0 ,
1055
- error (" AcceptToMemoryPool: rejecting replacement %s; new feerate %s <= old feerate %s" ,
1056
- hash.ToString (),
1057
- newFeeRate.ToString (),
1058
- oldFeeRate.ToString ()),
1059
- REJECT_INSUFFICIENTFEE, " insufficient fee" );
1060
- }
1061
1075
}
1062
1076
1063
1077
// Check against previous transactions
0 commit comments