protocol.cpp raw

   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  }
 126