LCOV - code coverage report
Current view: top level - src - protocol.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 132 198 66.7 %
Date: 2026-06-25 07:23:51 Functions: 11 23 47.8 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include <protocol.h>
       7             : 
       8             : #include <util/system.h>
       9             : 
      10             : #include <atomic>
      11             : 
      12             : static std::atomic<bool> g_initial_block_download_completed(false);
      13             : 
      14             : #define MAKE_MSG(var_name, p2p_name_str)   \
      15             :         const char* var_name=p2p_name_str; \
      16             :         static_assert(std::size(p2p_name_str) <= CMessageHeader::COMMAND_SIZE + 1, "p2p_name_str cannot be greater than COMMAND_SIZE"); // Includes +1 for null termination character.
      17             : 
      18             : namespace NetMsgType {
      19             : MAKE_MSG(VERSION, "version");
      20             : MAKE_MSG(VERACK, "verack");
      21             : MAKE_MSG(ADDR, "addr");
      22             : MAKE_MSG(ADDRV2, "addrv2");
      23             : MAKE_MSG(SENDADDRV2, "sendaddrv2");
      24             : MAKE_MSG(INV, "inv");
      25             : MAKE_MSG(GETDATA, "getdata");
      26             : MAKE_MSG(MERKLEBLOCK, "merkleblock");
      27             : MAKE_MSG(GETBLOCKS, "getblocks");
      28             : MAKE_MSG(GETHEADERS, "getheaders");
      29             : MAKE_MSG(TX, "tx");
      30             : MAKE_MSG(HEADERS, "headers");
      31             : MAKE_MSG(BLOCK, "block");
      32             : MAKE_MSG(GETADDR, "getaddr");
      33             : MAKE_MSG(MEMPOOL, "mempool");
      34             : MAKE_MSG(PING, "ping");
      35             : MAKE_MSG(PONG, "pong");
      36             : MAKE_MSG(NOTFOUND, "notfound");
      37             : MAKE_MSG(FILTERLOAD, "filterload");
      38             : MAKE_MSG(FILTERADD, "filteradd");
      39             : MAKE_MSG(FILTERCLEAR, "filterclear");
      40             : MAKE_MSG(SENDHEADERS, "sendheaders");
      41             : MAKE_MSG(SENDCMPCT, "sendcmpct");
      42             : MAKE_MSG(CMPCTBLOCK, "cmpctblock");
      43             : MAKE_MSG(GETBLOCKTXN, "getblocktxn");
      44             : MAKE_MSG(BLOCKTXN, "blocktxn");
      45             : MAKE_MSG(GETCFILTERS, "getcfilters");
      46             : MAKE_MSG(CFILTER, "cfilter");
      47             : MAKE_MSG(GETCFHEADERS, "getcfheaders");
      48             : MAKE_MSG(CFHEADERS, "cfheaders");
      49             : MAKE_MSG(GETCFCHECKPT, "getcfcheckpt");
      50             : MAKE_MSG(CFCHECKPT, "cfcheckpt");
      51             : MAKE_MSG(SENDTXRCNCL, "sendtxrcncl");
      52             : // Dash message types
      53             : MAKE_MSG(SPORK, "spork");
      54             : MAKE_MSG(GETSPORKS, "getsporks");
      55             : MAKE_MSG(DSACCEPT, "dsa");
      56             : MAKE_MSG(DSVIN, "dsi");
      57             : MAKE_MSG(DSFINALTX, "dsf");
      58             : MAKE_MSG(DSSIGNFINALTX, "dss");
      59             : MAKE_MSG(DSCOMPLETE, "dsc");
      60             : MAKE_MSG(DSSTATUSUPDATE, "dssu");
      61             : MAKE_MSG(DSTX, "dstx");
      62             : MAKE_MSG(DSQUEUE, "dsq");
      63             : MAKE_MSG(SENDDSQUEUE, "senddsq");
      64             : MAKE_MSG(SYNCSTATUSCOUNT, "ssc");
      65             : MAKE_MSG(MNGOVERNANCESYNC, "govsync");
      66             : MAKE_MSG(MNGOVERNANCEOBJECT, "govobj");
      67             : MAKE_MSG(MNGOVERNANCEOBJECTVOTE, "govobjvote");
      68             : MAKE_MSG(GETMNLISTDIFF, "getmnlistd");
      69             : MAKE_MSG(MNLISTDIFF, "mnlistdiff");
      70             : MAKE_MSG(QSENDRECSIGS, "qsendrecsigs");
      71             : MAKE_MSG(QFCOMMITMENT, "qfcommit");
      72             : MAKE_MSG(QCONTRIB, "qcontrib");
      73             : MAKE_MSG(QCOMPLAINT, "qcomplaint");
      74             : MAKE_MSG(QJUSTIFICATION, "qjustify");
      75             : MAKE_MSG(QPCOMMITMENT, "qpcommit");
      76             : MAKE_MSG(QWATCH, "qwatch");
      77             : MAKE_MSG(QSIGSESANN, "qsigsesann");
      78             : MAKE_MSG(QSIGSHARESINV, "qsigsinv");
      79             : MAKE_MSG(QGETSIGSHARES, "qgetsigs");
      80             : MAKE_MSG(QBSIGSHARES, "qbsigs");
      81             : MAKE_MSG(QSIGREC, "qsigrec");
      82             : MAKE_MSG(QSIGSHARE, "qsigshare");
      83             : MAKE_MSG(QGETDATA, "qgetdata");
      84             : MAKE_MSG(QDATA, "qdata");
      85             : MAKE_MSG(CLSIG, "clsig");
      86             : MAKE_MSG(ISDLOCK, "isdlock");
      87             : MAKE_MSG(MNAUTH, "mnauth");
      88             : MAKE_MSG(GETHEADERS2, "getheaders2");
      89             : MAKE_MSG(SENDHEADERS2, "sendheaders2");
      90             : MAKE_MSG(HEADERS2, "headers2");
      91             : MAKE_MSG(GETQUORUMROTATIONINFO, "getqrinfo");
      92             : MAKE_MSG(QUORUMROTATIONINFO, "qrinfo");
      93             : MAKE_MSG(PLATFORMBAN, "platformban");
      94             : }; // namespace NetMsgType
      95             : 
      96             : /** All known message types. Keep this in the same order as the list of
      97             :  * messages above and in protocol.h.
      98             :  */
      99         146 : const static std::string allNetMessageTypes[] = {
     100         146 :     NetMsgType::VERSION,
     101         146 :     NetMsgType::VERACK,
     102         146 :     NetMsgType::ADDR,
     103         146 :     NetMsgType::ADDRV2,
     104         146 :     NetMsgType::SENDADDRV2,
     105         146 :     NetMsgType::INV,
     106         146 :     NetMsgType::GETDATA,
     107         146 :     NetMsgType::MERKLEBLOCK,
     108         146 :     NetMsgType::GETBLOCKS,
     109         146 :     NetMsgType::GETHEADERS,
     110         146 :     NetMsgType::TX,
     111         146 :     NetMsgType::HEADERS,
     112         146 :     NetMsgType::BLOCK,
     113         146 :     NetMsgType::GETADDR,
     114         146 :     NetMsgType::MEMPOOL,
     115         146 :     NetMsgType::PING,
     116         146 :     NetMsgType::PONG,
     117         146 :     NetMsgType::NOTFOUND,
     118         146 :     NetMsgType::FILTERLOAD,
     119         146 :     NetMsgType::FILTERADD,
     120         146 :     NetMsgType::FILTERCLEAR,
     121         146 :     NetMsgType::SENDHEADERS,
     122         146 :     NetMsgType::SENDCMPCT,
     123         146 :     NetMsgType::CMPCTBLOCK,
     124         146 :     NetMsgType::GETBLOCKTXN,
     125         146 :     NetMsgType::BLOCKTXN,
     126         146 :     NetMsgType::GETCFILTERS,
     127         146 :     NetMsgType::CFILTER,
     128         146 :     NetMsgType::GETCFHEADERS,
     129         146 :     NetMsgType::CFHEADERS,
     130         146 :     NetMsgType::GETCFCHECKPT,
     131         146 :     NetMsgType::CFCHECKPT,
     132         146 :     NetMsgType::SENDTXRCNCL,
     133             :     // Dash message types
     134             :     // NOTE: do NOT include non-implmented here, we want them to be "Unknown command" in ProcessMessage()
     135         146 :     NetMsgType::SPORK,
     136         146 :     NetMsgType::GETSPORKS,
     137         146 :     NetMsgType::SENDDSQUEUE,
     138         146 :     NetMsgType::DSACCEPT,
     139         146 :     NetMsgType::DSVIN,
     140         146 :     NetMsgType::DSFINALTX,
     141         146 :     NetMsgType::DSSIGNFINALTX,
     142         146 :     NetMsgType::DSCOMPLETE,
     143         146 :     NetMsgType::DSSTATUSUPDATE,
     144         146 :     NetMsgType::DSTX,
     145         146 :     NetMsgType::DSQUEUE,
     146         146 :     NetMsgType::SYNCSTATUSCOUNT,
     147         146 :     NetMsgType::MNGOVERNANCESYNC,
     148         146 :     NetMsgType::MNGOVERNANCEOBJECT,
     149         146 :     NetMsgType::MNGOVERNANCEOBJECTVOTE,
     150         146 :     NetMsgType::GETMNLISTDIFF,
     151         146 :     NetMsgType::MNLISTDIFF,
     152         146 :     NetMsgType::QSENDRECSIGS,
     153         146 :     NetMsgType::QFCOMMITMENT,
     154         146 :     NetMsgType::QCONTRIB,
     155         146 :     NetMsgType::QCOMPLAINT,
     156         146 :     NetMsgType::QJUSTIFICATION,
     157         146 :     NetMsgType::QPCOMMITMENT,
     158         146 :     NetMsgType::QWATCH,
     159         146 :     NetMsgType::QSIGSESANN,
     160         146 :     NetMsgType::QSIGSHARESINV,
     161         146 :     NetMsgType::QGETSIGSHARES,
     162         146 :     NetMsgType::QBSIGSHARES,
     163         146 :     NetMsgType::QSIGREC,
     164         146 :     NetMsgType::QSIGSHARE,
     165         146 :     NetMsgType::QGETDATA,
     166         146 :     NetMsgType::QDATA,
     167         146 :     NetMsgType::CLSIG,
     168         146 :     NetMsgType::ISDLOCK,
     169         146 :     NetMsgType::MNAUTH,
     170         146 :     NetMsgType::GETHEADERS2,
     171         146 :     NetMsgType::SENDHEADERS2,
     172         146 :     NetMsgType::HEADERS2,
     173         146 :     NetMsgType::GETQUORUMROTATIONINFO,
     174         146 :     NetMsgType::QUORUMROTATIONINFO,
     175         146 :     NetMsgType::PLATFORMBAN,
     176             : };
     177         146 : const static std::vector<std::string> allNetMessageTypesVec(std::begin(allNetMessageTypes), std::end(allNetMessageTypes));
     178             : 
     179             : /** Message types that are not allowed by blocks-relay-only policy.
     180             :  *  We do not want most of CoinJoin, DKG or LLMQ signing messages to be relayed
     181             :  *  to/from nodes via connections that were established in this mode.
     182             :  *  Make sure to keep this list up to date whenever a new message type is added.
     183             :  *  NOTE: Unlike the list above, this list is sorted alphabetically.
     184             :  */
     185         146 : const static std::string netMessageTypesViolateBlocksOnly[] = {
     186         146 :     NetMsgType::DSACCEPT,
     187         146 :     NetMsgType::DSCOMPLETE,
     188         146 :     NetMsgType::DSFINALTX,
     189         146 :     NetMsgType::DSQUEUE,
     190         146 :     NetMsgType::DSSIGNFINALTX,
     191         146 :     NetMsgType::DSSTATUSUPDATE,
     192         146 :     NetMsgType::DSTX,
     193         146 :     NetMsgType::DSVIN,
     194         146 :     NetMsgType::GETQUORUMROTATIONINFO,
     195         146 :     NetMsgType::PLATFORMBAN,
     196         146 :     NetMsgType::QBSIGSHARES,
     197         146 :     NetMsgType::QCOMPLAINT,
     198         146 :     NetMsgType::QCONTRIB,
     199         146 :     NetMsgType::QDATA,
     200         146 :     NetMsgType::QGETDATA,
     201         146 :     NetMsgType::QGETSIGSHARES,
     202         146 :     NetMsgType::QJUSTIFICATION,
     203         146 :     NetMsgType::QPCOMMITMENT,
     204         146 :     NetMsgType::QSENDRECSIGS,
     205         146 :     NetMsgType::QSIGREC,
     206         146 :     NetMsgType::QSIGSESANN,
     207         146 :     NetMsgType::QSIGSHARE,
     208         146 :     NetMsgType::QSIGSHARESINV,
     209         146 :     NetMsgType::QUORUMROTATIONINFO,
     210         146 :     NetMsgType::QWATCH,
     211         146 :     NetMsgType::TX,
     212             : };
     213         146 : const static std::set<std::string> netMessageTypesViolateBlocksOnlySet(std::begin(netMessageTypesViolateBlocksOnly), std::end(netMessageTypesViolateBlocksOnly));
     214             : 
     215           8 : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
     216           4 : {
     217             :     memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
     218             : 
     219             :     // Copy the command name
     220             :     size_t i = 0;
     221             :     for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
     222             :     assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
     223             : 
     224             :     nMessageSize = nMessageSizeIn;
     225           4 : }
     226             : 
     227           2 : std::string CMessageHeader::GetCommand() const
     228             : {
     229           2 :     return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
     230             : }
     231             : 
     232           2 : bool CMessageHeader::IsCommandValid() const
     233             : {
     234             :     // Check the command string for errors
     235          17 :     for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
     236          15 :         if (*p1 == 0) {
     237             :             // Must be all zeros after the first zero
     238          13 :             for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
     239          11 :                 if (*p1 != 0) {
     240           0 :                     return false;
     241             :                 }
     242          11 :             }
     243          15 :         } else if (*p1 < ' ' || *p1 > 0x7E) {
     244           0 :             return false;
     245             :         }
     246          15 :     }
     247             : 
     248           2 :     return true;
     249           2 : }
     250             : 
     251             : 
     252           4 : ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
     253           4 :     if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
     254           0 :         return ServiceFlags(NODE_NETWORK_LIMITED);
     255             :     }
     256           4 :     return ServiceFlags(NODE_NETWORK);
     257           4 : }
     258             : 
     259           0 : void SetServiceFlagsIBDCache(bool state) {
     260           0 :     g_initial_block_download_completed = state;
     261           0 : }
     262             : 
     263           0 : CInv::CInv()
     264           0 : {
     265           0 :     type = 0;
     266           0 :     hash.SetNull();
     267           0 : }
     268             : 
     269           0 : CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
     270             : 
     271           0 : bool operator<(const CInv& a, const CInv& b)
     272             : {
     273           0 :     return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
     274             : }
     275             : 
     276           0 : bool CInv::IsKnownType() const
     277             : {
     278           0 :     return GetCommandInternal() != nullptr;
     279             : }
     280             : 
     281           0 : const char* CInv::GetCommandInternal() const
     282             : {
     283           0 :     switch (type)
     284             :     {
     285           0 :         case MSG_TX:                            return NetMsgType::TX;
     286           0 :         case MSG_BLOCK:                         return NetMsgType::BLOCK;
     287           0 :         case MSG_FILTERED_BLOCK:                return NetMsgType::MERKLEBLOCK;
     288           0 :         case MSG_CMPCT_BLOCK:                   return NetMsgType::CMPCTBLOCK;
     289           0 :         case MSG_SPORK:                         return NetMsgType::SPORK;
     290           0 :         case MSG_DSTX:                          return NetMsgType::DSTX;
     291           0 :         case MSG_GOVERNANCE_OBJECT:             return NetMsgType::MNGOVERNANCEOBJECT;
     292           0 :         case MSG_GOVERNANCE_OBJECT_VOTE:        return NetMsgType::MNGOVERNANCEOBJECTVOTE;
     293           0 :         case MSG_QUORUM_FINAL_COMMITMENT:       return NetMsgType::QFCOMMITMENT;
     294           0 :         case MSG_QUORUM_CONTRIB:                return NetMsgType::QCONTRIB;
     295           0 :         case MSG_QUORUM_COMPLAINT:              return NetMsgType::QCOMPLAINT;
     296           0 :         case MSG_QUORUM_JUSTIFICATION:          return NetMsgType::QJUSTIFICATION;
     297           0 :         case MSG_QUORUM_PREMATURE_COMMITMENT:   return NetMsgType::QPCOMMITMENT;
     298           0 :         case MSG_QUORUM_RECOVERED_SIG:          return NetMsgType::QSIGREC;
     299           0 :         case MSG_CLSIG:                         return NetMsgType::CLSIG;
     300           0 :         case MSG_ISDLOCK:                       return NetMsgType::ISDLOCK;
     301           0 :         case MSG_DSQ:                           return NetMsgType::DSQUEUE;
     302           0 :         case MSG_PLATFORM_BAN:                  return NetMsgType::PLATFORMBAN;
     303             :         default:
     304           0 :             return nullptr;
     305             :     }
     306           0 : }
     307             : 
     308           0 : std::string CInv::GetCommand() const
     309             : {
     310           0 :     auto cmd = GetCommandInternal();
     311           0 :     if (cmd == nullptr) {
     312           0 :         throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
     313             :     }
     314           0 :     return cmd;
     315           0 : }
     316             : 
     317           0 : std::string CInv::ToString() const
     318             : {
     319           0 :     auto cmd = GetCommandInternal();
     320           0 :     if (!cmd) {
     321           0 :         return strprintf("0x%08x %s", type, hash.ToString());
     322             :     } else {
     323           0 :         return strprintf("%s %s", cmd, hash.ToString());
     324             :     }
     325           0 : }
     326             : 
     327          40 : const std::vector<std::string> &getAllNetMessageTypes()
     328             : {
     329          40 :     return allNetMessageTypesVec;
     330             : }
     331             : 
     332           0 : bool NetMessageViolatesBlocksOnly(const std::string& msg_type)
     333             : {
     334           0 :     return netMessageTypesViolateBlocksOnlySet.find(msg_type) != netMessageTypesViolateBlocksOnlySet.end();
     335             : }
     336             : 
     337             : /**
     338             :  * Convert a service flag (NODE_*) to a human readable string.
     339             :  * It supports unknown service flags which will be returned as "UNKNOWN[...]".
     340             :  * @param[in] bit the service flag is calculated as (1 << bit)
     341             :  */
     342           0 : static std::string serviceFlagToStr(size_t bit)
     343             : {
     344           0 :     const uint64_t service_flag = 1ULL << bit;
     345           0 :     switch ((ServiceFlags)service_flag) {
     346           0 :     case NODE_NONE: abort();  // impossible
     347           0 :     case NODE_NETWORK:         return "NETWORK";
     348           0 :     case NODE_BLOOM:           return "BLOOM";
     349           0 :     case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
     350           0 :     case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
     351           0 :     case NODE_HEADERS_COMPRESSED: return "HEADERS_COMPRESSED";
     352           0 :     case NODE_P2P_V2:          return "P2P_V2";
     353             :     // Not using default, so we get warned when a case is missing
     354             :     }
     355             : 
     356           0 :     return strprintf("UNKNOWN[2^%u]", bit);
     357           0 : }
     358             : 
     359           3 : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
     360             : {
     361           3 :     std::vector<std::string> str_flags;
     362             : 
     363         195 :     for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
     364         192 :         if (flags & (1ULL << i)) {
     365           0 :             str_flags.emplace_back(serviceFlagToStr(i));
     366           0 :         }
     367         192 :     }
     368             : 
     369           3 :     return str_flags;
     370           3 : }

Generated by: LCOV version 1.16