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 : 296004 : CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
11 : 296004 : : pchMessageStart{pchMessageStartIn}
12 : : {
13 : : // Copy the command name
14 : 296004 : size_t i = 0;
15 [ + + + + ]: 2284968 : for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
16 [ - + ]: 296004 : assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
17 : :
18 : 296004 : nMessageSize = nMessageSizeIn;
19 : 296004 : }
20 : :
21 : 198988 : std::string CMessageHeader::GetCommand() const
22 : : {
23 : 198988 : return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
24 : : }
25 : :
26 : 184543 : bool CMessageHeader::IsCommandValid() const
27 : : {
28 : : // Check the command string for errors
29 [ + + ]: 1246091 : for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {
30 [ + + ]: 1093339 : if (*p1 == 0) {
31 : : // Must be all zeros after the first zero
32 [ + + ]: 1179738 : for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {
33 [ + + ]: 1035383 : if (*p1 != 0) {
34 : : return false;
35 : : }
36 : : }
37 [ + + ]: 934956 : } else if (*p1 < ' ' || *p1 > 0x7E) {
38 : : return false;
39 : : }
40 : : }
41 : :
42 : : return true;
43 : : }
44 : :
45 : 2216295 : CInv::CInv()
46 : : {
47 : 2216295 : type = 0;
48 : 2216295 : hash.SetNull();
49 : 2216295 : }
50 : :
51 : 145309 : CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
52 : :
53 : 8 : bool operator<(const CInv& a, const CInv& b)
54 : : {
55 [ + + + + : 8 : return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
+ - ]
56 : : }
57 : :
58 : 44 : std::string CInv::GetCommand() const
59 : : {
60 [ + + ]: 44 : std::string cmd;
61 [ + + ]: 44 : if (type & MSG_WITNESS_FLAG)
62 [ + - ]: 32 : cmd.append("witness-");
63 : 44 : int masked = type & MSG_TYPE_MASK;
64 [ + + + + : 44 : 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 [ + - + - ]: 4 : case MSG_WTX: return cmd.append("wtx");
69 [ + - + - ]: 6 : case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
70 [ + - + - ]: 6 : case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
71 [ + - + - ]: 8 : case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
72 : 14 : default:
73 [ + - + - ]: 28 : throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
74 : : }
75 : 30 : }
76 : :
77 : 22 : std::string CInv::ToString() const
78 : : {
79 : 22 : try {
80 [ + - + + : 44 : return strprintf("%s %s", GetCommand(), hash.ToString());
+ - ]
81 [ - + ]: 7 : } catch(const std::out_of_range &) {
82 [ + - + - ]: 7 : return strprintf("0x%08x %s", type, hash.ToString());
83 : 7 : }
84 : : }
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 : : }
107 : :
108 : 3 : std::vector<std::string> serviceFlagsToStr(uint64_t flags)
109 : : {
110 : 3 : std::vector<std::string> str_flags;
111 : :
112 [ + + ]: 195 : for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
113 [ - + ]: 192 : if (flags & (1ULL << i)) {
114 [ # # # # ]: 0 : str_flags.emplace_back(serviceFlagToStr(i));
115 : : }
116 : : }
117 : :
118 : 3 : return str_flags;
119 : 0 : }
120 : :
121 : 181327 : GenTxid ToGenTxid(const CInv& inv)
122 : : {
123 [ + + ]: 181327 : assert(inv.IsGenTxMsg());
124 [ + + ]: 181327 : return inv.IsMsgWtx() ? GenTxid::Wtxid(inv.hash) : GenTxid::Txid(inv.hash);
125 : : }
|