Branch data 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/strencodings.h>
# 9 : : #include <util/system.h>
# 10 : :
# 11 : : static std::atomic<bool> g_initial_block_download_completed(false);
# 12 : :
# 13 : : namespace NetMsgType {
# 14 : : const char *VERSION="version";
# 15 : : const char *VERACK="verack";
# 16 : : const char *ADDR="addr";
# 17 : : const char *ADDRv2="addrv2";
# 18 : : const char *SENDADDRv2="sendaddrv2";
# 19 : : const char *INV="inv";
# 20 : : const char *GETDATA="getdata";
# 21 : : const char *MERKLEBLOCK="merkleblock";
# 22 : : const char *GETBLOCKS="getblocks";
# 23 : : const char *GETHEADERS="getheaders";
# 24 : : const char *TX="tx";
# 25 : : const char *HEADERS="headers";
# 26 : : const char *BLOCK="block";
# 27 : : const char *GETADDR="getaddr";
# 28 : : const char *MEMPOOL="mempool";
# 29 : : const char *PING="ping";
# 30 : : const char *PONG="pong";
# 31 : : const char *NOTFOUND="notfound";
# 32 : : const char *FILTERLOAD="filterload";
# 33 : : const char *FILTERADD="filteradd";
# 34 : : const char *FILTERCLEAR="filterclear";
# 35 : : const char *SENDHEADERS="sendheaders";
# 36 : : const char *FEEFILTER="feefilter";
# 37 : : const char *SENDCMPCT="sendcmpct";
# 38 : : const char *CMPCTBLOCK="cmpctblock";
# 39 : : const char *GETBLOCKTXN="getblocktxn";
# 40 : : const char *BLOCKTXN="blocktxn";
# 41 : : const char *GETCFILTERS="getcfilters";
# 42 : : const char *CFILTER="cfilter";
# 43 : : const char *GETCFHEADERS="getcfheaders";
# 44 : : const char *CFHEADERS="cfheaders";
# 45 : : const char *GETCFCHECKPT="getcfcheckpt";
# 46 : : const char *CFCHECKPT="cfcheckpt";
# 47 : : const char *WTXIDRELAY="wtxidrelay";
# 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::string allNetMessageTypes[] = {
# 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 : : };
# 89 : : const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
# 90 : :
# 91 : : CMessageHeader::CMessageHeader()
# 92 : 763 : {
# 93 : 763 : memset(pchMessageStart, 0, MESSAGE_START_SIZE);
# 94 : 763 : memset(pchCommand, 0, sizeof(pchCommand));
# 95 : 763 : nMessageSize = -1;
# 96 : 763 : memset(pchChecksum, 0, CHECKSUM_SIZE);
# 97 : 763 : }
# 98 : :
# 99 : : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
# 100 : 91041 : {
# 101 : 91041 : memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
# 102 : :
# 103 : : // Copy the command name, zero-padding to COMMAND_SIZE bytes
# 104 : 91041 : size_t i = 0;
# 105 : 631351 : for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
# 106 : 91041 : assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
# 107 : 643223 : for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0;
# 108 : :
# 109 : 91041 : nMessageSize = nMessageSizeIn;
# 110 : 91041 : memset(pchChecksum, 0, CHECKSUM_SIZE);
# 111 : 91041 : }
# 112 : :
# 113 : : std::string CMessageHeader::GetCommand() const
# 114 : 86126 : {
# 115 : 86126 : return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
# 116 : 86126 : }
# 117 : :
# 118 : : bool CMessageHeader::IsCommandValid() const
# 119 : 86120 : {
# 120 : : // Check the command string for errors
# 121 : 704190 : for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
# 122 : 618071 : if (*p1 == 0) {
# 123 : : // Must be all zeros after the first zero
# 124 : 587581 : for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
# 125 : 501472 : if (*p1 != 0) {
# 126 : 1 : return false;
# 127 : 1 : }
# 128 : 501472 : }
# 129 : 531961 : } else if (*p1 < ' ' || *p1 > 0x7E) {
# 130 : 0 : return false;
# 131 : 0 : }
# 132 : 618071 : }
# 133 : :
# 134 : 86119 : return true;
# 135 : 86120 : }
# 136 : :
# 137 : :
# 138 : 4345 : ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
# 139 : 4345 : if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
# 140 : 0 : return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
# 141 : 0 : }
# 142 : 4345 : return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
# 143 : 4345 : }
# 144 : :
# 145 : 39500 : void SetServiceFlagsIBDCache(bool state) {
# 146 : 39500 : g_initial_block_download_completed = state;
# 147 : 39500 : }
# 148 : :
# 149 : : CInv::CInv()
# 150 : 200499 : {
# 151 : 200499 : type = 0;
# 152 : 200499 : hash.SetNull();
# 153 : 200499 : }
# 154 : :
# 155 : 50871 : CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
# 156 : :
# 157 : : bool operator<(const CInv& a, const CInv& b)
# 158 : 0 : {
# 159 : 0 : return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
# 160 : 0 : }
# 161 : :
# 162 : : std::string CInv::GetCommand() const
# 163 : 41917 : {
# 164 : 41917 : std::string cmd;
# 165 : 41917 : if (type & MSG_WITNESS_FLAG)
# 166 : 5643 : cmd.append("witness-");
# 167 : 41917 : int masked = type & MSG_TYPE_MASK;
# 168 : 41917 : switch (masked)
# 169 : 41917 : {
# 170 : 20 : case MSG_TX: return cmd.append(NetMsgType::TX);
# 171 : : // WTX is not a message type, just an inv type
# 172 : 27248 : case MSG_WTX: return cmd.append("wtx");
# 173 : 14440 : case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
# 174 : 7 : case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
# 175 : 201 : case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
# 176 : 1 : default:
# 177 : 1 : throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
# 178 : 41917 : }
# 179 : 41917 : }
# 180 : :
# 181 : : std::string CInv::ToString() const
# 182 : 41917 : {
# 183 : 41917 : try {
# 184 : 41917 : return strprintf("%s %s", GetCommand(), hash.ToString());
# 185 : 1 : } catch(const std::out_of_range &) {
# 186 : 1 : return strprintf("0x%08x %s", type, hash.ToString());
# 187 : 1 : }
# 188 : 41917 : }
# 189 : :
# 190 : : const std::vector<std::string> &getAllNetMessageTypes()
# 191 : 763 : {
# 192 : 763 : return allNetMessageTypesVec;
# 193 : 763 : }
# 194 : :
# 195 : : /**
# 196 : : * Convert a service flag (NODE_*) to a human readable string.
# 197 : : * It supports unknown service flags which will be returned as "UNKNOWN[...]".
# 198 : : * @param[in] bit the service flag is calculated as (1 << bit)
# 199 : : */
# 200 : : static std::string serviceFlagToStr(size_t bit)
# 201 : 17490 : {
# 202 : 17490 : const uint64_t service_flag = 1ULL << bit;
# 203 : 17490 : switch ((ServiceFlags)service_flag) {
# 204 : 0 : case NODE_NONE: abort(); // impossible
# 205 : 6002 : case NODE_NETWORK: return "NETWORK";
# 206 : 0 : case NODE_GETUTXO: return "GETUTXO";
# 207 : 4 : case NODE_BLOOM: return "BLOOM";
# 208 : 5976 : case NODE_WITNESS: return "WITNESS";
# 209 : 22 : case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
# 210 : 5484 : case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
# 211 : : // Not using default, so we get warned when a case is missing
# 212 : 2 : }
# 213 : :
# 214 : 2 : std::ostringstream stream;
# 215 : 2 : stream.imbue(std::locale::classic());
# 216 : 2 : stream << "UNKNOWN[";
# 217 : 2 : stream << "2^" << bit;
# 218 : 2 : stream << "]";
# 219 : 2 : return stream.str();
# 220 : 2 : }
# 221 : :
# 222 : : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
# 223 : 6277 : {
# 224 : 6277 : std::vector<std::string> str_flags;
# 225 : :
# 226 : 408005 : for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
# 227 : 401728 : if (flags & (1ULL << i)) {
# 228 : 17490 : str_flags.emplace_back(serviceFlagToStr(i));
# 229 : 17490 : }
# 230 : 401728 : }
# 231 : :
# 232 : 6277 : return str_flags;
# 233 : 6277 : }
# 234 : :
# 235 : : GenTxid ToGenTxid(const CInv& inv)
# 236 : 47673 : {
# 237 : 47673 : assert(inv.IsGenTxMsg());
# 238 : 47673 : return {inv.IsMsgWtx(), inv.hash};
# 239 : 47673 : }
|