/ src / protocol.cpp
protocol.cpp
  1  // Copyright (c) 2009-2010 Satoshi Nakamoto
  2  // Copyright (c) 2009-2022 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 <common/system.h>
  9  
 10  #include <atomic>
 11  
 12  namespace NetMsgType {
 13  const char* VERSION = "version";
 14  const char* VERACK = "verack";
 15  const char* ADDR = "addr";
 16  const char* ADDRV2 = "addrv2";
 17  const char* SENDADDRV2 = "sendaddrv2";
 18  const char* INV = "inv";
 19  const char* GETDATA = "getdata";
 20  const char* MERKLEBLOCK = "merkleblock";
 21  const char* GETBLOCKS = "getblocks";
 22  const char* GETHEADERS = "getheaders";
 23  const char* TX = "tx";
 24  const char* HEADERS = "headers";
 25  const char* BLOCK = "block";
 26  const char* GETADDR = "getaddr";
 27  const char* MEMPOOL = "mempool";
 28  const char* PING = "ping";
 29  const char* PONG = "pong";
 30  const char* NOTFOUND = "notfound";
 31  const char* FILTERLOAD = "filterload";
 32  const char* FILTERADD = "filteradd";
 33  const char* FILTERCLEAR = "filterclear";
 34  const char* SENDHEADERS = "sendheaders";
 35  const char* FEEFILTER = "feefilter";
 36  const char* SENDCMPCT = "sendcmpct";
 37  const char* CMPCTBLOCK = "cmpctblock";
 38  const char* GETBLOCKTXN = "getblocktxn";
 39  const char* BLOCKTXN = "blocktxn";
 40  const char* GETCFILTERS = "getcfilters";
 41  const char* CFILTER = "cfilter";
 42  const char* GETCFHEADERS = "getcfheaders";
 43  const char* CFHEADERS = "cfheaders";
 44  const char* GETCFCHECKPT = "getcfcheckpt";
 45  const char* CFCHECKPT = "cfcheckpt";
 46  const char* WTXIDRELAY = "wtxidrelay";
 47  const char* SENDTXRCNCL = "sendtxrcncl";
 48  } // namespace NetMsgType
 49  
 50  /** All known message types. Keep this in the same order as the list of
 51   * messages above and in protocol.h.
 52   */
 53  const static std::vector<std::string> g_all_net_message_types{
 54      NetMsgType::VERSION,
 55      NetMsgType::VERACK,
 56      NetMsgType::ADDR,
 57      NetMsgType::ADDRV2,
 58      NetMsgType::SENDADDRV2,
 59      NetMsgType::INV,
 60      NetMsgType::GETDATA,
 61      NetMsgType::MERKLEBLOCK,
 62      NetMsgType::GETBLOCKS,
 63      NetMsgType::GETHEADERS,
 64      NetMsgType::TX,
 65      NetMsgType::HEADERS,
 66      NetMsgType::BLOCK,
 67      NetMsgType::GETADDR,
 68      NetMsgType::MEMPOOL,
 69      NetMsgType::PING,
 70      NetMsgType::PONG,
 71      NetMsgType::NOTFOUND,
 72      NetMsgType::FILTERLOAD,
 73      NetMsgType::FILTERADD,
 74      NetMsgType::FILTERCLEAR,
 75      NetMsgType::SENDHEADERS,
 76      NetMsgType::FEEFILTER,
 77      NetMsgType::SENDCMPCT,
 78      NetMsgType::CMPCTBLOCK,
 79      NetMsgType::GETBLOCKTXN,
 80      NetMsgType::BLOCKTXN,
 81      NetMsgType::GETCFILTERS,
 82      NetMsgType::CFILTER,
 83      NetMsgType::GETCFHEADERS,
 84      NetMsgType::CFHEADERS,
 85      NetMsgType::GETCFCHECKPT,
 86      NetMsgType::CFCHECKPT,
 87      NetMsgType::WTXIDRELAY,
 88      NetMsgType::SENDTXRCNCL,
 89  };
 90  
 91  CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
 92      : pchMessageStart{pchMessageStartIn}
 93  {
 94      // Copy the command name
 95      size_t i = 0;
 96      for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
 97      assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
 98  
 99      nMessageSize = nMessageSizeIn;
100  }
101  
102  std::string CMessageHeader::GetCommand() const
103  {
104      return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
105  }
106  
107  bool CMessageHeader::IsCommandValid() const
108  {
109      // Check the command string for errors
110      for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
111          if (*p1 == 0) {
112              // Must be all zeros after the first zero
113              for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
114                  if (*p1 != 0) {
115                      return false;
116                  }
117              }
118          } else if (*p1 < ' ' || *p1 > 0x7E) {
119              return false;
120          }
121      }
122  
123      return true;
124  }
125  
126  CInv::CInv()
127  {
128      type = 0;
129      hash.SetNull();
130  }
131  
132  CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
133  
134  bool operator<(const CInv& a, const CInv& b)
135  {
136      return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
137  }
138  
139  std::string CInv::GetCommand() const
140  {
141      std::string cmd;
142      if (type & MSG_WITNESS_FLAG)
143          cmd.append("witness-");
144      int masked = type & MSG_TYPE_MASK;
145      switch (masked)
146      {
147      case MSG_TX:             return cmd.append(NetMsgType::TX);
148      // WTX is not a message type, just an inv type
149      case MSG_WTX:            return cmd.append("wtx");
150      case MSG_BLOCK:          return cmd.append(NetMsgType::BLOCK);
151      case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
152      case MSG_CMPCT_BLOCK:    return cmd.append(NetMsgType::CMPCTBLOCK);
153      default:
154          throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
155      }
156  }
157  
158  std::string CInv::ToString() const
159  {
160      try {
161          return strprintf("%s %s", GetCommand(), hash.ToString());
162      } catch(const std::out_of_range &) {
163          return strprintf("0x%08x %s", type, hash.ToString());
164      }
165  }
166  
167  const std::vector<std::string> &getAllNetMessageTypes()
168  {
169      return g_all_net_message_types;
170  }
171  
172  /**
173   * Convert a service flag (NODE_*) to a human readable string.
174   * It supports unknown service flags which will be returned as "UNKNOWN[...]".
175   * @param[in] bit the service flag is calculated as (1 << bit)
176   */
177  static std::string serviceFlagToStr(size_t bit)
178  {
179      const uint64_t service_flag = 1ULL << bit;
180      switch ((ServiceFlags)service_flag) {
181      case NODE_NONE: abort();  // impossible
182      case NODE_NETWORK:         return "NETWORK";
183      case NODE_BLOOM:           return "BLOOM";
184      case NODE_WITNESS:         return "WITNESS";
185      case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
186      case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
187      case NODE_P2P_V2:          return "P2P_V2";
188      // Not using default, so we get warned when a case is missing
189      }
190  
191      return strprintf("UNKNOWN[2^%u]", bit);
192  }
193  
194  std::vector<std::string> serviceFlagsToStr(uint64_t flags)
195  {
196      std::vector<std::string> str_flags;
197  
198      for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
199          if (flags & (1ULL << i)) {
200              str_flags.emplace_back(serviceFlagToStr(i));
201          }
202      }
203  
204      return str_flags;
205  }
206  
207  GenTxid ToGenTxid(const CInv& inv)
208  {
209      assert(inv.IsGenTxMsg());
210      return inv.IsMsgWtx() ? GenTxid::Wtxid(inv.hash) : GenTxid::Txid(inv.hash);
211  }