[tests] Rename NodeConn and NodeConnCB

NodeConn -> P2PConnection
NodeConnCB -> P2PInterface
This commit is contained in:
John Newbery 2017-10-17 16:16:39 -04:00
parent 9f2c2dba21
commit 873beca6de
18 changed files with 50 additions and 55 deletions

View File

@ -63,12 +63,12 @@ wrappers for them, `msg_block`, `msg_tx`, etc).
with the bitcoind(s) being tested (using python's asyncore package); the other with the bitcoind(s) being tested (using python's asyncore package); the other
implements the test logic. implements the test logic.
- `NodeConn` is the class used to connect to a bitcoind. If you implement - `P2PConnection` is the class used to connect to a bitcoind. `P2PInterface`
a callback class that derives from `NodeConnCB` and pass that to the contains the higher level logic for processing P2P payloads and connecting to
`NodeConn` object, your code will receive the appropriate callbacks when the Bitcoin Core node application logic. For custom behaviour, subclass the
events of interest arrive. P2PInterface object and override the callback methods.
- Call `NetworkThread.start()` after all `NodeConn` objects are created to - Call `NetworkThread.start()` after all `P2PInterface` objects are created to
start the networking thread. (Continue with the test logic in your existing start the networking thread. (Continue with the test logic in your existing
thread.) thread.)

View File

@ -39,14 +39,14 @@ from test_framework.mininode import (CBlockHeader,
CTxIn, CTxIn,
CTxOut, CTxOut,
NetworkThread, NetworkThread,
NodeConnCB, P2PInterface,
msg_block, msg_block,
msg_headers) msg_headers)
from test_framework.script import (CScript, OP_TRUE) from test_framework.script import (CScript, OP_TRUE)
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal from test_framework.util import assert_equal
class BaseNode(NodeConnCB): class BaseNode(P2PInterface):
def send_header_for_blocks(self, new_blocks): def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers() headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks] headers_message.headers = [CBlockHeader(b) for b in new_blocks]

View File

