mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
bcf5455bfd
* net: Consistent checksum handling In principle, the checksums of P2P packets are simply 4-byte blobs which are the first four bytes of SHA256(SHA256(payload)). Currently they are handled as little-endian 32-bit integers half of the time, as blobs the other half, sometimes copying the one to the other, resulting in somewhat confused code. This PR changes the handling to be consistent both at packet creation and receiving, making it (I think) easier to understand. * net: Hardcode protocol sizes and use fixed-size types The P2P network uses a fixed protocol, these sizes shouldn't change based on what happens to be the architecture.
279 lines
7.9 KiB
C++
279 lines
7.9 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2015 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 "util.h"
|
|
#include "utilstrencodings.h"
|
|
|
|
#ifndef WIN32
|
|
# include <arpa/inet.h>
|
|
#endif
|
|
|
|
namespace NetMsgType {
|
|
const char *VERSION="version";
|
|
const char *VERACK="verack";
|
|
const char *ADDR="addr";
|
|
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 *ALERT="alert";
|
|
const char *NOTFOUND="notfound";
|
|
const char *FILTERLOAD="filterload";
|
|
const char *FILTERADD="filteradd";
|
|
const char *FILTERCLEAR="filterclear";
|
|
const char *REJECT="reject";
|
|
const char *SENDHEADERS="sendheaders";
|
|
// Dash message types
|
|
const char *TXLOCKREQUEST="ix";
|
|
const char *TXLOCKVOTE="txlvote";
|
|
const char *SPORK="spork";
|
|
const char *GETSPORKS="getsporks";
|
|
const char *MASTERNODEPAYMENTVOTE="mnw";
|
|
const char *MASTERNODEPAYMENTBLOCK="mnwb";
|
|
const char *MASTERNODEPAYMENTSYNC="mnget";
|
|
const char *MNBUDGETSYNC="mnvs"; // depreciated since 12.1
|
|
const char *MNBUDGETVOTE="mvote"; // depreciated since 12.1
|
|
const char *MNBUDGETPROPOSAL="mprop"; // depreciated since 12.1
|
|
const char *MNBUDGETFINAL="fbs"; // depreciated since 12.1
|
|
const char *MNBUDGETFINALVOTE="fbvote"; // depreciated since 12.1
|
|
const char *MNQUORUM="mn quorum"; // not implemented
|
|
const char *MNANNOUNCE="mnb";
|
|
const char *MNPING="mnp";
|
|
const char *DSACCEPT="dsa";
|
|
const char *DSVIN="dsi";
|
|
const char *DSFINALTX="dsf";
|
|
const char *DSSIGNFINALTX="dss";
|
|
const char *DSCOMPLETE="dsc";
|
|
const char *DSSTATUSUPDATE="dssu";
|
|
const char *DSTX="dstx";
|
|
const char *DSQUEUE="dsq";
|
|
const char *DSEG="dseg";
|
|
const char *SYNCSTATUSCOUNT="ssc";
|
|
const char *MNGOVERNANCESYNC="govsync";
|
|
const char *MNGOVERNANCEOBJECT="govobj";
|
|
const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
|
|
const char *MNVERIFY="mnv";
|
|
};
|
|
|
|
static const char* ppszTypeName[] =
|
|
{
|
|
"ERROR", // Should never occur
|
|
NetMsgType::TX,
|
|
NetMsgType::BLOCK,
|
|
"filtered block", // Should never occur
|
|
// Dash message types
|
|
// NOTE: include non-implmented here, we must keep this list in sync with enum in protocol.h
|
|
NetMsgType::TXLOCKREQUEST,
|
|
NetMsgType::TXLOCKVOTE,
|
|
NetMsgType::SPORK,
|
|
NetMsgType::MASTERNODEPAYMENTVOTE,
|
|
NetMsgType::MASTERNODEPAYMENTBLOCK, // reusing, was MNSCANERROR previousely, was NOT used in 12.0, we need this for inv
|
|
NetMsgType::MNBUDGETVOTE, // depreciated since 12.1
|
|
NetMsgType::MNBUDGETPROPOSAL, // depreciated since 12.1
|
|
NetMsgType::MNBUDGETFINAL, // depreciated since 12.1
|
|
NetMsgType::MNBUDGETFINALVOTE, // depreciated since 12.1
|
|
NetMsgType::MNQUORUM, // not implemented
|
|
NetMsgType::MNANNOUNCE,
|
|
NetMsgType::MNPING,
|
|
NetMsgType::DSTX,
|
|
NetMsgType::MNGOVERNANCEOBJECT,
|
|
NetMsgType::MNGOVERNANCEOBJECTVOTE,
|
|
NetMsgType::MNVERIFY,
|
|
};
|
|
|
|
/** 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::INV,
|
|
NetMsgType::GETDATA,
|
|
NetMsgType::MERKLEBLOCK,
|
|
NetMsgType::GETBLOCKS,
|
|
NetMsgType::GETHEADERS,
|
|
NetMsgType::TX,
|
|
NetMsgType::HEADERS,
|
|
NetMsgType::BLOCK,
|
|
NetMsgType::GETADDR,
|
|
NetMsgType::MEMPOOL,
|
|
NetMsgType::PING,
|
|
NetMsgType::PONG,
|
|
NetMsgType::ALERT,
|
|
NetMsgType::NOTFOUND,
|
|
NetMsgType::FILTERLOAD,
|
|
NetMsgType::FILTERADD,
|
|
NetMsgType::FILTERCLEAR,
|
|
NetMsgType::REJECT,
|
|
NetMsgType::SENDHEADERS,
|
|
// Dash message types
|
|
// NOTE: do NOT include non-implmented here, we want them to be "Unknown command" in ProcessMessage()
|
|
NetMsgType::TXLOCKREQUEST,
|
|
NetMsgType::TXLOCKVOTE,
|
|
NetMsgType::SPORK,
|
|
NetMsgType::GETSPORKS,
|
|
NetMsgType::MASTERNODEPAYMENTVOTE,
|
|
// NetMsgType::MASTERNODEPAYMENTBLOCK, // there is no message for this, only inventory
|
|
NetMsgType::MASTERNODEPAYMENTSYNC,
|
|
NetMsgType::MNANNOUNCE,
|
|
NetMsgType::MNPING,
|
|
NetMsgType::DSACCEPT,
|
|
NetMsgType::DSVIN,
|
|
NetMsgType::DSFINALTX,
|
|
NetMsgType::DSSIGNFINALTX,
|
|
NetMsgType::DSCOMPLETE,
|
|
NetMsgType::DSSTATUSUPDATE,
|
|
NetMsgType::DSTX,
|
|
NetMsgType::DSQUEUE,
|
|
NetMsgType::DSEG,
|
|
NetMsgType::SYNCSTATUSCOUNT,
|
|
NetMsgType::MNGOVERNANCESYNC,
|
|
NetMsgType::MNGOVERNANCEOBJECT,
|
|
NetMsgType::MNGOVERNANCEOBJECTVOTE,
|
|
NetMsgType::MNVERIFY,
|
|
};
|
|
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
|
|
|
|
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
|
|
{
|
|
memcpy(pchMessageStart, pchMessageStartIn, 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);
|
|
memset(pchCommand, 0, sizeof(pchCommand));
|
|
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
|
|
nMessageSize = nMessageSizeIn;
|
|
memset(pchChecksum, 0, CHECKSUM_SIZE);
|
|
}
|
|
|
|
std::string CMessageHeader::GetCommand() const
|
|
{
|
|
return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
|
|
}
|
|
|
|
bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
|
|
{
|
|
// Check start string
|
|
if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
|
|
return false;
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Message size
|
|
if (nMessageSize > MAX_SIZE)
|
|
{
|
|
LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
CAddress::CAddress() : CService()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn)
|
|
{
|
|
Init();
|
|
nServices = nServicesIn;
|
|
}
|
|
|
|
void CAddress::Init()
|
|
{
|
|
nServices = NODE_NONE;
|
|
nTime = 100000000;
|
|
}
|
|
|
|
CInv::CInv()
|
|
{
|
|
type = 0;
|
|
hash.SetNull();
|
|
}
|
|
|
|
CInv::CInv(int typeIn, const uint256& hashIn)
|
|
{
|
|
type = typeIn;
|
|
hash = hashIn;
|
|
}
|
|
|
|
CInv::CInv(const std::string& strType, const uint256& hashIn)
|
|
{
|
|
unsigned int i;
|
|
for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
|
|
{
|
|
if (strType == ppszTypeName[i])
|
|
{
|
|
type = i;
|
|
break;
|
|
}
|
|
}
|
|
if (i == ARRAYLEN(ppszTypeName))
|
|
throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType));
|
|
hash = hashIn;
|
|
}
|
|
|
|
bool operator<(const CInv& a, const CInv& b)
|
|
{
|
|
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
|
|
}
|
|
|
|
bool CInv::IsKnownType() const
|
|
{
|
|
return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName));
|
|
}
|
|
|
|
const char* CInv::GetCommand() const
|
|
{
|
|
if (!IsKnownType())
|
|
throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
|
|
return ppszTypeName[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;
|
|
}
|