Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 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 : :
# 10 : : static std::atomic<bool> g_initial_block_download_completed(false);
# 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 : : } // namespace NetMsgType
# 48 : :
# 49 : : /** All known message types. Keep this in the same order as the list of
# 50 : : * messages above and in protocol.h.
# 51 : : */
# 52 : : const static std::string allNetMessageTypes[] = {
# 53 : : NetMsgType::VERSION,
# 54 : : NetMsgType::VERACK,
# 55 : : NetMsgType::ADDR,
# 56 : : NetMsgType::ADDRV2,
# 57 : : NetMsgType::SENDADDRV2,
# 58 : : NetMsgType::INV,
# 59 : : NetMsgType::GETDATA,
# 60 : : NetMsgType::MERKLEBLOCK,
# 61 : : NetMsgType::GETBLOCKS,
# 62 : : NetMsgType::GETHEADERS,
# 63 : : NetMsgType::TX,
# 64 : : NetMsgType::HEADERS,
# 65 : : NetMsgType::BLOCK,
# 66 : : NetMsgType::GETADDR,
# 67 : : NetMsgType::MEMPOOL,
# 68 : : NetMsgType::PING,
# 69 : : NetMsgType::PONG,
# 70 : : NetMsgType::NOTFOUND,
# 71 : : NetMsgType::FILTERLOAD,
# 72 : : NetMsgType::FILTERADD,
# 73 : : NetMsgType::FILTERCLEAR,
# 74 : : NetMsgType::SENDHEADERS,
# 75 : : NetMsgType::FEEFILTER,
# 76 : : NetMsgType::SENDCMPCT,
# 77 : : NetMsgType::CMPCTBLOCK,
# 78 : : NetMsgType::GETBLOCKTXN,
# 79 : : NetMsgType::BLOCKTXN,
# 80 : : NetMsgType::GETCFILTERS,
# 81 : : NetMsgType::CFILTER,
# 82 : : NetMsgType::GETCFHEADERS,
# 83 : : NetMsgType::CFHEADERS,
# 84 : : NetMsgType::GETCFCHECKPT,
# 85 : : NetMsgType::CFCHECKPT,
# 86 : : NetMsgType::WTXIDRELAY,
# 87 : : };
# 88 : : const static std::vector<std::string> allNetMessageTypesVec(std::begin(allNetMessageTypes), std::end(allNetMessageTypes));
# 89 : :
# 90 : : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
# 91 : 113377 : {
# 92 : 113377 : memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
# 93 : :
# 94 : : // Copy the command name
# 95 : 113377 : size_t i = 0;
# 96 [ + - ][ + + ]: 840750 : for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
# 97 : 113377 : assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
# 98 : :
# 99 : 0 : nMessageSize = nMessageSizeIn;
# 100 : 113377 : }
# 101 : :
# 102 : : std::string CMessageHeader::GetCommand() const
# 103 : 111792 : {
# 104 : 111792 : return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
# 105 : 111792 : }
# 106 : :
# 107 : : bool CMessageHeader::IsCommandValid() const
# 108 : 111709 : {
# 109 : : // Check the command string for errors
# 110 [ + + ]: 942415 : for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
# 111 [ + + ]: 830787 : if (*p1 == 0) {
# 112 : : // Must be all zeros after the first zero
# 113 [ + + ]: 732551 : for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
# 114 [ + + ]: 620933 : if (*p1 != 0) {
# 115 : 1 : return false;
# 116 : 1 : }
# 117 : 620933 : }
# 118 [ + + ][ - + ]: 719168 : } else if (*p1 < ' ' || *p1 > 0x7E) {
# 119 : 80 : return false;
# 120 : 80 : }
# 121 : 830787 : }
# 122 : :
# 123 : 111628 : return true;
# 124 : 111709 : }
# 125 : :
# 126 : :
# 127 : 83 : ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
# 128 [ - + ][ # # ]: 83 : if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
# 129 : 0 : return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
# 130 : 0 : }
# 131 : 83 : return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
# 132 : 83 : }
# 133 : :
# 134 : 52434 : void SetServiceFlagsIBDCache(bool state) {
# 135 : 52434 : g_initial_block_download_completed = state;
# 136 : 52434 : }
# 137 : :
# 138 : : CInv::CInv()
# 139 : 221714 : {
# 140 : 221714 : type = 0;
# 141 : 221714 : hash.SetNull();
# 142 : 221714 : }
# 143 : :
# 144 : 64616 : CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
# 145 : :
# 146 : : bool operator<(const CInv& a, const CInv& b)
# 147 : 0 : {
# 148 [ # # ][ # # ]: 0 : return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
# [ # # ]
# 149 : 0 : }
# 150 : :
# 151 : : std::string CInv::GetCommand() const
# 152 : 46524 : {
# 153 : 46524 : std::string cmd;
# 154 [ + + ]: 46524 : if (type & MSG_WITNESS_FLAG)
# 155 : 8658 : cmd.append("witness-");
# 156 : 46524 : int masked = type & MSG_TYPE_MASK;
# 157 : 46524 : switch (masked)
# 158 : 46524 : {
# 159 [ + + ]: 12 : case MSG_TX: return cmd.append(NetMsgType::TX);
# 160 : : // WTX is not a message type, just an inv type
# 161 [ + + ]: 31578 : case MSG_WTX: return cmd.append("wtx");
# 162 [ + + ]: 14647 : case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
# 163 [ + + ]: 7 : case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
# 164 [ + + ]: 279 : case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
# 165 [ + + ]: 1 : default:
# 166 : 1 : throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
# 167 : 46524 : }
# 168 : 46524 : }
# 169 : :
# 170 : : std::string CInv::ToString() const
# 171 : 46524 : {
# 172 : 46524 : try {
# 173 : 46524 : return strprintf("%s %s", GetCommand(), hash.ToString());
# 174 : 46524 : } catch(const std::out_of_range &) {
# 175 : 1 : return strprintf("0x%08x %s", type, hash.ToString());
# 176 : 1 : }
# 177 : 46524 : }
# 178 : :
# 179 : : const std::vector<std::string> &getAllNetMessageTypes()
# 180 : 1157 : {
# 181 : 1157 : return allNetMessageTypesVec;
# 182 : 1157 : }
# 183 : :
# 184 : : /**
# 185 : : * Convert a service flag (NODE_*) to a human readable string.
# 186 : : * It supports unknown service flags which will be returned as "UNKNOWN[...]".
# 187 : : * @param[in] bit the service flag is calculated as (1 << bit)
# 188 : : */
# 189 : : static std::string serviceFlagToStr(size_t bit)
# 190 : 41802 : {
# 191 : 41802 : const uint64_t service_flag = 1ULL << bit;
# 192 [ + + ]: 41802 : switch ((ServiceFlags)service_flag) {
# 193 [ - + ]: 0 : case NODE_NONE: abort(); // impossible
# 194 [ + + ]: 13915 : case NODE_NETWORK: return "NETWORK";
# 195 [ + + ]: 4 : case NODE_BLOOM: return "BLOOM";
# 196 [ + + ]: 14533 : case NODE_WITNESS: return "WITNESS";
# 197 [ + + ]: 39 : case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
# 198 [ + + ]: 13307 : case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
# 199 : : // Not using default, so we get warned when a case is missing
# 200 : 41802 : }
# 201 : :
# 202 : 4 : std::ostringstream stream;
# 203 : 4 : stream.imbue(std::locale::classic());
# 204 : 4 : stream << "UNKNOWN[";
# 205 : 4 : stream << "2^" << bit;
# 206 : 4 : stream << "]";
# 207 : 4 : return stream.str();
# 208 : 41802 : }
# 209 : :
# 210 : : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
# 211 : 14954 : {
# 212 : 14954 : std::vector<std::string> str_flags;
# 213 : :
# 214 [ + + ]: 972010 : for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
# 215 [ + + ]: 957056 : if (flags & (1ULL << i)) {
# 216 : 41802 : str_flags.emplace_back(serviceFlagToStr(i));
# 217 : 41802 : }
# 218 : 957056 : }
# 219 : :
# 220 : 14954 : return str_flags;
# 221 : 14954 : }
# 222 : :
# 223 : : GenTxid ToGenTxid(const CInv& inv)
# 224 : 52357 : {
# 225 : 52357 : assert(inv.IsGenTxMsg());
# 226 [ + + ]: 52357 : return inv.IsMsgWtx() ? GenTxid::Wtxid(inv.hash) : GenTxid::Txid(inv.hash);
# 227 : 52357 : }
|