@ -66,7 +66,7 @@ class BIP65Test(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
def run_test(self): def run_test(self):
self.nodes[0].add_p2p_connection(NodeConnCB()) self.nodes[0].add_p2p_connection(P2PInterface())
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread

View File

@ -54,7 +54,7 @@ class BIP66Test(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
def run_test(self): def run_test(self):
self.nodes[0].add_p2p_connection(NodeConnCB()) self.nodes[0].add_p2p_connection(P2PInterface())
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread

View File

@ -18,10 +18,11 @@ from test_framework.blocktools import (create_block, create_coinbase)
from test_framework.mininode import ( from test_framework.mininode import (
CInv, CInv,
NetworkThread, NetworkThread,
NodeConnCB, P2PInterface,
mininode_lock, mininode_lock,
msg_block, msg_block,
msg_getdata, msg_getdata,
NODE_NETWORK,
) )
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import ( from test_framework.util import (
@ -30,15 +31,15 @@ from test_framework.util import (
wait_until, wait_until,
) )
# NodeConnCB is a class containing callbacks to be executed when a P2P # P2PInterface is a class containing callbacks to be executed when a P2P
# message is received from the node-under-test. Subclass NodeConnCB and # message is received from the node-under-test. Subclass P2PInterface and
# override the on_*() methods if you need custom behaviour. # override the on_*() methods if you need custom behaviour.
class BaseNode(NodeConnCB): class BaseNode(P2PInterface):
def __init__(self): def __init__(self):
"""Initialize the NodeConnCB """Initialize the P2PInterface
Used to inialize custom properties for the Node that aren't Used to inialize custom properties for the Node that aren't
included by default in the base class. Be aware that the NodeConnCB included by default in the base class. Be aware that the P2PInterface
base class already stores a counter for each P2P message type and the base class already stores a counter for each P2P message type and the
last received message of each type, which should be sufficient for the last received message of each type, which should be sufficient for the
needs of most tests. needs of most tests.
@ -174,7 +175,7 @@ class ExampleTest(BitcoinTestFramework):
block = create_block(self.tip, create_coinbase(height), self.block_time) block = create_block(self.tip, create_coinbase(height), self.block_time)
block.solve() block.solve()
block_message = msg_block(block) block_message = msg_block(block)
# Send message is used to send a P2P message to the node over our NodeConn connection # Send message is used to send a P2P message to the node over our P2PInterface
self.nodes[0].p2p.send_message(block_message) self.nodes[0].p2p.send_message(block_message)
self.tip = block.sha256 self.tip = block.sha256
blocks.append(self.tip) blocks.append(self.tip)
@ -199,12 +200,12 @@ class ExampleTest(BitcoinTestFramework):
self.nodes[2].p2p.send_message(getdata_request) self.nodes[2].p2p.send_message(getdata_request)
# wait_until() will loop until a predicate condition is met. Use it to test properties of the # wait_until() will loop until a predicate condition is met. Use it to test properties of the
# NodeConnCB objects. # P2PInterface objects.
wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5, lock=mininode_lock) wait_until(lambda: sorted(blocks) == sorted(list(self.nodes[2].p2p.block_receive_map.keys())), timeout=5, lock=mininode_lock)
self.log.info("Check that each block was received only once") self.log.info("Check that each block was received only once")
# The network thread uses a global lock on data access to the NodeConn objects when sending and receiving # The network thread uses a global lock on data access to the P2PConnection objects when sending and receiving
# messages. The test thread should acquire the global lock before accessing any NodeConn data to avoid locking # messages. The test thread should acquire the global lock before accessing any P2PConnection data to avoid locking
# and synchronization issues. Note wait_until() acquires this global lock when testing the predicate. # and synchronization issues. Note wait_until() acquires this global lock when testing the predicate.
with mininode_lock: with mininode_lock:
for block in self.nodes[2].p2p.block_receive_map.values(): for block in self.nodes[2].p2p.block_receive_map.values():

View File

@ -17,7 +17,7 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import * from test_framework.util import *
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.block_receive_map = defaultdict(int) self.block_receive_map = defaultdict(int)

View File

@ -7,7 +7,7 @@
Setup: two nodes, node0+node1, not connected to each other. Node1 will have Setup: two nodes, node0+node1, not connected to each other. Node1 will have
nMinimumChainWork set to 0x10, so it won't process low-work unrequested blocks. nMinimumChainWork set to 0x10, so it won't process low-work unrequested blocks.
We have one NodeConn connection to node0 called test_node, and one to node1 We have one P2PInterface connection to node0 called test_node, and one to node1
called min_work_node. called min_work_node.
The test: The test:
@ -79,9 +79,9 @@ class AcceptBlockTest(BitcoinTestFramework):
def run_test(self): def run_test(self):
# Setup the p2p connections and start up the network thread. # Setup the p2p connections and start up the network thread.
# test_node connects to node0 (not whitelisted) # test_node connects to node0 (not whitelisted)
test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) test_node = self.nodes[0].add_p2p_connection(P2PInterface())
# min_work_node connects to node1 # min_work_node connects to node1 (whitelisted)
min_work_node = self.nodes[1].add_p2p_connection(NodeConnCB()) min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread
@ -207,7 +207,7 @@ class AcceptBlockTest(BitcoinTestFramework):
# disconnect/reconnect first # disconnect/reconnect first
self.nodes[0].disconnect_p2ps() self.nodes[0].disconnect_p2ps()
test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) test_node = self.nodes[0].add_p2p_connection(P2PInterface())
test_node.wait_for_verack() test_node.wait_for_verack()
test_node.send_message(msg_block(block_h1f)) test_node.send_message(msg_block(block_h1f))
@ -292,7 +292,7 @@ class AcceptBlockTest(BitcoinTestFramework):
test_node.wait_for_disconnect() test_node.wait_for_disconnect()
self.nodes[0].disconnect_p2ps() self.nodes[0].disconnect_p2ps()
test_node = self.nodes[0].add_p2p_connection(NodeConnCB()) test_node = self.nodes[0].add_p2p_connection(P2PInterface())
NetworkThread().start() # Start up network handling in another thread NetworkThread().start() # Start up network handling in another thread
test_node.wait_for_verack() test_node.wait_for_verack()

