git / moonbite-core / src/protocol.cpp · raw

// Copyright (c) 2009-2010 Satoshi Nakamoto// Copyright (c) 2009-2019 The Bitcoin Core developers// Distributed under the MIT software license, see the accompanying// file COPYING or http://www.opensource.org/licenses/mit-license.php.#include <protocol.h>#include <chainparams.h>#include <util/strencodings.h>#include <util/system.h>static std::atomic<bool> g_initial_block_download_completed(false);namespace NetMsgType {const char *VERSION="version";const char *VERACK="verack";const char *ADDR="addr";const char *ADDRV2="addrv2";const char *SENDADDRV2="sendaddrv2";const char *INV="inv";const char *GETDATA="getdata";const char *MERKLEBLOCK="merkleblock";const char *GETBLOCKS="getblocks";const char *GETHEADERS="getheaders";const char *TX="tx";const char *HEADERS="headers";const char *BLOCK="block";const char *GETADDR="getaddr";const char *MEMPOOL="mempool";const char *PING="ping";const char *PONG="pong";const char *NOTFOUND="notfound";const char *FILTERLOAD="filterload";const char *FILTERADD="filteradd";const char *FILTERCLEAR="filterclear";const char *SENDHEADERS="sendheaders";const char *FEEFILTER="feefilter";const char *SENDCMPCT="sendcmpct";const char *CMPCTBLOCK="cmpctblock";const char *GETBLOCKTXN="getblocktxn";const char *BLOCKTXN="blocktxn";const char *GETCFILTERS="getcfilters";const char *CFILTER="cfilter";const char *GETCFHEADERS="getcfheaders";const char *CFHEADERS="cfheaders";const char *GETCFCHECKPT="getcfcheckpt";const char *CFCHECKPT="cfcheckpt";const char *WTXIDRELAY="wtxidrelay";const char *MWEBHEADER="mwebheader";const char *MWEBLEAFSET="mwebleafset";const char *GETMWEBUTXOS="getmwebutxos";const char *MWEBUTXOS="mwebutxos";} // namespace NetMsgType/** All known message types. Keep this in the same order as the list of * messages above and in protocol.h. */const static std::string allNetMessageTypes[] = {    NetMsgType::VERSION,    NetMsgType::VERACK,    NetMsgType::ADDR,    NetMsgType::ADDRV2,    NetMsgType::SENDADDRV2,    NetMsgType::INV,    NetMsgType::GETDATA,    NetMsgType::MERKLEBLOCK,    NetMsgType::GETBLOCKS,    NetMsgType::GETHEADERS,    NetMsgType::TX,    NetMsgType::HEADERS,    NetMsgType::BLOCK,    NetMsgType::GETADDR,    NetMsgType::MEMPOOL,    NetMsgType::PING,    NetMsgType::PONG,    NetMsgType::NOTFOUND,    NetMsgType::FILTERLOAD,    NetMsgType::FILTERADD,    NetMsgType::FILTERCLEAR,    NetMsgType::SENDHEADERS,    NetMsgType::FEEFILTER,    NetMsgType::SENDCMPCT,    NetMsgType::CMPCTBLOCK,    NetMsgType::GETBLOCKTXN,    NetMsgType::BLOCKTXN,    NetMsgType::GETCFILTERS,    NetMsgType::CFILTER,    NetMsgType::GETCFHEADERS,    NetMsgType::CFHEADERS,    NetMsgType::GETCFCHECKPT,    NetMsgType::CFCHECKPT,    NetMsgType::WTXIDRELAY,    NetMsgType::MWEBHEADER,    NetMsgType::MWEBLEAFSET,    NetMsgType::GETMWEBUTXOS,    NetMsgType::MWEBUTXOS,};const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));CMessageHeader::CMessageHeader(){    memset(pchMessageStart, 0, MESSAGE_START_SIZE);    memset(pchCommand, 0, sizeof(pchCommand));    nMessageSize = -1;    memset(pchChecksum, 0, CHECKSUM_SIZE);}CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn){    memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);    // Copy the command name, zero-padding to COMMAND_SIZE bytes    size_t i = 0;    for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];    assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE    for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0;    nMessageSize = nMessageSizeIn;    memset(pchChecksum, 0, CHECKSUM_SIZE);}std::string CMessageHeader::GetCommand() const{    return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));}bool CMessageHeader::IsCommandValid() const{    // Check the command string for errors    for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; ++p1) {        if (*p1 == 0) {            // Must be all zeros after the first zero            for (; p1 < pchCommand + COMMAND_SIZE; ++p1) {                if (*p1 != 0) {                    return false;                }            }        } else if (*p1 < ' ' || *p1 > 0x7E) {            return false;        }    }    return true;}ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {    if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {        return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS | NODE_MWEB);    }    return ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_MWEB);}void SetServiceFlagsIBDCache(bool state) {    g_initial_block_download_completed = state;}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::GetCommand() const{    std::string cmd;    if (type & MSG_MWEB_FLAG)        cmd.append("mweb-");    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);    case MSG_MWEB_HEADER:    return cmd.append(NetMsgType::MWEBHEADER);    case MSG_MWEB_LEAFSET:   return cmd.append(NetMsgType::MWEBLEAFSET);    default:        throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));    }}std::string CInv::ToString() const{    try {        return strprintf("%s %s", GetCommand(), hash.ToString());    } catch(const std::out_of_range &) {        return strprintf("0x%08x %s", type, hash.ToString());    }}const std::vector<std::string> &getAllNetMessageTypes(){    return allNetMessageTypesVec;}/** * 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_GETUTXO:           return "GETUTXO";    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_MWEB:              return "MWEB";    case NODE_MWEB_LIGHT_CLIENT: return "MWEB_LIGHT_CLIENT";    // Not using default, so we get warned when a case is missing    }    std::ostringstream stream;    stream.imbue(std::locale::classic());    stream << "UNKNOWN[";    stream << "2^" << bit;    stream << "]";    return stream.str();}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(), inv.hash};}