diff options
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r-- | src/net_processing.cpp | 233 |
1 files changed, 112 insertions, 121 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5267f96f70..a6a8814dff 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2017 The Bitcoin Core developers +// Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -76,7 +76,7 @@ std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans); void EraseOrphansFor(NodeId peer); /** Increase a node's misbehavior score. */ -void Misbehaving(NodeId nodeid, int howmuch, const std::string& message=""); +void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="") EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Average delay between local address broadcasts in seconds. */ static constexpr unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60; @@ -96,22 +96,20 @@ static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; // Internal stuff namespace { /** Number of nodes with fSyncStarted. */ - int nSyncStarted = 0; + int nSyncStarted GUARDED_BY(cs_main) = 0; /** * Sources of received blocks, saved to be able to send them reject - * messages or ban them when processing happens afterwards. Protected by - * cs_main. + * messages or ban them when processing happens afterwards. * Set mapBlockSource[hash].second to false if the node should not be * punished if the block is invalid. */ - std::map<uint256, std::pair<NodeId, bool>> mapBlockSource; + std::map<uint256, std::pair<NodeId, bool>> mapBlockSource GUARDED_BY(cs_main); /** * Filter for transactions that were recently rejected by * AcceptToMemoryPool. These are not rerequested until the chain tip - * changes, at which point the entire filter is reset. Protected by - * cs_main. + * changes, at which point the entire filter is reset. * * Without this filter we'd be re-requesting txs from each of our peers, * increasing bandwidth consumption considerably. For instance, with 100 @@ -127,38 +125,38 @@ namespace { * * Memory used: 1.3 MB */ - std::unique_ptr<CRollingBloomFilter> recentRejects; - uint256 hashRecentRejectsChainTip; + std::unique_ptr<CRollingBloomFilter> recentRejects GUARDED_BY(cs_main); + uint256 hashRecentRejectsChainTip GUARDED_BY(cs_main); - /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ + /** Blocks that are in flight, and that are in the queue to be downloaded. */ struct QueuedBlock { uint256 hash; const CBlockIndex* pindex; //!< Optional. bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request. std::unique_ptr<PartiallyDownloadedBlock> partialBlock; //!< Optional, used for CMPCTBLOCK downloads }; - std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight; + std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight GUARDED_BY(cs_main); /** Stack of nodes which we have set to announce using compact blocks */ - std::list<NodeId> lNodesAnnouncingHeaderAndIDs; + std::list<NodeId> lNodesAnnouncingHeaderAndIDs GUARDED_BY(cs_main); /** Number of preferable block download peers. */ - int nPreferredDownload = 0; + int nPreferredDownload GUARDED_BY(cs_main) = 0; /** Number of peers from which we're downloading blocks. */ - int nPeersWithValidatedDownloads = 0; + int nPeersWithValidatedDownloads GUARDED_BY(cs_main) = 0; /** Number of outbound peers with m_chain_sync.m_protect. */ - int g_outbound_peers_with_protect_from_disconnect = 0; + int g_outbound_peers_with_protect_from_disconnect GUARDED_BY(cs_main) = 0; /** When our tip was last updated. */ std::atomic<int64_t> g_last_tip_update(0); - /** Relay map, protected by cs_main. */ + /** Relay map */ typedef std::map<uint256, CTransactionRef> MapRelay; - MapRelay mapRelay; - /** Expiration-time ordered list of (expire time, relay map entry) pairs, protected by cs_main). */ - std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration; + MapRelay mapRelay GUARDED_BY(cs_main); + /** Expiration-time ordered list of (expire time, relay map entry) pairs. */ + std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration GUARDED_BY(cs_main); std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of when we last received a block @@ -302,18 +300,17 @@ struct CNodeState { } }; -/** Map maintaining per-node state. Requires cs_main. */ -static std::map<NodeId, CNodeState> mapNodeState; +/** Map maintaining per-node state. */ +static std::map<NodeId, CNodeState> mapNodeState GUARDED_BY(cs_main); -// Requires cs_main. -static CNodeState *State(NodeId pnode) { +static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { std::map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode); if (it == mapNodeState.end()) return nullptr; return &it->second; } -static void UpdatePreferredDownload(CNode* node, CNodeState* state) +static void UpdatePreferredDownload(CNode* node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { nPreferredDownload -= state->fPreferredDownload; @@ -344,10 +341,9 @@ static void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime) } } -// Requires cs_main. // Returns a bool indicating whether we requested this block. // Also used if a block was /not/ received and timed out or started with another peer -static bool MarkBlockAsReceived(const uint256& hash) { +static bool MarkBlockAsReceived(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); if (itInFlight != mapBlocksInFlight.end()) { CNodeState *state = State(itInFlight->second.first); @@ -370,10 +366,9 @@ static bool MarkBlockAsReceived(const uint256& hash) { return false; } -// Requires cs_main. // returns false, still setting pit, if the block was already in flight from the same peer // pit will only be valid as long as the same cs_main lock is being held -static bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) { +static bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr, std::list<QueuedBlock>::iterator** pit = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { CNodeState *state = State(nodeid); assert(state != nullptr); @@ -407,7 +402,7 @@ static bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlock } /** Check whether the last unknown block a peer advertised is not yet known. */ -static void ProcessBlockAvailability(NodeId nodeid) { +static void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { CNodeState *state = State(nodeid); assert(state != nullptr); @@ -423,7 +418,7 @@ static void ProcessBlockAvailability(NodeId nodeid) { } /** Update tracking information about which blocks a peer is assumed to have. */ -static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { +static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { CNodeState *state = State(nodeid); assert(state != nullptr); @@ -447,7 +442,8 @@ static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { * lNodesAnnouncingHeaderAndIDs, and keeping that list under a certain size by * removing the first element if necessary. */ -static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) { +static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +{ AssertLockHeld(cs_main); CNodeState* nodestate = State(nodeid); if (!nodestate || !nodestate->fSupportsDesiredCmpctVersion) { @@ -463,11 +459,13 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connma } } connman->ForNode(nodeid, [connman](CNode* pfrom){ + AssertLockHeld(cs_main); uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1; if (lNodesAnnouncingHeaderAndIDs.size() >= 3) { // As per BIP152, we only get 3 of our peers to announce // blocks using compact encodings. connman->ForNode(lNodesAnnouncingHeaderAndIDs.front(), [connman, nCMPCTBLOCKVersion](CNode* pnodeStop){ + AssertLockHeld(cs_main); connman->PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetSendVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/false, nCMPCTBLOCKVersion)); return true; }); @@ -480,7 +478,7 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connma } } -static bool TipMayBeStale(const Consensus::Params &consensusParams) +static bool TipMayBeStale(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); if (g_last_tip_update == 0) { @@ -489,14 +487,12 @@ static bool TipMayBeStale(const Consensus::Params &consensusParams) return g_last_tip_update < GetTime() - consensusParams.nPowTargetSpacing * 3 && mapBlocksInFlight.empty(); } -// Requires cs_main -static bool CanDirectFetch(const Consensus::Params &consensusParams) +static bool CanDirectFetch(const Consensus::Params &consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - consensusParams.nPowTargetSpacing * 20; } -// Requires cs_main -static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) +static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight)) return true; @@ -507,7 +503,8 @@ static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) /** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has * at most count entries. */ -static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) { +static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +{ if (count == 0) return; @@ -797,10 +794,8 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) /** * Mark a misbehaving peer to be banned depending upon the value of `-banscore`. - * - * Requires cs_main. */ -void Misbehaving(NodeId pnode, int howmuch, const std::string& message) +void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { if (howmuch == 0) return; @@ -836,7 +831,7 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) // active chain if they are no more than a month older (both in time, and in // best equivalent proof of work) than the best header chain we know about and // we fully-validated them at some point. -static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) +static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); if (chainActive.Contains(pindex)) return true; @@ -898,10 +893,10 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb // All of the following cache a recent block, and are protected by cs_most_recent_block static CCriticalSection cs_most_recent_block; -static std::shared_ptr<const CBlock> most_recent_block; -static std::shared_ptr<const CBlockHeaderAndShortTxIDs> most_recent_compact_block; -static uint256 most_recent_block_hash; -static bool fWitnessesPresentInMostRecentCompactBlock; +static std::shared_ptr<const CBlock> most_recent_block GUARDED_BY(cs_most_recent_block); +static std::shared_ptr<const CBlockHeaderAndShortTxIDs> most_recent_compact_block GUARDED_BY(cs_most_recent_block); +static uint256 most_recent_block_hash GUARDED_BY(cs_most_recent_block); +static bool fWitnessesPresentInMostRecentCompactBlock GUARDED_BY(cs_most_recent_block); /** * Maintain state about the best-seen block and fast-announce a compact block @@ -930,6 +925,8 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std: } connman->ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled, &hashBlock](CNode* pnode) { + AssertLockHeld(cs_main); + // TODO: Avoid the repeated-serialization here if (pnode->nVersion < INVALID_CB_NO_BAN_VERSION || pnode->fDisconnect) return; @@ -1263,7 +1260,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c } } -void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) +void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main) { AssertLockNotHeld(cs_main); @@ -1327,7 +1324,7 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm } } -static uint32_t GetFetchFlags(CNode* pfrom) { +static uint32_t GetFetchFlags(CNode* pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { uint32_t nFetchFlags = 0; if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) { nFetchFlags |= MSG_WITNESS_FLAG; @@ -1621,8 +1618,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; } - else if (strCommand == NetMsgType::VERSION) - { + if (strCommand == NetMsgType::VERSION) { // Each connection can only send one version message if (pfrom->nVersion != 0) { @@ -1665,8 +1661,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return false; } - if (nVersion < MIN_PEER_PROTO_VERSION) - { + if (nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); if (enable_bip61) { @@ -1677,8 +1672,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return false; } - if (nVersion == 10300) - nVersion = 300; if (!vRecv.empty()) vRecv >> addrFrom >> nNonce; if (!vRecv.empty()) { @@ -1799,9 +1792,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; } - - else if (pfrom->nVersion == 0) - { + if (pfrom->nVersion == 0) { // Must have a version message before anything else LOCK(cs_main); Misbehaving(pfrom->GetId(), 1); @@ -1845,18 +1836,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion)); } pfrom->fSuccessfullyConnected = true; + return true; } - else if (!pfrom->fSuccessfullyConnected) - { + if (!pfrom->fSuccessfullyConnected) { // Must have a verack message before anything else LOCK(cs_main); Misbehaving(pfrom->GetId(), 1); return false; } - else if (strCommand == NetMsgType::ADDR) - { + if (strCommand == NetMsgType::ADDR) { std::vector<CAddress> vAddr; vRecv >> vAddr; @@ -1903,16 +1893,16 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->fGetAddr = false; if (pfrom->fOneShot) pfrom->fDisconnect = true; + return true; } - else if (strCommand == NetMsgType::SENDHEADERS) - { + if (strCommand == NetMsgType::SENDHEADERS) { LOCK(cs_main); State(pfrom->GetId())->fPreferHeaders = true; + return true; } - else if (strCommand == NetMsgType::SENDCMPCT) - { + if (strCommand == NetMsgType::SENDCMPCT) { bool fAnnounceUsingCMPCTBLOCK = false; uint64_t nCMPCTBLOCKVersion = 0; vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion; @@ -1932,11 +1922,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1); } } + return true; } - - else if (strCommand == NetMsgType::INV) - { + if (strCommand == NetMsgType::INV) { std::vector<CInv> vInv; vRecv >> vInv; if (vInv.size() > MAX_INV_SZ) @@ -1990,11 +1979,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } } + return true; } - - else if (strCommand == NetMsgType::GETDATA) - { + if (strCommand == NetMsgType::GETDATA) { std::vector<CInv> vInv; vRecv >> vInv; if (vInv.size() > MAX_INV_SZ) @@ -2012,15 +2000,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); ProcessGetData(pfrom, chainparams, connman, interruptMsgProc); + return true; } - - else if (strCommand == NetMsgType::GETBLOCKS) - { + if (strCommand == NetMsgType::GETBLOCKS) { CBlockLocator locator; uint256 hashStop; vRecv >> locator >> hashStop; + if (locator.vHave.size() > MAX_LOCATOR_SZ) { + LogPrint(BCLog::NET, "getblocks locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId()); + pfrom->fDisconnect = true; + return true; + } + // We might have announced the currently-being-connected tip using a // compact block, which resulted in the peer sending a getblocks // request, which we would otherwise respond to without the new block. @@ -2075,11 +2068,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr break; } } + return true; } - - else if (strCommand == NetMsgType::GETBLOCKTXN) - { + if (strCommand == NetMsgType::GETBLOCKTXN) { BlockTransactionsRequest req; vRecv >> req; @@ -2125,15 +2117,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr assert(ret); SendBlockTransactions(block, req, pfrom, connman); + return true; } - - else if (strCommand == NetMsgType::GETHEADERS) - { + if (strCommand == NetMsgType::GETHEADERS) { CBlockLocator locator; uint256 hashStop; vRecv >> locator >> hashStop; + if (locator.vHave.size() > MAX_LOCATOR_SZ) { + LogPrint(BCLog::NET, "getheaders locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId()); + pfrom->fDisconnect = true; + return true; + } + LOCK(cs_main); if (IsInitialBlockDownload() && !pfrom->fWhitelisted) { LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId()); @@ -2187,11 +2184,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // in the SendMessages logic. nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip(); connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders)); + return true; } - - else if (strCommand == NetMsgType::TX) - { + if (strCommand == NetMsgType::TX) { // Stop processing the transaction early if // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off if (!fRelayTxes && (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) @@ -2375,10 +2371,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr Misbehaving(pfrom->GetId(), nDoS); } } + return true; } - - else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing + if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing { CBlockHeaderAndShortTxIDs cmpctblock; vRecv >> cmpctblock; @@ -2596,10 +2592,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr MarkBlockAsReceived(pblock->GetHash()); } } - + return true; } - else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing + if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing { BlockTransactions resp; vRecv >> resp; @@ -2671,10 +2667,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr mapBlockSource.erase(pblock->GetHash()); } } + return true; } - - else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing + if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing { std::vector<CBlockHeader> headers; @@ -2699,7 +2695,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return ProcessHeadersMessage(pfrom, connman, headers, chainparams, should_punish); } - else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing + if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing { std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); vRecv >> *pblock; @@ -2725,11 +2721,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); mapBlockSource.erase(pblock->GetHash()); } + return true; } - - else if (strCommand == NetMsgType::GETADDR) - { + if (strCommand == NetMsgType::GETADDR) { // This asymmetric behavior for inbound and outbound connections was introduced // to prevent a fingerprinting attack: an attacker can send specific fake addresses // to users' AddrMan and later request them by sending getaddr messages. @@ -2753,11 +2748,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr FastRandomContext insecure_rand; for (const CAddress &addr : vAddr) pfrom->PushAddress(addr, insecure_rand); + return true; } - - else if (strCommand == NetMsgType::MEMPOOL) - { + if (strCommand == NetMsgType::MEMPOOL) { if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted) { LogPrint(BCLog::NET, "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId()); @@ -2774,11 +2768,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(pfrom->cs_inventory); pfrom->fSendMempool = true; + return true; } - - else if (strCommand == NetMsgType::PING) - { + if (strCommand == NetMsgType::PING) { if (pfrom->nVersion > BIP0031_VERSION) { uint64_t nonce = 0; @@ -2796,11 +2789,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // return very quickly. connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce)); } + return true; } - - else if (strCommand == NetMsgType::PONG) - { + if (strCommand == NetMsgType::PONG) { int64_t pingUsecEnd = nTimeReceived; uint64_t nonce = 0; size_t nAvail = vRecv.in_avail(); @@ -2853,11 +2845,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (bPingFinished) { pfrom->nPingNonceSent = 0; } + return true; } - - else if (strCommand == NetMsgType::FILTERLOAD) - { + if (strCommand == NetMsgType::FILTERLOAD) { CBloomFilter filter; vRecv >> filter; @@ -2874,11 +2865,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->pfilter->UpdateEmptyFull(); pfrom->fRelayTxes = true; } + return true; } - - else if (strCommand == NetMsgType::FILTERADD) - { + if (strCommand == NetMsgType::FILTERADD) { std::vector<unsigned char> vData; vRecv >> vData; @@ -2899,19 +2889,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); } + return true; } - - else if (strCommand == NetMsgType::FILTERCLEAR) - { + if (strCommand == NetMsgType::FILTERCLEAR) { LOCK(pfrom->cs_filter); if (pfrom->GetLocalServices() & NODE_BLOOM) { pfrom->pfilter.reset(new CBloomFilter()); } pfrom->fRelayTxes = true; + return true; } - else if (strCommand == NetMsgType::FEEFILTER) { + if (strCommand == NetMsgType::FEEFILTER) { CAmount newFeeFilter = 0; vRecv >> newFeeFilter; if (MoneyRange(newFeeFilter)) { @@ -2921,24 +2911,21 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->GetId()); } + return true; } - else if (strCommand == NetMsgType::NOTFOUND) { + if (strCommand == NetMsgType::NOTFOUND) { // We do not care about the NOTFOUND message, but logging an Unknown Command // message would be undesirable as we transmit it ourselves. + return true; } - else { - // Ignore unknown commands for extensibility - LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId()); - } - - - + // Ignore unknown commands for extensibility + LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId()); return true; } -static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61) +static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); CNodeState &state = *State(pnode->GetId()); @@ -3160,6 +3147,8 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds) LOCK(cs_main); connman->ForEachNode([&](CNode* pnode) { + AssertLockHeld(cs_main); + // Ignore non-outbound peers, or nodes marked for disconnect already if (!IsOutboundDisconnectionCandidate(pnode) || pnode->fDisconnect) return; CNodeState *state = State(pnode->GetId()); @@ -3173,6 +3162,8 @@ void PeerLogicValidation::EvictExtraOutboundPeers(int64_t time_in_seconds) }); if (worst_peer != -1) { bool disconnected = connman->ForNode(worst_peer, [&](CNode *pnode) { + AssertLockHeld(cs_main); + // Only disconnect a peer that has been connected to us for // some reasonable fraction of our check-frequency, to give // it time for new information to have arrived. |