/ src / protocol.cpp
protocol.cpp
  1  // Copyright (c) 2009-2010 Satoshi Nakamoto
  2  // Copyright (c) 2009-present 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  CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* msg_type, unsigned int nMessageSizeIn)
 11      : pchMessageStart{pchMessageStartIn}
 12  {
 13      // Copy the message type name
 14      size_t i = 0;
 15      for (; i < MESSAGE_TYPE_SIZE && msg_type[i] != 0; ++i) m_msg_type[i] = msg_type[i];
 16      assert(msg_type[i] == 0); // Assert that the message type name passed in is not longer than MESSAGE_TYPE_SIZE
 17  
 18      nMessageSize = nMessageSizeIn;
 19  }
 20  
 21  std::string CMessageHeader::GetMessageType() const
 22  {
 23      return std::string(m_msg_type, m_msg_type + strnlen(m_msg_type, MESSAGE_TYPE_SIZE));
 24  }
 25  
 26  bool CMessageHeader::IsMessageTypeValid() const
 27  {
 28      // Check the message type string for errors
 29      for (const char* p1 = m_msg_type; p1 < m_msg_type + MESSAGE_TYPE_SIZE; ++p1) {
 30          if (*p1 == 0) {
 31              // Must be all zeros after the first zero
 32              for (; p1 < m_msg_type + MESSAGE_TYPE_SIZE; ++p1) {
 33                  if (*p1 != 0) {
 34                      return false;
 35                  }
 36              }
 37          } else if (*p1 < ' ' || *p1 > 0x7E) {
 38              return false;
 39          }
 40      }
 41  
 42      return true;
 43  }
 44  
 45  CInv::CInv()
 46  {
 47      type = 0;
 48      hash.SetNull();
 49  }
 50  
 51  CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
 52  
 53  bool operator<(const CInv& a, const CInv& b)
 54  {
 55      return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
 56  }
 57  
 58  std::string CInv::GetMessageType() const
 59  {
 60      std::string cmd;
 61      if (type & MSG_WITNESS_FLAG)
 62          cmd.append("witness-");
 63      int masked = type & MSG_TYPE_MASK;
 64      switch (masked)
 65      {
 66      case MSG_TX:             return cmd.append(NetMsgType::TX);
 67      // WTX is not a message type, just an inv type
 68      case MSG_WTX:            return cmd.append("wtx");
 69      case MSG_BLOCK:          return cmd.append(NetMsgType::BLOCK);
 70      case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
 71      case MSG_CMPCT_BLOCK:    return cmd.append(NetMsgType::CMPCTBLOCK);
 72      default:
 73          throw std::out_of_range(strprintf("CInv::GetMessageType(): type=%d unknown type", type));
 74      }
 75  }
 76  
 77  std::string CInv::ToString() const
 78  {
 79      try {
 80          return strprintf("%s %s", GetMessageType(), hash.ToString());
 81      } catch(const std::out_of_range &) {
 82          return strprintf("0x%08x %s", type, hash.ToString());
 83      }
 84  }
 85  
 86  /**
 87   * Convert a service flag (NODE_*) to a human readable string.
 88   * It supports unknown service flags which will be returned as "UNKNOWN[...]".
 89   * @param[in] bit the service flag is calculated as (1 << bit)
 90   */
 91  static std::string serviceFlagToStr(size_t bit)
 92  {
 93      const uint64_t service_flag = 1ULL << bit;
 94      switch ((ServiceFlags)service_flag) {
 95      case NODE_NONE: abort();  // impossible
 96      case NODE_NETWORK:         return "NETWORK";
 97      case NODE_BLOOM:           return "BLOOM";
 98      case NODE_WITNESS:         return "WITNESS";
 99      case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
100      case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
101      case NODE_P2P_V2:          return "P2P_V2";
102      // Not using default, so we get warned when a case is missing
103      }
104  
105      return strprintf("UNKNOWN[2^%u]", bit);
106  }
107  
108  std::vector<std::string> serviceFlagsToStr(uint64_t flags)
109  {
110      std::vector<std::string> str_flags;
111  
112      for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
113          if (flags & (1ULL << i)) {
114              str_flags.emplace_back(serviceFlagToStr(i));
115          }
116      }
117  
118      return str_flags;
119  }
120  
121  GenTxid ToGenTxid(const CInv& inv)
122  {
123      assert(inv.IsGenTxMsg());
124      return inv.IsMsgWtx() ? GenTxid{Wtxid::FromUint256(inv.hash)} : GenTxid{Txid::FromUint256(inv.hash)};
125  }