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 }