View File

@ -15,7 +15,7 @@ from test_framework.blocktools import create_block, create_coinbase, add_witness
from test_framework.script import CScript, OP_TRUE from test_framework.script import CScript, OP_TRUE
# TestNode: A peer we use to send messages to bitcoind, and store responses. # TestNode: A peer we use to send messages to bitcoind, and store responses.
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.last_sendcmpct = [] self.last_sendcmpct = []

View File

@ -22,7 +22,7 @@ def allInvsMatch(invsExpected, testnode):
time.sleep(1) time.sleep(1)
return False return False
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.txinvs = [] self.txinvs = []

View File

@ -14,7 +14,7 @@ from test_framework.blocktools import (create_block, create_coinbase)
from test_framework.mininode import ( from test_framework.mininode import (
CInv, CInv,
NetworkThread, NetworkThread,
NodeConnCB, P2PInterface,
msg_headers, msg_headers,
msg_block, msg_block,
msg_getdata, msg_getdata,
@ -75,7 +75,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
# This does not currently test that stale blocks timestamped within the # This does not currently test that stale blocks timestamped within the
# last month but that have over a month's worth of work are also withheld. # last month but that have over a month's worth of work are also withheld.
def run_test(self): def run_test(self):
node0 = self.nodes[0].add_p2p_connection(NodeConnCB()) node0 = self.nodes[0].add_p2p_connection(P2PInterface())
NetworkThread().start() NetworkThread().start()
node0.wait_for_verack() node0.wait_for_verack()

View File

@ -20,7 +20,7 @@ from test_framework.util import *
banscore = 10 banscore = 10
class CLazyNode(NodeConnCB): class CLazyNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.unexpected_msg = False self.unexpected_msg = False
@ -139,10 +139,10 @@ class P2PLeakTest(BitcoinTestFramework):
self.log.info("Service bits 5 and 7 are allowed after August 1st 2018") self.log.info("Service bits 5 and 7 are allowed after August 1st 2018")
self.nodes[0].setmocktime(1533168000) # August 2nd 2018 self.nodes[0].setmocktime(1533168000) # August 2nd 2018
allowed_service_bit5_node = self.nodes[0].add_p2p_connection(NodeConnCB(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5) allowed_service_bit5_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)
allowed_service_bit7_node = self.nodes[0].add_p2p_connection(NodeConnCB(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7) allowed_service_bit7_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)
NetworkThread().start() # Network thread stopped when all previous NodeConnCBs disconnected. Restart it NetworkThread().start() # Network thread stopped when all previous P2PInterfaces disconnected. Restart it
wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock) wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock)
wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock) wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock)

View File

@ -20,7 +20,7 @@ class P2PMempoolTests(BitcoinTestFramework):
def run_test(self): def run_test(self):
# Add a p2p connection # Add a p2p connection
self.nodes[0].add_p2p_connection(NodeConnCB()) self.nodes[0].add_p2p_connection(P2PInterface())
NetworkThread().start() NetworkThread().start()
self.nodes[0].p2p.wait_for_verack() self.nodes[0].p2p.wait_for_verack()

View File

@ -59,7 +59,7 @@ def test_witness_block(rpc, p2p, block, accepted, with_witness=True):
p2p.sync_with_ping() p2p.sync_with_ping()
assert_equal(rpc.getbestblockhash() == block.hash, accepted) assert_equal(rpc.getbestblockhash() == block.hash, accepted)
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.getdataset = set() self.getdataset = set()

View File

@ -27,7 +27,7 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import * from test_framework.util import *
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def on_version(self, message): def on_version(self, message):
# Don't send a verack in response # Don't send a verack in response
pass pass

View File

@ -23,7 +23,7 @@ WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible un
WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
VB_PATTERN = re.compile("^Warning.*versionbit") VB_PATTERN = re.compile("^Warning.*versionbit")
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def on_inv(self, message): def on_inv(self, message):
pass pass

View File

