bitcoin/src/protocol.cpp

126 lines
3.8 KiB
C++
Raw Normal View History

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2022 The Bitcoin Core developers
2014-12-13 01:09:33 -03:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <protocol.h>
#include <common/system.h>
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* msg_type, unsigned int nMessageSizeIn)
: pchMessageStart{pchMessageStartIn}
{
// Copy the message type name
size_t i = 0;
for (; i < MESSAGE_TYPE_SIZE && msg_type[i] != 0; ++i) m_msg_type[i] = msg_type[i];
assert(msg_type[i] == 0); // Assert that the message type name passed in is not longer than MESSAGE_TYPE_SIZE
nMessageSize = nMessageSizeIn;
}
std::string CMessageHeader::GetMessageType() const
{
return std::string(m_msg_type, m_msg_type + strnlen(m_msg_type, MESSAGE_TYPE_SIZE));
}
bool CMessageHeader::IsMessageTypeValid() const
{
// Check the message type string for errors
for (const char* p1 = m_msg_type; p1 < m_msg_type + MESSAGE_TYPE_SIZE; ++p1) {
if (*p1 == 0) {
// Must be all zeros after the first zero
for (; p1 < m_msg_type + MESSAGE_TYPE_SIZE; ++p1) {
if (*p1 != 0) {
return false;
}
}
} else if (*p1 < ' ' || *p1 > 0x7E) {
return false;
}
}
return true;
}
CInv::CInv()
{
type = 0;
hash.SetNull();
}
CInv::CInv(uint32_t typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
bool operator<(const CInv& a, const CInv& b)
{
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
}
std::string CInv::GetMessageType() const
{
std::string cmd;
if (type & MSG_WITNESS_FLAG)
cmd.append("witness-");
int masked = type & MSG_TYPE_MASK;
switch (masked)
{
case MSG_TX: return cmd.append(NetMsgType::TX);
// WTX is not a message type, just an inv type
case MSG_WTX: return cmd.append("wtx");
case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
default:
throw std::out_of_range(strprintf("CInv::GetMessageType(): type=%d unknown type", type));
}
}
std::string CInv::ToString() const
{
try {
return strprintf("%s %s", GetMessageType(), hash.ToString());
} catch(const std::out_of_range &) {
return strprintf("0x%08x %s", type, hash.ToString());
}
}
/**
* Convert a service flag (NODE_*) to a human readable string.
* It supports unknown service flags which will be returned as "UNKNOWN[...]".
* @param[in] bit the service flag is calculated as (1 << bit)
*/
static std::string serviceFlagToStr(size_t bit)
{
const uint64_t service_flag = 1ULL << bit;
switch ((ServiceFlags)service_flag) {
case NODE_NONE: abort(); // impossible
case NODE_NETWORK: return "NETWORK";
case NODE_BLOOM: return "BLOOM";
case NODE_WITNESS: return "WITNESS";
case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
case NODE_NETWORK_LIMITED: return "NETWORK_LIMITED";
case NODE_P2P_V2: return "P2P_V2";
// Not using default, so we get warned when a case is missing
}
return strprintf("UNKNOWN[2^%u]", bit);
}
std::vector<std::string> serviceFlagsToStr(uint64_t flags)
{
std::vector<std::string> str_flags;
for (size_t i = 0; i < sizeof(flags) * 8; ++i) {
if (flags & (1ULL << i)) {
str_flags.emplace_back(serviceFlagToStr(i));
}
}
return str_flags;
}
GenTxid ToGenTxid(const CInv& inv)
{
assert(inv.IsGenTxMsg());
return inv.IsMsgWtx() ? GenTxid::Wtxid(inv.hash) : GenTxid::Txid(inv.hash);
}