Skip to content

Commit

Permalink
Remove SingleNodeConnCB
Browse files Browse the repository at this point in the history
Summary:
This commit merges the NodeConnCB and SingleNodeConnCB into a single
class (called NodeConnCB). The original intent for the NodeConnCB was to
be able to have a python 'mininode' connect to multiple running
bitcoinds. This has never been used and can be achieved more easily by
having multiple NodeConns backed by a common datastore if it is ever
needed.

The changes in mininode.py are just code moves (and merging the two
classes into a single class). The code changes in the individual test
cases are changing the subclasses to subclass from NodeConnCB instead of
SingleNodeConnCB. There is a lot of duplicate code in the subclasses
that can be removed in future commits.

Backport of Core PR10109, Fixes T143

Test Plan: Run functional tests

Reviewers: #bitcoin_abc, deadalnix

Reviewed By: #bitcoin_abc, deadalnix

Subscribers: teamcity

Maniphest Tasks: T143

Differential Revision: https://reviews.bitcoinabc.org/D968
  • Loading branch information
jnewbery authored and schancel committed Jan 19, 2018
1 parent 34326d6 commit d485139
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 98 deletions.
4 changes: 2 additions & 2 deletions test/functional/abc-p2p-fullblocktest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ def __init__(self, tx=CTransaction(), n=-1):


# TestNode: A peer we use to send messages to bitcoind, and store responses.
class TestNode(SingleNodeConnCB):
class TestNode(NodeConnCB):

def __init__(self):
self.last_sendcmpct = None
self.last_cmpctblock = None
self.last_getheaders = None
self.last_headers = None
SingleNodeConnCB.__init__(self)
super().__init__()

def on_sendcmpct(self, conn, message):
self.last_sendcmpct = message
Expand Down
7 changes: 2 additions & 5 deletions test/functional/assumevalid.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,15 @@
CTxOut,
NetworkThread,
NodeConn,
SingleNodeConnCB,
NodeConnCB,
msg_block,
msg_headers)
from test_framework.script import (CScript, OP_TRUE)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (start_node, p2p_port, assert_equal)


class BaseNode(SingleNodeConnCB):
def __init__(self):
super().__init__()

class BaseNode(NodeConnCB):
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
Expand Down
7 changes: 1 addition & 6 deletions test/functional/maxblocksinflight.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@


class TestManager(NodeConnCB):
# set up NodeConnCB callbacks, overriding base class

def on_getdata(self, conn, message):
self.log.debug("got getdata %s" % repr(message))
# Log the requests
Expand All @@ -31,11 +29,8 @@ def on_close(self, conn):
if not self.disconnectOkay:
raise EarlyDisconnectError(0)

def __init__(self):
NodeConnCB.__init__(self)

def add_new_connection(self, connection):
self.connection = connection
super().add_connection(connection)
self.blockReqCounts = {}
self.disconnectOkay = False

Expand Down
2 changes: 1 addition & 1 deletion test/functional/maxuploadtarget.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
class TestNode(NodeConnCB):

def __init__(self):
NodeConnCB.__init__(self)
super().__init__()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p-acceptblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
class TestNode(NodeConnCB):

def __init__(self):
NodeConnCB.__init__(self)
super().__init__()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
Expand Down
5 changes: 2 additions & 3 deletions test/functional/p2p-compactblocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
# TestNode: A peer we use to send messages to bitcoind, and store responses.


class TestNode(SingleNodeConnCB):

class TestNode(NodeConnCB):
def __init__(self):
SingleNodeConnCB.__init__(self)
super().__init__()
self.last_sendcmpct = []
self.last_headers = None
self.last_inv = None
Expand Down
5 changes: 2 additions & 3 deletions test/functional/p2p-feefilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ def allInvsMatch(invsExpected, testnode):
# and to send the node feefilter messages.


class TestNode(SingleNodeConnCB):

class TestNode(NodeConnCB):
def __init__(self):
SingleNodeConnCB.__init__(self)
super().__init__()
self.txinvs = []

def on_inv(self, conn, message):
Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p-leaktests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
class CLazyNode(NodeConnCB):

def __init__(self):
super().__init__()
self.connection = None
self.unexpected_msg = False
self.connected = False
super().__init__()

def add_connection(self, conn):
self.connection = conn
Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p-mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class TestNode(NodeConnCB):

def __init__(self):
NodeConnCB.__init__(self)
super().__init__()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
Expand Down
5 changes: 2 additions & 3 deletions test/functional/p2p-timeouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@
from test_framework.util import *


class TestNode(SingleNodeConnCB):

class TestNode(NodeConnCB):
def __init__(self):
SingleNodeConnCB.__init__(self)
super().__init__()
self.connected = False
self.received_version = False

Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p-versionbits-warning.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
class TestNode(NodeConnCB):

def __init__(self):
NodeConnCB.__init__(self)
super().__init__()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
Expand Down
5 changes: 2 additions & 3 deletions test/functional/sendheaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,9 @@
direct_fetch_response_time = 0.05


class BaseNode(SingleNodeConnCB):

class BaseNode(NodeConnCB):
def __init__(self):
SingleNodeConnCB.__init__(self)
super().__init__()
self.last_inv = None
self.last_headers = None
self.last_block = None
Expand Down
2 changes: 1 addition & 1 deletion test/functional/test_framework/comptool.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def __repr__(self):
class TestNode(NodeConnCB):

