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

Generated by: LCOV version 1.14