zcashd/src/protocol.h

206 lines
6.6 KiB
C++

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin Core developers
// Copyright (c) 2018-2023 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#ifndef __cplusplus
#error This header can only be compiled as C++.
#endif
#ifndef BITCOIN_PROTOCOL_H
#define BITCOIN_PROTOCOL_H
#include "netbase.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
#include <stdint.h>
#include <string>
/** Message header.
* (4) message start.
* (12) command.
* (4) size.
* (4) checksum.
*/
class CMessageHeader
{
public:
enum {
MESSAGE_START_SIZE = 4,
COMMAND_SIZE = 12,
MESSAGE_SIZE_SIZE = 4,
CHECKSUM_SIZE = 4,
MESSAGE_SIZE_OFFSET = MESSAGE_START_SIZE + COMMAND_SIZE,
CHECKSUM_OFFSET = MESSAGE_SIZE_OFFSET + MESSAGE_SIZE_SIZE,
HEADER_SIZE = MESSAGE_START_SIZE + COMMAND_SIZE + MESSAGE_SIZE_SIZE + CHECKSUM_SIZE
};
typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
CMessageHeader(const MessageStartChars& pchMessageStartIn);
CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn);
std::string GetCommand() const;
bool IsValid(const MessageStartChars& messageStart) const;
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(nMessageSize);
READWRITE(FLATDATA(pchChecksum));
}
char pchMessageStart[MESSAGE_START_SIZE];
char pchCommand[COMMAND_SIZE];
uint32_t nMessageSize;
uint8_t pchChecksum[CHECKSUM_SIZE];
};
/** nServices flags */
enum {
// NODE_NETWORK means that the node is capable of serving the block chain. It is currently
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
// network services but don't provide them.
NODE_NETWORK = (1 << 0),
// NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections.
// Zcash nodes used to support this by default, without advertising this bit,
// but no longer do as of protocol version 170004 (= NO_BLOOM_VERSION)
NODE_BLOOM = (1 << 2),
// Bits 24-31 are reserved for temporary experiments. Just pick a bit that
// isn't getting used, or one not being used much, and notify the
// bitcoin-development mailing list. Remember that service bits are just
// unauthenticated advertisements, so your code must be robust against
// collisions and other cases where nodes may be advertising a service they
// do not actually support. Other service bits should be allocated via the
// BIP process.
};
/** A CService with information about it as peer */
class CAddress : public CService
{
public:
CAddress();
explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK);
void Init();
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
if (ser_action.ForRead())
Init();
int nVersion = s.GetVersion();
if (s.GetType() & SER_DISK)
READWRITE(nVersion);
if ((s.GetType() & SER_DISK) ||
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
READWRITE(nTime);
READWRITE(nServices);
READWRITE(*(CService*)this);
}
// TODO: make private (improves encapsulation)
public:
uint64_t nServices;
// disk and network only
unsigned int nTime;
};
/** getdata / inv message types.
* These numbers are defined by the protocol. When adding a new value, be sure
* to mention it in the respective ZIP, as well as checking for collisions with
* BIPs we might want to backport.
*/
enum GetDataMsg : uint32_t {
UNDEFINED = 0,
MSG_TX = 1,
MSG_BLOCK = 2,
MSG_WTX = 5, //!< Defined in ZIP 239
// The following can only occur in getdata. Invs always use TX/WTX or BLOCK.
MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37
};
/** inv message data */
class CInv
{
public:
CInv();
CInv(int typeIn, const uint256& hashIn);
CInv(int typeIn, const uint256& hashIn, const uint256& hashAuxIn);
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
int nVersion = s.GetVersion();
READWRITE(type);
// The implicit P2P network protocol inherited from Bitcoin Core has
// zcashd nodes sort-of ignoring unknown CInv message types in inv
// messages: they are added to the known transaction inventory, but
// AlreadyHave returns true, so we do nothing with them. Meanwhile for
// getdata messages, ProcessGetData ignores unknown message types
// entirely.
//
// As of v4.5.0, we change the implementation behaviour to reject
// undefined message types instead of ignoring them.
switch (type) {
case MSG_TX:
case MSG_BLOCK:
case MSG_FILTERED_BLOCK:
break;
case MSG_WTX:
if (nVersion < CINV_WTX_VERSION) {
throw std::ios_base::failure(
"Negotiated protocol version does not support CInv message type MSG_WTX");
}
break;
default:
// This includes UNDEFINED, which should never be serialized.
throw std::ios_base::failure("Unknown CInv message type");
}
READWRITE(hash);
if (type == MSG_WTX) {
// We've already checked above that nVersion >= CINV_WTX_VERSION.
READWRITE(hashAux);
} else if (type == MSG_TX && ser_action.ForRead()) {
// Ensure that this value is set consistently in memory for MSG_TX.
hashAux = LEGACY_TX_AUTH_DIGEST;
}
}
friend bool operator<(const CInv& a, const CInv& b);
std::string GetCommand() const;
std::vector<unsigned char> GetWideHash() const;
std::string ToString() const;
// TODO: make private (improves encapsulation)
public:
int type;
// The main hash. This is:
// - MSG_BLOCK: the block hash.
// - MSG_TX and MSG_WTX: the txid.
uint256 hash;
// The auxiliary hash. This is:
// - MSG_BLOCK: null (all-zeroes) and not parsed or serialized.
// - MSG_TX: legacy auth digest (all-ones) and not parsed or serialized.
// - MSG_WTX: the auth digest.
uint256 hashAux;
};
#endif // BITCOIN_PROTOCOL_H