aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp251
1 files changed, 111 insertions, 140 deletions
diff --git a/src/main.cpp b/src/main.cpp
index dc891fecf3..c058843ae3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -84,8 +84,8 @@ struct COrphanTx {
CTransaction tx;
NodeId fromPeer;
};
-map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);;
-map<uint256, set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);;
+map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
+map<uint256, set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);
void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
@@ -181,7 +181,7 @@ namespace {
* million to make it highly unlikely for users to have issues with this
* filter.
*
- * Memory used: 1.7MB
+ * Memory used: 1.3 MB
*/
boost::scoped_ptr<CRollingBloomFilter> recentRejects;
uint256 hashRecentRejectsChainTip;
@@ -800,32 +800,6 @@ void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) {
pcoinsTip->Uncache(removed);
}
-CAmount GetMinRelayFee(const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes, bool fAllowFree)
-{
- uint256 hash = tx.GetHash();
- double dPriorityDelta = 0;
- CAmount nFeeDelta = 0;
- pool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
- if (dPriorityDelta > 0 || nFeeDelta > 0)
- return 0;
-
- CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
-
- if (fAllowFree)
- {
- // There is a free transaction area in blocks created by most miners,
- // * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
- // to be considered to fall into this category. We don't want to encourage sending
- // multiple transactions instead of one big transaction to avoid fees.
- if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000))
- nMinFee = 0;
- }
-
- if (!MoneyRange(nMinFee))
- nMinFee = MAX_MONEY;
- return nMinFee;
-}
-
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state)
{
@@ -968,6 +942,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
CAmount nValueOut = tx.GetValueOut();
CAmount nFees = nValueIn-nValueOut;
+ // nModifiedFees includes any fee deltas from PrioritiseTransaction
+ CAmount nModifiedFees = nFees;
+ double nPriorityDummy = 0;
+ pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);
+
CAmount inChainInputValue;
double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);
@@ -985,16 +964,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps);
unsigned int nSize = entry.GetTxSize();
- // Don't accept it if it can't get into a block
- CAmount txMinFee = GetMinRelayFee(tx, pool, nSize, true);
- if (fLimitFree && nFees < txMinFee)
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false,
- strprintf("%d < %d", nFees, txMinFee));
-
CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
- if (mempoolRejectFee > 0 && nFees < mempoolRejectFee) {
+ if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
- } else if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) {
+ } else if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nModifiedFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) {
// Require that free transactions have sufficient priority to be mined in the next block.
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
}
@@ -1002,7 +975,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
- if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
+ if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize))
{
static CCriticalSection csFreeLimiter;
static double dFreeCount;
@@ -1067,7 +1040,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
LOCK(pool.cs);
if (setConflicts.size())
{
- CFeeRate newFeeRate(nFees, nSize);
+ CFeeRate newFeeRate(nModifiedFees, nSize);
set<uint256> setConflictsParents;
const int maxDescendantsToVisit = 100;
CTxMemPool::setEntries setIterConflicting;
@@ -1110,7 +1083,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// ignored when deciding whether or not to replace, we do
// require the replacement to pay more overall fees too,
// mitigating most cases.
- CFeeRate oldFeeRate(mi->GetFee(), mi->GetTxSize());
+ CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
return state.DoS(0,
@@ -1138,7 +1111,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
pool.CalculateDescendants(it, allConflicting);
}
BOOST_FOREACH(CTxMemPool::txiter it, allConflicting) {
- nConflictingFees += it->GetFee();
+ nConflictingFees += it->GetModifiedFee();
nConflictingSize += it->GetTxSize();
}
} else {
@@ -1171,16 +1144,16 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// The replacement must pay greater fees than the transactions it
// replaces - if we did the bandwidth used by those conflicting
// transactions would not be paid for.
- if (nFees < nConflictingFees)
+ if (nModifiedFees < nConflictingFees)
{
return state.DoS(0, error("AcceptToMemoryPool: rejecting replacement %s, less fees than conflicting txs; %s < %s",
- hash.ToString(), FormatMoney(nFees), FormatMoney(nConflictingFees)),
+ hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)),
REJECT_INSUFFICIENTFEE, "insufficient fee");
}
// Finally in addition to paying more fees than the conflicts the
// new transaction must pay for its own bandwidth.
- CAmount nDeltaFees = nFees - nConflictingFees;
+ CAmount nDeltaFees = nModifiedFees - nConflictingFees;
if (nDeltaFees < ::minRelayTxFee.GetFee(nSize))
{
return state.DoS(0,
@@ -1218,7 +1191,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
LogPrint("mempool", "replacing tx %s with %s for %s BTC additional fees, %d delta bytes\n",
it->GetTx().GetHash().ToString(),
hash.ToString(),
- FormatMoney(nFees - nConflictingFees),
+ FormatMoney(nModifiedFees - nConflictingFees),
(int)nSize - (int)nConflictingSize);
}
pool.RemoveStaged(allConflicting);
@@ -1680,9 +1653,9 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// arguments; if so, don't trigger DoS protection to
// avoid splitting the network between upgraded and
// non-upgraded nodes.
- CScriptCheck check(*coins, tx, i,
+ CScriptCheck check2(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
- if (check())
+ if (check2())
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
}
// Failures of other flags indicate a transaction that is
@@ -3005,7 +2978,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
}
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("CheckBlock(): out-of-bounds SigOpCount"),
- REJECT_INVALID, "bad-blk-sigops", true);
+ REJECT_INVALID, "bad-blk-sigops");
if (fCheckPOW && fCheckMerkleRoot)
block.fChecked = true;
@@ -4171,14 +4144,14 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if (!ReadBlockFromDisk(block, (*mi).second, consensusParams))
assert(!"cannot load block from disk");
if (inv.type == MSG_BLOCK)
- pfrom->PushMessage("block", block);
+ pfrom->PushMessage(NetMsgType::BLOCK, block);
else // MSG_FILTERED_BLOCK)
{
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
{
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
- pfrom->PushMessage("merkleblock", merkleBlock);
+ pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock);
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
// This avoids hurting performance by pointlessly requiring a round-trip
// Note that there is currently no way for a node to request any single transactions we didn't send here -
@@ -4187,8 +4160,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// however we MUST always provide at least what the remote peer needs
typedef std::pair<unsigned int, uint256> PairType;
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
- if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
- pfrom->PushMessage("tx", block.vtx[pair.first]);
+ pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);
}
// else
// no response
@@ -4202,7 +4174,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// wait for other stuff first.
vector<CInv> vInv;
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
- pfrom->PushMessage("inv", vInv);
+ pfrom->PushMessage(NetMsgType::INV, vInv);
pfrom->hashContinue.SetNull();
}
}
@@ -4225,7 +4197,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << tx;
- pfrom->PushMessage("tx", ss);
+ pfrom->PushMessage(NetMsgType::TX, ss);
pushed = true;
}
}
@@ -4252,7 +4224,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
// do that because they want to know about (and store and rebroadcast and
// risk analyze) the dependencies of transactions relevant to them, without
// having to download the entire memory pool.
- pfrom->PushMessage("notfound", vNotFound);
+ pfrom->PushMessage(NetMsgType::NOTFOUND, vNotFound);
}
}
@@ -4269,9 +4241,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!(nLocalServices & NODE_BLOOM) &&
- (strCommand == "filterload" ||
- strCommand == "filteradd" ||
- strCommand == "filterclear"))
+ (strCommand == NetMsgType::FILTERLOAD ||
+ strCommand == NetMsgType::FILTERADD ||
+ strCommand == NetMsgType::FILTERCLEAR))
{
if (pfrom->nVersion >= NO_BLOOM_VERSION) {
Misbehaving(pfrom->GetId(), 100);
@@ -4283,12 +4255,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- if (strCommand == "version")
+ if (strCommand == NetMsgType::VERSION)
{
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
- pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
+ pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
Misbehaving(pfrom->GetId(), 1);
return false;
}
@@ -4302,7 +4274,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
// disconnect from peers older than this proto version
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
- pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
+ pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION));
pfrom->fDisconnect = true;
return false;
@@ -4347,7 +4319,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
// Change version
- pfrom->PushMessage("verack");
+ pfrom->PushMessage(NetMsgType::VERACK);
pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
if (!pfrom->fInbound)
@@ -4370,7 +4342,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Get recent addresses
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
{
- pfrom->PushMessage("getaddr");
+ pfrom->PushMessage(NetMsgType::GETADDR);
pfrom->fGetAddr = true;
}
addrman.Good(pfrom->addr);
@@ -4414,7 +4386,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "verack")
+ else if (strCommand == NetMsgType::VERACK)
{
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
@@ -4429,12 +4401,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// We send this to non-NODE NETWORK peers as well, because even
// non-NODE NETWORK peers can announce blocks (such as pruning
// nodes)
- pfrom->PushMessage("sendheaders");
+ pfrom->PushMessage(NetMsgType::SENDHEADERS);
}
}
- else if (strCommand == "addr")
+ else if (strCommand == NetMsgType::ADDR)
{
vector<CAddress> vAddr;
vRecv >> vAddr;
@@ -4500,14 +4472,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->fDisconnect = true;
}
- else if (strCommand == "sendheaders")
+ else if (strCommand == NetMsgType::SENDHEADERS)
{
LOCK(cs_main);
State(pfrom->GetId())->fPreferHeaders = true;
}
- else if (strCommand == "inv")
+ else if (strCommand == NetMsgType::INV)
{
vector<CInv> vInv;
vRecv >> vInv;
@@ -4548,7 +4520,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// time the block arrives, the header chain leading up to it is already validated. Not
// doing this will result in the received block being rejected as an orphan in case it is
// not a direct successor.
- pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash);
+ pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
CNodeState *nodestate = State(pfrom->GetId());
if (CanDirectFetch(chainparams.GetConsensus()) &&
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
@@ -4578,11 +4550,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
if (!vToFetch.empty())
- pfrom->PushMessage("getdata", vToFetch);
+ pfrom->PushMessage(NetMsgType::GETDATA, vToFetch);
}
- else if (strCommand == "getdata")
+ else if (strCommand == NetMsgType::GETDATA)
{
vector<CInv> vInv;
vRecv >> vInv;
@@ -4603,7 +4575,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "getblocks")
+ else if (strCommand == NetMsgType::GETBLOCKS)
{
CBlockLocator locator;
uint256 hashStop;
@@ -4647,7 +4619,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "getheaders")
+ else if (strCommand == NetMsgType::GETHEADERS)
{
CBlockLocator locator;
uint256 hashStop;
@@ -4692,11 +4664,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// headers message). In both cases it's safe to update
// pindexBestHeaderSent to be our tip.
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
- pfrom->PushMessage("headers", vHeaders);
+ pfrom->PushMessage(NetMsgType::HEADERS, vHeaders);
}
- else if (strCommand == "tx")
+ else if (strCommand == NetMsgType::TX)
{
// Stop processing the transaction early if
// We are in blocks only mode and peer is either not whitelisted or whitelistalwaysrelay is off
@@ -4825,7 +4797,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->id,
FormatStateMessage(state));
if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
- pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
+ pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
@@ -4834,7 +4806,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "headers" && !fImporting && !fReindex) // Ignore headers received while importing
+ else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing
{
std::vector<CBlockHeader> headers;
@@ -4882,7 +4854,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
// from there instead.
LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight);
- pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256());
+ pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256());
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
@@ -4927,7 +4899,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
}
if (vGetData.size() > 0) {
- pfrom->PushMessage("getdata", vGetData);
+ pfrom->PushMessage(NetMsgType::GETDATA, vGetData);
}
}
}
@@ -4935,7 +4907,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CheckBlockIndex(chainparams.GetConsensus());
}
- else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
+ else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
{
CBlock block;
vRecv >> block;
@@ -4955,7 +4927,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS;
if (state.IsInvalid(nDoS)) {
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
- pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
+ pfrom->PushMessage(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0) {
LOCK(cs_main);
@@ -4971,7 +4943,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// to users' AddrMan and later request them by sending getaddr messages.
// Making nodes which are behind NAT and can only make outgoing connections ignore
// the getaddr message mitigates the attack.
- else if ((strCommand == "getaddr") && (pfrom->fInbound))
+ else if ((strCommand == NetMsgType::GETADDR) && (pfrom->fInbound))
{
pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr();
@@ -4980,8 +4952,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "mempool")
+ else if (strCommand == NetMsgType::MEMPOOL)
{
+ if (CNode::OutboundTargetReached(false) && !pfrom->fWhitelisted)
+ {
+ LogPrint("net", "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId());
+ pfrom->fDisconnect = true;
+ return true;
+ }
LOCK2(cs_main, pfrom->cs_filter);
std::vector<uint256> vtxid;
@@ -4989,23 +4967,24 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vector<CInv> vInv;
BOOST_FOREACH(uint256& hash, vtxid) {
CInv inv(MSG_TX, hash);
- CTransaction tx;
- bool fInMemPool = mempool.lookup(hash, tx);
- if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
- if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(tx)) ||
- (!pfrom->pfilter))
- vInv.push_back(inv);
+ if (pfrom->pfilter) {
+ CTransaction tx;
+ bool fInMemPool = mempool.lookup(hash, tx);
+ if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
+ if (!pfrom->pfilter->IsRelevantAndUpdate(tx)) continue;
+ }
+ vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {
- pfrom->PushMessage("inv", vInv);
+ pfrom->PushMessage(NetMsgType::INV, vInv);
vInv.clear();
}
}
if (vInv.size() > 0)
- pfrom->PushMessage("inv", vInv);
+ pfrom->PushMessage(NetMsgType::INV, vInv);
}
- else if (strCommand == "ping")
+ else if (strCommand == NetMsgType::PING)
{
if (pfrom->nVersion > BIP0031_VERSION)
{
@@ -5022,12 +5001,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// it, if the remote node sends a ping once per second and this node takes 5
// seconds to respond to each, the 5th ping the remote sends would appear to
// return very quickly.
- pfrom->PushMessage("pong", nonce);
+ pfrom->PushMessage(NetMsgType::PONG, nonce);
}
}
- else if (strCommand == "pong")
+ else if (strCommand == NetMsgType::PONG)
{
int64_t pingUsecEnd = nTimeReceived;
uint64_t nonce = 0;
@@ -5084,7 +5063,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (fAlerts && strCommand == "alert")
+ else if (fAlerts && strCommand == NetMsgType::ALERT)
{
CAlert alert;
vRecv >> alert;
@@ -5115,7 +5094,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "filterload")
+ else if (strCommand == NetMsgType::FILTERLOAD)
{
CBloomFilter filter;
vRecv >> filter;
@@ -5134,7 +5113,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "filteradd")
+ else if (strCommand == NetMsgType::FILTERADD)
{
vector<unsigned char> vData;
vRecv >> vData;
@@ -5154,7 +5133,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "filterclear")
+ else if (strCommand == NetMsgType::FILTERCLEAR)
{
LOCK(pfrom->cs_filter);
delete pfrom->pfilter;
@@ -5163,7 +5142,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (strCommand == "reject")
+ else if (strCommand == NetMsgType::REJECT)
{
if (fDebug) {
try {
@@ -5173,7 +5152,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
ostringstream ss;
ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
- if (strMsg == "block" || strMsg == "tx")
+ if (strMsg == NetMsgType::BLOCK || strMsg == NetMsgType::TX)
{
uint256 hash;
vRecv >> hash;
@@ -5281,7 +5260,7 @@ bool ProcessMessages(CNode* pfrom)
}
catch (const std::ios_base::failure& e)
{
- pfrom->PushMessage("reject", strCommand, REJECT_MALFORMED, string("error parsing message"));
+ pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, string("error parsing message"));
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
@@ -5320,7 +5299,7 @@ bool ProcessMessages(CNode* pfrom)
}
-bool SendMessages(CNode* pto, bool fSendTrickle)
+bool SendMessages(CNode* pto)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
{
@@ -5349,11 +5328,11 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->nPingUsecStart = GetTimeMicros();
if (pto->nVersion > BIP0031_VERSION) {
pto->nPingNonceSent = nonce;
- pto->PushMessage("ping", nonce);
+ pto->PushMessage(NetMsgType::PING, nonce);
} else {
// Peer is too old to support ping command with nonce, pong will never arrive.
pto->nPingNonceSent = 0;
- pto->PushMessage("ping");
+ pto->PushMessage(NetMsgType::PING);
}
}
@@ -5362,28 +5341,17 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
return true;
// Address refresh broadcast
- static int64_t nLastRebroadcast;
- if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60))
- {
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- {
- // Periodically clear addrKnown to allow refresh broadcasts
- if (nLastRebroadcast)
- pnode->addrKnown.reset();
-
- // Rebroadcast our address
- AdvertizeLocal(pnode);
- }
- if (!vNodes.empty())
- nLastRebroadcast = GetTime();
+ int64_t nNow = GetTimeMicros();
+ if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
+ AdvertizeLocal(pto);
+ pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
//
// Message: addr
//
- if (fSendTrickle)
- {
+ if (pto->nNextAddrSend < nNow) {
+ pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL);
vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend)
@@ -5395,14 +5363,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// receiver rejects addr messages larger than 1000
if (vAddr.size() >= 1000)
{
- pto->PushMessage("addr", vAddr);
+ pto->PushMessage(NetMsgType::ADDR, vAddr);
vAddr.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddr.empty())
- pto->PushMessage("addr", vAddr);
+ pto->PushMessage(NetMsgType::ADDR, vAddr);
}
CNodeState &state = *State(pto->GetId());
@@ -5422,7 +5390,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
}
BOOST_FOREACH(const CBlockReject& reject, state.rejects)
- pto->PushMessage("reject", (string)"block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
+ pto->PushMessage(NetMsgType::REJECT, (string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
state.rejects.clear();
// Start block sync
@@ -5445,7 +5413,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
- pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256());
+ pto->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256());
}
}
@@ -5545,7 +5513,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
LogPrint("net", "%s: sending header %s to peer=%d\n", __func__,
vHeaders.front().GetHash().ToString(), pto->id);
}
- pto->PushMessage("headers", vHeaders);
+ pto->PushMessage(NetMsgType::HEADERS, vHeaders);
state.pindexBestHeaderSent = pBestIndex;
}
pto->vBlockHashesToAnnounce.clear();
@@ -5557,12 +5525,17 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
vector<CInv> vInv;
vector<CInv> vInvWait;
{
+ bool fSendTrickle = pto->fWhitelisted;
+ if (pto->nNextInvSend < nNow) {
+ fSendTrickle = true;
+ pto->nNextInvSend = PoissonNextSend(nNow, AVG_INVENTORY_BROADCAST_INTERVAL);
+ }
LOCK(pto->cs_inventory);
- vInv.reserve(pto->vInventoryToSend.size());
+ vInv.reserve(std::min<size_t>(1000, pto->vInventoryToSend.size()));
vInvWait.reserve(pto->vInventoryToSend.size());
BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend)
{
- if (pto->setInventoryKnown.count(inv))
+ if (inv.type == MSG_TX && pto->filterInventoryKnown.contains(inv.hash))
continue;
// trickle out tx inv to protect privacy
@@ -5583,24 +5556,22 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
}
}
- // returns true if wasn't already contained in the set
- if (pto->setInventoryKnown.insert(inv).second)
+ pto->filterInventoryKnown.insert(inv.hash);
+
+ vInv.push_back(inv);
+ if (vInv.size() >= 1000)
{
- vInv.push_back(inv);
- if (vInv.size() >= 1000)
- {
- pto->PushMessage("inv", vInv);
- vInv.clear();
- }
+ pto->PushMessage(NetMsgType::INV, vInv);
+ vInv.clear();
}
}
pto->vInventoryToSend = vInvWait;
}
if (!vInv.empty())
- pto->PushMessage("inv", vInv);
+ pto->PushMessage(NetMsgType::INV, vInv);
// Detect whether we're stalling
- int64_t nNow = GetTimeMicros();
+ nNow = GetTimeMicros();
if (!pto->fDisconnect && state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
// Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
@@ -5666,7 +5637,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
- pto->PushMessage("getdata", vGetData);
+ pto->PushMessage(NetMsgType::GETDATA, vGetData);
vGetData.clear();
}
} else {
@@ -5676,7 +5647,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vGetData.empty())
- pto->PushMessage("getdata", vGetData);
+ pto->PushMessage(NetMsgType::GETDATA, vGetData);
}
return true;