Implement "feefilter" P2P message.
This commit is contained in:
75
src/main.cpp
75
src/main.cpp
@@ -18,12 +18,14 @@
|
||||
#include "key.h"
|
||||
#include "merkleblock.h"
|
||||
#include "net.h"
|
||||
#include "policy/fees.h"
|
||||
#include "policy/policy.h"
|
||||
#include "pos.h"
|
||||
#include "pow.h"
|
||||
#include "pubkey.h"
|
||||
#include "primitives/block.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "random.h"
|
||||
#include "script/drivechain.h"
|
||||
#include "script/script.h"
|
||||
#include "script/sigcache.h"
|
||||
@@ -91,6 +93,7 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
|
||||
|
||||
CTxMemPool mempool(::minRelayTxFee);
|
||||
FeeFilterRounder filterRounder(::minRelayTxFee);
|
||||
|
||||
struct COrphanTx {
|
||||
CTransaction tx;
|
||||
@@ -1058,8 +1061,8 @@ static bool RespendRelayExceeded(const CTransaction& doubleSpend)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee,
|
||||
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee,
|
||||
std::vector<uint256>& vHashTxnToUncache)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
@@ -1250,6 +1253,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
|
||||
@@ -1502,10 +1508,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
|
||||
}
|
||||
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
|
||||
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee)
|
||||
bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
|
||||
{
|
||||
std::vector<uint256> vHashTxToUncache;
|
||||
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, fRejectAbsurdFee, vHashTxToUncache);
|
||||
bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, txFeeRate, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache);
|
||||
if (!res) {
|
||||
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache)
|
||||
pcoinsTip->Uncache(hashTx);
|
||||
@@ -2857,7 +2863,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
|
||||
// ignore validation errors in resurrected transactions
|
||||
list<CTransaction> removed;
|
||||
CValidationState stateDummy;
|
||||
if (tx.IsCoinBase() || tx.IsCoinStake() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
|
||||
if (tx.IsCoinBase() || tx.IsCoinStake() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, NULL, true)) {
|
||||
mempool.removeRecursive(tx, removed);
|
||||
} else if (mempool.exists(tx.GetHash())) {
|
||||
vHashUpdate.push_back(tx.GetHash());
|
||||
@@ -5328,10 +5334,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",
|
||||
@@ -5362,10 +5368,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);
|
||||
}
|
||||
@@ -5418,7 +5424,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));
|
||||
}
|
||||
@@ -5645,6 +5651,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);
|
||||
@@ -5806,8 +5819,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);
|
||||
}
|
||||
@@ -6280,6 +6304,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user