aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework/messages.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/test_framework/messages.py')
-rwxr-xr-xtest/functional/test_framework/messages.py226
1 files changed, 115 insertions, 111 deletions
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index d008cb39aa..4e496a9275 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -25,7 +25,6 @@ from io import BytesIO
import math
import random
import socket
-import struct
import time
import unittest
@@ -47,6 +46,7 @@ MAX_PROTOCOL_MESSAGE_LENGTH = 4000000 # Maximum length of incoming protocol mes
MAX_HEADERS_RESULTS = 2000 # Number of headers sent in one getheaders result
MAX_INV_SIZE = 50000 # Maximum number of entries in an 'inv' protocol message
+NODE_NONE = 0
NODE_NETWORK = (1 << 0)
NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
@@ -75,6 +75,13 @@ MAX_OP_RETURN_RELAY = 83
DEFAULT_MEMPOOL_EXPIRY_HOURS = 336 # hours
+MAGIC_BYTES = {
+ "mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
+ "testnet3": b"\x0b\x11\x09\x07", # testnet3
+ "regtest": b"\xfa\xbf\xb5\xda", # regtest
+ "signet": b"\x0a\x03\xcf\x40", # signet
+}
+
def sha256(s):
return hashlib.sha256(s).digest()
@@ -90,24 +97,24 @@ def hash256(s):
def ser_compact_size(l):
r = b""
if l < 253:
- r = struct.pack("B", l)
+ r = l.to_bytes(1, "little")
elif l < 0x10000:
- r = struct.pack("<BH", 253, l)
+ r = (253).to_bytes(1, "little") + l.to_bytes(2, "little")
elif l < 0x100000000:
- r = struct.pack("<BI", 254, l)
+ r = (254).to_bytes(1, "little") + l.to_bytes(4, "little")
else:
- r = struct.pack("<BQ", 255, l)
+ r = (255).to_bytes(1, "little") + l.to_bytes(8, "little")
return r
def deser_compact_size(f):
- nit = struct.unpack("<B", f.read(1))[0]
+ nit = int.from_bytes(f.read(1), "little")
if nit == 253:
- nit = struct.unpack("<H", f.read(2))[0]
+ nit = int.from_bytes(f.read(2), "little")
elif nit == 254:
- nit = struct.unpack("<I", f.read(4))[0]
+ nit = int.from_bytes(f.read(4), "little")
elif nit == 255:
- nit = struct.unpack("<Q", f.read(8))[0]
+ nit = int.from_bytes(f.read(8), "little")
return nit
@@ -272,13 +279,13 @@ class CAddress:
"""Deserialize from addrv1 format (pre-BIP155)"""
if with_time:
# VERSION messages serialize CAddress objects without time
- self.time = struct.unpack("<I", f.read(4))[0]
- self.nServices = struct.unpack("<Q", f.read(8))[0]
+ self.time = int.from_bytes(f.read(4), "little")
+ self.nServices = int.from_bytes(f.read(8), "little")
# We only support IPv4 which means skip 12 bytes and read the next 4 as IPv4 address.
f.read(12)
self.net = self.NET_IPV4
self.ip = socket.inet_ntoa(f.read(4))
- self.port = struct.unpack(">H", f.read(2))[0]
+ self.port = int.from_bytes(f.read(2), "big")
def serialize(self, *, with_time=True):
"""Serialize in addrv1 format (pre-BIP155)"""
@@ -286,20 +293,20 @@ class CAddress:
r = b""
if with_time:
# VERSION messages serialize CAddress objects without time
- r += struct.pack("<I", self.time)
- r += struct.pack("<Q", self.nServices)
+ r += self.time.to_bytes(4, "little")
+ r += self.nServices.to_bytes(8, "little")
r += b"\x00" * 10 + b"\xff" * 2
r += socket.inet_aton(self.ip)
- r += struct.pack(">H", self.port)
+ r += self.port.to_bytes(2, "big")
return r
def deserialize_v2(self, f):
"""Deserialize from addrv2 format (BIP155)"""
- self.time = struct.unpack("<I", f.read(4))[0]
+ self.time = int.from_bytes(f.read(4), "little")
self.nServices = deser_compact_size(f)
- self.net = struct.unpack("B", f.read(1))[0]
+ self.net = int.from_bytes(f.read(1), "little")
assert self.net in self.ADDRV2_NET_NAME
address_length = deser_compact_size(f)
@@ -322,15 +329,15 @@ class CAddress:
else:
raise Exception(f"Address type not supported")
- self.port = struct.unpack(">H", f.read(2))[0]
+ self.port = int.from_bytes(f.read(2), "big")
def serialize_v2(self):
"""Serialize in addrv2 format (BIP155)"""
assert self.net in self.ADDRV2_NET_NAME
r = b""
- r += struct.pack("<I", self.time)
+ r += self.time.to_bytes(4, "little")
r += ser_compact_size(self.nServices)
- r += struct.pack("B", self.net)
+ r += self.net.to_bytes(1, "little")
r += ser_compact_size(self.ADDRV2_ADDRESS_LENGTH[self.net])
if self.net == self.NET_IPV4:
r += socket.inet_aton(self.ip)
@@ -348,7 +355,7 @@ class CAddress:
r += socket.inet_pton(socket.AF_INET6, self.ip)
else:
raise Exception(f"Address type not supported")
- r += struct.pack(">H", self.port)
+ r += self.port.to_bytes(2, "big")
return r
def __repr__(self):
@@ -375,12 +382,12 @@ class CInv:
self.hash = h
def deserialize(self, f):
- self.type = struct.unpack("<I", f.read(4))[0]
+ self.type = int.from_bytes(f.read(4), "little")
self.hash = deser_uint256(f)
def serialize(self):
r = b""
- r += struct.pack("<I", self.type)
+ r += self.type.to_bytes(4, "little")
r += ser_uint256(self.hash)
return r
@@ -399,12 +406,12 @@ class CBlockLocator:
self.vHave = []
def deserialize(self, f):
- struct.unpack("<i", f.read(4))[0] # Ignore version field.
+ int.from_bytes(f.read(4), "little", signed=True) # Ignore version field.
self.vHave = deser_uint256_vector(f)
def serialize(self):
r = b""
- r += struct.pack("<i", 0) # Bitcoin Core ignores version field. Set it to 0.
+ r += (0).to_bytes(4, "little", signed=True) # Bitcoin Core ignores the version field. Set it to 0.
r += ser_uint256_vector(self.vHave)
return r
@@ -421,12 +428,12 @@ class COutPoint:
def deserialize(self, f):
self.hash = deser_uint256(f)
- self.n = struct.unpack("<I", f.read(4))[0]
+ self.n = int.from_bytes(f.read(4), "little")
def serialize(self):
r = b""
r += ser_uint256(self.hash)
- r += struct.pack("<I", self.n)
+ r += self.n.to_bytes(4, "little")
return r
def __repr__(self):
@@ -448,13 +455,13 @@ class CTxIn:
self.prevout = COutPoint()
self.prevout.deserialize(f)
self.scriptSig = deser_string(f)
- self.nSequence = struct.unpack("<I", f.read(4))[0]
+ self.nSequence = int.from_bytes(f.read(4), "little")
def serialize(self):
r = b""
r += self.prevout.serialize()
r += ser_string(self.scriptSig)
- r += struct.pack("<I", self.nSequence)
+ r += self.nSequence.to_bytes(4, "little")
return r
def __repr__(self):
@@ -471,12 +478,12 @@ class CTxOut:
self.scriptPubKey = scriptPubKey
def deserialize(self, f):
- self.nValue = struct.unpack("<q", f.read(8))[0]
+ self.nValue = int.from_bytes(f.read(8), "little", signed=True)
self.scriptPubKey = deser_string(f)
def serialize(self):
r = b""
- r += struct.pack("<q", self.nValue)
+ r += self.nValue.to_bytes(8, "little", signed=True)
r += ser_string(self.scriptPubKey)
return r
@@ -575,11 +582,11 @@ class CTransaction:
self.wit = copy.deepcopy(tx.wit)
def deserialize(self, f):
- self.nVersion = struct.unpack("<i", f.read(4))[0]
+ self.nVersion = int.from_bytes(f.read(4), "little", signed=True)
self.vin = deser_vector(f, CTxIn)
flags = 0
if len(self.vin) == 0:
- flags = struct.unpack("<B", f.read(1))[0]
+ flags = int.from_bytes(f.read(1), "little")
# Not sure why flags can't be zero, but this
# matches the implementation in bitcoind
if (flags != 0):
@@ -592,16 +599,16 @@ class CTransaction:
self.wit.deserialize(f)
else:
self.wit = CTxWitness()
- self.nLockTime = struct.unpack("<I", f.read(4))[0]
+ self.nLockTime = int.from_bytes(f.read(4), "little")
self.sha256 = None
self.hash = None
def serialize_without_witness(self):
r = b""
- r += struct.pack("<i", self.nVersion)
+ r += self.nVersion.to_bytes(4, "little", signed=True)
r += ser_vector(self.vin)
r += ser_vector(self.vout)
- r += struct.pack("<I", self.nLockTime)
+ r += self.nLockTime.to_bytes(4, "little")
return r
# Only serialize with witness when explicitly called for
@@ -610,11 +617,11 @@ class CTransaction:
if not self.wit.is_null():
flags |= 1
r = b""
- r += struct.pack("<i", self.nVersion)
+ r += self.nVersion.to_bytes(4, "little", signed=True)
if flags:
dummy = []
r += ser_vector(dummy)
- r += struct.pack("<B", flags)
+ r += flags.to_bytes(1, "little")
r += ser_vector(self.vin)
r += ser_vector(self.vout)
if flags & 1:
@@ -624,7 +631,7 @@ class CTransaction:
for _ in range(len(self.wit.vtxinwit), len(self.vin)):
self.wit.vtxinwit.append(CTxInWitness())
r += self.wit.serialize()
- r += struct.pack("<I", self.nLockTime)
+ r += self.nLockTime.to_bytes(4, "little")
return r
# Regular serialization is with witness -- must explicitly
@@ -703,34 +710,34 @@ class CBlockHeader:
self.hash = None
def deserialize(self, f):
- self.nVersion = struct.unpack("<i", f.read(4))[0]
+ self.nVersion = int.from_bytes(f.read(4), "little", signed=True)
self.hashPrevBlock = deser_uint256(f)
self.hashMerkleRoot = deser_uint256(f)
- self.nTime = struct.unpack("<I", f.read(4))[0]
- self.nBits = struct.unpack("<I", f.read(4))[0]
- self.nNonce = struct.unpack("<I", f.read(4))[0]
+ self.nTime = int.from_bytes(f.read(4), "little")
+ self.nBits = int.from_bytes(f.read(4), "little")
+ self.nNonce = int.from_bytes(f.read(4), "little")
self.sha256 = None
self.hash = None
def serialize(self):
r = b""
- r += struct.pack("<i", self.nVersion)
+ r += self.nVersion.to_bytes(4, "little", signed=True)
r += ser_uint256(self.hashPrevBlock)
r += ser_uint256(self.hashMerkleRoot)
- r += struct.pack("<I", self.nTime)
- r += struct.pack("<I", self.nBits)
- r += struct.pack("<I", self.nNonce)
+ r += self.nTime.to_bytes(4, "little")
+ r += self.nBits.to_bytes(4, "little")
+ r += self.nNonce.to_bytes(4, "little")
return r
def calc_sha256(self):
if self.sha256 is None:
r = b""
- r += struct.pack("<i", self.nVersion)
+ r += self.nVersion.to_bytes(4, "little", signed=True)
r += ser_uint256(self.hashPrevBlock)
r += ser_uint256(self.hashMerkleRoot)
- r += struct.pack("<I", self.nTime)
- r += struct.pack("<I", self.nBits)
- r += struct.pack("<I", self.nNonce)
+ r += self.nTime.to_bytes(4, "little")
+ r += self.nBits.to_bytes(4, "little")
+ r += self.nNonce.to_bytes(4, "little")
self.sha256 = uint256_from_str(hash256(r))
self.hash = hash256(r)[::-1].hex()
@@ -874,12 +881,12 @@ class P2PHeaderAndShortIDs:
def deserialize(self, f):
self.header.deserialize(f)
- self.nonce = struct.unpack("<Q", f.read(8))[0]
+ self.nonce = int.from_bytes(f.read(8), "little")
self.shortids_length = deser_compact_size(f)
for _ in range(self.shortids_length):
# shortids are defined to be 6 bytes in the spec, so append
# two zero bytes and read it in as an 8-byte number
- self.shortids.append(struct.unpack("<Q", f.read(6) + b'\x00\x00')[0])
+ self.shortids.append(int.from_bytes(f.read(6) + b'\x00\x00', "little"))
self.prefilled_txn = deser_vector(f, PrefilledTransaction)
self.prefilled_txn_length = len(self.prefilled_txn)
@@ -887,11 +894,11 @@ class P2PHeaderAndShortIDs:
def serialize(self, with_witness=False):
r = b""
r += self.header.serialize()
- r += struct.pack("<Q", self.nonce)
+ r += self.nonce.to_bytes(8, "little")
r += ser_compact_size(self.shortids_length)
for x in self.shortids:
# We only want the first 6 bytes
- r += struct.pack("<Q", x)[0:6]
+ r += x.to_bytes(8, "little")[0:6]
if with_witness:
r += ser_vector(self.prefilled_txn, "serialize_with_witness")
else:
@@ -956,10 +963,10 @@ class HeaderAndShortIDs:
def get_siphash_keys(self):
header_nonce = self.header.serialize()
- header_nonce += struct.pack("<Q", self.nonce)
+ header_nonce += self.nonce.to_bytes(8, "little")
hash_header_nonce_as_str = sha256(header_nonce)
- key0 = struct.unpack("<Q", hash_header_nonce_as_str[0:8])[0]
- key1 = struct.unpack("<Q", hash_header_nonce_as_str[8:16])[0]
+ key0 = int.from_bytes(hash_header_nonce_as_str[0:8], "little")
+ key1 = int.from_bytes(hash_header_nonce_as_str[8:16], "little")
return [ key0, key1 ]
# Version 2 compact blocks use wtxid in shortids (rather than txid)
@@ -1057,7 +1064,7 @@ class CPartialMerkleTree:
self.vBits = []
def deserialize(self, f):
- self.nTransactions = struct.unpack("<i", f.read(4))[0]
+ self.nTransactions = int.from_bytes(f.read(4), "little")
self.vHash = deser_uint256_vector(f)
vBytes = deser_string(f)
self.vBits = []
@@ -1066,7 +1073,7 @@ class CPartialMerkleTree:
def serialize(self):
r = b""
- r += struct.pack("<i", self.nTransactions)
+ r += self.nTransactions.to_bytes(4, "little")
r += ser_uint256_vector(self.vHash)
vBytesArray = bytearray([0x00] * ((len(self.vBits) + 7)//8))
for i in range(len(self.vBits)):
@@ -1117,37 +1124,34 @@ class msg_version:
self.relay = 0
def deserialize(self, f):
- self.nVersion = struct.unpack("<i", f.read(4))[0]
- self.nServices = struct.unpack("<Q", f.read(8))[0]
- self.nTime = struct.unpack("<q", f.read(8))[0]
+ self.nVersion = int.from_bytes(f.read(4), "little", signed=True)
+ self.nServices = int.from_bytes(f.read(8), "little")
+ self.nTime = int.from_bytes(f.read(8), "little", signed=True)
self.addrTo = CAddress()
self.addrTo.deserialize(f, with_time=False)
self.addrFrom = CAddress()
self.addrFrom.deserialize(f, with_time=False)
- self.nNonce = struct.unpack("<Q", f.read(8))[0]
+ self.nNonce = int.from_bytes(f.read(8), "little")
self.strSubVer = deser_string(f).decode('utf-8')
- self.nStartingHeight = struct.unpack("<i", f.read(4))[0]
+ self.nStartingHeight = int.from_bytes(f.read(4), "little", signed=True)
# Relay field is optional for version 70001 onwards
# But, unconditionally check it to match behaviour in bitcoind
- try:
- self.relay = struct.unpack("<b", f.read(1))[0]
- except struct.error:
- self.relay = 0
+ self.relay = int.from_bytes(f.read(1), "little") # f.read(1) may return an empty b''
def serialize(self):
r = b""
- r += struct.pack("<i", self.nVersion)
- r += struct.pack("<Q", self.nServices)
- r += struct.pack("<q", self.nTime)
+ r += self.nVersion.to_bytes(4, "little", signed=True)
+ r += self.nServices.to_bytes(8, "little")
+ r += self.nTime.to_bytes(8, "little", signed=True)
r += self.addrTo.serialize(with_time=False)
r += self.addrFrom.serialize(with_time=False)
- r += struct.pack("<Q", self.nNonce)
+ r += self.nNonce.to_bytes(8, "little")
r += ser_string(self.strSubVer.encode('utf-8'))
- r += struct.pack("<i", self.nStartingHeight)
- r += struct.pack("<b", self.relay)
+ r += self.nStartingHeight.to_bytes(4, "little", signed=True)
+ r += self.relay.to_bytes(1, "little")
return r
def __repr__(self):
@@ -1393,11 +1397,11 @@ class msg_ping:
self.nonce = nonce
def deserialize(self, f):
- self.nonce = struct.unpack("<Q", f.read(8))[0]
+ self.nonce = int.from_bytes(f.read(8), "little")
def serialize(self):
r = b""
- r += struct.pack("<Q", self.nonce)
+ r += self.nonce.to_bytes(8, "little")
return r
def __repr__(self):
@@ -1412,11 +1416,11 @@ class msg_pong:
self.nonce = nonce
def deserialize(self, f):
- self.nonce = struct.unpack("<Q", f.read(8))[0]
+ self.nonce = int.from_bytes(f.read(8), "little")
def serialize(self):
r = b""
- r += struct.pack("<Q", self.nonce)
+ r += self.nonce.to_bytes(8, "little")
return r
def __repr__(self):
@@ -1557,16 +1561,16 @@ class msg_filterload:
def deserialize(self, f):
self.data = deser_string(f)
- self.nHashFuncs = struct.unpack("<I", f.read(4))[0]
- self.nTweak = struct.unpack("<I", f.read(4))[0]
- self.nFlags = struct.unpack("<B", f.read(1))[0]
+ self.nHashFuncs = int.from_bytes(f.read(4), "little")
+ self.nTweak = int.from_bytes(f.read(4), "little")
+ self.nFlags = int.from_bytes(f.read(1), "little")
def serialize(self):
r = b""
r += ser_string(self.data)
- r += struct.pack("<I", self.nHashFuncs)
- r += struct.pack("<I", self.nTweak)
- r += struct.pack("<B", self.nFlags)
+ r += self.nHashFuncs.to_bytes(4, "little")
+ r += self.nTweak.to_bytes(4, "little")
+ r += self.nFlags.to_bytes(1, "little")
return r
def __repr__(self):
@@ -1618,11 +1622,11 @@ class msg_feefilter:
self.feerate = feerate
def deserialize(self, f):
- self.feerate = struct.unpack("<Q", f.read(8))[0]
+ self.feerate = int.from_bytes(f.read(8), "little")
def serialize(self):
r = b""
- r += struct.pack("<Q", self.feerate)
+ r += self.feerate.to_bytes(8, "little")
return r
def __repr__(self):
@@ -1638,13 +1642,13 @@ class msg_sendcmpct:
self.version = version
def deserialize(self, f):
- self.announce = struct.unpack("<?", f.read(1))[0]
- self.version = struct.unpack("<Q", f.read(8))[0]
+ self.announce = bool(int.from_bytes(f.read(1), "little"))
+ self.version = int.from_bytes(f.read(8), "little")
def serialize(self):
r = b""
- r += struct.pack("<?", self.announce)
- r += struct.pack("<Q", self.version)
+ r += int(self.announce).to_bytes(1, "little")
+ r += self.version.to_bytes(8, "little")
return r
def __repr__(self):
@@ -1727,14 +1731,14 @@ class msg_getcfilters:
self.stop_hash = stop_hash
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
- self.start_height = struct.unpack("<I", f.read(4))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
+ self.start_height = int.from_bytes(f.read(4), "little")
self.stop_hash = deser_uint256(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
- r += struct.pack("<I", self.start_height)
+ r += self.filter_type.to_bytes(1, "little")
+ r += self.start_height.to_bytes(4, "little")
r += ser_uint256(self.stop_hash)
return r
@@ -1752,13 +1756,13 @@ class msg_cfilter:
self.filter_data = filter_data
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
self.block_hash = deser_uint256(f)
self.filter_data = deser_string(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
+ r += self.filter_type.to_bytes(1, "little")
r += ser_uint256(self.block_hash)
r += ser_string(self.filter_data)
return r
@@ -1777,14 +1781,14 @@ class msg_getcfheaders:
self.stop_hash = stop_hash
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
- self.start_height = struct.unpack("<I", f.read(4))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
+ self.start_height = int.from_bytes(f.read(4), "little")
self.stop_hash = deser_uint256(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
- r += struct.pack("<I", self.start_height)
+ r += self.filter_type.to_bytes(1, "little")
+ r += self.start_height.to_bytes(4, "little")
r += ser_uint256(self.stop_hash)
return r
@@ -1803,14 +1807,14 @@ class msg_cfheaders:
self.hashes = hashes
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
self.stop_hash = deser_uint256(f)
self.prev_header = deser_uint256(f)
self.hashes = deser_uint256_vector(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
+ r += self.filter_type.to_bytes(1, "little")
r += ser_uint256(self.stop_hash)
r += ser_uint256(self.prev_header)
r += ser_uint256_vector(self.hashes)
@@ -1829,12 +1833,12 @@ class msg_getcfcheckpt:
self.stop_hash = stop_hash
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
self.stop_hash = deser_uint256(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
+ r += self.filter_type.to_bytes(1, "little")
r += ser_uint256(self.stop_hash)
return r
@@ -1852,13 +1856,13 @@ class msg_cfcheckpt:
self.headers = headers
def deserialize(self, f):
- self.filter_type = struct.unpack("<B", f.read(1))[0]
+ self.filter_type = int.from_bytes(f.read(1), "little")
self.stop_hash = deser_uint256(f)
self.headers = deser_uint256_vector(f)
def serialize(self):
r = b""
- r += struct.pack("<B", self.filter_type)
+ r += self.filter_type.to_bytes(1, "little")
r += ser_uint256(self.stop_hash)
r += ser_uint256_vector(self.headers)
return r
@@ -1876,13 +1880,13 @@ class msg_sendtxrcncl:
self.salt = 0
def deserialize(self, f):
- self.version = struct.unpack("<I", f.read(4))[0]
- self.salt = struct.unpack("<Q", f.read(8))[0]
+ self.version = int.from_bytes(f.read(4), "little")
+ self.salt = int.from_bytes(f.read(8), "little")
def serialize(self):
r = b""
- r += struct.pack("<I", self.version)
- r += struct.pack("<Q", self.salt)
+ r += self.version.to_bytes(4, "little")
+ r += self.salt.to_bytes(8, "little")
return r
def __repr__(self):