@ -91,7 +91,7 @@ from test_framework.mininode import (
CInv, CInv,
NODE_WITNESS, NODE_WITNESS,
NetworkThread, NetworkThread,
NodeConnCB, P2PInterface,
mininode_lock, mininode_lock,
msg_block, msg_block,
msg_getblocks, msg_getblocks,
@ -110,7 +110,7 @@ from test_framework.util import (
DIRECT_FETCH_RESPONSE_TIME = 0.05 DIRECT_FETCH_RESPONSE_TIME = 0.05
class BaseNode(NodeConnCB): class BaseNode(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()

View File

@ -39,7 +39,7 @@ class RejectResult():
def __repr__(self): def __repr__(self):
return '%i:%s' % (self.code,self.reason or '*') return '%i:%s' % (self.code,self.reason or '*')
class TestNode(NodeConnCB): class TestNode(P2PInterface):
def __init__(self, block_store, tx_store): def __init__(self, block_store, tx_store):
super().__init__() super().__init__()

View File

@ -9,10 +9,8 @@
This python code was modified from ArtForz' public domain half-a-node, as This python code was modified from ArtForz' public domain half-a-node, as
found in the mini-node branch of http://github.com/jgarzik/pynode. found in the mini-node branch of http://github.com/jgarzik/pynode.
NodeConn: an object which manages p2p connectivity to a bitcoin node P2PConnection: A low-level connection object to a node's P2P interface
NodeConnCB: a base class that describes the interface for receiving P2PInterface: A high-level interface object for communicating to a node over P2P"""
callbacks with network messages from a NodeConn
"""
import asyncore import asyncore
from collections import defaultdict from collections import defaultdict
from io import BytesIO from io import BytesIO
@ -57,7 +55,7 @@ MAGIC_BYTES = {
"regtest": b"\xfa\xbf\xb5\xda", # regtest "regtest": b"\xfa\xbf\xb5\xda", # regtest
} }
class NodeConn(asyncore.dispatcher): class P2PConnection(asyncore.dispatcher):
"""A low-level connection object to a node's P2P interface. """A low-level connection object to a node's P2P interface.
This class is responsible for: This class is responsible for:
@ -68,9 +66,7 @@ class NodeConn(asyncore.dispatcher):
- logging messages as they are sent and received - logging messages as they are sent and received
This class contains no logic for handing the P2P message payloads. It must be This class contains no logic for handing the P2P message payloads. It must be
sub-classed and the on_message() callback overridden. sub-classed and the on_message() callback overridden."""
TODO: rename this class P2PConnection."""
def __init__(self): def __init__(self):
super().__init__(map=mininode_socket_map) super().__init__(map=mininode_socket_map)
@ -244,7 +240,7 @@ class NodeConn(asyncore.dispatcher):
logger.debug(log_message) logger.debug(log_message)
class NodeConnCB(NodeConn): class P2PInterface(P2PConnection):
"""A high-level P2P interface class for communicating with a Bitcoin node. """A high-level P2P interface class for communicating with a Bitcoin node.
This class provides high-level callbacks for processing P2P message This class provides high-level callbacks for processing P2P message
@ -252,9 +248,7 @@ class NodeConnCB(NodeConn):
node over P2P. node over P2P.
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."""
TODO: rename this class P2PInterface"""
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@ -399,10 +393,10 @@ mininode_socket_map = dict()
# One lock for synchronizing all data access between the networking thread (see # One lock for synchronizing all data access between the networking thread (see
# NetworkThread below) and the thread running the test logic. For simplicity, # NetworkThread below) and the thread running the test logic. For simplicity,
# NodeConn acquires this lock whenever delivering a message to a NodeConnCB, # P2PConnection acquires this lock whenever delivering a message to a P2PInterface,
# and whenever adding anything to the send buffer (in send_message()). This # and whenever adding anything to the send buffer (in send_message()). This
# lock should be acquired in the thread running the test logic to synchronize # lock should be acquired in the thread running the test logic to synchronize
# access to any data shared with the NodeConnCB or NodeConn. # access to any data shared with the P2PInterface or P2PConnection.
mininode_lock = RLock() mininode_lock = RLock()
class NetworkThread(Thread): class NetworkThread(Thread):