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