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