Line data Source code
# 1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : // Copyright (c) 2009-2019 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 <util/system.h>
# 9 : #include <util/strencodings.h>
# 10 :
# 11 : #ifndef WIN32
# 12 : # include <arpa/inet.h>
# 13 : #endif
# 14 :
# 15 : static std::atomic<bool> g_initial_block_download_completed(false);
# 16 :
# 17 : namespace NetMsgType {
# 18 : const char *VERSION="version";
# 19 : const char *VERACK="verack";
# 20 : const char *ADDR="addr";
# 21 : const char *ADDRv2="addrv2";
# 22 : const char *INV="inv";
# 23 : const char *GETDATA="getdata";
# 24 : const char *MERKLEBLOCK="merkleblock";
# 25 : const char *GETBLOCKS="getblocks";
# 26 : const char *GETHEADERS="getheaders";
# 27 : const char *TX="tx";
# 28 : const char *HEADERS="headers";
# 29 : const char *BLOCK="block";
# 30 : const char *GETADDR="getaddr";
# 31 : const char *MEMPOOL="mempool";
# 32 : const char *PING="ping";
# 33 : const char *PONG="pong";
# 34 : const char *NOTFOUND="notfound";
# 35 : const char *FILTERLOAD="filterload";
# 36 : const char *FILTERADD="filteradd";
# 37 : const char *FILTERCLEAR="filterclear";
# 38 : const char *SENDHEADERS="sendheaders";
# 39 : const char *FEEFILTER="feefilter";
# 40 : const char *SENDCMPCT="sendcmpct";
# 41 : const char *CMPCTBLOCK="cmpctblock";
# 42 : const char *GETBLOCKTXN="getblocktxn";
# 43 : const char *BLOCKTXN="blocktxn";
# 44 : const char *GETCFILTERS="getcfilters";
# 45 : const char *CFILTER="cfilter";
# 46 : const char *GETCFHEADERS="getcfheaders";
# 47 : const char *CFHEADERS="cfheaders";
# 48 : const char *GETCFCHECKPT="getcfcheckpt";
# 49 : const char *CFCHECKPT="cfcheckpt";
# 50 : } // namespace NetMsgType
# 51 :
# 52 : /** All known message types. Keep this in the same order as the list of
# 53 : * messages above and in protocol.h.
# 54 : */
# 55 : const static std::string allNetMessageTypes[] = {
# 56 : NetMsgType::VERSION,
# 57 : NetMsgType::VERACK,
# 58 : NetMsgType::ADDR,
# 59 : NetMsgType::ADDRv2,
# 60 : NetMsgType::INV,
# 61 : NetMsgType::GETDATA,
# 62 : NetMsgType::MERKLEBLOCK,
# 63 : NetMsgType::GETBLOCKS,
# 64 : NetMsgType::GETHEADERS,
# 65 : NetMsgType::TX,
# 66 : NetMsgType::HEADERS,
# 67 : NetMsgType::BLOCK,
# 68 : NetMsgType::GETADDR,
# 69 : NetMsgType::MEMPOOL,
# 70 : NetMsgType::PING,
# 71 : NetMsgType::PONG,
# 72 : NetMsgType::NOTFOUND,
# 73 : NetMsgType::FILTERLOAD,
# 74 : NetMsgType::FILTERADD,
# 75 : NetMsgType::FILTERCLEAR,
# 76 : NetMsgType::SENDHEADERS,
# 77 : NetMsgType::FEEFILTER,
# 78 : NetMsgType::SENDCMPCT,
# 79 : NetMsgType::CMPCTBLOCK,
# 80 : NetMsgType::GETBLOCKTXN,
# 81 : NetMsgType::BLOCKTXN,
# 82 : NetMsgType::GETCFILTERS,
# 83 : NetMsgType::CFILTER,
# 84 : NetMsgType::GETCFHEADERS,
# 85 : NetMsgType::CFHEADERS,
# 86 : NetMsgType::GETCFCHECKPT,
# 87 : NetMsgType::CFCHECKPT,
# 88 : };
# 89 : const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
# 90 :
# 91 : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
# 92 34 : {
# 93 34 : memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
# 94 34 : memset(pchCommand, 0, sizeof(pchCommand));
# 95 34 : nMessageSize = -1;
# 96 34 : memset(pchChecksum, 0, CHECKSUM_SIZE);
# 97 34 : }
# 98 :
# 99 : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
# 100 38 : {
# 101 38 : memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
# 102 38 :
# 103 38 : // Copy the command name, zero-padding to COMMAND_SIZE bytes
# 104 38 : size_t i = 0;
# 105 298 : for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
# 106 38 : assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
# 107 234 : for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0;
# 108 38 :
# 109 38 : nMessageSize = nMessageSizeIn;
# 110 38 : memset(pchChecksum, 0, CHECKSUM_SIZE);
# 111 38 : }
# 112 :
# 113 : std::string CMessageHeader::GetCommand() const
# 114 0 : {
# 115 0 : return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
# 116 0 : }
# 117 :
# 118 : bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
# 119 0 : {
# 120 0 : // Check start string
# 121 0 : if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
# 122 0 : return false;
# 123 0 :
# 124 0 : // Check the command string for errors
# 125 0 : for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
# 126 0 : {
# 127 0 : if (*p1 == 0)
# 128 0 : {
# 129 0 : // Must be all zeros after the first zero
# 130 0 : for (; p1 < pchCommand + COMMAND_SIZE; p1++)
# 131 0 : if (*p1 != 0)
# 132 0 : return false;
# 133 0 : }
# 134 0 : else if (*p1 < ' ' || *p1 > 0x7E)
# 135 0 : return false;
# 136 0 : }
# 137 0 :
# 138 0 : // Message size
# 139 0 : if (nMessageSize > MAX_SIZE)
# 140 0 : {
# 141 0 : LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
# 142 0 : return false;
# 143 0 : }
# 144 0 :
# 145 0 : return true;
# 146 0 : }
# 147 :
# 148 :
# 149 0 : ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
# 150 0 : if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
# 151 0 : return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
# 152 0 : }
# 153 0 : return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
# 154 0 : }
# 155 :
# 156 0 : void SetServiceFlagsIBDCache(bool state) {
# 157 0 : g_initial_block_download_completed = state;
# 158 0 : }
# 159 :
# 160 : CInv::CInv()
# 161 0 : {
# 162 0 : type = 0;
# 163 0 : hash.SetNull();
# 164 0 : }
# 165 :
# 166 0 : CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
# 167 :
# 168 : bool operator<(const CInv& a, const CInv& b)
# 169 0 : {
# 170 0 : return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
# 171 0 : }
# 172 :
# 173 : std::string CInv::GetCommand() const
# 174 0 : {
# 175 0 : std::string cmd;
# 176 0 : if (type & MSG_WITNESS_FLAG)
# 177 0 : cmd.append("witness-");
# 178 0 : int masked = type & MSG_TYPE_MASK;
# 179 0 : switch (masked)
# 180 0 : {
# 181 0 : case MSG_TX: return cmd.append(NetMsgType::TX);
# 182 0 : case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
# 183 0 : case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
# 184 0 : case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
# 185 0 : default:
# 186 0 : throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
# 187 0 : }
# 188 0 : }
# 189 :
# 190 : std::string CInv::ToString() const
# 191 0 : {
# 192 0 : try {
# 193 0 : return strprintf("%s %s", GetCommand(), hash.ToString());
# 194 0 : } catch(const std::out_of_range &) {
# 195 0 : return strprintf("0x%08x %s", type, hash.ToString());
# 196 0 : }
# 197 0 : }
# 198 :
# 199 : const std::vector<std::string> &getAllNetMessageTypes()
# 200 34 : {
# 201 34 : return allNetMessageTypesVec;
# 202 34 : }
# 203 :
# 204 : /**
# 205 : * Convert a service flag (NODE_*) to a human readable string.
# 206 : * It supports unknown service flags which will be returned as "UNKNOWN[...]".
# 207 : * @param[in] bit the service flag is calculated as (1 << bit)
# 208 : */
# 209 : static std::string serviceFlagToStr(size_t bit)
# 210 0 : {
# 211 0 : const uint64_t service_flag = 1ULL << bit;
# 212 0 : switch ((ServiceFlags)service_flag) {
# 213 0 : case NODE_NONE: abort(); // impossible
# 214 0 : case NODE_NETWORK: return "NETWORK";
# 215 0 : case NODE_GETUTXO: return "GETUTXO";
# 216 0 : case NODE_BLOOM: return "BLOOM";
# 217 0 : case NODE_WITNESS: return "WITNESS";
# 218 0 : case NODE_ADDRv2: return "ADDRv2";
# 219 0 : case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
# 220 0 : // Not using default, so we get warned when a case is missing
# 221 0 : }
# 222 0 :
# 223 0 : std::ostringstream stream;
# 224 0 : stream.imbue(std::locale::classic());
# 225 0 : stream << "UNKNOWN[";
# 226 0 : if (bit < 8) {
# 227 0 : stream << service_flag;
# 228 0 : } else {
# 229 0 : stream << "2^" << bit;
# 230 0 : }
# 231 0 : stream << "]";
# 232 0 : return stream.str();
# 233 0 : }
# 234 :
# 235 : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
# 236 6 : {
# 237 6 : std::vector<std::string> str_flags;
# 238 6 :
# 239 390 : for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
# 240 384 : if (flags & (1ULL << i)) {
# 241 0 : str_flags.emplace_back(serviceFlagToStr(i));
# 242 0 : }
# 243 384 : }
# 244 6 :
# 245 6 : return str_flags;
# 246 6 : }
|