@ -17,10 +17,12 @@
@@ -17,10 +17,12 @@
# include "init.h"
# include "merkleblock.h"
# include "net.h"
# include "policy/fees.h"
# include "policy/policy.h"
# include "pow.h"
# include "primitives/block.h"
# include "primitives/transaction.h"
# include "random.h"
# include "script/script.h"
# include "script/sigcache.h"
# include "script/standard.h"
@ -81,6 +83,7 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
@@ -81,6 +83,7 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE ;
CTxMemPool mempool ( : : minRelayTxFee ) ;
FeeFilterRounder filterRounder ( : : minRelayTxFee ) ;
struct COrphanTx {
CTransaction tx ;
@ -987,7 +990,7 @@ std::string FormatStateMessage(const CValidationState &state)
@@ -987,7 +990,7 @@ std::string FormatStateMessage(const CValidationState &state)
}
bool AcceptToMemoryPoolWorker ( CTxMemPool & pool , CValidationState & state , const CTransaction & tx , bool fLimitFree ,
bool * pfMissingInputs , bool fOverrideMempoolLimit , const CAmount nAbsurdFee ,
bool * pfMissingInputs , CFeeRate * txFeeRate , bool fOverrideMempoolLimit , const CAmount & nAbsurdFee ,
std : : vector < uint256 > & vHashTxnToUncache )
{
const uint256 hash = tx . GetHash ( ) ;
@ -1144,6 +1147,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
@@ -1144,6 +1147,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CTxMemPoolEntry entry ( tx , nFees , GetTime ( ) , dPriority , chainActive . Height ( ) , pool . HasNoInputsOf ( tx ) , inChainInputValue , fSpendsCoinbase , nSigOps , lp ) ;
unsigned int nSize = entry . GetTxSize ( ) ;
if ( txFeeRate ) {
* txFeeRate = CFeeRate ( nFees , nSize ) ;
}
// Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction
@ -1392,10 +1398,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
@@ -1392,10 +1398,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
bool AcceptToMemoryPool ( CTxMemPool & pool , CValidationState & state , const CTransaction & tx , bool fLimitFree ,
bool * pfMissingInputs , bool fOverrideMempoolLimit , const CAmount nAbsurdFee )
bool * pfMissingInputs , CFeeRate * txFeeRate , bool fOverrideMempoolLimit , const CAmount nAbsurdFee )
{
std : : vector < uint256 > vHashTxToUncache ;
bool res = AcceptToMemoryPoolWorker ( pool , state , tx , fLimitFree , pfMissingInputs , fOverrideMempoolLimit , nAbsurdFee , vHashTxToUncache ) ;
bool res = AcceptToMemoryPoolWorker ( pool , state , tx , fLimitFree , pfMissingInputs , txFeeRate , fOverrideMempoolLimit , nAbsurdFee , vHashTxToUncache ) ;
if ( ! res ) {
BOOST_FOREACH ( const uint256 & hashTx , vHashTxToUncache )
pcoinsTip - > Uncache ( hashTx ) ;
@ -2620,7 +2626,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
@@ -2620,7 +2626,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
// ignore validation errors in resurrected transactions
list < CTransaction > removed ;
CValidationState stateDummy ;
if ( tx . IsCoinBase ( ) | | ! AcceptToMemoryPool ( mempool , stateDummy , tx , false , NULL , true ) ) {
if ( tx . IsCoinBase ( ) | | ! AcceptToMemoryPool ( mempool , stateDummy , tx , false , NULL , NULL , true ) ) {
mempool . removeRecursive ( tx , removed ) ;
} else if ( mempool . exists ( tx . GetHash ( ) ) ) {
vHashUpdate . push_back ( tx . GetHash ( ) ) ;
@ -4916,10 +4922,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4916,10 +4922,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom - > setAskFor . erase ( inv . hash ) ;
mapAlreadyAskedFor . erase ( inv ) ;
if ( ! AlreadyHave ( inv ) & & AcceptToMemoryPool ( mempool , state , tx , true , & fMissingInputs ) )
{
CFeeRate txFeeRate = CFeeRate ( 0 ) ;
if ( ! AlreadyHave ( inv ) & & AcceptToMemoryPool ( mempool , state , tx , true , & fMissingInputs , & txFeeRate ) ) {
mempool . check ( pcoinsTip ) ;
RelayTransaction ( tx ) ;
RelayTransaction ( tx , txFeeRate ) ;
vWorkQueue . push_back ( inv . hash ) ;
LogPrint ( " mempool " , " AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB) \n " ,
@ -4950,10 +4956,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -4950,10 +4956,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if ( setMisbehaving . count ( fromPeer ) )
continue ;
if ( AcceptToMemoryPool ( mempool , stateDummy , orphanTx , true , & fMissingInputs2 ) )
{
CFeeRate orphanFeeRate = CFeeRate ( 0 ) ;
if ( AcceptToMemoryPool ( mempool , stateDummy , orphanTx , true , & fMissingInputs2 , & orphanFeeRate ) ) {
LogPrint ( " mempool " , " accepted orphan tx %s \n " , orphanHash . ToString ( ) ) ;
RelayTransaction ( orphanTx ) ;
RelayTransaction ( orphanTx , orphanFeeRate ) ;
vWorkQueue . push_back ( orphanHash ) ;
vEraseQueue . push_back ( orphanHash ) ;
}
@ -5006,7 +5012,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -5006,7 +5012,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS = 0 ;
if ( ! state . IsInvalid ( nDoS ) | | nDoS = = 0 ) {
LogPrintf ( " Force relaying tx %s from whitelisted peer=%d \n " , tx . GetHash ( ) . ToString ( ) , pfrom - > id ) ;
RelayTransaction ( tx ) ;
RelayTransaction ( tx , txFeeRate ) ;
} else {
LogPrintf ( " Not relaying invalid transaction %s from whitelisted peer=%d (%s) \n " , tx . GetHash ( ) . ToString ( ) , pfrom - > id , FormatStateMessage ( state ) ) ;
}
@ -5200,6 +5206,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -5200,6 +5206,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if ( ! fInMemPool ) continue ; // another thread removed since queryHashes, maybe...
if ( ! pfrom - > pfilter - > IsRelevantAndUpdate ( tx ) ) continue ;
}
if ( pfrom - > minFeeFilter ) {
CFeeRate feeRate ;
mempool . lookupFeeRate ( hash , feeRate ) ;
LOCK ( pfrom - > cs_feeFilter ) ;
if ( feeRate . GetFeePerK ( ) < pfrom - > minFeeFilter )
continue ;
}
vInv . push_back ( inv ) ;
if ( vInv . size ( ) = = MAX_INV_SZ ) {
pfrom - > PushMessage ( NetMsgType : : INV , vInv ) ;
@ -5362,8 +5375,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -5362,8 +5375,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
else
{
else if ( strCommand = = NetMsgType : : FEEFILTER ) {
CAmount newFeeFilter = 0 ;
vRecv > > newFeeFilter ;
if ( MoneyRange ( newFeeFilter ) ) {
{
LOCK ( pfrom - > cs_feeFilter ) ;
pfrom - > minFeeFilter = newFeeFilter ;
}
LogPrint ( " net " , " received: feefilter of %s from peer=%d \n " , CFeeRate ( newFeeFilter ) . ToString ( ) , pfrom - > id ) ;
}
}
else {
// Ignore unknown commands for extensibility
LogPrint ( " net " , " Unknown command \" %s \" from peer=%d \n " , SanitizeString ( strCommand ) , pfrom - > id ) ;
}
@ -5845,6 +5869,29 @@ bool SendMessages(CNode* pto)
@@ -5845,6 +5869,29 @@ bool SendMessages(CNode* pto)
if ( ! vGetData . empty ( ) )
pto - > PushMessage ( NetMsgType : : GETDATA , vGetData ) ;
//
// Message: feefilter
//
// We don't want white listed peers to filter txs to us if we have -whitelistforcerelay
if ( pto - > nVersion > = FEEFILTER_VERSION & & GetBoolArg ( " -feefilter " , DEFAULT_FEEFILTER ) & &
! ( pto - > fWhitelisted & & GetBoolArg ( " -whitelistforcerelay " , DEFAULT_WHITELISTFORCERELAY ) ) ) {
CAmount currentFilter = mempool . GetMinFee ( GetArg ( " -maxmempool " , DEFAULT_MAX_MEMPOOL_SIZE ) * 1000000 ) . GetFeePerK ( ) ;
int64_t timeNow = GetTimeMicros ( ) ;
if ( timeNow > pto - > nextSendTimeFeeFilter ) {
CAmount filterToSend = filterRounder . round ( currentFilter ) ;
if ( filterToSend ! = pto - > lastSentFeeFilter ) {
pto - > PushMessage ( NetMsgType : : FEEFILTER , filterToSend ) ;
pto - > lastSentFeeFilter = filterToSend ;
}
pto - > nextSendTimeFeeFilter = PoissonNextSend ( timeNow , AVG_FEEFILTER_BROADCAST_INTERVAL ) ;
}
// If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY
// until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
else if ( timeNow + MAX_FEEFILTER_CHANGE_DELAY * 1000000 < pto - > nextSendTimeFeeFilter & &
( currentFilter < 3 * pto - > lastSentFeeFilter / 4 | | currentFilter > 4 * pto - > lastSentFeeFilter / 3 ) ) {
pto - > nextSendTimeFeeFilter = timeNow + ( insecure_rand ( ) % MAX_FEEFILTER_CHANGE_DELAY ) * 1000000 ;
}
}
}
return true ;
}