def __init__(self, block_store, tx_store):
NodeConnCB.__init__(self)
super().__init__()
self.conn = None
self.bestblockhash = None
self.block_store = block_store
Expand Down
129 changes: 62 additions & 67 deletions test/functional/test_framework/mininode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1550,25 +1550,9 @@ def __init__(self):
self.deliver_sleep_time = None
# Remember the services our peer has advertised
self.peer_services = None

def set_deliver_sleep_time(self, value):
with mininode_lock:
self.deliver_sleep_time = value

def get_deliver_sleep_time(self):
with mininode_lock:
return self.deliver_sleep_time

# Spin until verack message is received from the node.
# Tests may want to use this as a signal that the test can begin.
# This can be called from the testing thread, so it needs to acquire the
# global lock.
def wait_for_verack(self):
while True:
with mininode_lock:
if self.verack_received:
return
time.sleep(0.05)
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()

def deliver(self, conn, message):
deliver_sleep = self.get_deliver_sleep_time()
Expand All @@ -1581,82 +1565,84 @@ def deliver(self, conn, message):
except:
logger.exception("ERROR delivering %s" % repr(message))

def on_version(self, conn, message):
if message.nVersion >= 209:
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
def set_deliver_sleep_time(self, value):
with mininode_lock:
self.deliver_sleep_time = value

def on_verack(self, conn, message):
conn.ver_recv = conn.ver_send
self.verack_received = True
def get_deliver_sleep_time(self):
with mininode_lock:
return self.deliver_sleep_time

def on_inv(self, conn, message):
want = msg_getdata()
for i in message.inv:
if i.type != 0:
want.inv.append(i)
if len(want.inv):
conn.send_message(want)
# Callbacks which can be overridden by subclasses
#################################################

def on_addr(self, conn, message): pass

def on_alert(self, conn, message): pass

def on_getdata(self, conn, message): pass
def on_block(self, conn, message): pass

def on_getblocks(self, conn, message): pass
def on_blocktxn(self, conn, message): pass

def on_tx(self, conn, message): pass
def on_close(self, conn): pass

def on_block(self, conn, message): pass
def on_cmpctblock(self, conn, message): pass

def on_getaddr(self, conn, message): pass
def on_feefilter(self, conn, message): pass

def on_headers(self, conn, message): pass
def on_getaddr(self, conn, message): pass

def on_getheaders(self, conn, message): pass
def on_getblocks(self, conn, message): pass

def on_ping(self, conn, message):
if conn.ver_send > BIP0031_VERSION:
conn.send_message(msg_pong(message.nonce))
def on_getblocktxn(self, conn, message): pass

def on_reject(self, conn, message): pass
def on_getdata(self, conn, message): pass

def on_open(self, conn): pass
def on_getheaders(self, conn, message): pass

def on_close(self, conn): pass
def on_headers(self, conn, message): pass

def on_mempool(self, conn): pass

def on_pong(self, conn, message): pass

def on_feefilter(self, conn, message): pass
def on_open(self, conn): pass

def on_sendheaders(self, conn, message): pass
def on_reject(self, conn, message): pass

def on_sendcmpct(self, conn, message): pass

def on_cmpctblock(self, conn, message): pass
def on_sendheaders(self, conn, message): pass

def on_getblocktxn(self, conn, message): pass
def on_tx(self, conn, message): pass

def on_blocktxn(self, conn, message): pass
def on_inv(self, conn, message):
want = msg_getdata()
for i in message.inv:
if i.type != 0:
want.inv.append(i)
if len(want.inv):
conn.send_message(want)

# More useful callbacks and functions for NodeConnCB's which have a single
# NodeConn
def on_ping(self, conn, message):
if conn.ver_send > BIP0031_VERSION:
conn.send_message(msg_pong(message.nonce))

def on_pong(self, conn, message):
self.last_pong = message

class SingleNodeConnCB(NodeConnCB):
def on_verack(self, conn, message):
conn.ver_recv = conn.ver_send
self.verack_received = True

def __init__(self):
NodeConnCB.__init__(self)
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
def on_version(self, conn, message):
if message.nVersion >= 209:
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

# Helper functions
##################
def add_connection(self, conn):
self.connection = conn

Expand All @@ -1668,18 +1654,27 @@ def send_and_ping(self, message):
self.send_message(message)
self.sync_with_ping()

def on_pong(self, conn, message):
self.last_pong = message

# Sync up with the node
def sync_with_ping(self, timeout=30):
def received_pong():
return (self.last_pong.nonce == self.ping_counter)
self.send_message(msg_ping(nonce=self.ping_counter))
success = wait_until(received_pong, timeout=timeout)
self.ping_counter += 1

return success

# Spin until verack message is received from the node.
# Tests may want to use this as a signal that the test can begin.
# This can be called from the testing thread, so it needs to acquire the
# global lock.
def wait_for_verack(self):
while True:
with mininode_lock:
if self.verack_received:
return
time.sleep(0.05)

# The actual NodeConn class
# This class provides an interface for a p2p connection to a specified node

Expand Down

0 comments on commit d485139

Please sign in to comment.