Merge #11638: [tests] Dead mininode code
fb00c45c3
[tests] Explicitly disallow support for p2p versions below 60001 (John Newbery)3858aabbd
[tests] Remove support for p2p alert messages (John Newbery)c0b127470
[tests] Remove support for bre-BIP31 ping messages (John Newbery)2904e301c
[tests] Remove dead code from mininode.py (John Newbery) Pull request description: This is the first part of #11518. It removes a ~150 lines of unused code from the mininode module: - remove unused `deliver_sleep_time` and `EarlyDisconnectError` code - remove support for pre-BIP31 ping messages - remove support for alert message - explicitly don't support p2p versions lower than 60001 Should be an easy ACK for reviewers. If all extended tests pass, then this code really was dead :) Tree-SHA512: 508e612ceb0b094250d18e75522d51e6b14cd069443050ba4af34d6f890c58721cb5653e8bc000b60635b9474d035b0dcd9c509c0dcdb3a7501df17b787f83b0
This commit is contained in:
commit
5e3f5e4f25
2 changed files with 32 additions and 193 deletions
|
@ -39,7 +39,6 @@ class CLazyNode(NodeConnCB):
|
||||||
def on_reject(self, conn, message): self.bad_message(message)
|
def on_reject(self, conn, message): self.bad_message(message)
|
||||||
def on_inv(self, conn, message): self.bad_message(message)
|
def on_inv(self, conn, message): self.bad_message(message)
|
||||||
def on_addr(self, conn, message): self.bad_message(message)
|
def on_addr(self, conn, message): self.bad_message(message)
|
||||||
def on_alert(self, conn, message): self.bad_message(message)
|
|
||||||
def on_getdata(self, conn, message): self.bad_message(message)
|
def on_getdata(self, conn, message): self.bad_message(message)
|
||||||
def on_getblocks(self, conn, message): self.bad_message(message)
|
def on_getblocks(self, conn, message): self.bad_message(message)
|
||||||
def on_tx(self, conn, message): self.bad_message(message)
|
def on_tx(self, conn, message): self.bad_message(message)
|
||||||
|
|
|
@ -37,7 +37,7 @@ from threading import RLock, Thread
|
||||||
from test_framework.siphash import siphash256
|
from test_framework.siphash import siphash256
|
||||||
from test_framework.util import hex_str_to_bytes, bytes_to_hex_str, wait_until
|
from test_framework.util import hex_str_to_bytes, bytes_to_hex_str, wait_until
|
||||||
|
|
||||||
BIP0031_VERSION = 60000
|
MIN_VERSION_SUPPORTED = 60001
|
||||||
MY_VERSION = 70014 # past bip-31 for ping/pong
|
MY_VERSION = 70014 # past bip-31 for ping/pong
|
||||||
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
|
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
|
||||||
MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
|
MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
|
||||||
|
@ -666,81 +666,6 @@ class CBlock(CBlockHeader):
|
||||||
time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
|
time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
|
||||||
|
|
||||||
|
|
||||||
class CUnsignedAlert():
|
|
||||||
def __init__(self):
|
|
||||||
self.nVersion = 1
|
|
||||||
self.nRelayUntil = 0
|
|
||||||
self.nExpiration = 0
|
|
||||||
self.nID = 0
|
|
||||||
self.nCancel = 0
|
|
||||||
self.setCancel = []
|
|
||||||
self.nMinVer = 0
|
|
||||||
self.nMaxVer = 0
|
|
||||||
self.setSubVer = []
|
|
||||||
self.nPriority = 0
|
|
||||||
self.strComment = b""
|
|
||||||
self.strStatusBar = b""
|
|
||||||
self.strReserved = b""
|
|
||||||
|
|
||||||
def deserialize(self, f):
|
|
||||||
self.nVersion = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.nRelayUntil = struct.unpack("<q", f.read(8))[0]
|
|
||||||
self.nExpiration = struct.unpack("<q", f.read(8))[0]
|
|
||||||
self.nID = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.nCancel = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.setCancel = deser_int_vector(f)
|
|
||||||
self.nMinVer = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.nMaxVer = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.setSubVer = deser_string_vector(f)
|
|
||||||
self.nPriority = struct.unpack("<i", f.read(4))[0]
|
|
||||||
self.strComment = deser_string(f)
|
|
||||||
self.strStatusBar = deser_string(f)
|
|
||||||
self.strReserved = deser_string(f)
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
r = b""
|
|
||||||
r += struct.pack("<i", self.nVersion)
|
|
||||||
r += struct.pack("<q", self.nRelayUntil)
|
|
||||||
r += struct.pack("<q", self.nExpiration)
|
|
||||||
r += struct.pack("<i", self.nID)
|
|
||||||
r += struct.pack("<i", self.nCancel)
|
|
||||||
r += ser_int_vector(self.setCancel)
|
|
||||||
r += struct.pack("<i", self.nMinVer)
|
|
||||||
r += struct.pack("<i", self.nMaxVer)
|
|
||||||
r += ser_string_vector(self.setSubVer)
|
|
||||||
r += struct.pack("<i", self.nPriority)
|
|
||||||
r += ser_string(self.strComment)
|
|
||||||
r += ser_string(self.strStatusBar)
|
|
||||||
r += ser_string(self.strReserved)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "CUnsignedAlert(nVersion %d, nRelayUntil %d, nExpiration %d, nID %d, nCancel %d, nMinVer %d, nMaxVer %d, nPriority %d, strComment %s, strStatusBar %s, strReserved %s)" \
|
|
||||||
% (self.nVersion, self.nRelayUntil, self.nExpiration, self.nID,
|
|
||||||
self.nCancel, self.nMinVer, self.nMaxVer, self.nPriority,
|
|
||||||
self.strComment, self.strStatusBar, self.strReserved)
|
|
||||||
|
|
||||||
|
|
||||||
class CAlert():
|
|
||||||
def __init__(self):
|
|
||||||
self.vchMsg = b""
|
|
||||||
self.vchSig = b""
|
|
||||||
|
|
||||||
def deserialize(self, f):
|
|
||||||
self.vchMsg = deser_string(f)
|
|
||||||
self.vchSig = deser_string(f)
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
r = b""
|
|
||||||
r += ser_string(self.vchMsg)
|
|
||||||
r += ser_string(self.vchSig)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "CAlert(vchMsg.sz %d, vchSig.sz %d)" \
|
|
||||||
% (len(self.vchMsg), len(self.vchSig))
|
|
||||||
|
|
||||||
|
|
||||||
class PrefilledTransaction():
|
class PrefilledTransaction():
|
||||||
def __init__(self, index=0, tx = None):
|
def __init__(self, index=0, tx = None):
|
||||||
self.index = index
|
self.index = index
|
||||||
|
@ -1044,25 +969,6 @@ class msg_addr():
|
||||||
return "msg_addr(addrs=%s)" % (repr(self.addrs))
|
return "msg_addr(addrs=%s)" % (repr(self.addrs))
|
||||||
|
|
||||||
|
|
||||||
class msg_alert():
|
|
||||||
command = b"alert"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.alert = CAlert()
|
|
||||||
|
|
||||||
def deserialize(self, f):
|
|
||||||
self.alert = CAlert()
|
|
||||||
self.alert.deserialize(f)
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
r = b""
|
|
||||||
r += self.alert.serialize()
|
|
||||||
return r
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "msg_alert(alert=%s)" % (repr(self.alert), )
|
|
||||||
|
|
||||||
|
|
||||||
class msg_inv():
|
class msg_inv():
|
||||||
command = b"inv"
|
command = b"inv"
|
||||||
|
|
||||||
|
@ -1195,22 +1101,6 @@ class msg_getaddr():
|
||||||
return "msg_getaddr()"
|
return "msg_getaddr()"
|
||||||
|
|
||||||
|
|
||||||
class msg_ping_prebip31():
|
|
||||||
command = b"ping"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def deserialize(self, f):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return b""
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "msg_ping() (pre-bip31)"
|
|
||||||
|
|
||||||
|
|
||||||
class msg_ping():
|
class msg_ping():
|
||||||
command = b"ping"
|
command = b"ping"
|
||||||
|
|
||||||
|
@ -1458,9 +1348,7 @@ class NodeConnCB():
|
||||||
"""Callback and helper functions for P2P connection to a bitcoind node.
|
"""Callback and helper functions for P2P connection to a bitcoind node.
|
||||||
|
|
||||||
Individual testcases should subclass this and override the on_* methods
|
Individual testcases should subclass this and override the on_* methods
|
||||||
if they want to alter message handling behaviour.
|
if they want to alter message handling behaviour."""
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Track whether we have a P2P connection open to the node
|
# Track whether we have a P2P connection open to the node
|
||||||
self.connected = False
|
self.connected = False
|
||||||
|
@ -1474,25 +1362,13 @@ class NodeConnCB():
|
||||||
# A count of the number of ping messages we've sent to the node
|
# A count of the number of ping messages we've sent to the node
|
||||||
self.ping_counter = 1
|
self.ping_counter = 1
|
||||||
|
|
||||||
# deliver_sleep_time is helpful for debugging race conditions in p2p
|
|
||||||
# tests; it causes message delivery to sleep for the specified time
|
|
||||||
# before acquiring the global lock and delivering the next message.
|
|
||||||
self.deliver_sleep_time = None
|
|
||||||
|
|
||||||
# Message receiving methods
|
# Message receiving methods
|
||||||
|
|
||||||
def deliver(self, conn, message):
|
def deliver(self, conn, message):
|
||||||
"""Receive message and dispatch message to appropriate callback.
|
"""Receive message and dispatch message to appropriate callback.
|
||||||
|
|
||||||
We keep a count of how many of each message type has been received
|
We keep a count of how many of each message type has been received
|
||||||
and the most recent message of each type.
|
and the most recent message of each type."""
|
||||||
|
|
||||||
Optionally waits for deliver_sleep_time before dispatching message.
|
|
||||||
"""
|
|
||||||
|
|
||||||
deliver_sleep = self.get_deliver_sleep_time()
|
|
||||||
if deliver_sleep is not None:
|
|
||||||
time.sleep(deliver_sleep)
|
|
||||||
with mininode_lock:
|
with mininode_lock:
|
||||||
try:
|
try:
|
||||||
command = message.command.decode('ascii')
|
command = message.command.decode('ascii')
|
||||||
|
@ -1504,10 +1380,6 @@ class NodeConnCB():
|
||||||
sys.exc_info()[0]))
|
sys.exc_info()[0]))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_deliver_sleep_time(self):
|
|
||||||
with mininode_lock:
|
|
||||||
return self.deliver_sleep_time
|
|
||||||
|
|
||||||
# Callback methods. Can be overridden by subclasses in individual test
|
# Callback methods. Can be overridden by subclasses in individual test
|
||||||
# cases to provide custom message handling behaviour.
|
# cases to provide custom message handling behaviour.
|
||||||
|
|
||||||
|
@ -1519,7 +1391,6 @@ class NodeConnCB():
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
def on_addr(self, conn, message): pass
|
def on_addr(self, conn, message): pass
|
||||||
def on_alert(self, conn, message): pass
|
|
||||||
def on_block(self, conn, message): pass
|
def on_block(self, conn, message): pass
|
||||||
def on_blocktxn(self, conn, message): pass
|
def on_blocktxn(self, conn, message): pass
|
||||||
def on_cmpctblock(self, conn, message): pass
|
def on_cmpctblock(self, conn, message): pass
|
||||||
|
@ -1546,19 +1417,15 @@ class NodeConnCB():
|
||||||
conn.send_message(want)
|
conn.send_message(want)
|
||||||
|
|
||||||
def on_ping(self, conn, message):
|
def on_ping(self, conn, message):
|
||||||
if conn.ver_send > BIP0031_VERSION:
|
conn.send_message(msg_pong(message.nonce))
|
||||||
conn.send_message(msg_pong(message.nonce))
|
|
||||||
|
|
||||||
def on_verack(self, conn, message):
|
def on_verack(self, conn, message):
|
||||||
conn.ver_recv = conn.ver_send
|
conn.ver_recv = conn.ver_send
|
||||||
self.verack_received = True
|
self.verack_received = True
|
||||||
|
|
||||||
def on_version(self, conn, message):
|
def on_version(self, conn, message):
|
||||||
if message.nVersion >= 209:
|
assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED)
|
||||||
conn.send_message(msg_verack())
|
conn.send_message(msg_verack())
|
||||||
conn.ver_send = min(MY_VERSION, message.nVersion)
|
|
||||||
if message.nVersion < 209:
|
|
||||||
conn.ver_recv = conn.ver_send
|
|
||||||
conn.nServices = message.nServices
|
conn.nServices = message.nServices
|
||||||
|
|
||||||
# Connection helper methods
|
# Connection helper methods
|
||||||
|
@ -1616,14 +1483,14 @@ class NodeConnCB():
|
||||||
wait_until(test_function, timeout=timeout, lock=mininode_lock)
|
wait_until(test_function, timeout=timeout, lock=mininode_lock)
|
||||||
self.ping_counter += 1
|
self.ping_counter += 1
|
||||||
|
|
||||||
# The actual NodeConn class
|
|
||||||
# This class provides an interface for a p2p connection to a specified node
|
|
||||||
class NodeConn(asyncore.dispatcher):
|
class NodeConn(asyncore.dispatcher):
|
||||||
|
"""The actual NodeConn class
|
||||||
|
|
||||||
|
This class provides an interface for a p2p connection to a specified node."""
|
||||||
messagemap = {
|
messagemap = {
|
||||||
b"version": msg_version,
|
b"version": msg_version,
|
||||||
b"verack": msg_verack,
|
b"verack": msg_verack,
|
||||||
b"addr": msg_addr,
|
b"addr": msg_addr,
|
||||||
b"alert": msg_alert,
|
|
||||||
b"inv": msg_inv,
|
b"inv": msg_inv,
|
||||||
b"getdata": msg_getdata,
|
b"getdata": msg_getdata,
|
||||||
b"getblocks": msg_getblocks,
|
b"getblocks": msg_getblocks,
|
||||||
|
@ -1740,40 +1607,27 @@ class NodeConn(asyncore.dispatcher):
|
||||||
return
|
return
|
||||||
if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
|
if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
|
||||||
raise ValueError("got garbage %s" % repr(self.recvbuf))
|
raise ValueError("got garbage %s" % repr(self.recvbuf))
|
||||||
if self.ver_recv < 209:
|
if len(self.recvbuf) < 4 + 12 + 4 + 4:
|
||||||
if len(self.recvbuf) < 4 + 12 + 4:
|
return
|
||||||
return
|
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
|
||||||
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
|
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
||||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
checksum = self.recvbuf[4+12+4:4+12+4+4]
|
||||||
checksum = None
|
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
|
||||||
if len(self.recvbuf) < 4 + 12 + 4 + msglen:
|
return
|
||||||
return
|
msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
|
||||||
msg = self.recvbuf[4+12+4:4+12+4+msglen]
|
th = sha256(msg)
|
||||||
self.recvbuf = self.recvbuf[4+12+4+msglen:]
|
h = sha256(th)
|
||||||
else:
|
if checksum != h[:4]:
|
||||||
if len(self.recvbuf) < 4 + 12 + 4 + 4:
|
raise ValueError("got bad checksum " + repr(self.recvbuf))
|
||||||
return
|
self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
|
||||||
command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
|
if command not in self.messagemap:
|
||||||
msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
|
raise ValueError("Received unknown command from %s:%d: '%s' %s" % (self.dstaddr, self.dstport, command, repr(msg)))
|
||||||
checksum = self.recvbuf[4+12+4:4+12+4+4]
|
f = BytesIO(msg)
|
||||||
if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
|
t = self.messagemap[command]()
|
||||||
return
|
t.deserialize(f)
|
||||||
msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
|
self.got_message(t)
|
||||||
th = sha256(msg)
|
|
||||||
h = sha256(th)
|
|
||||||
if checksum != h[:4]:
|
|
||||||
raise ValueError("got bad checksum " + repr(self.recvbuf))
|
|
||||||
self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
|
|
||||||
if command in self.messagemap:
|
|
||||||
f = BytesIO(msg)
|
|
||||||
t = self.messagemap[command]()
|
|
||||||
t.deserialize(f)
|
|
||||||
self.got_message(t)
|
|
||||||
else:
|
|
||||||
logger.warning("Received unknown command from %s:%d: '%s' %s" % (self.dstaddr, self.dstport, command, repr(msg)))
|
|
||||||
raise ValueError("Unknown command: '%s'" % (command))
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception('got_data:', repr(e))
|
logger.exception('Error reading message:', repr(e))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def send_message(self, message, pushbuf=False):
|
def send_message(self, message, pushbuf=False):
|
||||||
|
@ -1786,10 +1640,9 @@ class NodeConn(asyncore.dispatcher):
|
||||||
tmsg += command
|
tmsg += command
|
||||||
tmsg += b"\x00" * (12 - len(command))
|
tmsg += b"\x00" * (12 - len(command))
|
||||||
tmsg += struct.pack("<I", len(data))
|
tmsg += struct.pack("<I", len(data))
|
||||||
if self.ver_send >= 209:
|
th = sha256(data)
|
||||||
th = sha256(data)
|
h = sha256(th)
|
||||||
h = sha256(th)
|
tmsg += h[:4]
|
||||||
tmsg += h[:4]
|
|
||||||
tmsg += data
|
tmsg += data
|
||||||
with mininode_lock:
|
with mininode_lock:
|
||||||
if (len(self.sendbuf) == 0 and not pushbuf):
|
if (len(self.sendbuf) == 0 and not pushbuf):
|
||||||
|
@ -1803,9 +1656,6 @@ class NodeConn(asyncore.dispatcher):
|
||||||
self.last_sent = time.time()
|
self.last_sent = time.time()
|
||||||
|
|
||||||
def got_message(self, message):
|
def got_message(self, message):
|
||||||
if message.command == b"version":
|
|
||||||
if message.nVersion <= BIP0031_VERSION:
|
|
||||||
self.messagemap[b'ping'] = msg_ping_prebip31
|
|
||||||
if self.last_sent + 30 * 60 < time.time():
|
if self.last_sent + 30 * 60 < time.time():
|
||||||
self.send_message(self.messagemap[b'ping']())
|
self.send_message(self.messagemap[b'ping']())
|
||||||
self._log_message("receive", message)
|
self._log_message("receive", message)
|
||||||
|
@ -1838,13 +1688,3 @@ class NetworkThread(Thread):
|
||||||
[ obj.handle_close() for obj in disconnected ]
|
[ obj.handle_close() for obj in disconnected ]
|
||||||
asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
|
asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
|
||||||
logger.debug("Network thread closing")
|
logger.debug("Network thread closing")
|
||||||
|
|
||||||
|
|
||||||
# An exception we can raise if we detect a potential disconnect
|
|
||||||
# (p2p or rpc) before the test is complete
|
|
||||||
class EarlyDisconnectError(Exception):
|
|
||||||
def __init__(self, value):
|
|
||||||
self.value = value
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return repr(self.value)
|
|
||||||
|
|
Loading…
Reference in a new issue