Branch data Line data Source code
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 : 461665 : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
11 : 461665 : : pchMessageStart{pchMessageStartIn}
12 : : {
13 : : // Copy the command name
14 : 461665 : size_t i = 0;
15 [ + + + + ]: 3526212 : for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
16 [ + - ]: 461665 : assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
17 : :
18 : 461665 : nMessageSize = nMessageSizeIn;
19 : : }
20 : :
21 : 278601 : std::string CMessageHeader::GetCommand() const
22 : : {
23 [ + - ]: 278601 : return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
24 : 0 : }
25 : :
26 : 255134 : bool CMessageHeader::IsCommandValid() const
27 : : {
28 : : // Check the command string for errors
29 [ + + - + : 1727823 : for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
+ ]
30 [ + + ]: 1472689 : if (*p1 == 0) {
31 : : // Must be all zeros after the first zero
32 [ + + ]: 1689816 : for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
33 [ + + ]: 1483489 : if (*p1 != 0) {
34 : 14753 : return false;
35 : : }
36 : 1468736 : }
37 [ + + + + ]: 1457936 : } else if (*p1 < ' ' || *p1 > 0x7E) {
38 : 26193 : return false;
39 : : }
40 : 1431743 : }
41 : :
42 : 214188 : return true;
43 : 255134 : }
44 : :
45 : 1924022 : CInv::CInv()
46 : : {
47 : 1924022 : type = 0;
48 : 1924022 : hash.SetNull();
49 : 1924022 : }
50 : :
51 : 206110 : CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
52 : :
53 : 15 : bool operator<(const CInv& a, const CInv& b)
54 : : {
55 [ + + + + ]: 15 : return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
56 : : }
57 : :
58 : 86 : std::string CInv::GetCommand() const
59 : : {
60 : 86 : std::string cmd;
61 [ + + ]: 86 : if (type & MSG_WITNESS_FLAG)
62 [ + - ]: 60 : cmd.append("witness-");
63 : 86 : int masked = type & MSG_TYPE_MASK;
64 [ + + + + : 86 : switch (masked)
+ + ]
65 : : {
66 [ + - + - ]: 6 : case MSG_TX: return cmd.append(NetMsgType::TX);
67 : : // WTX is not a message type, just an inv type
68 [ + - + - ]: 10 : case MSG_WTX: return cmd.append("wtx");
69 [ + - + - ]: 8 : case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
70 [ + - + - ]: 16 : case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
71 [ + - + - ]: 14 : case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
72 : : default:
73 [ + - + - : 32 : throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
+ - + - ]
74 : : }
75 : 118 : }
76 : :
77 : 43 : std::string CInv::ToString() const
78 : : {
79 : : try {
80 [ + + + - : 59 : return strprintf("%s %s", GetCommand(), hash.ToString());
+ - ]
81 [ - + ]: 16 : } catch(const std::out_of_range &) {
82 [ + - + - ]: 16 : return strprintf("0x%08x %s", type, hash.ToString());
83 [ # # ]: 16 : }
84 : 59 : }
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 : 0 : static std::string serviceFlagToStr(size_t bit)
92 : : {
93 : 0 : const uint64_t service_flag = 1ULL << bit;
94 [ # # # # : 0 : switch ((ServiceFlags)service_flag) {
# # # # ]
95 : 0 : case NODE_NONE: abort(); // impossible
96 [ # # ]: 0 : case NODE_NETWORK: return "NETWORK";
97 [ # # ]: 0 : case NODE_BLOOM: return "BLOOM";
98 [ # # ]: 0 : case NODE_WITNESS: return "WITNESS";
99 [ # # ]: 0 : case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
100 [ # # ]: 0 : case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
101 [ # # ]: 0 : case NODE_P2P_V2: return "P2P_V2";
102 : : // Not using default, so we get warned when a case is missing
103 : : }
104 : :
105 : 0 : return strprintf("UNKNOWN[2^%u]", bit);
106 : 0 : }
107 : :
108 : 5 : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
109 : : {
110 : 5 : std::vector<std::string> str_flags;
111 : :
112 [ + + ]: 325 : for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
113 [ + - ]: 320 : if (flags & (1ULL << i)) {
114 [ # # # # ]: 0 : str_flags.emplace_back(serviceFlagToStr(i));
115 : 0 : }
116 : 320 : }
117 : :
118 : 5 : return str_flags;
119 [ + - ]: 5 : }
120 : :
121 : 183692 : GenTxid ToGenTxid(const CInv& inv)
122 : : {
123 [ + - ]: 183692 : assert(inv.IsGenTxMsg());
124 [ + + ]: 183692 : return inv.IsMsgWtx() ? GenTxid::Wtxid(inv.hash) : GenTxid::Txid(inv.hash);
125 : : }
|