LCOV - code coverage report
Current view: top level - src - net_processing.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 1151 1357 84.8 %
Date: 2025-04-02 01:23:23 Functions: 45 48 93.8 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2016 The Bitcoin Core developers
       3             : // Copyright (c) 2014-2021 The Dash Core developers
       4             : // Copyright (c) 2015-2022 The PIVX Core developers
       5             : // Distributed under the MIT software license, see the accompanying
       6             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       7             : 
       8             : #include "net_processing.h"
       9             : 
      10             : #include "budget/budgetmanager.h"
      11             : #include "chain.h"
      12             : #include "evo/deterministicmns.h"
      13             : #include "evo/mnauth.h"
      14             : #include "llmq/quorums_blockprocessor.h"
      15             : #include "llmq/quorums_chainlocks.h"
      16             : #include "llmq/quorums_dkgsessionmgr.h"
      17             : #include "llmq/quorums_signing.h"
      18             : #include "masternode-payments.h"
      19             : #include "masternode-sync.h"
      20             : #include "masternodeman.h"
      21             : #include "merkleblock.h"
      22             : #include "netbase.h"
      23             : #include "netmessagemaker.h"
      24             : #include "primitives/block.h"
      25             : #include "primitives/transaction.h"
      26             : #include "spork.h"
      27             : #include "sporkdb.h"
      28             : #include "streams.h"
      29             : #include "tiertwo/tiertwo_sync_state.h"
      30             : #include "util/validation.h"
      31             : #include "validation.h"
      32             : 
      33             : #include <chrono>
      34             : 
      35             : using namespace std::chrono_literals;
      36             : 
      37             : 
      38             : static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8]
      39             : 
      40             : /** the maximum percentage of addresses from our addrman to return in response to a getaddr message. */
      41             : static constexpr size_t MAX_PCT_ADDR_TO_SEND = 23;
      42             : 
      43             : struct IteratorComparator
      44             : {
      45             :     template<typename I>
      46         182 :     bool operator()(const I& a, const I& b) const
      47             :     {
      48         182 :         return &(*a) < &(*b);
      49             :     }
      50             : };
      51             : 
      52         364 : struct COrphanTx {
      53             :     // When modifying, adapt the copy of this definition in tests/DoS_tests.
      54             :     CTransactionRef tx;
      55             :     NodeId fromPeer;
      56             :     int64_t nTimeExpire;
      57             :     size_t list_pos;
      58             : };
      59             : RecursiveMutex g_cs_orphans;
      60             : std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
      61             : std::map<COutPoint, std::set<std::map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(g_cs_orphans);
      62             : std::vector<std::map<uint256, COrphanTx>::iterator> g_orphan_list GUARDED_BY(g_cs_orphans); //! For random eviction
      63             : 
      64             : void EraseOrphansFor(NodeId peer);
      65             : 
      66             : // Internal stuff
      67             : namespace {
      68             : 
      69             : /** Number of nodes with fSyncStarted. */
      70             : int nSyncStarted = 0;
      71             : 
      72             : /**
      73             :  * Sources of received blocks, to be able to send them reject messages or ban
      74             :  * them, if processing happens afterwards. Protected by cs_main.
      75             :  */
      76             : std::map<uint256, NodeId> mapBlockSource;
      77             : 
      78             : /**
      79             :  * Filter for transactions that were recently rejected by
      80             :  * AcceptToMemoryPool. These are not rerequested until the chain tip
      81             :  * changes, at which point the entire filter is reset. Protected by
      82             :  * cs_main.
      83             :  *
      84             :  * Without this filter we'd be re-requesting txs from each of our peers,
      85             :  * increasing bandwidth consumption considerably. For instance, with 100
      86             :  * peers, half of which relay a tx we don't accept, that might be a 50x
      87             :  * bandwidth increase. A flooding attacker attempting to roll-over the
      88             :  * filter using minimum-sized, 60byte, transactions might manage to send
      89             :  * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a
      90             :  * two minute window to send invs to us.
      91             :  *
      92             :  * Decreasing the false positive rate is fairly cheap, so we pick one in a
      93             :  * million to make it highly unlikely for users to have issues with this
      94             :  * filter.
      95             :  *
      96             :  * Memory used: 1.3MB
      97             :  */
      98             : std::unique_ptr<CRollingBloomFilter> recentRejects;
      99             : uint256 hashRecentRejectsChainTip;
     100             : 
     101             : /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
     102             : struct QueuedBlock {
     103             :     uint256 hash;
     104             :     const CBlockIndex* pindex; //! Optional.
     105             :     int64_t nTime;              //! Time of "getdata" request in microseconds.
     106             :     int nValidatedQueuedBefore; //! Number of blocks queued with validated headers (globally) at the time this one is requested.
     107             :     bool fValidatedHeaders;     //! Whether this block has validated headers at the time of request.
     108             : };
     109             : std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight;
     110             : 
     111             : /** Number of blocks in flight with validated headers. */
     112             : int nQueuedValidatedHeaders = 0;
     113             : 
     114             : /** Number of preferable block download peers. */
     115             : int nPreferredDownload = 0;
     116             : 
     117             : } // anon namespace
     118             : 
     119             : namespace
     120             : {
     121             : 
     122             : class CNodeBlocks
     123             : {
     124             : public:
     125        1432 :     CNodeBlocks():
     126             :             maxSize(0),
     127        1432 :             maxAvg(0)
     128             :     {
     129        1432 :         maxSize = gArgs.GetArg("-blockspamfiltermaxsize", DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE);
     130        1432 :         maxAvg = gArgs.GetArg("-blockspamfiltermaxavg", DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG);
     131        1432 :     }
     132             : 
     133          23 :     bool onBlockReceived(int nHeight) {
     134          23 :         if(nHeight > 0 && maxSize && maxAvg) {
     135          23 :             addPoint(nHeight);
     136          23 :             return true;
     137             :         }
     138             :         return false;
     139             :     }
     140             : 
     141          23 :     bool updateState(CValidationState& state, bool ret)
     142             :     {
     143             :         // No Blocks
     144          23 :         size_t size = points.size();
     145          23 :         if(size == 0)
     146             :             return ret;
     147             : 
     148             :         // Compute the number of the received blocks
     149          23 :         size_t nBlocks = 0;
     150          49 :         for (auto point : points) {
     151          26 :             nBlocks += point.second;
     152             :         }
     153             : 
     154             :         // Compute the average value per height
     155          23 :         double nAvgValue = (double)nBlocks / size;
     156             : 
     157             :         // Ban the node if try to spam
     158          46 :         bool banNode = (nAvgValue >= 1.5 * maxAvg && size >= maxAvg) ||
     159          23 :                        (nAvgValue >= maxAvg && nBlocks >= maxSize) ||
     160          23 :                        (nBlocks >= maxSize * 3);
     161             :         if (banNode) {
     162             :             // Clear the points and ban the node
     163           0 :             points.clear();
     164           0 :             return state.DoS(100, error("block-spam ban node for sending spam"));
     165             :         }
     166             : 
     167             :         return ret;
     168             :     }
     169             : 
     170             : private:
     171          23 :     void addPoint(int height)
     172             :     {
     173             :         // Remove the last element in the list
     174          23 :         if(points.size() == maxSize)
     175             :         {
     176           0 :             points.erase(points.begin());
     177             :         }
     178             : 
     179             :         // Add the point to the list
     180          23 :         int occurrence = 0;
     181          23 :         auto mi = points.find(height);
     182          23 :         if (mi != points.end())
     183           1 :             occurrence = (*mi).second;
     184          23 :         occurrence++;
     185          23 :         points[height] = occurrence;
     186          23 :     }
     187             : 
     188             : private:
     189             :     std::map<int,int> points;
     190             :     size_t maxSize;
     191             :     size_t maxAvg;
     192             : };
     193             : 
     194             : 
     195             : 
     196             :  /**
     197             :  * Maintain validation-specific state about nodes, protected by cs_main, instead
     198             :  * by CNode's own locks. This simplifies asynchronous operation, where
     199             :  * processing of incoming data is done after the ProcessMessage call returns,
     200             :  * and we're no longer holding the node's locks.
     201             :  */
     202             : struct CNodeState {
     203             :     //! The peer's address
     204             :     const CService address;
     205             :     //! Whether we have a fully established connection.
     206             :     bool fCurrentlyConnected;
     207             :     //! Accumulated misbehaviour score for this peer.
     208             :     int nMisbehavior;
     209             :     //! Whether this peer should be disconnected and banned (unless whitelisted).
     210             :     bool fShouldBan;
     211             :     //! String name of this peer (debugging/logging purposes).
     212             :     const std::string name;
     213             :     //! The best known block we know this peer has announced.
     214             :     const CBlockIndex* pindexBestKnownBlock;
     215             :     //! The hash of the last unknown block this peer has announced.
     216             :     uint256 hashLastUnknownBlock;
     217             :     //! The last full block we both have.
     218             :     const CBlockIndex* pindexLastCommonBlock;
     219             :     //! Whether we've started headers synchronization with this peer.
     220             :     bool fSyncStarted;
     221             :     //! Since when we're stalling block download progress (in microseconds), or 0.
     222             :     int64_t nStallingSince;
     223             :     std::list<QueuedBlock> vBlocksInFlight;
     224             :     int nBlocksInFlight;
     225             :     //! Whether we consider this a preferred download peer.
     226             :     bool fPreferredDownload;
     227             :     //! Addresses processed
     228             :     uint64_t amt_addr_processed = 0;
     229             :     //! Addresses rate limited
     230             :     uint64_t amt_addr_rate_limited = 0;
     231             : 
     232             :     CNodeBlocks nodeBlocks;
     233             : 
     234        4296 :     CNodeState(CAddress addrIn, std::string addrNameIn) : address(addrIn), name(addrNameIn) {
     235        1432 :         fCurrentlyConnected = false;
     236        1432 :         nMisbehavior = 0;
     237        1432 :         fShouldBan = false;
     238        1432 :         pindexBestKnownBlock = nullptr;
     239        1432 :         hashLastUnknownBlock.SetNull();
     240        1432 :         pindexLastCommonBlock = nullptr;
     241        1432 :         fSyncStarted = false;
     242        1432 :         nStallingSince = 0;
     243        1432 :         nBlocksInFlight = 0;
     244        1432 :         fPreferredDownload = false;
     245        1432 :     }
     246             : };
     247             : 
     248             : /** Map maintaining per-node state. Requires cs_main. */
     249             : std::map<NodeId, CNodeState> mapNodeState;
     250             : 
     251             : // Requires cs_main.
     252     6546123 : CNodeState* State(NodeId pnode)
     253             : {
     254     6546123 :     std::map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
     255     6546123 :     if (it == mapNodeState.end())
     256             :         return nullptr;
     257     6546023 :     return &it->second;
     258             : }
     259             : 
     260        1358 : void UpdatePreferredDownload(CNode* node, CNodeState* state)
     261             : {
     262        1358 :     nPreferredDownload -= state->fPreferredDownload;
     263             : 
     264             :     // Whether this node should be marked as a preferred download node.
     265        1358 :     state->fPreferredDownload = (!node->fInbound || node->fWhitelisted) && !node->fOneShot && !node->fClient;
     266             : 
     267        1358 :     nPreferredDownload += state->fPreferredDownload;
     268        1358 : }
     269             : 
     270        1379 : void PushNodeVersion(CNode* pnode, CConnman* connman, int64_t nTime)
     271             : {
     272        1379 :     ServiceFlags nLocalNodeServices = pnode->GetLocalServices();
     273        1379 :     uint64_t nonce = pnode->GetLocalNonce();
     274        1379 :     int nNodeStartingHeight = pnode->GetMyStartingHeight();
     275        1379 :     NodeId nodeid = pnode->GetId();
     276        1379 :     CAddress addr = pnode->addr;
     277             : 
     278        2769 :     CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
     279        4137 :     CAddress addrMe = CAddress(CService(), nLocalNodeServices);
     280             : 
     281             :     // Create the version message
     282        1379 :     auto version_msg = CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
     283        2758 :                                           nonce, strSubVersion, nNodeStartingHeight, true);
     284             : 
     285             :     // DMN-to-DMN, set auth connection type and create challenge.
     286        1379 :     if (pnode->m_masternode_connection) {
     287         208 :         uint256 mnauthChallenge;
     288         208 :         GetRandBytes(mnauthChallenge.begin(), (int) mnauthChallenge.size());
     289         416 :         WITH_LOCK(pnode->cs_mnauth, pnode->sentMNAuthChallenge = mnauthChallenge);
     290         208 :         CVectorWriter{SER_NETWORK, 0 | INIT_PROTO_VERSION, version_msg.data, version_msg.data.size(), pnode->sentMNAuthChallenge};
     291             :     }
     292             : 
     293        1379 :     connman->PushMessage(pnode, std::move(version_msg));
     294             : 
     295        1379 :     if (fLogIPs)
     296           0 :         LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
     297             :     else
     298        2734 :         LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
     299        1379 : }
     300             : 
     301             : // Requires cs_main.
     302       25510 : void MarkBlockAsReceived(const uint256& hash)
     303             : {
     304       25510 :     std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
     305       25510 :     if (itInFlight != mapBlocksInFlight.end()) {
     306           0 :         CNodeState* state = State(itInFlight->second.first);
     307           0 :         assert(state != nullptr);
     308           0 :         nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
     309           0 :         state->vBlocksInFlight.erase(itInFlight->second.second);
     310           0 :         state->nBlocksInFlight--;
     311           0 :         state->nStallingSince = 0;
     312           0 :         mapBlocksInFlight.erase(itInFlight);
     313             :     }
     314       25510 : }
     315             : 
     316             : // Requires cs_main.
     317           0 : void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex* pindex = nullptr)
     318             : {
     319           0 :     CNodeState* state = State(nodeid);
     320           0 :     assert(state != nullptr);
     321             : 
     322             :     // Make sure it's not listed somewhere already.
     323           0 :     MarkBlockAsReceived(hash);
     324             : 
     325           0 :     QueuedBlock newentry = {hash, pindex, GetTimeMicros(), nQueuedValidatedHeaders, pindex != nullptr};
     326           0 :     nQueuedValidatedHeaders += newentry.fValidatedHeaders;
     327           0 :     std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
     328           0 :     state->nBlocksInFlight++;
     329           0 :     mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
     330           0 : }
     331             : 
     332             : /** Check whether the last unknown block a peer advertised is not yet known. */
     333     1242613 : static void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     334             : {
     335     1242613 :     AssertLockHeld(cs_main);
     336             : 
     337     1242613 :     CNodeState* state = State(nodeid);
     338     1242613 :     assert(state != nullptr);
     339             : 
     340    37974299 :     if (!state->hashLastUnknownBlock.IsNull()) {
     341       97812 :         CBlockIndex* pindex = LookupBlockIndex(state->hashLastUnknownBlock);
     342      115240 :         if (pindex && pindex->nChainWork > 0) {
     343       17428 :             if (!state->pindexBestKnownBlock || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork)
     344       17427 :                 state->pindexBestKnownBlock = pindex;
     345       17428 :             state->hashLastUnknownBlock.SetNull();
     346             :         }
     347             :     }
     348     1242613 : }
     349             : 
     350             : /** Update tracking information about which blocks a peer is assumed to have. */
     351      185877 : static void UpdateBlockAvailability(NodeId nodeid, const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     352             : {
     353      185877 :     AssertLockHeld(cs_main);
     354             : 
     355      185877 :     CNodeState* state = State(nodeid);
     356      185877 :     assert(state != nullptr);
     357             : 
     358      185877 :     ProcessBlockAvailability(nodeid);
     359             : 
     360      185877 :     CBlockIndex* pindex = LookupBlockIndex(hash);
     361      322260 :     if (pindex && pindex->nChainWork > 0) {
     362             :         // An actually better block was announced.
     363      136383 :         if (!state->pindexBestKnownBlock || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork)
     364      135611 :             state->pindexBestKnownBlock = pindex;
     365             :     } else {
     366             :         // An unknown block was announced; just assume that the latest one is the best one.
     367       49494 :         state->hashLastUnknownBlock = hash;
     368             :     }
     369      185877 : }
     370             : 
     371             : /** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
     372             :  *  at most count entries. */
     373     1056733 : static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     374             : {
     375     1056733 :     AssertLockHeld(cs_main);
     376             : 
     377     1056733 :     if (count == 0)
     378     1021163 :         return;
     379             : 
     380     1056733 :     vBlocks.reserve(vBlocks.size() + count);
     381     1056733 :     CNodeState* state = State(nodeid);
     382     1056733 :     assert(state != nullptr);
     383             : 
     384             :     // Make sure pindexBestKnownBlock is up to date, we'll need it.
     385     1056733 :     ProcessBlockAvailability(nodeid);
     386             : 
     387     1994843 :     if (!state->pindexBestKnownBlock || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork) {
     388             :         // This peer has nothing interesting.
     389      353002 :         return;
     390             :     }
     391             : 
     392      703732 :     if (!state->pindexLastCommonBlock) {
     393             :         // Bootstrap quickly by guessing a parent of our best tip is the forking point.
     394             :         // Guessing wrong in either direction is not a problem.
     395        1360 :         state->pindexLastCommonBlock = chainActive[std::min(state->pindexBestKnownBlock->nHeight, chainActive.Height())];
     396             :     }
     397             : 
     398             :     // If the peer reorganized, our previous pindexLastCommonBlock may not be an ancestor
     399             :     // of their current tip anymore. Go back enough to fix that.
     400      703732 :     state->pindexLastCommonBlock = LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
     401      703732 :     if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
     402             :         return;
     403             : 
     404       71140 :     std::vector<const CBlockIndex*> vToFetch;
     405       35570 :     const CBlockIndex* pindexWalk = state->pindexLastCommonBlock;
     406             :     // Never fetch further than the best block we know the peer has, or more than BLOCK_DOWNLOAD_WINDOW + 1 beyond the last
     407             :     // linked block we have in common with this peer. The +1 is so we can detect stalling, namely if we would be able to
     408             :     // download that next block if the window were 1 larger.
     409       35570 :     int nWindowEnd = state->pindexLastCommonBlock->nHeight + BLOCK_DOWNLOAD_WINDOW;
     410       35570 :     int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
     411       35570 :     NodeId waitingfor = -1;
     412       71152 :     while (pindexWalk->nHeight < nMaxHeight) {
     413             :         // Read up to 128 (or more, if more blocks than that are needed) successors of pindexWalk (towards
     414             :         // pindexBestKnownBlock) into vToFetch. We fetch 128, because CBlockIndex::GetAncestor may be as expensive
     415             :         // as iterating over ~100 CBlockIndex* entries anyway.
     416       71164 :         int nToFetch = std::min(nMaxHeight - pindexWalk->nHeight, std::max<int>(count - vBlocks.size(), 128));
     417       35582 :         vToFetch.resize(nToFetch);
     418       35582 :         pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->nHeight + nToFetch);
     419       35582 :         vToFetch[nToFetch - 1] = pindexWalk;
     420       97146 :         for (unsigned int i = nToFetch - 1; i > 0; i--) {
     421       61564 :             vToFetch[i - 1] = vToFetch[i]->pprev;
     422             :         }
     423             : 
     424             :         // Iterate over those blocks in vToFetch (in forward direction), adding the ones that
     425             :         // are not yet downloaded and not in flight to vBlocks. In the mean time, update
     426             :         // pindexLastCommonBlock as long as all ancestors are already downloaded.
     427      132728 :         for (const CBlockIndex* pindex : vToFetch) {
     428       97146 :             if (!pindex->IsValid(BLOCK_VALID_TREE)) {
     429             :                 // We consider the chain that this peer is on invalid.
     430           0 :                 return;
     431             :             }
     432       97146 :             if (pindex->nStatus & BLOCK_HAVE_DATA) {
     433       97146 :                 if (pindex->nChainTx)
     434       97146 :                     state->pindexLastCommonBlock = pindex;
     435           0 :             } else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
     436             :                 // The block is not already downloaded, and not yet in flight.
     437           0 :                 if (pindex->nHeight > nWindowEnd) {
     438             :                     // We reached the end of the window.
     439           0 :                     if (vBlocks.size() == 0 && waitingfor != nodeid) {
     440             :                         // We aren't able to fetch anything, but we would be if the download window was one larger.
     441           0 :                         nodeStaller = waitingfor;
     442             :                     }
     443           0 :                     return;
     444             :                 }
     445           0 :                 vBlocks.push_back(pindex);
     446           0 :                 if (vBlocks.size() == count) {
     447             :                     return;
     448             :                 }
     449           0 :             } else if (waitingfor == -1) {
     450             :                 // This is the first already-in-flight block.
     451           0 :                 waitingfor = mapBlocksInFlight[pindex->GetBlockHash()].first;
     452             :             }
     453             :         }
     454             :     }
     455             : }
     456             : 
     457             : } // anon namespace
     458             : 
     459        1432 : void PeerLogicValidation::InitializeNode(CNode *pnode) {
     460        1432 :     CAddress addr = pnode->addr;
     461        2864 :     std::string addrName = pnode->GetAddrName();
     462        1432 :     NodeId nodeid = pnode->GetId();
     463        1432 :     {
     464        1432 :         LOCK(cs_main);
     465        1432 :         mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, std::move(addrName)));
     466             :     }
     467        1432 :     if(!pnode->fInbound)
     468         668 :         PushNodeVersion(pnode, connman, GetTime());
     469        1432 : }
     470             : 
     471        1428 : void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime)
     472             : {
     473        1428 :     fUpdateConnectionTime = false;
     474        1428 :     LOCK(cs_main);
     475        1428 :     CNodeState* state = State(nodeid);
     476             : 
     477        1428 :     if (state->fSyncStarted)
     478        1224 :         nSyncStarted--;
     479             : 
     480        1428 :     if (state->nMisbehavior == 0 && state->fCurrentlyConnected) {
     481         642 :         fUpdateConnectionTime = true;
     482             :     }
     483             : 
     484        1428 :     for (const QueuedBlock& entry : state->vBlocksInFlight)
     485           0 :         mapBlocksInFlight.erase(entry.hash);
     486        1428 :     EraseOrphansFor(nodeid);
     487        1428 :     nPreferredDownload -= state->fPreferredDownload;
     488             : 
     489        1428 :     mapNodeState.erase(nodeid);
     490        1428 :     LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
     491        1428 : }
     492             : 
     493       56794 : bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats)
     494             : {
     495      113588 :     LOCK(cs_main);
     496       56794 :     CNodeState* state = State(nodeid);
     497       56794 :     if (!state)
     498             :         return false;
     499       56794 :     stats.nMisbehavior = state->nMisbehavior;
     500       56794 :     stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
     501       56794 :     stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
     502       56794 :     for (const QueuedBlock& queue : state->vBlocksInFlight) {
     503           0 :         if (queue.pindex)
     504           0 :             stats.vHeightInFlight.push_back(queue.pindex->nHeight);
     505             :     }
     506             : 
     507       56794 :     stats.m_addr_processed = state->amt_addr_processed;
     508       56794 :     stats.m_addr_rate_limited = state->amt_addr_rate_limited;
     509       56794 :     return true;
     510             : }
     511             : 
     512             : //////////////////////////////////////////////////////////////////////////////
     513             : //
     514             : // mapOrphanTransactions
     515             : //
     516             : 
     517         215 : bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
     518             : {
     519         215 :     const uint256& hash = tx->GetHash();
     520         215 :     if (mapOrphanTransactions.count(hash))
     521          23 :         return false;
     522             : 
     523             :     // Ignore big transactions, to avoid a
     524             :     // send-big-orphans memory exhaustion attack. If a peer has a legitimate
     525             :     // large transaction with a missing parent then we assume
     526             :     // it will rebroadcast it later, after the parent transaction(s)
     527             :     // have been mined or received.
     528             :     // 25 orphans, each of which is at most 400,000 bytes big is
     529             :     // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
     530         192 :     unsigned int sz = tx->GetTotalSize();
     531         192 :     unsigned int nMaxSize = tx->IsShieldedTx() ? MAX_TX_SIZE_AFTER_SAPLING : MAX_STANDARD_TX_SIZE;
     532         192 :     if (sz >= nMaxSize) {
     533          10 :         LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
     534          10 :         return false;
     535             :     }
     536             : 
     537         182 :     auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME, g_orphan_list.size()});
     538         182 :     assert(ret.second);
     539         182 :     g_orphan_list.emplace_back(ret.first);
     540         364 :     for (const CTxIn& txin : tx->vin) {
     541         182 :         mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first);
     542             :     }
     543             : 
     544         287 :     LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(),
     545             :         mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size());
     546             :     return true;
     547             : }
     548             : 
     549         182 : int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans)
     550             : {
     551         182 :     std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash);
     552         182 :     if (it == mapOrphanTransactions.end())
     553             :         return 0;
     554         364 :     for (const CTxIn& txin : it->second.tx->vin) {
     555         182 :         auto itPrev = mapOrphanTransactionsByPrev.find(txin.prevout);
     556         182 :         if (itPrev == mapOrphanTransactionsByPrev.end())
     557           0 :             continue;
     558         182 :         itPrev->second.erase(it);
     559         182 :         if (itPrev->second.empty())
     560         182 :             mapOrphanTransactionsByPrev.erase(itPrev);
     561             :     }
     562             : 
     563         182 :     size_t old_pos = it->second.list_pos;
     564         182 :     assert(g_orphan_list[old_pos] == it);
     565         182 :     if (old_pos + 1 != g_orphan_list.size()) {
     566             :         // Unless we're deleting the last entry in g_orphan_list, move the last
     567             :         // entry to the position we're deleting.
     568         166 :         auto it_last = g_orphan_list.back();
     569         166 :         g_orphan_list[old_pos] = it_last;
     570         166 :         it_last->second.list_pos = old_pos;
     571             :     }
     572         182 :     g_orphan_list.pop_back();
     573             : 
     574         182 :     mapOrphanTransactions.erase(it);
     575         182 :     return 1;
     576             : }
     577             : 
     578        1431 : void EraseOrphansFor(NodeId peer)
     579             : {
     580        1431 :     LOCK(g_cs_orphans);
     581        1431 :     int nErased = 0;
     582        1431 :     std::map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin();
     583        1681 :     while (iter != mapOrphanTransactions.end()) {
     584         250 :         std::map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
     585         250 :         if (maybeErase->second.fromPeer == peer) {
     586          30 :             nErased += EraseOrphanTx(maybeErase->second.tx->GetHash());
     587             :         }
     588             :     }
     589        1431 :     if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer %d\n", nErased, peer);
     590        1431 : }
     591             : 
     592             : 
     593         108 : unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
     594             : {
     595         108 :     LOCK(g_cs_orphans);
     596             : 
     597         108 :     unsigned int nEvicted = 0;
     598         108 :     static int64_t nNextSweep;
     599         108 :     int64_t nNow = GetTime();
     600         108 :     if (nNextSweep <= nNow) {
     601             :         // Sweep out expired orphan pool entries:
     602           2 :         int nErased = 0;
     603           2 :         int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL;
     604           2 :         auto iter = mapOrphanTransactions.begin();
     605          75 :         while (iter != mapOrphanTransactions.end()) {
     606          73 :             auto maybeErase = iter++;
     607          73 :             if (maybeErase->second.nTimeExpire <= nNow) {
     608           0 :                 nErased += EraseOrphanTx(maybeErase->second.tx->GetHash());
     609             :             } else {
     610         146 :                 nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime);
     611             :             }
     612             :         }
     613             :         // Sweep again 5 minutes after the next entry that expires in order to batch the linear scan.
     614           2 :         nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL;
     615           2 :         if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", nErased);
     616             :     }
     617         108 :     FastRandomContext rng;
     618         256 :     while (mapOrphanTransactions.size() > nMaxOrphans) {
     619             :         // Evict a random orphan:
     620         148 :         size_t randompos = rng.randrange(g_orphan_list.size());
     621         148 :         EraseOrphanTx(g_orphan_list[randompos]->first);
     622         148 :         ++nEvicted;
     623             :     }
     624         216 :     return nEvicted;
     625             : }
     626             : 
     627             : // Requires cs_main.
     628          99 : void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     629             : {
     630          99 :     if (howmuch == 0)
     631           1 :         return;
     632             : 
     633          99 :     CNodeState* state = State(pnode);
     634          99 :     if (state == nullptr)
     635             :         return;
     636             : 
     637          98 :     state->nMisbehavior += howmuch;
     638          98 :     int banscore = gArgs.GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD);
     639         196 :     std::string message_prefixed = message.empty() ? "" : (": " + message);
     640          98 :     if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore) {
     641          44 :         LogPrint(BCLog::NET, "%s: %s peer=%d (%d -> %d) BAN THRESHOLD EXCEEDED%s\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior, message_prefixed);
     642          44 :         state->fShouldBan = true;
     643             :     } else {
     644          54 :         LogPrint(BCLog::NET, "%s: %s peer=%d (%d -> %d)%s\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior, message_prefixed);
     645             :     }
     646             : }
     647             : 
     648             : // Requires cs_main.
     649       24041 : bool IsBanned(NodeId pnode)
     650             : {
     651       24041 :     CNodeState* state = State(pnode);
     652       24041 :     if (state == nullptr)
     653             :         return false;
     654       23949 :     if (state->fShouldBan) {
     655           0 :         return true;
     656             :     }
     657             :     return false;
     658             : }
     659             : 
     660          60 : static void CheckBlockSpam(NodeId nodeId, const uint256& hashBlock)
     661             : {
     662             :     // Block spam filtering
     663         120 :     if (!gArgs.GetBoolArg("-blockspamfilter", DEFAULT_BLOCK_SPAM_FILTER)) {
     664          37 :         return;
     665             :     }
     666             : 
     667          60 :     CNodeState* nodestate = nullptr;
     668          60 :     int blockReceivedHeight = 0;
     669          60 :     {
     670          60 :         LOCK(cs_main);
     671          60 :         nodestate = State(nodeId);
     672          97 :         if (!nodestate) { return; }
     673             : 
     674          60 :         CBlockIndex* pindex = LookupBlockIndex(hashBlock);
     675          60 :         if (!pindex) { return; }
     676          23 :         blockReceivedHeight = pindex->nHeight;
     677             :     }
     678             : 
     679          23 :     nodestate->nodeBlocks.onBlockReceived(blockReceivedHeight);
     680          23 :     bool nodeStatus = true;
     681             :     // UpdateState will return false if the node is attacking us or update the score and return true.
     682          46 :     CValidationState state;
     683          23 :     nodeStatus = nodestate->nodeBlocks.updateState(state, nodeStatus);
     684          23 :     int nDoS = 0;
     685          23 :     if (state.IsInvalid(nDoS)) {
     686           0 :         if (nDoS > 0) {
     687           0 :             LOCK(cs_main);
     688           0 :             Misbehaving(nodeId, nDoS);
     689             :         }
     690             :         nodeStatus = false;
     691             :     }
     692             : 
     693          23 :     if (!nodeStatus) {
     694           0 :         LogPrintf("Block spam protection: %s\n", hashBlock.ToString());
     695             :     }
     696             : }
     697             : 
     698             : 
     699             : //////////////////////////////////////////////////////////////////////////////
     700             : //
     701             : // blockchain -> download logic notification
     702             : //
     703             : 
     704         484 : PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn) :
     705         484 :         connman(connmanIn)
     706             : {
     707             :     // Initialize global variables that cannot be constructed at startup.
     708         484 :     recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
     709         484 : }
     710             : 
     711       38563 : void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindex)
     712             : {
     713       38563 :     LOCK(g_cs_orphans);
     714             : 
     715       77126 :     std::vector<uint256> vOrphanErase;
     716             : 
     717      271825 :     for (const CTransactionRef& ptx : pblock->vtx) {
     718      233262 :         const CTransaction& tx = *ptx;
     719             : 
     720             :         // Which orphan pool entries must we evict?
     721      610659 :         for (size_t j = 0; j < tx.vin.size(); j++) {
     722      377397 :             auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout);
     723      377397 :             if (itByPrev == mapOrphanTransactionsByPrev.end()) continue;
     724           0 :             for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) {
     725           0 :                 const CTransaction& orphanTx = *(*mi)->second.tx;
     726           0 :                 const uint256& orphanHash = orphanTx.GetHash();
     727           0 :                 vOrphanErase.emplace_back(orphanHash);
     728             :             }
     729             :         }
     730             :     }
     731             : 
     732             :     // Erase orphan transactions include or precluded by this block
     733       38563 :     if (!vOrphanErase.empty()) {
     734           0 :         int nErased = 0;
     735           0 :         for (uint256& orphanHash : vOrphanErase) {
     736           0 :             nErased += EraseOrphanTx(orphanHash);
     737             :         }
     738           0 :         LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);
     739             :     }
     740       38563 : }
     741             : 
     742       38497 : void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
     743             : {
     744       38497 :     const int nNewHeight = pindexNew->nHeight;
     745       38497 :     connman->SetBestHeight(nNewHeight);
     746             : 
     747       38497 :     if (!fInitialDownload) {
     748       37938 :         const uint256& hashNewTip = pindexNew->GetBlockHash();
     749             :         // Relay inventory, but don't relay old inventory during initial block download.
     750       37938 :         connman->ForEachNode([nNewHeight, hashNewTip](CNode* pnode) {
     751             :             // Don't sync from MN only connections.
     752      182759 :             if (!pnode->CanRelay()) {
     753             :                 return;
     754             :             }
     755      182465 :             if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
     756      182465 :                 pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
     757             :             }
     758             :         });
     759             :     }
     760       38497 : }
     761             : 
     762       38635 : void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state)
     763             : {
     764       38635 :     LOCK(cs_main);
     765             : 
     766       38635 :     const uint256& hash = block.GetHash();
     767       38635 :     std::map<uint256, NodeId>::iterator it = mapBlockSource.find(hash);
     768             : 
     769       38635 :     int nDoS = 0;
     770       38635 :     if (state.IsInvalid(nDoS)) {
     771          69 :         if (it != mapBlockSource.end() && State(it->second)) {
     772          60 :             assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
     773          60 :             if (nDoS > 0) {
     774         116 :                 Misbehaving(it->second, nDoS);
     775             :             }
     776             : 
     777             :             // Spam filter
     778          60 :             CheckBlockSpam(it->second, block.GetHash());
     779             :         }
     780             :     }
     781             : 
     782       38635 :     if (it != mapBlockSource.end())
     783       25468 :         mapBlockSource.erase(it);
     784       38635 : }
     785             : 
     786             : //////////////////////////////////////////////////////////////////////////////
     787             : //
     788             : // Messages
     789             : //
     790             : 
     791      352037 : bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
     792             : {
     793      352037 :     switch (inv.type) {
     794       22697 :     case MSG_TX: {
     795       22697 :         assert(recentRejects);
     796       45394 :         if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip) {
     797             :             // If the chain tip has changed previously rejected transactions
     798             :             // might be now valid, e.g. due to a nLockTime'd tx becoming valid,
     799             :             // or a double-spend. Reset the rejects filter and give those
     800             :             // txs a second chance.
     801        1290 :             hashRecentRejectsChainTip = chainActive.Tip()->GetBlockHash();
     802         645 :             recentRejects->reset();
     803             :         }
     804             : 
     805       22697 :         {
     806       22697 :             LOCK(g_cs_orphans);
     807       45397 :             if (mapOrphanTransactions.count(inv.hash)) return true;
     808             :         }
     809             : 
     810       45388 :         return recentRejects->contains(inv.hash) ||
     811       41585 :                mempool.exists(inv.hash) ||
     812       60416 :                pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 0)) || // Best effort: only try output 0 and 1
     813       41525 :                pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 1));
     814             :     }
     815             : 
     816      185877 :     case MSG_BLOCK:
     817      185877 :         return LookupBlockIndex(inv.hash) != nullptr;
     818             :     case MSG_TXLOCK_REQUEST:
     819             :         // deprecated
     820             :         return true;
     821             :     case MSG_TXLOCK_VOTE:
     822             :         // deprecated
     823             :         return true;
     824        2289 :     case MSG_SPORK:
     825        4578 :         return mapSporks.count(inv.hash);
     826        4051 :     case MSG_MASTERNODE_WINNER:
     827        6145 :         if (masternodePayments.mapMasternodePayeeVotes.count(inv.hash)) {
     828        1957 :             g_tiertwo_sync_state.AddedMasternodeWinner(inv.hash);
     829        1957 :             return true;
     830             :         }
     831             :         return false;
     832         517 :     case MSG_BUDGET_VOTE:
     833         517 :         if (g_budgetman.HaveSeenProposalVote(inv.hash)) {
     834         420 :             g_tiertwo_sync_state.AddedBudgetItem(inv.hash);
     835         420 :             return true;
     836             :         }
     837             :         return false;
     838        5678 :     case MSG_BUDGET_PROPOSAL:
     839        5678 :         if (g_budgetman.HaveProposal(inv.hash)) {
     840        5268 :             g_tiertwo_sync_state.AddedBudgetItem(inv.hash);
     841        5268 :             return true;
     842             :         }
     843             :         return false;
     844         469 :     case MSG_BUDGET_FINALIZED_VOTE:
     845         469 :         if (g_budgetman.HaveSeenFinalizedBudgetVote(inv.hash)) {
     846         383 :             g_tiertwo_sync_state.AddedBudgetItem(inv.hash);
     847         383 :             return true;
     848             :         }
     849             :         return false;
     850         358 :     case MSG_BUDGET_FINALIZED:
     851         358 :         if (g_budgetman.HaveFinalizedBudget(inv.hash)) {
     852         323 :             g_tiertwo_sync_state.AddedBudgetItem(inv.hash);
     853         323 :             return true;
     854             :         }
     855             :         return false;
     856         341 :     case MSG_MASTERNODE_ANNOUNCE:
     857         508 :         if (mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
     858         174 :             g_tiertwo_sync_state.AddedMasternodeList(inv.hash);
     859         174 :             return true;
     860             :         }
     861             :         return false;
     862      109874 :     case MSG_MASTERNODE_PING:
     863      219748 :         return mnodeman.mapSeenMasternodePing.count(inv.hash);
     864        1548 :     case MSG_QUORUM_FINAL_COMMITMENT:
     865        1548 :         return llmq::quorumBlockProcessor->HasMinableCommitment(inv.hash);
     866         958 :     case MSG_QUORUM_CONTRIB:
     867         958 :     case MSG_QUORUM_COMPLAINT:
     868         958 :     case MSG_QUORUM_JUSTIFICATION:
     869         958 :     case MSG_QUORUM_PREMATURE_COMMITMENT:
     870         958 :         return llmq::quorumDKGSessionManager->AlreadyHave(inv);
     871        8324 :     case MSG_QUORUM_RECOVERED_SIG:
     872        8324 :         return llmq::quorumSigningManager->AlreadyHave(inv);
     873        9056 :     case MSG_CLSIG:
     874        9056 :         return llmq::chainLocksHandler->AlreadyHave(inv);
     875             :     }
     876             : 
     877             :     // Don't know what it is, just say we already got one
     878             :     return true;
     879             : }
     880             : 
     881        9281 : static void RelayTransaction(const CTransaction& tx, CConnman* connman)
     882             : {
     883        9281 :     CInv inv(MSG_TX, tx.GetHash());
     884        9281 :     connman->RelayInv(inv);
     885        9281 : }
     886             : 
     887          21 : static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connman)
     888             : {
     889          21 :     if (!fReachable && !addr.IsRelayable()) return;
     890          21 :     unsigned int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s)
     891             : 
     892             :     // Relay to a limited number of other nodes
     893             :     // Use deterministic randomness to send to the same nodes for 24 hours
     894             :     // at a time so the addrKnowns of the chosen nodes prevent repeats
     895          21 :     uint64_t hashAddr = addr.GetHash();
     896          21 :     const CSipHasher hasher = connman->GetDeterministicRandomizer(RANDOMIZER_ID_ADDRESS_RELAY).Write(hashAddr << 32).Write((GetTime() + hashAddr) / (24*60*60));
     897          21 :     FastRandomContext insecure_rand;
     898             : 
     899          21 :     std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
     900             : 
     901          41 :     auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
     902          41 :         uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
     903          48 :         for (unsigned int i = 0; i < nRelayNodes; i++) {
     904          48 :             if (hashKey > best[i].first) {
     905          41 :                 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
     906          41 :                 best[i] = std::make_pair(hashKey, pnode);
     907          41 :                 break;
     908             :             }
     909             :         }
     910          41 :     };
     911             : 
     912         187 :     auto pushfunc = [&addr, &best, nRelayNodes, &insecure_rand] {
     913          62 :         for (unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
     914          41 :             best[i].second->PushAddress(addr, insecure_rand);
     915             :         }
     916          42 :     };
     917             : 
     918          21 :     connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
     919             : }
     920             : 
     921        6209 : bool static PushTierTwoGetDataRequest(const CInv& inv,
     922             :                                       CNode* pfrom,
     923             :                                       CConnman* connman,
     924             :                                       CNetMsgMaker& msgMaker)
     925             : {
     926        6209 :     if (inv.type == MSG_SPORK) {
     927         184 :         if (mapSporks.count(inv.hash)) {
     928         368 :             CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     929         184 :             ss.reserve(1000);
     930         184 :             ss << mapSporks[inv.hash];
     931         184 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SPORK, ss));
     932         184 :             return true;
     933             :         }
     934             :     }
     935             : 
     936        6025 :     if (inv.type == MSG_QUORUM_FINAL_COMMITMENT) {
     937             :         // Only respond if v6.0.0 is enforced and SPORK 22 is not active
     938          84 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
     939          84 :         if (sporkManager.IsSporkActive(SPORK_22_LLMQ_DKG_MAINTENANCE)) return false;
     940          85 :         llmq::CFinalCommitment o;
     941          84 :         if (llmq::quorumBlockProcessor->GetMinableCommitmentByHash(inv.hash, o)) {
     942          83 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QFCOMMITMENT, o));
     943         166 :             return true;
     944             :         }
     945             :     }
     946             : 
     947        5942 :     if (inv.type == MSG_QUORUM_CONTRIB) {
     948             :         // Only respond if v6.0.0 is enforced.
     949         231 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
     950         126 :         llmq::CDKGContribution o;
     951         119 :         if (llmq::quorumDKGSessionManager->GetContribution(inv.hash, o)) {
     952         112 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QCONTRIB, o));
     953         112 :             return true;
     954             :         }
     955             :     }
     956             : 
     957        5830 :     if (inv.type == MSG_QUORUM_COMPLAINT) {
     958             :         // Only respond if v6.0.0 is enforced.
     959          36 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
     960          47 :         llmq::CDKGComplaint o;
     961          36 :         if (llmq::quorumDKGSessionManager->GetComplaint(inv.hash, o)) {
     962          25 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QCOMPLAINT, o));
     963          50 :             return true;
     964             :         }
     965             :     }
     966             : 
     967        5805 :     if (inv.type == MSG_QUORUM_JUSTIFICATION) {
     968             :         // Only respond if v6.0.0 is enforced.
     969           8 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
     970           8 :         llmq::CDKGJustification o;
     971           8 :         if (llmq::quorumDKGSessionManager->GetJustification(inv.hash, o)) {
     972           8 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QJUSTIFICATION, o));
     973           8 :             return true;
     974             :         }
     975             :     }
     976             : 
     977        5797 :     if (inv.type == MSG_QUORUM_PREMATURE_COMMITMENT) {
     978             :         // Only respond if v6.0.0 is enforced.
     979          90 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
     980          90 :         llmq::CDKGPrematureCommitment o;
     981          90 :         if (llmq::quorumDKGSessionManager->GetPrematureCommitment(inv.hash, o)) {
     982          90 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QPCOMMITMENT, o));
     983         180 :             return true;
     984             :         }
     985             :     }
     986             : 
     987             :     // !TODO: remove when transition to DMN is complete
     988        5707 :     if (inv.type == MSG_MASTERNODE_WINNER && !deterministicMNManager->LegacyMNObsolete()) {
     989         922 :         if (masternodePayments.mapMasternodePayeeVotes.count(inv.hash)) {
     990        1844 :             CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
     991         922 :             ss.reserve(1000);
     992         922 :             ss << masternodePayments.mapMasternodePayeeVotes[inv.hash];
     993         922 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MNWINNER, ss));
     994         922 :             return true;
     995             :         }
     996             :     }
     997             : 
     998        4785 :     if (inv.type == MSG_BUDGET_VOTE) {
     999          38 :         if (g_budgetman.HaveSeenProposalVote(inv.hash)) {
    1000          38 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BUDGETVOTE, g_budgetman.GetProposalVoteSerialized(inv.hash)));
    1001          38 :             return true;
    1002             :         }
    1003             :     }
    1004             : 
    1005        4747 :     if (inv.type == MSG_BUDGET_PROPOSAL) {
    1006         163 :         if (g_budgetman.HaveProposal(inv.hash)) {
    1007         163 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BUDGETPROPOSAL, g_budgetman.GetProposalSerialized(inv.hash)));
    1008         163 :             return true;
    1009             :         }
    1010             :     }
    1011             : 
    1012        4584 :     if (inv.type == MSG_BUDGET_FINALIZED_VOTE) {
    1013          31 :         if (g_budgetman.HaveSeenFinalizedBudgetVote(inv.hash)) {
    1014          31 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::FINALBUDGETVOTE, g_budgetman.GetFinalizedBudgetVoteSerialized(inv.hash)));
    1015          31 :             return true;
    1016             :         }
    1017             :     }
    1018             : 
    1019        4553 :     if (inv.type == MSG_BUDGET_FINALIZED) {
    1020          14 :         if (g_budgetman.HaveFinalizedBudget(inv.hash)) {
    1021          14 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::FINALBUDGET, g_budgetman.GetFinalizedBudgetSerialized(inv.hash)));
    1022          14 :             return true;
    1023             :         }
    1024             :     }
    1025             : 
    1026             :     // !TODO: remove when transition to DMN is complete
    1027        4539 :     if (inv.type == MSG_MASTERNODE_ANNOUNCE && !deterministicMNManager->LegacyMNObsolete()) {
    1028          68 :         auto it = mnodeman.mapSeenMasternodeBroadcast.find(inv.hash);
    1029          68 :         if (it != mnodeman.mapSeenMasternodeBroadcast.end()) {
    1030          68 :             const auto& mnb = it->second;
    1031             : 
    1032          68 :             int version = !mnb.addr.IsAddrV1Compatible() ? PROTOCOL_VERSION | ADDRV2_FORMAT : PROTOCOL_VERSION;
    1033         136 :             CDataStream ss(SER_NETWORK, version);
    1034          68 :             ss.reserve(1000);
    1035          68 :             ss << mnb;
    1036         136 :             std::string msgType = !mnb.addr.IsAddrV1Compatible() ? NetMsgType::MNBROADCAST2 : NetMsgType::MNBROADCAST;
    1037         136 :             connman->PushMessage(pfrom, msgMaker.Make(msgType, ss));
    1038          68 :             return true;
    1039             :         }
    1040             :     }
    1041             : 
    1042             :     // !TODO: remove when transition to DMN is complete
    1043        4471 :     if (inv.type == MSG_MASTERNODE_PING && !deterministicMNManager->LegacyMNObsolete()) {
    1044        2129 :         if (mnodeman.mapSeenMasternodePing.count(inv.hash)) {
    1045        4242 :             CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    1046        2121 :             ss.reserve(1000);
    1047        2121 :             ss << mnodeman.mapSeenMasternodePing[inv.hash];
    1048        2121 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MNPING, ss));
    1049        2121 :             return true;
    1050             :         }
    1051             :     }
    1052        2350 :     if (inv.type == MSG_QUORUM_RECOVERED_SIG) {
    1053        1664 :         if (!deterministicMNManager->IsDIP3Enforced()) return false;
    1054        1664 :         llmq::CRecoveredSig o;
    1055        1664 :         if (llmq::quorumSigningManager->GetRecoveredSigForGetData(inv.hash, o)) {
    1056        1664 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::QSIGREC, o));
    1057        3328 :             return true;
    1058             :         }
    1059             :     }
    1060         686 :     if (inv.type == MSG_CLSIG) {
    1061         661 :         llmq::CChainLockSig o;
    1062         661 :         if (llmq::chainLocksHandler->GetChainLockByHash(inv.hash, o)) {
    1063         635 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CLSIG, o));
    1064             :         }
    1065             :     }
    1066             :     // nothing was pushed.
    1067             :     return false;
    1068             : }
    1069             : 
    1070       49726 : void static ProcessGetBlockData(CNode* pfrom, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
    1071             : {
    1072       49726 :     LOCK(cs_main);
    1073       49726 :     CNetMsgMaker msgMaker(pfrom->GetSendVersion());
    1074             : 
    1075       49726 :     bool send = false;
    1076       49726 :     CBlockIndex* pindex = LookupBlockIndex(inv.hash);
    1077       49726 :     if (pindex) {
    1078       99452 :         if (chainActive.Contains(pindex)) {
    1079             :             send = true;
    1080             :         } else {
    1081             :             // To prevent fingerprinting attacks, only send blocks outside of the active
    1082             :             // chain if they are valid, and no more than a max reorg depth than the best header
    1083             :             // chain we know about.
    1084           0 :             send = pindex->IsValid(BLOCK_VALID_SCRIPTS) && pindexBestHeader &&
    1085           0 :                    (chainActive.Height() - pindex->nHeight < gArgs.GetArg("-maxreorg", DEFAULT_MAX_REORG_DEPTH));
    1086           0 :             if (!send) {
    1087           0 :                 LogPrint(BCLog::NET, "ProcessGetData(): ignoring request from peer=%i for old block that isn't in the main chain\n", pfrom->GetId());
    1088             :             }
    1089             :         }
    1090             :     }
    1091             :     // Don't send not-validated blocks
    1092       49726 :     if (send && (pindex->nStatus & BLOCK_HAVE_DATA)) {
    1093             :         // Send block from disk
    1094       99452 :         CBlock block;
    1095       49726 :         if (!ReadBlockFromDisk(block, pindex))
    1096           0 :             assert(!"cannot load block from disk");
    1097       49726 :         if (inv.type == MSG_BLOCK)
    1098       49726 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, block));
    1099             :         else // MSG_FILTERED_BLOCK)
    1100             :         {
    1101           0 :             bool send_ = false;
    1102           0 :             CMerkleBlock merkleBlock;
    1103           0 :             {
    1104           0 :                 LOCK(pfrom->cs_filter);
    1105           0 :                 if (pfrom->pfilter) {
    1106           0 :                     send_ = true;
    1107           0 :                     merkleBlock = CMerkleBlock(block, *pfrom->pfilter);
    1108             :                 }
    1109             :             }
    1110           0 :             if (send_) {
    1111           0 :                 connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
    1112             :                 // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
    1113             :                 // This avoids hurting performance by pointlessly requiring a round-trip
    1114             :                 // Note that there is currently no way for a node to request any single transactions we didn't send here -
    1115             :                 // they must either disconnect and retry or request the full block.
    1116             :                 // Thus, the protocol spec specified allows for us to provide duplicate txn here,
    1117             :                 // however we MUST always provide at least what the remote peer needs
    1118           0 :                 for (std::pair<unsigned int, uint256>& pair : merkleBlock.vMatchedTxn)
    1119           0 :                     connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *block.vtx[pair.first]));
    1120             :             }
    1121             :             // else
    1122             :             // no response
    1123             :         }
    1124             : 
    1125             :         // Trigger them to send a getblocks request for the next batch of inventory
    1126       49726 :         if (inv.hash == pfrom->hashContinue) {
    1127             :             // Bypass PushInventory, this must send even if redundant,
    1128             :             // and we want it right after the last block so they don't
    1129             :             // wait for other stuff first.
    1130           0 :             std::vector<CInv> vInv;
    1131           0 :             vInv.emplace_back(MSG_BLOCK, chainActive.Tip()->GetBlockHash());
    1132           0 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::INV, vInv));
    1133           0 :             pfrom->hashContinue.SetNull();
    1134             :         }
    1135             :     }
    1136       49726 : }
    1137             : 
    1138             : // Only return true if the inv type can be answered, not supported types return false.
    1139       55933 : bool static IsTierTwoInventoryTypeKnown(int type)
    1140             : {
    1141       55933 :     return type == MSG_SPORK ||
    1142       55933 :            type == MSG_MASTERNODE_WINNER ||
    1143       55933 :            type == MSG_BUDGET_VOTE ||
    1144       54789 :            type == MSG_BUDGET_PROPOSAL ||
    1145             :            type == MSG_BUDGET_FINALIZED ||
    1146       54612 :            type == MSG_BUDGET_FINALIZED_VOTE ||
    1147       54612 :            type == MSG_MASTERNODE_ANNOUNCE ||
    1148       54513 :            type == MSG_MASTERNODE_PING ||
    1149       54513 :            type == MSG_QUORUM_FINAL_COMMITMENT ||
    1150       52304 :            type == MSG_QUORUM_CONTRIB ||
    1151             :            type == MSG_QUORUM_COMPLAINT ||
    1152       52149 :            type == MSG_QUORUM_JUSTIFICATION ||
    1153             :            type == MSG_QUORUM_PREMATURE_COMMITMENT ||
    1154      107984 :            type == MSG_QUORUM_RECOVERED_SIG ||
    1155       55933 :            type == MSG_CLSIG;
    1156             : }
    1157             : 
    1158       55673 : void static ProcessGetData(CNode* pfrom, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
    1159             : {
    1160       55673 :     AssertLockNotHeld(cs_main);
    1161             : 
    1162       55673 :     std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
    1163      111346 :     std::vector<CInv> vNotFound;
    1164       55673 :     CNetMsgMaker msgMaker(pfrom->GetSendVersion());
    1165       55673 :     {
    1166       55673 :         LOCK(cs_main);
    1167             : 
    1168       71162 :         while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || IsTierTwoInventoryTypeKnown(it->type))) {
    1169       15489 :             if (interruptMsgProc)
    1170           0 :                 return;
    1171             :             // Don't bother if send buffer is too full to respond anyway
    1172       15489 :             if (pfrom->fPauseSend)
    1173             :                 break;
    1174             : 
    1175       15489 :             const CInv &inv = *it;
    1176       15489 :             it++;
    1177             : 
    1178             :             // Send stream from relay memory
    1179       15489 :             bool pushed = false;
    1180       15489 :             if (inv.type == MSG_TX) {
    1181        9282 :                 auto txinfo = mempool.info(inv.hash);
    1182        9282 :                 if (txinfo.tx) { // future: add timeLastMempoolReq check
    1183       18560 :                     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
    1184        9280 :                     ss.reserve(1000);
    1185        9280 :                     ss << *txinfo.tx;
    1186        9280 :                     connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, ss));
    1187        9280 :                     pushed = true;
    1188             :                 }
    1189             :             }
    1190             : 
    1191        9282 :             if (!pushed) {
    1192             :                 // Now check if it's a tier two data request and push it.
    1193        6209 :                 pushed = PushTierTwoGetDataRequest(inv, pfrom, connman, msgMaker);
    1194             :             }
    1195             : 
    1196       15489 :             if (!pushed) {
    1197         686 :                 vNotFound.push_back(inv);
    1198             :             }
    1199             : 
    1200             :             // todo: inventory signal
    1201             :         }
    1202             :     } // release cs_main
    1203             : 
    1204       55673 :     if (it != pfrom->vRecvGetData.end() && !pfrom->fPauseSend) {
    1205       49726 :         const CInv &inv = *it;
    1206       49726 :         if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) {
    1207       49726 :             it++;
    1208       49726 :             ProcessGetBlockData(pfrom, inv, connman, interruptMsgProc);
    1209             :         }
    1210             :     }
    1211             : 
    1212       55673 :     pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);
    1213             : 
    1214       55673 :     if (!vNotFound.empty()) {
    1215             :         // Let the peer know that we didn't find what it asked for, so it doesn't
    1216             :         // have to wait around forever. Currently only SPV clients actually care
    1217             :         // about this message: it's needed when they are recursively walking the
    1218             :         // dependencies of relevant unconfirmed transactions. SPV clients want to
    1219             :         // do that because they want to know about (and store and rebroadcast and
    1220             :         // risk analyze) the dependencies of transactions relevant to them, without
    1221             :         // having to download the entire memory pool.
    1222         679 :         connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound));
    1223             :     }
    1224             : }
    1225             : 
    1226             : bool fRequestedSporksIDB = false;
    1227      372487 : bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vRecv, int64_t nTimeReceived, CConnman* connman, std::atomic<bool>& interruptMsgProc)
    1228             : {
    1229      739408 :     LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
    1230      744974 :     if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0) {
    1231           0 :         LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
    1232           0 :         return true;
    1233             :     }
    1234             : 
    1235      372487 :     if (strCommand == NetMsgType::VERSION) {
    1236             :         // Each connection can only send one version message
    1237        1360 :         if (pfrom->nVersion != 0) {
    1238           0 :             LOCK(cs_main);
    1239           0 :             Misbehaving(pfrom->GetId(), 1);
    1240           0 :             return false;
    1241             :         }
    1242             : 
    1243        1360 :         int64_t nTime;
    1244        2720 :         CAddress addrMe;
    1245        2720 :         CAddress addrFrom;
    1246        1360 :         uint64_t nNonce = 1;
    1247        1360 :         uint64_t nServiceInt;
    1248        1360 :         ServiceFlags nServices;
    1249        1360 :         int nVersion;
    1250        1360 :         int nSendVersion;
    1251        2720 :         std::string strSubVer;
    1252        1360 :         std::string cleanSubVer;
    1253        1360 :         int nStartingHeight = -1;
    1254        1360 :         bool fRelay = true;
    1255        1360 :         vRecv >> nVersion >> nServiceInt >> nTime >> addrMe;
    1256        1360 :         nSendVersion = std::min(nVersion, PROTOCOL_VERSION);
    1257        1360 :         nServices = ServiceFlags(nServiceInt);
    1258        1360 :         if (!pfrom->fInbound) {
    1259         647 :             connman->SetServices(pfrom->addr, nServices);
    1260             :         }
    1261        1360 :         if (pfrom->nServicesExpected & ~nServices) {
    1262           0 :             LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, pfrom->nServicesExpected);
    1263           0 :             pfrom->fDisconnect = true;
    1264           0 :             return false;
    1265             :         }
    1266             : 
    1267        1360 :         if (pfrom->DisconnectOldProtocol(nVersion, ActiveProtocol())) {
    1268             :             return false;
    1269             :         }
    1270             : 
    1271        1359 :         if (nVersion == 10300)
    1272           0 :             nVersion = 300;
    1273        1359 :         if (!vRecv.empty())
    1274        1359 :             vRecv >> addrFrom >> nNonce;
    1275        1359 :         if (!vRecv.empty()) {
    1276        1359 :             vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
    1277        1359 :             cleanSubVer = SanitizeString(strSubVer);
    1278             :         }
    1279        1359 :         if (!vRecv.empty()) {
    1280        1359 :             vRecv >> nStartingHeight;
    1281             :         }
    1282        1359 :         if (!vRecv.empty()) {
    1283        1359 :             vRecv >> fRelay;
    1284             :         }
    1285             :         // Check if this is a quorum connection
    1286        1359 :         if (!vRecv.empty()) {
    1287         609 :             WITH_LOCK(pfrom->cs_mnauth, vRecv >> pfrom->receivedMNAuthChallenge;);
    1288         203 :             bool fOtherMasternode = !pfrom->receivedMNAuthChallenge.IsNull();
    1289         203 :             if (pfrom->fInbound) {
    1290         102 :                 pfrom->m_masternode_connection = fOtherMasternode;
    1291         102 :                 if (fOtherMasternode) {
    1292         102 :                     LogPrint(BCLog::NET, "peer=%d is an inbound masternode connection, not relaying anything to it\n", pfrom->GetId());
    1293         102 :                     if (!fMasterNode) { // global MN flag
    1294           1 :                         LogPrint(BCLog::NET, "but we're not a masternode, disconnecting\n");
    1295           1 :                         pfrom->fDisconnect = true;
    1296           1 :                         return true;
    1297             :                     }
    1298             :                 }
    1299             :             }
    1300             :         }
    1301             : 
    1302             :         // Disconnect if we connected to ourself
    1303        1358 :         if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce)) {
    1304           0 :             LogPrintf("connected to self at %s, disconnecting\n", pfrom->addr.ToString());
    1305           0 :             pfrom->fDisconnect = true;
    1306           0 :             return true;
    1307             :         }
    1308             : 
    1309        1358 :         if (pfrom->fInbound && addrMe.IsRoutable()) {
    1310           0 :             SeenLocal(addrMe);
    1311             :         }
    1312             : 
    1313             :         // Be shy and don't send version until we hear
    1314        1358 :         if (pfrom->fInbound)
    1315         711 :             PushNodeVersion(pfrom, connman, GetAdjustedTime());
    1316             : 
    1317        1358 :         CNetMsgMaker msg_maker(INIT_PROTO_VERSION);
    1318             : 
    1319        1358 :         if (nVersion >= 70923) {
    1320             :             // BIP155 defines addrv2 and sendaddrv2 for all protocol versions, but some
    1321             :             // implementations reject messages they don't know. As a courtesy, don't send
    1322             :             // it to nodes with a version before 70923 (v5.2.99), as no software is known to support
    1323             :             // BIP155 that doesn't announce at least that protocol version number.
    1324             : 
    1325        1358 :             connman->PushMessage(pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
    1326             :         }
    1327             : 
    1328        1358 :         connman->PushMessage(pfrom, msg_maker.Make(NetMsgType::VERACK));
    1329             : 
    1330        1358 :         pfrom->nServices = nServices;
    1331        1358 :         pfrom->SetAddrLocal(addrMe);
    1332        1358 :         {
    1333        1358 :             LOCK(pfrom->cs_SubVer);
    1334        1358 :             pfrom->strSubVer = strSubVer;
    1335        1358 :             pfrom->cleanSubVer = cleanSubVer;
    1336             :         }
    1337        1358 :         pfrom->nStartingHeight = nStartingHeight;
    1338        1358 :         pfrom->fClient = !(nServices & NODE_NETWORK);
    1339             : 
    1340        1358 :         {
    1341        1358 :             LOCK(pfrom->cs_filter);
    1342        1358 :             pfrom->fRelayTxes = fRelay; // set to true after we get the first filter* message
    1343             :         }
    1344             : 
    1345             :         // Change version
    1346        1358 :         pfrom->SetSendVersion(nSendVersion);
    1347        1358 :         pfrom->nVersion = nVersion;
    1348             : 
    1349        1358 :         {
    1350        1358 :             LOCK(cs_main);
    1351             :             // Potentially mark this peer as a preferred download peer.
    1352        1358 :             UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
    1353             :         }
    1354             : 
    1355        1358 :         if (!pfrom->fInbound) {
    1356             :             // Advertise our address
    1357         647 :             if (fListen && !IsInitialBlockDownload()) {
    1358         430 :                 CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices());
    1359         215 :                 FastRandomContext insecure_rand;
    1360         215 :                 if (addr.IsRoutable()) {
    1361           0 :                     LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString());
    1362           0 :                     pfrom->PushAddress(addr, insecure_rand);
    1363         215 :                 } else if (IsPeerAddrLocalGood(pfrom)) {
    1364           0 :                     addr.SetIP(addrMe);
    1365           0 :                     LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString());
    1366           0 :                     pfrom->PushAddress(addr, insecure_rand);
    1367             :                 }
    1368             :             }
    1369             : 
    1370             :             // Get recent addresses
    1371         647 :             connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETADDR));
    1372         647 :             pfrom->fGetAddr = true;
    1373             :             // When requesting a getaddr, accept an additional MAX_ADDR_TO_SEND addresses in response
    1374             :             // (bypassing the MAX_ADDR_PROCESSING_TOKEN_BUCKET limit).
    1375         647 :             pfrom->m_addr_token_bucket += MAX_ADDR_TO_SEND;
    1376         647 :             connman->MarkAddressGood(pfrom->addr);
    1377             :         }
    1378             : 
    1379        2718 :         std::string remoteAddr;
    1380        1358 :         if (fLogIPs)
    1381           0 :             remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
    1382             : 
    1383        2692 :         LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
    1384             :             cleanSubVer, pfrom->nVersion,
    1385             :             pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(),
    1386             :             remoteAddr);
    1387             : 
    1388        1358 :         int64_t nTimeOffset = nTime - GetTime();
    1389        1358 :         pfrom->nTimeOffset = nTimeOffset;
    1390        1358 :         const int nTimeSlotLength = Params().GetConsensus().nTimeSlotLength;
    1391        1358 :         if (abs64(nTimeOffset) < 2 * nTimeSlotLength) {
    1392        1355 :             AddTimeData(pfrom->addr, nTimeOffset, nTimeSlotLength);
    1393             :         } else {
    1394           6 :             LogPrintf("timeOffset (%d seconds) too large. Disconnecting node %s\n",
    1395           3 :                     nTimeOffset, pfrom->addr.ToString().c_str());
    1396           3 :             pfrom->fDisconnect = true;
    1397           3 :             CheckOffsetDisconnectedPeers(pfrom->addr);
    1398             :         }
    1399             : 
    1400             :         // Feeler connections exist only to verify if address is online.
    1401        1358 :         if (pfrom->fFeeler) {
    1402           0 :             assert(pfrom->fInbound == false);
    1403           0 :             pfrom->fDisconnect = true;
    1404             :         }
    1405             : 
    1406             :         // PIVX: We use certain sporks during IBD, so check to see if they are
    1407             :         // available. If not, ask the first peer connected for them.
    1408             :         // TODO: Move this to an instant broadcast of the sporks.
    1409        1358 :         bool fMissingSporks = !pSporkDB->SporkExists(SPORK_14_NEW_PROTOCOL_ENFORCEMENT) ||
    1410           0 :                               !pSporkDB->SporkExists(SPORK_15_NEW_PROTOCOL_ENFORCEMENT_2) ||
    1411        1358 :                               !pSporkDB->SporkExists(SPORK_19_COLDSTAKING_MAINTENANCE) ||
    1412           0 :                               !pSporkDB->SporkExists(SPORK_20_SAPLING_MAINTENANCE);
    1413             : 
    1414           0 :         if (fMissingSporks || !fRequestedSporksIDB){
    1415        1358 :             LogPrintf("asking peer for sporks\n");
    1416        1358 :             connman->PushMessage(pfrom, CNetMsgMaker(nSendVersion).Make(NetMsgType::GETSPORKS));
    1417        1358 :             fRequestedSporksIDB = true;
    1418             :         }
    1419             : 
    1420        1358 :         return true;
    1421             :     }
    1422             : 
    1423             : 
    1424      371127 :     else if (pfrom->nVersion == 0) {
    1425             :         // Must have a version message before anything else
    1426          24 :         LOCK(cs_main);
    1427          12 :         Misbehaving(pfrom->GetId(), 1);
    1428          12 :         return false;
    1429             :     }
    1430             : 
    1431             :     // At this point, the outgoing message serialization version can't change.
    1432      371115 :     CNetMsgMaker msgMaker(pfrom->GetSendVersion());
    1433             : 
    1434      371115 :     if (strCommand == NetMsgType::VERACK) {
    1435        1353 :         pfrom->SetRecvVersion(std::min(pfrom->nVersion.load(), PROTOCOL_VERSION));
    1436             : 
    1437        1353 :         if (!pfrom->fInbound) {
    1438             :             // Mark this node as currently connected, so we update its timestamp later.
    1439        1292 :             LOCK(cs_main);
    1440         646 :             State(pfrom->GetId())->fCurrentlyConnected = true;
    1441             :         }
    1442             : 
    1443        1353 :         if (pfrom->nVersion >= MNAUTH_NODE_VER_VERSION && !pfrom->m_masternode_probe_connection) {
    1444             :             // Only relayed if this is a mn connection
    1445        1307 :             CMNAuth::PushMNAUTH(pfrom, *connman);
    1446             :         }
    1447             : 
    1448        1353 :         pfrom->fSuccessfullyConnected = true;
    1449        1353 :         LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s\n",
    1450        1353 :                   pfrom->nVersion.load(), pfrom->nStartingHeight, pfrom->GetId(),
    1451        2706 :                   (fLogIPs ? strprintf(", peeraddr=%s", pfrom->addr.ToString()) : ""));
    1452        1353 :         return true;
    1453             :     }
    1454             : 
    1455      369762 :     else if (strCommand == NetMsgType::SENDADDRV2) {
    1456        1292 :         pfrom->m_wants_addrv2 = true;
    1457        1292 :         return true;
    1458             :     }
    1459             : 
    1460      368470 :     else if (!pfrom->fSuccessfullyConnected)
    1461             :     {
    1462             :         // Must have a verack message before anything else
    1463           8 :         LOCK(cs_main);
    1464           4 :         Misbehaving(pfrom->GetId(), 1);
    1465           4 :         return false;
    1466             :     }
    1467             : 
    1468      368466 :     else if (strCommand == NetMsgType::QSENDRECSIGS) {
    1469         105 :         bool b;
    1470         105 :         vRecv >> b;
    1471         105 :         if (pfrom->m_wants_recsigs == b) return true;
    1472             :         // Only accept recsigs messages every 20 min to prevent spam.
    1473         105 :         int64_t nNow = GetAdjustedTime();
    1474         105 :         if (pfrom->m_last_wants_recsigs_recv > 0 &&
    1475           0 :             nNow - pfrom->m_last_wants_recsigs_recv < 20 * 60) {
    1476           0 :             LOCK(cs_main);
    1477           0 :             Misbehaving(pfrom->GetId(), 20, "sendrecssigs msg is only accepted every 20 minutes");
    1478           0 :             return false;
    1479             :         }
    1480         105 :         pfrom->m_wants_recsigs = b;
    1481         105 :         pfrom->m_last_wants_recsigs_recv = nNow;
    1482             :         // Check if this is a iqr connection, and update the value
    1483             :         // if we haven't updated the connection during:
    1484             :         // (1) the relay quorum set function call, and (2) the verack receive.
    1485         105 :         connman->UpdateQuorumRelayMemberIfNeeded(pfrom);
    1486         105 :         return true;
    1487             :     }
    1488             : 
    1489      368361 :     if (strCommand != NetMsgType::GETSPORKS &&
    1490      368361 :         strCommand != NetMsgType::SPORK &&
    1491      364833 :         !pfrom->fFirstMessageReceived.exchange(true)) {
    1492             :         // First message after VERSION/VERACK (without counting the GETSPORKS/SPORK messages)
    1493        1352 :         pfrom->fFirstMessageReceived = true;
    1494        1352 :         pfrom->fFirstMessageIsMNAUTH = strCommand == NetMsgType::MNAUTH;
    1495        1352 :         if (pfrom->m_masternode_probe_connection && !pfrom->fFirstMessageIsMNAUTH) {
    1496           0 :             LogPrint(BCLog::NET, "masternode probe connection first received message is not a MNAUTH, disconnecting peer=%d\n", pfrom->GetId());
    1497           0 :             pfrom->fDisconnect = true;
    1498           0 :             return false;
    1499             :         }
    1500             :     }
    1501             : 
    1502      368361 :     if (strCommand == NetMsgType::ADDR || strCommand == NetMsgType::ADDRV2) {
    1503          13 :         int stream_version = vRecv.GetVersion();
    1504          13 :         if (strCommand == NetMsgType::ADDRV2) {
    1505             :             // Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
    1506             :             // unserialize methods know that an address in v2 format is coming.
    1507           6 :             stream_version |= ADDRV2_FORMAT;
    1508             :         }
    1509             : 
    1510          13 :         OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), stream_version);
    1511          22 :         std::vector<CAddress> vAddr;
    1512          13 :         s >> vAddr;
    1513             : 
    1514          11 :         if (vAddr.size() > MAX_ADDR_TO_SEND) {
    1515           4 :             LOCK(cs_main);
    1516           2 :             Misbehaving(pfrom->GetId(), 20, strprintf("%s message size = %u", strCommand, vAddr.size()));
    1517           2 :             return false;
    1518             :         }
    1519             : 
    1520             :         // Store the new addresses
    1521           9 :         std::vector<CAddress> vAddrOk;
    1522           9 :         int64_t nNow = GetAdjustedTime();
    1523           9 :         int64_t nSince = nNow - 10 * 60;
    1524             : 
    1525             :         // Update/increment addr rate limiting bucket.
    1526             :         // TODO: Slight time improvement calculation, continue backporting
    1527           9 :         const auto current_time = GetTime<std::chrono::microseconds>();
    1528           9 :         if (pfrom->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
    1529             :             // Don't increment bucket if it's already full
    1530           9 :             const auto time_diff = std::max(current_time - pfrom->m_addr_token_timestamp, 0us);
    1531           9 :             const double increment = CountSecondsDouble(time_diff) * MAX_ADDR_RATE_PER_SECOND;
    1532           9 :             pfrom->m_addr_token_bucket = std::min<double>(pfrom->m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET);
    1533             :             }
    1534           9 :         pfrom->m_addr_token_timestamp = current_time;
    1535             : 
    1536           9 :         uint64_t num_proc = 0;
    1537           9 :         uint64_t num_rate_limit = 0;
    1538           9 :         Shuffle(vAddr.begin(), vAddr.end(), FastRandomContext());
    1539             : 
    1540        1441 :         for (CAddress& addr : vAddr) {
    1541        1432 :             if (interruptMsgProc)
    1542           0 :                 return true;
    1543             : 
    1544             :             // Apply rate limiting.
    1545        1432 :             if (pfrom->m_addr_token_bucket < 1.0) {
    1546        1290 :                     ++num_rate_limit;
    1547        1290 :                     continue;
    1548             :             } else {
    1549         142 :                 pfrom->m_addr_token_bucket -= 1.0;
    1550             :             }
    1551             : 
    1552         142 :             if ((addr.nServices & REQUIRED_SERVICES) != REQUIRED_SERVICES)
    1553           0 :                 continue;
    1554             : 
    1555         142 :             if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
    1556          20 :                 addr.nTime = nNow - 5 * 24 * 60 * 60;
    1557         142 :             pfrom->AddAddressKnown(addr);
    1558         142 :             if (connman->IsBanned(addr)) continue; // Do not process banned addresses beyond remembering we received them
    1559         142 :             ++num_proc;
    1560         142 :             bool fReachable = IsReachable(addr);
    1561         142 :             if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) {
    1562             :                 // Relay to a limited number of other nodes
    1563          21 :                 RelayAddress(addr, fReachable, connman);
    1564             :             }
    1565             :             // Do not store addresses outside our network
    1566         142 :             if (fReachable)
    1567         142 :                 vAddrOk.push_back(addr);
    1568             :         }
    1569           9 :         CNodeState* state = State(pfrom->GetId());
    1570           9 :         state->amt_addr_processed += num_proc;
    1571           9 :         state->amt_addr_rate_limited += num_rate_limit;
    1572           9 :         LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
    1573             :                  vAddr.size(), num_proc, num_rate_limit, pfrom->GetId());
    1574           9 :         connman->AddNewAddresses(vAddrOk, pfrom->addr, 2 * 60 * 60);
    1575           9 :         if (vAddr.size() < 1000)
    1576           9 :             pfrom->fGetAddr = false;
    1577           9 :         if (pfrom->fOneShot)
    1578           9 :             pfrom->fDisconnect = true;
    1579             :     }
    1580             : 
    1581      368348 :     else if (strCommand == NetMsgType::INV) {
    1582      358067 :         std::vector<CInv> vInv;
    1583      179034 :         vRecv >> vInv;
    1584      179034 :         if (vInv.size() > MAX_INV_SZ) {
    1585           2 :             LOCK(cs_main);
    1586           1 :             Misbehaving(pfrom->GetId(), 20, strprintf("message inv size() = %u", vInv.size()));
    1587           1 :             return false;
    1588             :         }
    1589             : 
    1590      358066 :         LOCK(cs_main);
    1591             : 
    1592      358066 :         std::vector<CInv> vToFetch;
    1593             : 
    1594      465324 :         for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
    1595      286291 :             const CInv& inv = vInv[nInv];
    1596             : 
    1597      286291 :             if (interruptMsgProc)
    1598           0 :                 return true;
    1599             : 
    1600             :             // Reject deprecated messages
    1601      286291 :             if (inv.type == MSG_TXLOCK_REQUEST || inv.type == MSG_TXLOCK_VOTE) {
    1602           0 :                 Misbehaving(pfrom->GetId(), 100, strprintf("message inv deprecated %d", (int)inv.type));
    1603           0 :                 return false;
    1604             :             }
    1605             : 
    1606      286291 :             pfrom->AddInventoryKnown(inv);
    1607             : 
    1608      286291 :             bool fAlreadyHave = AlreadyHave(inv);
    1609      685960 :             LogPrint(BCLog::NET, "got inv: %s  %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->GetId());
    1610             : 
    1611      286291 :             if (inv.type == MSG_BLOCK) {
    1612      185877 :                 UpdateBlockAvailability(pfrom->GetId(), inv.hash);
    1613      185877 :                 if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
    1614             :                     // Add this to the list of blocks to request
    1615       49494 :                     vToFetch.push_back(inv);
    1616       97706 :                     LogPrint(BCLog::NET, "getblocks (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
    1617             :                 }
    1618             :             } else {
    1619             :                 // Allowed inv request types while we are in IBD
    1620      100414 :                 static std::set<int> allowWhileInIBDObjs = {
    1621             :                         MSG_SPORK
    1622      100414 :                 };
    1623             : 
    1624             :                 // Can be safely removed post v6.0.0 enforcement
    1625             :                 // Disallowed inv request
    1626      100414 :                 static std::set<int> disallowedRequestsUntilV6 = {
    1627             :                         MSG_QUORUM_FINAL_COMMITMENT
    1628      100414 :                 };
    1629      200828 :                 if (disallowedRequestsUntilV6.count(inv.type) &&
    1630        1462 :                     !deterministicMNManager->IsDIP3Enforced()) {
    1631           0 :                     continue; // Move to next inv
    1632             :                 }
    1633             : 
    1634             :                 // If we don't have it, check if we should ask for it now or
    1635             :                 // wait until we are sync
    1636      100414 :                 if (!fAlreadyHave) {
    1637       70043 :                     bool allowWhileInIBD = allowWhileInIBDObjs.count(inv.type);
    1638       70043 :                     if (allowWhileInIBD || !IsInitialBlockDownload()) {
    1639       70043 :                         int64_t doubleRequestDelay = 2 * 60 * 1000000;
    1640             :                         // some messages need to be re-requested faster when the first announcing peer did not answer to GETDATA
    1641       70043 :                         switch (inv.type) {
    1642        2412 :                         case MSG_QUORUM_RECOVERED_SIG:
    1643        2412 :                             doubleRequestDelay = 5 * 1000000;
    1644        2412 :                             break;
    1645        2540 :                         case MSG_CLSIG:
    1646        2540 :                             doubleRequestDelay = 5 * 1000000;
    1647        2540 :                             break;
    1648             :                         }
    1649       70043 :                         pfrom->AskFor(inv, doubleRequestDelay);
    1650             :                     }
    1651             :                 }
    1652             :             }
    1653             : 
    1654             :         }
    1655             : 
    1656      179033 :         if (!vToFetch.empty())
    1657       31363 :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
    1658             :     }
    1659             : 
    1660             : 
    1661      189314 :     else if (strCommand == NetMsgType::GETDATA) {
    1662       74873 :         std::vector<CInv> vInv;
    1663       37437 :         vRecv >> vInv;
    1664       37437 :         if (vInv.size() > MAX_INV_SZ) {
    1665           2 :             LOCK(cs_main);
    1666           1 :             Misbehaving(pfrom->GetId(), 20, strprintf("message getdata size() = %u", vInv.size()));
    1667           1 :             return false;
    1668             :         }
    1669             : 
    1670       37436 :         if (vInv.size() != 1)
    1671        4612 :             LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->GetId());
    1672             : 
    1673       37436 :         if (vInv.size() > 0)
    1674       74489 :             LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->GetId());
    1675             : 
    1676       37436 :         pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
    1677       37436 :         ProcessGetData(pfrom, connman, interruptMsgProc);
    1678             :     }
    1679             : 
    1680             : 
    1681      151877 :     else if (strCommand == NetMsgType::GETBLOCKS || strCommand == NetMsgType::GETHEADERS) {
    1682             : 
    1683             :         // Don't relay blocks inv to masternode-only connections
    1684        1181 :         if (!pfrom->CanRelay()) {
    1685           8 :             LogPrint(BCLog::NET, "getblocks, don't relay blocks inv to masternode connection. peer=%d\n", pfrom->GetId());
    1686           8 :             return true;
    1687             :         }
    1688             : 
    1689        2346 :         CBlockLocator locator;
    1690        1173 :         uint256 hashStop;
    1691        1173 :         vRecv >> locator >> hashStop;
    1692             : 
    1693        1173 :         if (locator.vHave.size() > MAX_LOCATOR_SZ) {
    1694           0 :             LogPrint(BCLog::NET, "getblocks locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId());
    1695           0 :             pfrom->fDisconnect = true;
    1696           8 :             return true;
    1697             :         }
    1698             : 
    1699        2346 :         LOCK(cs_main);
    1700             : 
    1701             :         // Find the last block the caller has in the main chain
    1702        1173 :         CBlockIndex* pindex = FindForkInGlobalIndex(chainActive, locator);
    1703             : 
    1704             :         // Send the rest of the chain
    1705        1173 :         if (pindex)
    1706        1173 :             pindex = chainActive.Next(pindex);
    1707        1173 :         int nLimit = 500;
    1708        2340 :         LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->GetId());
    1709        4956 :         for (; pindex; pindex = chainActive.Next(pindex)) {
    1710        3801 :             if (pindex->GetBlockHash() == hashStop) {
    1711          36 :                 LogPrint(BCLog::NET, "  getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
    1712             :                 break;
    1713             :             }
    1714        3783 :             pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
    1715        3783 :             if (--nLimit <= 0) {
    1716             :                 // When this block is requested, we'll send an inv that'll make them
    1717             :                 // getblocks the next batch of inventory.
    1718           0 :                 LogPrint(BCLog::NET, "  getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
    1719           0 :                 pfrom->hashContinue = pindex->GetBlockHash();
    1720           0 :                 break;
    1721             :             }
    1722             :         }
    1723             :     }
    1724             : 
    1725             : 
    1726      150696 :     else if (strCommand == NetMsgType::HEADERS && Params().HeadersFirstSyncingActive()) {
    1727             :         CBlockLocator locator;
    1728             :         uint256 hashStop;
    1729             :         vRecv >> locator >> hashStop;
    1730             : 
    1731             :         if (locator.vHave.size() > MAX_LOCATOR_SZ) {
    1732             :             LogPrint(BCLog::NET, "getblocks locator size %lld > %d, disconnect peer=%d\n", locator.vHave.size(), MAX_LOCATOR_SZ, pfrom->GetId());
    1733             :             pfrom->fDisconnect = true;
    1734             :             return true;
    1735             :         }
    1736             : 
    1737             :         LOCK(cs_main);
    1738             : 
    1739             :         if (IsInitialBlockDownload())
    1740             :             return true;
    1741             : 
    1742             :         CBlockIndex* pindex = nullptr;
    1743             :         if (locator.IsNull()) {
    1744             :             // If locator is null, return the hashStop block
    1745             :             CBlockIndex* pindex = LookupBlockIndex(hashStop);
    1746             :             if (!pindex)
    1747             :                 return true;
    1748             :         } else {
    1749             :             // Find the last block the caller has in the main chain
    1750             :             pindex = FindForkInGlobalIndex(chainActive, locator);
    1751             :             if (pindex)
    1752             :                 pindex = chainActive.Next(pindex);
    1753             :         }
    1754             : 
    1755             :         // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
    1756             :         std::vector<CBlock> vHeaders;
    1757             :         int nLimit = MAX_HEADERS_RESULTS;
    1758             :         LogPrintf("getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->GetId());
    1759             :         for (; pindex; pindex = chainActive.Next(pindex)) {
    1760             :             vHeaders.push_back(pindex->GetBlockHeader());
    1761             :             if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
    1762             :                 break;
    1763             :         }
    1764             :         connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
    1765             :     }
    1766             : 
    1767             : 
    1768      150696 :     else if (strCommand == NetMsgType::TX) {
    1769       18776 :         std::deque<COutPoint> vWorkQueue;
    1770       18776 :         std::vector<uint256> vEraseQueue;
    1771       18776 :         CTransaction tx(deserialize, vRecv);
    1772       18776 :         CTransactionRef ptx = MakeTransactionRef(tx);
    1773             : 
    1774        9388 :         CInv inv(MSG_TX, tx.GetHash());
    1775        9388 :         pfrom->AddInventoryKnown(inv);
    1776             : 
    1777       28164 :         LOCK2(cs_main, g_cs_orphans);
    1778             : 
    1779        9388 :         bool ignoreFees = false;
    1780        9388 :         bool fMissingInputs = false;
    1781       18776 :         CValidationState state;
    1782             : 
    1783        9388 :         pfrom->setAskFor.erase(inv.hash);
    1784        9388 :         mapAlreadyAskedFor.erase(inv);
    1785             : 
    1786        9388 :         if (ptx->ContainsZerocoins()) {
    1787             :             // Don't even try to check zerocoins at all.
    1788           0 :             Misbehaving(pfrom->GetId(), 100, strprintf("received a zc transaction"));
    1789           0 :             return false;
    1790             :         }
    1791             : 
    1792        9388 :         if (AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs, false, ignoreFees)) {
    1793        9279 :             mempool.check(pcoinsTip.get());
    1794        9279 :             RelayTransaction(tx, connman);
    1795       26672 :             for (unsigned int i = 0; i < tx.vout.size(); i++) {
    1796       17393 :                 vWorkQueue.emplace_back(inv.hash, i);
    1797             :             }
    1798             : 
    1799       18558 :             LogPrint(BCLog::MEMPOOL, "%s : peer=%d %s : accepted %s (poolsz %u txn, %u kB)\n",
    1800             :                     __func__, pfrom->GetId(), pfrom->cleanSubVer, tx.GetHash().ToString(),
    1801             :                     mempool.size(), mempool.DynamicMemoryUsage() / 1000);
    1802             : 
    1803             :             // Recursively process any orphan transactions that depended on this one
    1804       18558 :             std::set<NodeId> setMisbehaving;
    1805       26676 :             while (!vWorkQueue.empty()) {
    1806       17397 :                 auto itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue.front());
    1807       17397 :                 vWorkQueue.pop_front();
    1808       17397 :                 if(itByPrev == mapOrphanTransactionsByPrev.end())
    1809       17393 :                     continue;
    1810           8 :                 for (auto mi = itByPrev->second.begin();
    1811           8 :                     mi != itByPrev->second.end();
    1812           8 :                     ++mi) {
    1813           4 :                     const CTransactionRef& orphanTx = (*mi)->second.tx;
    1814           4 :                     const uint256& orphanHash = orphanTx->GetHash();
    1815           4 :                     NodeId fromPeer = (*mi)->second.fromPeer;
    1816           4 :                     bool fMissingInputs2 = false;
    1817             :                     // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
    1818             :                     // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
    1819             :                     // anyone relaying LegitTxX banned)
    1820           8 :                     CValidationState stateDummy;
    1821             : 
    1822             : 
    1823           4 :                     if (setMisbehaving.count(fromPeer))
    1824           0 :                         continue;
    1825           4 :                     if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) {
    1826           4 :                         LogPrint(BCLog::MEMPOOL, "   accepted orphan tx %s\n", orphanHash.ToString());
    1827           2 :                         RelayTransaction(*orphanTx, connman);
    1828           6 :                         for (unsigned int i = 0; i < orphanTx->vout.size(); i++) {
    1829           4 :                             vWorkQueue.emplace_back(orphanHash, i);
    1830             :                         }
    1831           2 :                         vEraseQueue.push_back(orphanHash);
    1832           2 :                     } else if (!fMissingInputs2) {
    1833           2 :                         int nDos = 0;
    1834           2 :                         if(stateDummy.IsInvalid(nDos) && nDos > 0) {
    1835             :                             // Punish peer that gave us an invalid orphan tx
    1836           0 :                             Misbehaving(fromPeer, nDos);
    1837           0 :                             setMisbehaving.insert(fromPeer);
    1838           0 :                             LogPrint(BCLog::MEMPOOL, "   invalid orphan tx %s\n", orphanHash.ToString());
    1839             :                         }
    1840             :                         // Has inputs but not accepted to mempool
    1841             :                         // Probably non-standard or insufficient fee
    1842           4 :                         LogPrint(BCLog::MEMPOOL, "   removed orphan tx %s\n", orphanHash.ToString());
    1843           2 :                         vEraseQueue.push_back(orphanHash);
    1844           2 :                         assert(recentRejects);
    1845           2 :                         recentRejects->insert(orphanHash);
    1846             :                     }
    1847           4 :                     mempool.check(pcoinsTip.get());
    1848             :                 }
    1849             :             }
    1850             : 
    1851        9283 :             for (uint256& hash : vEraseQueue) EraseOrphanTx(hash);
    1852             : 
    1853         109 :         } else if (fMissingInputs) {
    1854         106 :             bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
    1855             : 
    1856             :             // Deduplicate parent txids, so that we don't have to loop over
    1857             :             // the same parent txid more than once down below.
    1858         212 :             std::vector<uint256> unique_parents;
    1859         106 :             unique_parents.reserve(tx.vin.size());
    1860         212 :             for (const CTxIn& txin : ptx->vin) {
    1861             :                 // We start with all parents, and then remove duplicates below.
    1862         106 :                 unique_parents.emplace_back(txin.prevout.hash);
    1863             :             }
    1864         106 :             std::sort(unique_parents.begin(), unique_parents.end());
    1865         106 :             unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
    1866         211 :             for (const uint256& parent_txid : unique_parents) {
    1867         106 :                 if (recentRejects->contains(parent_txid)) {
    1868             :                     fRejectedParents = true;
    1869             :                     break;
    1870             :                 }
    1871             :             }
    1872         106 :             if (!fRejectedParents) {
    1873         210 :                 for (const uint256& parent_txid : unique_parents) {
    1874         105 :                     CInv _inv(MSG_TX, parent_txid);
    1875         105 :                     pfrom->AddInventoryKnown(_inv);
    1876         105 :                     if (!AlreadyHave(_inv)) pfrom->AskFor(_inv);
    1877             :                 }
    1878         105 :                 AddOrphanTx(ptx, pfrom->GetId());
    1879             : 
    1880             :                 // DoS prevention: do not allow mapOrphanTransactions to grow unbounded
    1881         210 :                 unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, gArgs.GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
    1882         105 :                 unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
    1883         105 :                 if (nEvicted > 0)
    1884          76 :                     LogPrint(BCLog::MEMPOOL, "mapOrphan overflow, removed %u tx\n", nEvicted);
    1885             :             } else {
    1886           2 :                 LogPrint(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
    1887             :             }
    1888             :         } else {
    1889             :             // AcceptToMemoryPool() returned false, possibly because the tx is
    1890             :             // already in the mempool; if the tx isn't in the mempool that
    1891             :             // means it was rejected and we shouldn't ask for it again.
    1892           3 :             if (!mempool.exists(tx.GetHash())) {
    1893           3 :                 assert(recentRejects);
    1894           3 :                 recentRejects->insert(tx.GetHash());
    1895             :             }
    1896           3 :             if (pfrom->fWhitelisted) {
    1897             :                 // Always relay transactions received from whitelisted peers, even
    1898             :                 // if they were rejected from the mempool, allowing the node to
    1899             :                 // function as a gateway for nodes hidden behind it.
    1900             :                 //
    1901             :                 // FIXME: This includes invalid transactions, which means a
    1902             :                 // whitelisted peer could get us banned! We may want to change
    1903             :                 // that.
    1904           0 :                 RelayTransaction(tx, connman);
    1905             :             }
    1906             :         }
    1907             : 
    1908        9388 :         int nDoS = 0;
    1909        9391 :         if (state.IsInvalid(nDoS)) {
    1910           9 :             LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(),
    1911             :                 pfrom->GetId(), pfrom->cleanSubVer,
    1912             :                 FormatStateMessage(state));
    1913           3 :             if (nDoS > 0) {
    1914           2 :                 Misbehaving(pfrom->GetId(), nDoS);
    1915             :             }
    1916             :         }
    1917             :     }
    1918             : 
    1919      141308 :     else if (strCommand == NetMsgType::HEADERS && Params().HeadersFirstSyncingActive() && !fImporting && !fReindex) // Ignore headers received while importing
    1920             :     {
    1921             :         std::vector<CBlockHeader> headers;
    1922             : 
    1923             :         // Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
    1924             :         unsigned int nCount = ReadCompactSize(vRecv);
    1925             :         if (nCount > MAX_HEADERS_RESULTS) {
    1926             :             LOCK(cs_main);
    1927             :             Misbehaving(pfrom->GetId(), 20, strprintf("headers message size = %u", nCount));
    1928             :             return false;
    1929             :         }
    1930             :         headers.resize(nCount);
    1931             :         for (unsigned int n = 0; n < nCount; n++) {
    1932             :             vRecv >> headers[n];
    1933             :             ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
    1934             :         }
    1935             : 
    1936             :         LOCK(cs_main);
    1937             : 
    1938             :         if (nCount == 0) {
    1939             :             // Nothing interesting. Stop asking this peers for more headers.
    1940             :             return true;
    1941             :         }
    1942             :         CBlockIndex* pindexLast = nullptr;
    1943             :         for (const CBlockHeader& header : headers) {
    1944             :             CValidationState state;
    1945             :             if (pindexLast && header.hashPrevBlock != pindexLast->GetBlockHash()) {
    1946             :                 Misbehaving(pfrom->GetId(), 20, "non-continuous headers sequence");
    1947             :                 return false;
    1948             :             }
    1949             : 
    1950             :             /*TODO: this has a CBlock cast on it so that it will compile. There should be a solution for this
    1951             :              * before headers are reimplemented on mainnet
    1952             :              */
    1953             :             if (!AcceptBlockHeader((CBlock)header, state, &pindexLast)) {
    1954             :                 int nDoS;
    1955             :                 if (state.IsInvalid(nDoS)) {
    1956             :                     if (nDoS > 0) {
    1957             :                         Misbehaving(pfrom->GetId(), nDoS, "invalid header received");
    1958             :                     } else {
    1959             :                         LogPrint(BCLog::NET, "peer=%d: invalid header received\n", pfrom->GetId());
    1960             :                     }
    1961             :                     return false;
    1962             :                 }
    1963             :             }
    1964             :         }
    1965             : 
    1966             :         if (pindexLast)
    1967             :             UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
    1968             : 
    1969             :         if (nCount == MAX_HEADERS_RESULTS && pindexLast) {
    1970             :             // Headers message had its maximum size; the peer may have more headers.
    1971             :             // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
    1972             :             // from there instead.
    1973             :             LogPrintf("more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight);
    1974             :             connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), UINT256_ZERO));
    1975             :         }
    1976             :     }
    1977             : 
    1978      141308 :     else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
    1979             :     {
    1980       99382 :         std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
    1981       49691 :         vRecv >> *pblock;
    1982       49691 :         const uint256& hashBlock = pblock->GetHash();
    1983       49691 :         CInv inv(MSG_BLOCK, hashBlock);
    1984       98100 :         LogPrint(BCLog::NET, "received block %s peer=%d\n", inv.hash.ToString(), pfrom->GetId());
    1985             : 
    1986             :         // sometimes we will be sent their most recent block and its not the one we want, in that case tell where we are
    1987       49691 :         if (!mapBlockIndex.count(pblock->hashPrevBlock)) {
    1988         112 :             CBlockLocator locator = WITH_LOCK(cs_main, return chainActive.GetLocator(););
    1989          28 :             if (find(pfrom->vBlockRequested.begin(), pfrom->vBlockRequested.end(), hashBlock) != pfrom->vBlockRequested.end()) {
    1990             :                 // we already asked for this block, so lets work backwards and ask for the previous block
    1991          13 :                 connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKS, locator, pblock->hashPrevBlock));
    1992          13 :                 pfrom->vBlockRequested.emplace_back(pblock->hashPrevBlock);
    1993             :             } else {
    1994             :                 // ask to sync to this block
    1995          15 :                 connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETBLOCKS, locator, hashBlock));
    1996          15 :                 pfrom->vBlockRequested.emplace_back(hashBlock);
    1997             :             }
    1998             :         } else {
    1999       49663 :             pfrom->AddInventoryKnown(inv);
    2000       49663 :             if (!mapBlockIndex.count(hashBlock)) {
    2001       25510 :                 {
    2002       25510 :                     LOCK(cs_main);
    2003       25510 :                     MarkBlockAsReceived(hashBlock);
    2004       25510 :                     mapBlockSource.emplace(hashBlock, pfrom->GetId());
    2005             :                 }
    2006       25510 :                 ProcessNewBlock(pblock, nullptr);
    2007             : 
    2008             :                 // Disconnect node if its running an old protocol version,
    2009             :                 // used during upgrades, when the node is already connected.
    2010       25510 :                 pfrom->DisconnectOldProtocol(pfrom->nVersion, ActiveProtocol());
    2011             :             } else {
    2012       47624 :                 LogPrint(BCLog::NET, "%s : Already processed block %s, skipping ProcessNewBlock()\n", __func__, pblock->GetHash().GetHex());
    2013             :             }
    2014             :         }
    2015             :     }
    2016             : 
    2017             :     // This asymmetric behavior for inbound and outbound connections was introduced
    2018             :     // to prevent a fingerprinting attack: an attacker can send specific fake addresses
    2019             :     // to users' AddrMan and later request them by sending getaddr messages.
    2020             :     // Making users (which are behind NAT and can only make outgoing connections) ignore
    2021             :     // getaddr message mitigates the attack.
    2022       91617 :     else if ((strCommand == NetMsgType::GETADDR) && (pfrom->fInbound)) {
    2023         645 :         pfrom->vAddrToSend.clear();
    2024        1290 :         std::vector<CAddress> vAddr = connman->GetAddresses(MAX_ADDR_TO_SEND, MAX_PCT_ADDR_TO_SEND, /* network */ nullopt);
    2025         645 :         FastRandomContext insecure_rand;
    2026         645 :         for (const CAddress& addr : vAddr) {
    2027           0 :             if (!connman->IsBanned(addr)) {
    2028           0 :                 pfrom->PushAddress(addr, insecure_rand);
    2029             :             }
    2030             :         }
    2031             :     }
    2032             : 
    2033             : 
    2034       90972 :     else if (strCommand == NetMsgType::MEMPOOL) {
    2035             : 
    2036           1 :         if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted) {
    2037           1 :             LogPrint(BCLog::NET, "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId());
    2038           1 :             pfrom->fDisconnect = true;
    2039           1 :             return true;
    2040             :         }
    2041             : 
    2042             :         // todo: limit mempool request with a bandwidth limit
    2043           0 :         LOCK(pfrom->cs_inventory);
    2044           0 :         pfrom->fSendMempool = true;
    2045             :     }
    2046             : 
    2047             : 
    2048       90971 :     else if (strCommand == NetMsgType::PING) {
    2049        1616 :         uint64_t nonce = 0;
    2050        1616 :         vRecv >> nonce;
    2051             :         // Echo the message back with the nonce. This allows for two useful features:
    2052             :         //
    2053             :         // 1) A remote node can quickly check if the connection is operational
    2054             :         // 2) Remote nodes can measure the latency of the network thread. If this node
    2055             :         //    is overloaded it won't respond to pings quickly and the remote node can
    2056             :         //    avoid sending us more work, like chain download requests.
    2057             :         //
    2058             :         // The nonce stops the remote getting confused between different pings: without
    2059             :         // it, if the remote node sends a ping once per second and this node takes 5
    2060             :         // seconds to respond to each, the 5th ping the remote sends would appear to
    2061             :         // return very quickly.
    2062        1616 :         connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
    2063             :     }
    2064             : 
    2065             : 
    2066       89355 :     else if (strCommand == NetMsgType::PONG) {
    2067        1510 :         int64_t pingUsecEnd = nTimeReceived;
    2068        1510 :         uint64_t nonce = 0;
    2069        1510 :         size_t nAvail = vRecv.in_avail();
    2070        1510 :         bool bPingFinished = false;
    2071        3020 :         std::string sProblem;
    2072             : 
    2073        1510 :         if (nAvail >= sizeof(nonce)) {
    2074        1510 :             vRecv >> nonce;
    2075             : 
    2076             :             // Only process pong message if there is an outstanding ping (old ping without nonce should never pong)
    2077        1510 :             if (pfrom->nPingNonceSent != 0) {
    2078        1510 :                 if (nonce == pfrom->nPingNonceSent) {
    2079             :                     // Matching pong received, this ping is no longer outstanding
    2080        1510 :                     bPingFinished = true;
    2081        1510 :                     int64_t pingUsecTime = pingUsecEnd - pfrom->nPingUsecStart;
    2082        1510 :                     if (pingUsecTime > 0) {
    2083             :                         // Successful ping time measurement, replace previous
    2084        1510 :                         pfrom->nPingUsecTime = pingUsecTime;
    2085        2878 :                         pfrom->nMinPingUsecTime = std::min(pfrom->nMinPingUsecTime.load(), pingUsecTime);
    2086             :                     } else {
    2087             :                         // This should never happen
    2088        1510 :                         sProblem = "Timing mishap";
    2089             :                     }
    2090             :                 } else {
    2091             :                     // Nonce mismatches are normal when pings are overlapping
    2092           0 :                     sProblem = "Nonce mismatch";
    2093           0 :                     if (nonce == 0) {
    2094             :                         // This is most likely a bug in another implementation somewhere, cancel this ping
    2095           0 :                         bPingFinished = true;
    2096           0 :                         sProblem = "Nonce zero";
    2097             :                     }
    2098             :                 }
    2099             :             } else {
    2100           0 :                 sProblem = "Unsolicited pong without ping";
    2101             :             }
    2102             :         } else {
    2103             :             // This is most likely a bug in another implementation somewhere, cancel this ping
    2104           0 :             bPingFinished = true;
    2105           0 :             sProblem = "Short payload";
    2106             :         }
    2107             : 
    2108        1510 :         if (!(sProblem.empty())) {
    2109           0 :             LogPrint(BCLog::NET, "pong peer=%d %s: %s, %x expected, %x received, %u bytes\n",
    2110             :                 pfrom->GetId(),
    2111             :                 pfrom->cleanSubVer,
    2112             :                 sProblem,
    2113             :                 pfrom->nPingNonceSent,
    2114             :                 nonce,
    2115             :                 nAvail);
    2116             :         }
    2117        1510 :         if (bPingFinished) {
    2118        1510 :             pfrom->nPingNonceSent = 0;
    2119             :         }
    2120             :     }
    2121             : 
    2122       87845 :     else if (!(pfrom->GetLocalServices() & NODE_BLOOM) &&
    2123           0 :              (strCommand == NetMsgType::FILTERLOAD ||
    2124           0 :                  strCommand == NetMsgType::FILTERADD ||
    2125           0 :                  strCommand == NetMsgType::FILTERCLEAR)) {
    2126           0 :         LOCK(cs_main);
    2127           0 :         Misbehaving(pfrom->GetId(), 100, "banning, filter received.");
    2128           0 :         return false;
    2129             :     }
    2130             : 
    2131       87845 :     else if (strCommand == NetMsgType::FILTERLOAD) {
    2132           0 :         CBloomFilter filter;
    2133           0 :         vRecv >> filter;
    2134             : 
    2135           0 :         LOCK(pfrom->cs_filter);
    2136             : 
    2137           0 :         if (!filter.IsWithinSizeConstraints()) {
    2138             :             // There is no excuse for sending a too-large filter
    2139           0 :             LOCK(cs_main);
    2140           0 :             Misbehaving(pfrom->GetId(), 100);
    2141             :         } else {
    2142           0 :             pfrom->pfilter.reset(new CBloomFilter(filter));
    2143           0 :             pfrom->pfilter->UpdateEmptyFull();
    2144           0 :             pfrom->fRelayTxes = true;
    2145             :         }
    2146             :     }
    2147             : 
    2148             : 
    2149       87845 :     else if (strCommand == NetMsgType::FILTERADD) {
    2150           0 :         std::vector<unsigned char> vData;
    2151           0 :         vRecv >> vData;
    2152             : 
    2153             :         // Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
    2154             :         // and thus, the maximum size any matched object can have) in a filteradd message
    2155           0 :         bool bad = false;
    2156           0 :         if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
    2157             :             bad = true;
    2158             :         } else {
    2159           0 :             LOCK(pfrom->cs_filter);
    2160           0 :             if (pfrom->pfilter) {
    2161           0 :                 pfrom->pfilter->insert(vData);
    2162             :             } else {
    2163             :                 bad = true;
    2164             :             }
    2165             :         }
    2166           0 :         if (bad) {
    2167           0 :             LOCK(cs_main);
    2168           0 :             Misbehaving(pfrom->GetId(), 100);
    2169             :         }
    2170             :     }
    2171             : 
    2172             : 
    2173       87845 :     else if (strCommand == NetMsgType::FILTERCLEAR) {
    2174           0 :         LOCK(pfrom->cs_filter);
    2175           0 :         pfrom->pfilter.reset(new CBloomFilter());
    2176           0 :         pfrom->fRelayTxes = true;
    2177             :     }
    2178             : 
    2179       87845 :     else if (strCommand == NetMsgType::NOTFOUND) {
    2180             :         // We do not care about the NOTFOUND message (for now), but logging an Unknown Command
    2181             :         // message is undesirable as we transmit it ourselves.
    2182             :         return true;
    2183             :     }
    2184             : 
    2185             :     else {
    2186             :         // Tier two msg type search
    2187       87167 :         const std::vector<std::string>& allMessages = getTierTwoNetMessageTypes();
    2188       87167 :         if (std::find(allMessages.begin(), allMessages.end(), strCommand) != allMessages.end()) {
    2189             :             // Check if the dispatcher can process this message first. If not, try going with the old flow.
    2190       87087 :             if (!masternodeSync.MessageDispatcher(pfrom, strCommand, vRecv)) {
    2191             :                 // Probably one the extensions, future: encapsulate all of this inside tiertwo_networksync.
    2192       55657 :                 int dosScore{0};
    2193       55657 :                 if (!mnodeman.ProcessMessage(pfrom, strCommand, vRecv, dosScore)) {
    2194          36 :                     WITH_LOCK(cs_main, Misbehaving(pfrom->GetId(), dosScore));
    2195          17 :                     return false;
    2196             :                 }
    2197       55648 :                 if (!g_budgetman.ProcessMessage(pfrom, strCommand, vRecv, dosScore)) {
    2198           0 :                     WITH_LOCK(cs_main, Misbehaving(pfrom->GetId(), dosScore));
    2199           0 :                     return false;
    2200             :                 }
    2201      111288 :                 CValidationState state_payments;
    2202       55648 :                 if (!masternodePayments.ProcessMessageMasternodePayments(pfrom, strCommand, vRecv, state_payments)) {
    2203           8 :                     if (state_payments.IsInvalid(dosScore)) {
    2204          12 :                         WITH_LOCK(cs_main, Misbehaving(pfrom->GetId(), dosScore));
    2205             :                     }
    2206           8 :                     return false;
    2207             :                 }
    2208       55640 :                 if (!sporkManager.ProcessSpork(pfrom, strCommand, vRecv, dosScore)) {
    2209           0 :                     WITH_LOCK(cs_main, Misbehaving(pfrom->GetId(), dosScore));
    2210           0 :                     return false;
    2211             :                 }
    2212             : 
    2213       55640 :                 CValidationState mnauthState;
    2214       55640 :                 if (!CMNAuth::ProcessMessage(pfrom, strCommand, vRecv, *connman, mnauthState)) {
    2215           0 :                     int dosScore{0};
    2216       55640 :                     if (mnauthState.IsInvalid(dosScore) && dosScore > 0) {
    2217           0 :                         LOCK(cs_main);
    2218           0 :                         Misbehaving(pfrom->GetId(), dosScore, mnauthState.GetRejectReason());
    2219             :                     }
    2220             :                 }
    2221             :             }
    2222             :         } else {
    2223             :             // Ignore unknown commands for extensibility
    2224         160 :             LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
    2225             :         }
    2226             :     }
    2227             : 
    2228             :     return true;
    2229             : }
    2230             : 
    2231     2174447 : static bool DisconnectIfBanned(CNode* pnode, CConnman* connman)
    2232             : {
    2233     2174447 :     AssertLockHeld(cs_main);
    2234     2174447 :     CNodeState &state = *State(pnode->GetId());
    2235             : 
    2236     2174447 :     if (state.fShouldBan) {
    2237          44 :         state.fShouldBan = false;
    2238          44 :         if (pnode->fWhitelisted) {
    2239           2 :             LogPrintf("Warning: not punishing whitelisted peer %s!\n", pnode->addr.ToString());
    2240          43 :         } else if (pnode->fAddnode) {
    2241           0 :             LogPrintf("Warning: not punishing addnoded peer %s!\n", pnode->addr.ToString());
    2242             :         } else {
    2243          43 :             pnode->fDisconnect = true;
    2244          43 :             if (pnode->addr.IsLocal()) {
    2245          78 :                 LogPrintf("Warning: not banning local peer %s!\n", pnode->addr.ToString());
    2246             :             } else {
    2247           4 :                 connman->Ban(pnode->addr, BanReasonNodeMisbehaving);
    2248             :             }
    2249             :         }
    2250          44 :         return true;
    2251             :     }
    2252             :     return false;
    2253             : }
    2254             : 
    2255     1892020 : bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgProc)
    2256             : {
    2257             :     // Message format
    2258             :     //  (4) message start
    2259             :     //  (12) command
    2260             :     //  (4) size
    2261             :     //  (4) checksum
    2262             :     //  (x) data
    2263             :     //
    2264     1892020 :     bool fMoreWork = false;
    2265             : 
    2266     1892020 :     if (!pfrom->vRecvGetData.empty())
    2267       18237 :         ProcessGetData(pfrom, connman, interruptMsgProc);
    2268             : 
    2269     1892020 :     if (pfrom->fDisconnect)
    2270             :         return false;
    2271             : 
    2272             :     // this maintains the order of responses
    2273     1892020 :     if (!pfrom->vRecvGetData.empty()) return true;
    2274             : 
    2275             :     // Don't bother if send buffer is too full to respond anyway
    2276     1877320 :     if (pfrom->fPauseSend)
    2277             :         return false;
    2278             : 
    2279     3769330 :     std::list<CNetMessage> msgs;
    2280     1877320 :     {
    2281     1877320 :         LOCK(pfrom->cs_vProcessMsg);
    2282     1877320 :         if (pfrom->vProcessMsg.empty())
    2283     3009650 :             return false;
    2284             :         // Just take one message
    2285      372490 :         msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin());
    2286      372490 :         pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE;
    2287      372490 :         pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman->GetReceiveFloodSize();
    2288      372490 :         fMoreWork = !pfrom->vProcessMsg.empty();
    2289             :     }
    2290      372490 :     CNetMessage& msg(msgs.front());
    2291             : 
    2292      372490 :     msg.SetVersion(pfrom->GetRecvVersion());
    2293             :     // Scan for message start
    2294      372490 :     if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
    2295           2 :         LogPrint(BCLog::NET, "PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId());
    2296           1 :         pfrom->fDisconnect = true;
    2297           1 :         return false;
    2298             :     }
    2299             : 
    2300             :     // Read header
    2301      372489 :     CMessageHeader& hdr = msg.hdr;
    2302      372489 :     if (!hdr.IsValid(Params().MessageStart())) {
    2303           2 :         LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER '%s' peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId());
    2304           1 :         return fMoreWork;
    2305             :     }
    2306     2249800 :     std::string strCommand = hdr.GetCommand();
    2307             : 
    2308             :     // Message size
    2309      372488 :     unsigned int nMessageSize = hdr.nMessageSize;
    2310             : 
    2311             :     // Checksum
    2312      372488 :     CDataStream& vRecv = msg.vRecv;
    2313      372488 :     uint256 hash = msg.GetMessageHash();
    2314      372488 :     if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0)
    2315             :     {
    2316           2 :         LogPrint(BCLog::NET, "%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__,
    2317             :            SanitizeString(strCommand), nMessageSize,
    2318             :            HexStr(Span<uint8_t>(hash.begin(), hash.begin() + CMessageHeader::CHECKSUM_SIZE)),
    2319             :            HexStr(hdr.pchChecksum));
    2320           1 :         return fMoreWork;
    2321             :     }
    2322             : 
    2323             :     // Process message
    2324      372487 :     bool fRet = false;
    2325      372487 :     try {
    2326      744976 :         fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, connman, interruptMsgProc);
    2327      372485 :         if (interruptMsgProc)
    2328             :             return false;
    2329      372484 :         if (!pfrom->vRecvGetData.empty())
    2330        3536 :             fMoreWork = true;
    2331           4 :     } catch (const std::ios_base::failure& e) {
    2332           2 :         if (strstr(e.what(), "end of data")) {
    2333             :             // Allow exceptions from under-length message on vRecv
    2334           2 :             LogPrint(BCLog::NET, "ProcessMessages(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", SanitizeString(strCommand), nMessageSize, e.what());
    2335           1 :         } else if (strstr(e.what(), "size too large")) {
    2336             :             // Allow exceptions from over-long size
    2337           0 :             LogPrint(BCLog::NET, "ProcessMessages(%s, %u bytes): Exception '%s' caught\n", SanitizeString(strCommand), nMessageSize, e.what());
    2338             :         } else {
    2339           1 :             PrintExceptionContinue(&e, "ProcessMessages()");
    2340             :         }
    2341           0 :     } catch (const std::exception& e) {
    2342           0 :         PrintExceptionContinue(&e, "ProcessMessages()");
    2343           0 :     } catch (...) {
    2344           0 :         PrintExceptionContinue(nullptr, "ProcessMessages()");
    2345             :     }
    2346             : 
    2347      372486 :     if (!fRet) {
    2348          80 :         LogPrint(BCLog::NET, "ProcessMessage(%s, %u bytes) FAILED peer=%d\n", SanitizeString(strCommand), nMessageSize,
    2349             :                  pfrom->GetId());
    2350             :     }
    2351             : 
    2352      744974 :     LOCK(cs_main);
    2353      372486 :     DisconnectIfBanned(pfrom, connman);
    2354             : 
    2355      372486 :     return fMoreWork;
    2356             : }
    2357             : 
    2358             : class CompareInvMempoolOrder
    2359             : {
    2360             :     CTxMemPool *mp;
    2361             : public:
    2362      238653 :     explicit CompareInvMempoolOrder(CTxMemPool *_mempool)
    2363      238653 :     {
    2364      238653 :         mp = _mempool;
    2365             :     }
    2366             : 
    2367      118975 :     bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
    2368             :     {
    2369             :         /* As std::make_heap produces a max-heap, we want the entries with the
    2370             :          * fewest ancestors/highest fee to sort later. */
    2371      118975 :         return mp->CompareDepthAndScore(*b, *a);
    2372             :     }
    2373             : };
    2374             : 
    2375     1826207 : bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptMsgProc)
    2376             : {
    2377     1826207 :     {
    2378             :         // Don't send anything until the version handshake is complete
    2379     1826207 :         if (!pto->fSuccessfullyConnected || pto->fDisconnect)
    2380        4393 :             return true;
    2381             : 
    2382             :         // If we get here, the outgoing message serialization version is set and can't change.
    2383     1821817 :         CNetMsgMaker msgMaker(pto->GetSendVersion());
    2384             : 
    2385             :         //
    2386             :         // Message: ping
    2387             :         //
    2388     1821817 :         bool pingSend = false;
    2389     1821817 :         if (pto->fPingQueued) {
    2390             :             // RPC ping request by user
    2391           2 :             pingSend = true;
    2392             :         }
    2393     1821817 :         if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
    2394             :             // Ping automatically sent as a latency probe & keepalive.
    2395             :             pingSend = true;
    2396             :         }
    2397     1820293 :         if (pingSend) {
    2398        1520 :             uint64_t nonce = 0;
    2399        3040 :             while (nonce == 0) {
    2400        1520 :                 GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
    2401             :             }
    2402        1520 :             pto->fPingQueued = false;
    2403        1520 :             pto->nPingUsecStart = GetTimeMicros();
    2404        1520 :             pto->nPingNonceSent = nonce;
    2405        1520 :             connman->PushMessage(pto, msgMaker.Make(NetMsgType::PING, nonce));
    2406             :         }
    2407             : 
    2408     1821817 :         TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
    2409     1821817 :         if (!lockMain)
    2410       24252 :             return true;
    2411             : 
    2412     1801957 :         if (DisconnectIfBanned(pto, connman)) {
    2413             :             return true;
    2414             :         }
    2415             : 
    2416     1801953 :         CNodeState& state = *State(pto->GetId());
    2417             : 
    2418             :         // Address refresh broadcast
    2419     1801953 :         int64_t nNow = GetTimeMicros();
    2420     1801953 :         auto current_time = GetTime<std::chrono::microseconds>();
    2421             : 
    2422     1801953 :         if (!IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
    2423        1206 :             AdvertiseLocal(pto);
    2424        1206 :             pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
    2425             :         }
    2426             : 
    2427             :         //
    2428             :         // Message: addr
    2429             :         //
    2430     1801953 :         if (pto->m_next_addr_send < current_time) {
    2431       13802 :             pto->m_next_addr_send = PoissonNextSend(current_time, AVG_ADDRESS_BROADCAST_INTERVAL);
    2432       27604 :             std::vector<CAddress> vAddr;
    2433       13802 :             vAddr.reserve(pto->vAddrToSend.size());
    2434             : 
    2435       13802 :             const char* msg_type;
    2436       13802 :             int make_flags;
    2437       13802 :             if (pto->m_wants_addrv2) {
    2438       13723 :                 msg_type = NetMsgType::ADDRV2;
    2439       13723 :                 make_flags = ADDRV2_FORMAT;
    2440             :             } else {
    2441          79 :                 msg_type = NetMsgType::ADDR;
    2442          79 :                 make_flags = 0;
    2443             :             }
    2444             : 
    2445       13822 :             for (const CAddress& addr : pto->vAddrToSend) {
    2446          40 :                 if (!pto->addrKnown.contains(addr.GetKey())) {
    2447          20 :                     pto->addrKnown.insert(addr.GetKey());
    2448          20 :                     vAddr.push_back(addr);
    2449             :                     // receiver rejects addr messages larger than 1000
    2450          20 :                     if (vAddr.size() >= 1000) {
    2451           0 :                         connman->PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
    2452          20 :                         vAddr.clear();
    2453             :                     }
    2454             :                 }
    2455             :             }
    2456       13802 :             pto->vAddrToSend.clear();
    2457       13802 :             if (!vAddr.empty())
    2458           2 :                 connman->PushMessage(pto, msgMaker.Make(make_flags, msg_type, vAddr));
    2459             :         }
    2460             : 
    2461             :         // Start block sync
    2462     1801953 :         if (!pindexBestHeader)
    2463           0 :             pindexBestHeader = chainActive.Tip();
    2464     1801953 :         bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
    2465     1801953 :         if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex && pto->CanRelay()) {
    2466             :             // Only actively request headers from a single peer, unless we're close to end of initial download.
    2467       72043 :             if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 6 * 60 * 60) { // NOTE: was "close to today" and 24h in Bitcoin
    2468        1225 :                 state.fSyncStarted = true;
    2469        1225 :                 nSyncStarted++;
    2470             :                 //CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
    2471             :                 //LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
    2472             :                 //pto->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), UINT256_ZERO);
    2473        3675 :                 connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETBLOCKS, chainActive.GetLocator(chainActive.Tip()), UINT256_ZERO));
    2474             :             }
    2475             :         }
    2476             : 
    2477             :         // Resend wallet transactions that haven't gotten in a block yet
    2478             :         // Except during reindex, importing and IBD, when old wallet
    2479             :         // transactions become unconfirmed and spams other nodes.
    2480     1801953 :         if (!fReindex && !fImporting && !IsInitialBlockDownload()) {
    2481     1718160 :             GetMainSignals().Broadcast(connman);
    2482             :         }
    2483             : 
    2484             :         //
    2485             :         // Message: inventory
    2486             :         //
    2487     3603916 :         std::vector<CInv> vInv;
    2488     1801953 :         std::vector<CInv> vInvWait;
    2489     1801953 :         {
    2490     3603916 :             LOCK2(mempool.cs, pto->cs_inventory);
    2491     3603796 :             vInv.reserve(std::max<size_t>(pto->vInventoryBlockToSend.size() + pto->vInventoryTierTwoToSend.size(), INVENTORY_BROADCAST_MAX));
    2492             : 
    2493             :             // Add blocks
    2494     1988083 :             for (const uint256& hash : pto->vInventoryBlockToSend) {
    2495      186129 :                 vInv.emplace_back(CInv(MSG_BLOCK, hash));
    2496      186129 :                 if (vInv.size() == MAX_INV_SZ) {
    2497           0 :                     connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
    2498      186129 :                     vInv.clear();
    2499             :                 }
    2500             :             }
    2501     1801953 :             pto->vInventoryBlockToSend.clear();
    2502             : 
    2503             :             // Add tier two INVs
    2504     1839183 :             for (const CInv& tInv : pto->vInventoryTierTwoToSend) {
    2505       37231 :                 vInv.emplace_back(tInv);
    2506       37231 :                 if (vInv.size() == MAX_INV_SZ) {
    2507           0 :                     connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
    2508       37231 :                     vInv.clear();
    2509             :                 }
    2510             :             }
    2511     1801953 :             pto->vInventoryTierTwoToSend.clear();
    2512             : 
    2513             :             // Check whether periodic send should happen
    2514     1801953 :             bool fSendTrickle = pto->fWhitelisted;
    2515     1801953 :             if (pto->nNextInvSend < current_time) {
    2516       36891 :                 fSendTrickle = true;
    2517             :                 // Use half the delay for outbound peers, as there is less privacy concern for them.
    2518       36891 :                 pto->nNextInvSend = PoissonNextSend(current_time, std::chrono::seconds{INVENTORY_BROADCAST_INTERVAL >> !pto->fInbound});
    2519             :             }
    2520             : 
    2521             :             // Time to send but the peer has requested we not relay transactions.
    2522     1801953 :             if (fSendTrickle) {
    2523      477306 :                 LOCK(pto->cs_filter);
    2524      238655 :                 if (!pto->fRelayTxes) pto->setInventoryTxToSend.clear();
    2525             :             }
    2526             : 
    2527             :             // Respond to BIP35 mempool requests
    2528     1801953 :             if (fSendTrickle && pto->fSendMempool) {
    2529           0 :                 auto vtxinfo = mempool.infoAll();
    2530           0 :                 pto->fSendMempool = false;
    2531             :                 // future: back port fee filter rate
    2532           0 :                 LOCK(pto->cs_filter);
    2533             : 
    2534           0 :                 for (const auto& txinfo : vtxinfo) {
    2535           0 :                     const uint256& hash = txinfo.tx->GetHash();
    2536           0 :                     CInv inv(MSG_TX, hash);
    2537           0 :                     pto->setInventoryTxToSend.erase(hash);
    2538             :                     // future: add fee filter check here..
    2539           0 :                     if (pto->pfilter) {
    2540           0 :                         if (!pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue;
    2541             :                     }
    2542           0 :                     pto->filterInventoryKnown.insert(hash);
    2543           0 :                     vInv.emplace_back(inv);
    2544           0 :                     if (vInv.size() == MAX_INV_SZ) {
    2545           0 :                         connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
    2546           0 :                         vInv.clear();
    2547             :                     }
    2548             :                 }
    2549           0 :                 pto->timeLastMempoolReq = GetTime();
    2550             :             }
    2551             : 
    2552             :             // Determine transactions to relay
    2553     1801953 :             if (fSendTrickle) {
    2554             :                 // Produce a vector with all candidates for sending
    2555      477306 :                 std::vector<std::set<uint256>::iterator> vInvTx;
    2556      238653 :                 vInvTx.reserve(pto->setInventoryTxToSend.size());
    2557      267353 :                 for (std::set<uint256>::iterator it = pto->setInventoryTxToSend.begin(); it != pto->setInventoryTxToSend.end(); it++) {
    2558       28700 :                     vInvTx.push_back(it);
    2559             :                 }
    2560             :                 // Topologically and fee-rate sort the inventory we send for privacy and priority reasons.
    2561             :                 // A heap is used so that not all items need sorting if only a few are being sent.
    2562      238653 :                 CompareInvMempoolOrder compareInvMempoolOrder(&mempool);
    2563      238653 :                 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
    2564             :                 // No reason to drain out at many times the network's capacity,
    2565             :                 // especially since we have many peers and some will draw much shorter delays.
    2566      238653 :                 unsigned int nRelayedTransactions = 0;
    2567      477306 :                 LOCK(pto->cs_filter);
    2568      259726 :                 while (!vInvTx.empty() && nRelayedTransactions < INVENTORY_BROADCAST_MAX) {
    2569             :                     // Fetch the top element from the heap
    2570       21073 :                     std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
    2571       21073 :                     std::set<uint256>::iterator it = vInvTx.back();
    2572       21073 :                     vInvTx.pop_back();
    2573       21073 :                     uint256 hash = *it;
    2574             :                     // Remove it from the to-be-sent set
    2575       21073 :                     pto->setInventoryTxToSend.erase(it);
    2576             :                     // Check if not in the filter already
    2577       21073 :                     if (pto->filterInventoryKnown.contains(hash)) {
    2578        3802 :                         continue;
    2579             :                     }
    2580             :                     // Not in the mempool anymore? don't bother sending it.
    2581       30457 :                     auto txinfo = mempool.info(hash);
    2582       17271 :                     if (!txinfo.tx) {
    2583       11972 :                         continue;
    2584             :                     }
    2585             :                     // todo: back port feerate filter.
    2586       13186 :                     if (pto->pfilter && !pto->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue;
    2587             :                     // Send
    2588       13186 :                     vInv.emplace_back(CInv(MSG_TX, hash));
    2589       13186 :                     nRelayedTransactions++;
    2590       13186 :                     if (vInv.size() == MAX_INV_SZ) {
    2591           0 :                         connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
    2592           0 :                         vInv.clear();
    2593             :                     }
    2594       13186 :                     pto->filterInventoryKnown.insert(hash);
    2595             :                 }
    2596             :             }
    2597             :         }
    2598     1801953 :         if (!vInv.empty())
    2599      179180 :             connman->PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv));
    2600             : 
    2601             :         // Detect whether we're stalling
    2602     1801953 :         current_time = GetTime<std::chrono::microseconds>();
    2603     1801953 :         nNow = GetTimeMicros();
    2604     1801953 :         if (state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
    2605             :             // Stalling only triggers when the block download window cannot move. During normal steady state,
    2606             :             // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
    2607             :             // should only happen during initial block download.
    2608           0 :             LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->GetId());
    2609           0 :             pto->fDisconnect = true;
    2610           0 :             return true;
    2611             :         }
    2612             :         // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
    2613             :         // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
    2614             :         // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
    2615             :         // being saturated. We only count validated in-flight blocks so peers can't advertise nonexisting block hashes
    2616             :         // to unreasonably increase our timeout.
    2617     1801953 :         if (state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().GetConsensus().nTargetSpacing * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
    2618           0 :             LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->GetId());
    2619           0 :             pto->fDisconnect = true;
    2620           0 :             return true;
    2621             :         }
    2622             : 
    2623             :         //
    2624             :         // Message: getdata (blocks)
    2625             :         //
    2626     3603916 :         std::vector<CInv> vGetData;
    2627     1801953 :         if (!pto->fClient && pto->CanRelay() && fFetch && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
    2628     2113466 :             std::vector<const CBlockIndex*> vToDownload;
    2629     1056733 :             NodeId staller = -1;
    2630     1056733 :             FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
    2631     1056733 :             for (const CBlockIndex* pindex : vToDownload) {
    2632           0 :                 vGetData.emplace_back(MSG_BLOCK, pindex->GetBlockHash());
    2633           0 :                 MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex);
    2634           0 :                 LogPrintf("Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
    2635           0 :                     pindex->nHeight, pto->GetId());
    2636             :             }
    2637     1056733 :             if (state.nBlocksInFlight == 0 && staller != -1) {
    2638           0 :                 if (State(staller)->nStallingSince == 0) {
    2639           0 :                     State(staller)->nStallingSince = nNow;
    2640           0 :                     LogPrint(BCLog::NET, "Stall started peer=%d\n", staller);
    2641             :                 }
    2642             :             }
    2643             :         }
    2644             : 
    2645             :         //
    2646             :         // Message: getdata (non-blocks)
    2647             :         //
    2648     1867593 :         while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow) {
    2649       65641 :             const CInv& inv = (*pto->mapAskFor.begin()).second;
    2650       65641 :             if (!AlreadyHave(inv)) {
    2651      131184 :                 LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
    2652       65592 :                 vGetData.push_back(inv);
    2653       65592 :                 if (vGetData.size() >= 1000) {
    2654          50 :                     connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
    2655          50 :                     vGetData.clear();
    2656             :                 }
    2657             :             } else {
    2658             :                 //If we're not going to ask, don't expect a response.
    2659          49 :                 pto->setAskFor.erase(inv.hash);
    2660             :             }
    2661       65641 :             pto->mapAskFor.erase(pto->mapAskFor.begin());
    2662             :         }
    2663     1801953 :         if (!vGetData.empty())
    2664        6050 :             connman->PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
    2665             :     }
    2666     1801953 :     return true;
    2667             : }
    2668             : 
    2669             : class CNetProcessingCleanup
    2670             : {
    2671             : public:
    2672             :     CNetProcessingCleanup() {}
    2673         479 :     ~CNetProcessingCleanup() {
    2674             :         // orphan transactions
    2675         479 :         mapOrphanTransactions.clear();
    2676         479 :         mapOrphanTransactionsByPrev.clear();
    2677         479 :     }
    2678             : } instance_of_cnetprocessingcleanup;

Generated by: LCOV version 1.14