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