Implement CInv message type MSG_WTX
This adds the double-hash message variant. The extra hash field is set to null for block message types, and to all-ones for MSG_TX (to match the legacy authHash value used for pre-v5 transactions in the Merkle tree).
This commit is contained in:
parent
34954e39d0
commit
d715f4ecac
|
@ -334,25 +334,36 @@ class CInv(object):
|
|||
typemap = {
|
||||
0: b"Error",
|
||||
1: b"TX",
|
||||
2: b"Block"}
|
||||
2: b"Block",
|
||||
5: b"WTX",
|
||||
}
|
||||
|
||||
def __init__(self, t=0, h=0):
|
||||
def __init__(self, t=0, h=0, h_aux=0):
|
||||
self.type = t
|
||||
self.hash = h
|
||||
self.hash_aux = h_aux
|
||||
if self.type == 1:
|
||||
self.hash_aux = ((1 << 256) - 1)
|
||||
|
||||
def deserialize(self, f):
|
||||
self.type = struct.unpack("<i", f.read(4))[0]
|
||||
self.hash = deser_uint256(f)
|
||||
if self.type == 5:
|
||||
self.hash_aux = deser_uint256(f)
|
||||
elif self.type == 1:
|
||||
self.hash_aux = ((1 << 256) - 1)
|
||||
|
||||
def serialize(self):
|
||||
r = b""
|
||||
r += struct.pack("<i", self.type)
|
||||
r += ser_uint256(self.hash)
|
||||
if self.type == 5:
|
||||
r += ser_uint256(self.hash_aux)
|
||||
return r
|
||||
|
||||
def __repr__(self):
|
||||
return "CInv(type=%s hash=%064x)" \
|
||||
% (self.typemap[self.type], self.hash)
|
||||
return "CInv(type=%s hash=%064x hash_aux=%064x)" \
|
||||
% (self.typemap[self.type], self.hash, self.hash_aux)
|
||||
|
||||
|
||||
class CBlockLocator(object):
|
||||
|
|
|
@ -87,17 +87,33 @@ CInv::CInv()
|
|||
{
|
||||
type = 0;
|
||||
hash.SetNull();
|
||||
hashAux.SetNull();
|
||||
}
|
||||
|
||||
CInv::CInv(int typeIn, const uint256& hashIn)
|
||||
{
|
||||
assert(typeIn != MSG_WTX);
|
||||
type = typeIn;
|
||||
hash = hashIn;
|
||||
if (typeIn == MSG_TX) {
|
||||
hashAux = uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
} else {
|
||||
hashAux.SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
CInv::CInv(int typeIn, const uint256& hashIn, const uint256& hashAuxIn)
|
||||
{
|
||||
type = typeIn;
|
||||
hash = hashIn;
|
||||
hashAux = hashAuxIn;
|
||||
}
|
||||
|
||||
bool operator<(const CInv& a, const CInv& b)
|
||||
{
|
||||
return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
|
||||
return (a.type < b.type ||
|
||||
(a.type == b.type && a.hash < b.hash) ||
|
||||
(a.type == b.type && a.hash == b.hash && a.hashAux < b.hashAux));
|
||||
}
|
||||
|
||||
std::string CInv::GetCommand() const
|
||||
|
@ -107,13 +123,34 @@ std::string CInv::GetCommand() const
|
|||
{
|
||||
case MSG_TX: return cmd.append("tx");
|
||||
case MSG_BLOCK: return cmd.append("block");
|
||||
// WTX is not a message type, just an inv type
|
||||
case MSG_WTX: return cmd.append("wtx");
|
||||
case MSG_FILTERED_BLOCK: return cmd.append("merkleblock");
|
||||
default:
|
||||
throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> CInv::GetWideHash() const
|
||||
{
|
||||
assert(type != MSG_BLOCK);
|
||||
if (type == MSG_TX) {
|
||||
for (auto byte : hashAux) {
|
||||
assert(byte == 0xff);
|
||||
}
|
||||
};
|
||||
std::vector<unsigned char> vData(hash.begin(), hash.end());
|
||||
vData.insert(vData.end(), hashAux.begin(), hashAux.end());
|
||||
return vData;
|
||||
}
|
||||
|
||||
std::string CInv::ToString() const
|
||||
{
|
||||
return strprintf("%s %s", GetCommand(), hash.ToString());
|
||||
switch (type)
|
||||
{
|
||||
case MSG_WTX:
|
||||
return strprintf("%s(%s, %s)", GetCommand(), hash.ToString(), hashAux.ToString());
|
||||
default:
|
||||
return strprintf("%s %s", GetCommand(), hash.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,12 +121,12 @@ public:
|
|||
* to mention it in the respective ZIP, as well as checking for collisions with
|
||||
* BIPs we might want to backport.
|
||||
*/
|
||||
enum GetDataMsg
|
||||
{
|
||||
enum GetDataMsg : uint32_t {
|
||||
UNDEFINED = 0,
|
||||
MSG_TX = 1,
|
||||
MSG_BLOCK = 2,
|
||||
// The following can only occur in getdata. Invs always use TX or BLOCK.
|
||||
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
|
||||
};
|
||||
|
||||
|
@ -136,25 +136,42 @@ 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);
|
||||
READWRITE(hash);
|
||||
if (type == MSG_WTX && 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 = uint256S("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -33,4 +33,8 @@ static const int MEMPOOL_GD_VERSION = 60002;
|
|||
//! "filter*" commands are disabled without NODE_BLOOM after and including this version
|
||||
static const int NO_BLOOM_VERSION = 170004;
|
||||
|
||||
//! Changes to CInv parsing, starting with this version:
|
||||
//! - MSG_WTX type defined, which contains two 32-byte hashes.
|
||||
static const int CINV_WTX_VERSION = 170014;
|
||||
|
||||
#endif // BITCOIN_VERSION_H
|
||||
|
|
Loading…
Reference in New Issue