Changeset View
Changeset View
Standalone View
Standalone View
test/functional/test_framework/messages.py
Show First 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | |||||
def uint256_from_compact(c): | def uint256_from_compact(c): | ||||
nbytes = (c >> 24) & 0xFF | nbytes = (c >> 24) & 0xFF | ||||
v = (c & 0xFFFFFF) << (8 * (nbytes - 3)) | v = (c & 0xFFFFFF) << (8 * (nbytes - 3)) | ||||
return v | return v | ||||
def deser_vector(f, c): | # deser_function_name: Allow for an alternate deserialization function on the | ||||
# entries in the vector. | |||||
def deser_vector(f, c, deser_function_name=None): | |||||
nit = deser_compact_size(f) | nit = deser_compact_size(f) | ||||
r = [] | r = [] | ||||
for i in range(nit): | for i in range(nit): | ||||
t = c() | t = c() | ||||
if deser_function_name: | |||||
getattr(t, deser_function_name)(f) | |||||
else: | |||||
t.deserialize(f) | t.deserialize(f) | ||||
r.append(t) | r.append(t) | ||||
return r | return r | ||||
# ser_function_name: Allow for an alternate serialization function on the | # ser_function_name: Allow for an alternate serialization function on the | ||||
# entries in the vector. | # entries in the vector. | ||||
def ser_vector(v, ser_function_name=None): | def ser_vector(v, ser_function_name=None): | ||||
r = ser_compact_size(len(v)) | r = ser_compact_size(len(v)) | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | def ToHex(obj): | ||||
"""Convert a binary-serializable object to hex | """Convert a binary-serializable object to hex | ||||
(eg for submission via RPC)""" | (eg for submission via RPC)""" | ||||
return obj.serialize().hex() | return obj.serialize().hex() | ||||
# Objects that map to bitcoind objects, which can be serialized/deserialized | # Objects that map to bitcoind objects, which can be serialized/deserialized | ||||
class CAddress: | class CAddress: | ||||
__slots__ = ("ip", "nServices", "pchReserved", "port", "time") | __slots__ = ("net", "ip", "nServices", "port", "time") | ||||
# see https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki | |||||
NET_IPV4 = 1 | |||||
ADDRV2_NET_NAME = { | |||||
NET_IPV4: "IPv4" | |||||
} | |||||
ADDRV2_ADDRESS_LENGTH = { | |||||
NET_IPV4: 4 | |||||
} | |||||
def __init__(self): | def __init__(self): | ||||
self.time = 0 | self.time = 0 | ||||
self.nServices = 1 | self.nServices = 1 | ||||
self.pchReserved = b"\x00" * 10 + b"\xff" * 2 | self.net = self.NET_IPV4 | ||||
self.ip = "0.0.0.0" | self.ip = "0.0.0.0" | ||||
self.port = 0 | self.port = 0 | ||||
def deserialize(self, f, *, with_time=True): | def deserialize(self, f, *, with_time=True): | ||||
"""Deserialize from addrv1 format (pre-BIP155)""" | |||||
if with_time: | if with_time: | ||||
# VERSION messages serialize CAddress objects without time | # VERSION messages serialize CAddress objects without time | ||||
self.time = struct.unpack("<i", f.read(4))[0] | self.time = struct.unpack("<I", f.read(4))[0] | ||||
self.nServices = struct.unpack("<Q", f.read(8))[0] | self.nServices = struct.unpack("<Q", f.read(8))[0] | ||||
self.pchReserved = f.read(12) | # 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.ip = socket.inet_ntoa(f.read(4)) | ||||
self.port = struct.unpack(">H", f.read(2))[0] | self.port = struct.unpack(">H", f.read(2))[0] | ||||
def serialize(self, *, with_time=True): | def serialize(self, *, with_time=True): | ||||
"""Serialize in addrv1 format (pre-BIP155)""" | |||||
assert self.net == self.NET_IPV4 | |||||
r = b"" | r = b"" | ||||
if with_time: | if with_time: | ||||
# VERSION messages serialize CAddress objects without time | # VERSION messages serialize CAddress objects without time | ||||
r += struct.pack("<i", self.time) | r += struct.pack("<I", self.time) | ||||
r += struct.pack("<Q", self.nServices) | r += struct.pack("<Q", self.nServices) | ||||
r += self.pchReserved | r += b"\x00" * 10 + b"\xff" * 2 | ||||
r += socket.inet_aton(self.ip) | |||||
r += struct.pack(">H", self.port) | |||||
return r | |||||
def deserialize_v2(self, f): | |||||
"""Deserialize from addrv2 format (BIP155)""" | |||||
self.time = struct.unpack("<I", f.read(4))[0] | |||||
self.nServices = deser_compact_size(f) | |||||
self.net = struct.unpack("B", f.read(1))[0] | |||||
assert self.net == self.NET_IPV4 | |||||
address_length = deser_compact_size(f) | |||||
assert address_length == self.ADDRV2_ADDRESS_LENGTH[self.net] | |||||
self.ip = socket.inet_ntoa(f.read(4)) | |||||
self.port = struct.unpack(">H", f.read(2))[0] | |||||
def serialize_v2(self): | |||||
"""Serialize in addrv2 format (BIP155)""" | |||||
assert self.net == self.NET_IPV4 | |||||
r = b"" | |||||
r += struct.pack("<I", self.time) | |||||
r += ser_compact_size(self.nServices) | |||||
r += struct.pack("B", self.net) | |||||
r += ser_compact_size(self.ADDRV2_ADDRESS_LENGTH[self.net]) | |||||
r += socket.inet_aton(self.ip) | r += socket.inet_aton(self.ip) | ||||
r += struct.pack(">H", self.port) | r += struct.pack(">H", self.port) | ||||
return r | return r | ||||
def __repr__(self): | def __repr__(self): | ||||
return "CAddress(nServices={} ip={} port={})".format( | return ("CAddress(nServices=%i net=%s addr=%s port=%i)" | ||||
self.nServices, self.ip, self.port) | % (self.nServices, self.ADDRV2_NET_NAME[self.net], self.ip, self.port)) | ||||
class CInv: | class CInv: | ||||
__slots__ = ("hash", "type") | __slots__ = ("hash", "type") | ||||
typemap = { | typemap = { | ||||
0: "Error", | 0: "Error", | ||||
MSG_TX: "TX", | MSG_TX: "TX", | ||||
▲ Show 20 Lines • Show All 841 Lines • ▼ Show 20 Lines | class msg_addr: | ||||
def serialize(self): | def serialize(self): | ||||
return ser_vector(self.addrs) | return ser_vector(self.addrs) | ||||
def __repr__(self): | def __repr__(self): | ||||
return "msg_addr(addrs={})".format(repr(self.addrs)) | return "msg_addr(addrs={})".format(repr(self.addrs)) | ||||
class msg_addrv2: | |||||
__slots__ = ("addrs",) | |||||
msgtype = b"addrv2" | |||||
def __init__(self): | |||||
self.addrs = [] | |||||
def deserialize(self, f): | |||||
self.addrs = deser_vector(f, CAddress, "deserialize_v2") | |||||
def serialize(self): | |||||
return ser_vector(self.addrs, "serialize_v2") | |||||
def __repr__(self): | |||||
return "msg_addrv2(addrs={})".format(repr(self.addrs)) | |||||
class msg_sendaddrv2: | |||||
__slots__ = () | |||||
msgtype = b"sendaddrv2" | |||||
def __init__(self): | |||||
pass | |||||
def deserialize(self, f): | |||||
pass | |||||
def serialize(self): | |||||
return b"" | |||||
def __repr__(self): | |||||
return "msg_sendaddrv2()" | |||||
class msg_inv: | class msg_inv: | ||||
__slots__ = ("inv",) | __slots__ = ("inv",) | ||||
msgtype = b"inv" | msgtype = b"inv" | ||||
def __init__(self, inv=None): | def __init__(self, inv=None): | ||||
if inv is None: | if inv is None: | ||||
self.inv = [] | self.inv = [] | ||||
else: | else: | ||||
▲ Show 20 Lines • Show All 683 Lines • Show Last 20 Lines |