@@ -831,15 +831,42 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
831
831
return state.Invalid (false , REJECT_ALREADY_KNOWN, " txn-already-in-mempool" );
832
832
833
833
// Check for conflicts with in-memory transactions
834
+ set<uint256> setConflicts;
834
835
{
835
836
LOCK (pool.cs ); // protect pool.mapNextTx
836
- for ( unsigned int i = 0 ; i < tx.vin . size (); i++ )
837
+ BOOST_FOREACH ( const CTxIn &txin, tx.vin )
837
838
{
838
- COutPoint outpoint = tx.vin [i].prevout ;
839
- if (pool.mapNextTx .count (outpoint))
839
+ if (pool.mapNextTx .count (txin.prevout ))
840
840
{
841
- // Disable replacement feature for now
842
- return state.Invalid (false , REJECT_CONFLICT, " txn-mempool-conflict" );
841
+ const CTransaction *ptxConflicting = pool.mapNextTx [txin.prevout ].ptx ;
842
+ if (!setConflicts.count (ptxConflicting->GetHash ()))
843
+ {
844
+ // Allow opt-out of transaction replacement by setting
845
+ // nSequence >= maxint-1 on all inputs.
846
+ //
847
+ // maxint-1 is picked to still allow use of nLockTime by
848
+ // non-replacable transactions. All inputs rather than just one
849
+ // is for the sake of multi-party protocols, where we don't
850
+ // want a single party to be able to disable replacement.
851
+ //
852
+ // The opt-out ignores descendants as anyone relying on
853
+ // first-seen mempool behavior should be checking all
854
+ // unconfirmed ancestors anyway; doing otherwise is hopelessly
855
+ // insecure.
856
+ bool fReplacementOptOut = true ;
857
+ BOOST_FOREACH (const CTxIn &txin, ptxConflicting->vin )
858
+ {
859
+ if (txin.nSequence < std::numeric_limits<unsigned int >::max ()-1 )
860
+ {
861
+ fReplacementOptOut = false ;
862
+ break ;
863
+ }
864
+ }
865
+ if (fReplacementOptOut )
866
+ return state.Invalid (false , REJECT_CONFLICT, " txn-mempool-conflict" );
867
+
868
+ setConflicts.insert (ptxConflicting->GetHash ());
869
+ }
843
870
}
844
871
}
845
872
}
@@ -957,6 +984,82 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
957
984
return state.DoS (0 , false , REJECT_NONSTANDARD, " too-long-mempool-chain" , false , errString);
958
985
}
959
986
987
+ // A transaction that spends outputs that would be replaced by it is invalid. Now
988
+ // that we have the set of all ancestors we can detect this
989
+ // pathological case by making sure setConflicts and setAncestors don't
990
+ // intersect.
991
+ BOOST_FOREACH (CTxMemPool::txiter ancestorIt, setAncestors)
992
+ {
993
+ const uint256 &hashAncestor = ancestorIt->GetTx ().GetHash ();
994
+ if (setConflicts.count (hashAncestor))
995
+ {
996
+ return state.DoS (10 , error (" AcceptToMemoryPool: %s spends conflicting transaction %s" ,
997
+ hash.ToString (),
998
+ hashAncestor.ToString ()),
999
+ REJECT_INVALID, " bad-txns-spends-conflicting-tx" );
1000
+ }
1001
+ }
1002
+
1003
+ // Check if it's economically rational to mine this transaction rather
1004
+ // than the ones it replaces.
1005
+ CAmount nConflictingFees = 0 ;
1006
+ size_t nConflictingSize = 0 ;
1007
+ if (setConflicts.size ())
1008
+ {
1009
+ LOCK (pool.cs );
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.
1015
+ BOOST_FOREACH (const uint256 hashConflicting, setConflicts)
1016
+ {
1017
+ CTxMemPool::txiter mi = pool.mapTx .find (hashConflicting);
1018
+ if (mi == pool.mapTx .end ())
1019
+ continue ;
1020
+ nConflictingFees += mi->GetFeesWithDescendants ();
1021
+ nConflictingSize += mi->GetSizeWithDescendants ();
1022
+ }
1023
+
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
1028
+ if (nFees < nConflictingFees)
1029
+ {
1030
+ return state.DoS (0 , error (" AcceptToMemoryPool: rejecting replacement %s, less fees than conflicting txs; %s < %s" ,
1031
+ hash.ToString (), FormatMoney (nFees), FormatMoney (nConflictingFees)),
1032
+ REJECT_INSUFFICIENTFEE, " insufficient fee" );
1033
+ }
1034
+
1035
+ // Secondly in addition to paying more fees than the conflicts the
1036
+ // new transaction must additionally pay for its own bandwidth.
1037
+ CAmount nDeltaFees = nFees - nConflictingFees;
1038
+ if (nDeltaFees < ::minRelayTxFee.GetFee (nSize))
1039
+ {
1040
+ return state.DoS (0 ,
1041
+ error (" AcceptToMemoryPool: rejecting replacement %s, not enough additional fees to relay; %s < %s" ,
1042
+ hash.ToString (),
1043
+ FormatMoney (nDeltaFees),
1044
+ FormatMoney (::minRelayTxFee.GetFee (nSize))),
1045
+ REJECT_INSUFFICIENTFEE, " insufficient fee" );
1046
+ }
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
+ }
1062
+
960
1063
// Check against previous transactions
961
1064
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
962
1065
if (!CheckInputs (tx, state, view, true , STANDARD_SCRIPT_VERIFY_FLAGS, true ))
@@ -977,6 +1080,19 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
977
1080
__func__, hash.ToString (), FormatStateMessage (state));
978
1081
}
979
1082
1083
+ // Remove conflicting transactions from the mempool
1084
+ list<CTransaction> ltxConflicted;
1085
+ pool.removeConflicts (tx, ltxConflicted);
1086
+
1087
+ BOOST_FOREACH (const CTransaction &txConflicted, ltxConflicted)
1088
+ {
1089
+ LogPrint (" mempool" , " replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n " ,
1090
+ txConflicted.GetHash ().ToString (),
1091
+ hash.ToString (),
1092
+ FormatMoney (nFees - nConflictingFees),
1093
+ (int )nSize - (int )nConflictingSize);
1094
+ }
1095
+
980
1096
// Store transaction in memory
981
1097
pool.addUnchecked (hash, entry, setAncestors, !IsInitialBlockDownload ());
982
1098
0 commit comments