Skip to content

Commit

Permalink
[tests] use TestNode p2p connection in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewbery committed Nov 8, 2017
1 parent 5e5725c commit 32ae82f
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 249 deletions.
46 changes: 19 additions & 27 deletions test/functional/assumevalid.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@
CTxIn,
CTxOut,
NetworkThread,
NodeConn,
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 (p2p_port, assert_equal)
from test_framework.util import assert_equal

class BaseNode(NodeConnCB):
def send_header_for_blocks(self, new_blocks):
Expand All @@ -65,13 +64,13 @@ def setup_network(self):
# signature so we can pass in the block hash as assumevalid.
self.start_node(0)

def send_blocks_until_disconnected(self, node):
def send_blocks_until_disconnected(self, p2p_conn):
"""Keep sending blocks to the node until we're disconnected."""
for i in range(len(self.blocks)):
if not node.connection:
if not p2p_conn.connection:
break
try:
node.send_message(msg_block(self.blocks[i]))
p2p_conn.send_message(msg_block(self.blocks[i]))
except IOError as e:
assert str(e) == 'Not connected, no pushbuf'
break
Expand All @@ -97,13 +96,10 @@ def assert_blockchain_height(self, node, height):
def run_test(self):

# Connect to node0
node0 = BaseNode()
connections = []
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0))
node0.add_connection(connections[0])
p2p0 = self.nodes[0].add_p2p_connection(BaseNode())

NetworkThread().start() # Start up network handling in another thread
node0.wait_for_verack()
self.nodes[0].p2p.wait_for_verack()

# Build the blockchain
self.tip = int(self.nodes[0].getbestblockhash(), 16)
Expand Down Expand Up @@ -165,37 +161,33 @@ def run_test(self):

# Start node1 and node2 with assumevalid so they accept a block with a bad signature.
self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)])
node1 = BaseNode() # connects to node1
connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1))
node1.add_connection(connections[1])
node1.wait_for_verack()
p2p1 = self.nodes[1].add_p2p_connection(BaseNode())
p2p1.wait_for_verack()

self.start_node(2, extra_args=["-assumevalid=" + hex(block102.sha256)])
node2 = BaseNode() # connects to node2
connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2))
node2.add_connection(connections[2])
node2.wait_for_verack()
p2p2 = self.nodes[2].add_p2p_connection(BaseNode())
p2p2.wait_for_verack()

# send header lists to all three nodes
node0.send_header_for_blocks(self.blocks[0:2000])
node0.send_header_for_blocks(self.blocks[2000:])
node1.send_header_for_blocks(self.blocks[0:2000])
node1.send_header_for_blocks(self.blocks[2000:])
node2.send_header_for_blocks(self.blocks[0:200])
p2p0.send_header_for_blocks(self.blocks[0:2000])
p2p0.send_header_for_blocks(self.blocks[2000:])
p2p1.send_header_for_blocks(self.blocks[0:2000])
p2p1.send_header_for_blocks(self.blocks[2000:])
p2p2.send_header_for_blocks(self.blocks[0:200])

# Send blocks to node0. Block 102 will be rejected.
self.send_blocks_until_disconnected(node0)
self.send_blocks_until_disconnected(p2p0)
self.assert_blockchain_height(self.nodes[0], 101)

# Send all blocks to node1. All blocks will be accepted.
for i in range(2202):
node1.send_message(msg_block(self.blocks[i]))
p2p1.send_message(msg_block(self.blocks[i]))
# Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync.
node1.sync_with_ping(120)
p2p1.sync_with_ping(120)
assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202)

# Send blocks to node2. Block 102 will be rejected.
self.send_blocks_until_disconnected(node2)
self.send_blocks_until_disconnected(p2p2)
self.assert_blockchain_height(self.nodes[2], 101)

if __name__ == '__main__':
Expand Down
39 changes: 18 additions & 21 deletions test/functional/bip65-cltv-p2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,12 @@ def set_test_params(self):
self.setup_clean_chain = True

def run_test(self):
node0 = NodeConnCB()
connections = []
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0))
node0.add_connection(connections[0])
self.nodes[0].add_p2p_connection(NodeConnCB())

NetworkThread().start() # Start up network handling in another thread

# wait_for_verack ensures that the P2P connection is fully up.
node0.wait_for_verack()
self.nodes[0].p2p.wait_for_verack()

self.log.info("Mining %d blocks", CLTV_HEIGHT - 2)
self.coinbase_blocks = self.nodes[0].generate(CLTV_HEIGHT - 2)
Expand All @@ -95,7 +92,7 @@ def run_test(self):
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)

self.log.info("Test that blocks must now be at least version 4")
Expand All @@ -104,15 +101,15 @@ def run_test(self):
block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time)
block.nVersion = 3
block.solve()
node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)

wait_until(lambda: "reject" in node0.last_message.keys(), lock=mininode_lock)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
with mininode_lock:
assert_equal(node0.last_message["reject"].code, REJECT_OBSOLETE)
assert_equal(node0.last_message["reject"].reason, b'bad-version(0x00000003)')
assert_equal(node0.last_message["reject"].data, block.sha256)
del node0.last_message["reject"]
assert_equal(self.nodes[0].p2p.last_message["reject"].code, REJECT_OBSOLETE)
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'bad-version(0x00000003)')
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
del self.nodes[0].p2p.last_message["reject"]

self.log.info("Test that invalid-according-to-cltv transactions cannot appear in a block")
block.nVersion = 4
Expand All @@ -125,26 +122,26 @@ def run_test(self):
# First we show that this tx is valid except for CLTV by getting it
# accepted to the mempool (which we can achieve with
# -promiscuousmempoolflags).
node0.send_and_ping(msg_tx(spendtx))
self.nodes[0].p2p.send_and_ping(msg_tx(spendtx))
assert spendtx.hash in self.nodes[0].getrawmempool()

# Now we verify that a block with this transaction is invalid.
block.vtx.append(spendtx)
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)

wait_until(lambda: "reject" in node0.last_message.keys(), lock=mininode_lock)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
with mininode_lock:
assert node0.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(node0.last_message["reject"].data, block.sha256)
if node0.last_message["reject"].code == REJECT_INVALID:
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
if self.nodes[0].p2p.last_message["reject"].code == REJECT_INVALID:
# Generic rejection when a block is invalid
assert_equal(node0.last_message["reject"].reason, b'block-validation-failed')
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'block-validation-failed')
else:
assert b'Negative locktime' in node0.last_message["reject"].reason
assert b'Negative locktime' in self.nodes[0].p2p.last_message["reject"].reason

self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1)
Expand All @@ -155,7 +152,7 @@ def run_test(self):
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)


Expand Down
40 changes: 19 additions & 21 deletions test/functional/bipdersig-p2p.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,12 @@ def set_test_params(self):
self.setup_clean_chain = True

def run_test(self):
node0 = NodeConnCB()
connections = []
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0))
node0.add_connection(connections[0])
self.nodes[0].add_p2p_connection(NodeConnCB())

NetworkThread().start() # Start up network handling in another thread

# wait_for_verack ensures that the P2P connection is fully up.
node0.wait_for_verack()
self.nodes[0].p2p.wait_for_verack()

self.log.info("Mining %d blocks", DERSIG_HEIGHT - 2)
self.coinbase_blocks = self.nodes[0].generate(DERSIG_HEIGHT - 2)
Expand All @@ -83,7 +81,7 @@ def run_test(self):
block.rehash()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)

self.log.info("Test that blocks must now be at least version 3")
Expand All @@ -93,15 +91,15 @@ def run_test(self):
block.nVersion = 2
block.rehash()
block.solve()
node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)

wait_until(lambda: "reject" in node0.last_message.keys(), lock=mininode_lock)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
with mininode_lock:
assert_equal(node0.last_message["reject"].code, REJECT_OBSOLETE)
assert_equal(node0.last_message["reject"].reason, b'bad-version(0x00000002)')
assert_equal(node0.last_message["reject"].data, block.sha256)
del node0.last_message["reject"]
assert_equal(self.nodes[0].p2p.last_message["reject"].code, REJECT_OBSOLETE)
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'bad-version(0x00000002)')
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
del self.nodes[0].p2p.last_message["reject"]

self.log.info("Test that transactions with non-DER signatures cannot appear in a block")
block.nVersion = 3
Expand All @@ -114,7 +112,7 @@ def run_test(self):
# First we show that this tx is valid except for DERSIG by getting it
# accepted to the mempool (which we can achieve with
# -promiscuousmempoolflags).
node0.send_and_ping(msg_tx(spendtx))
self.nodes[0].p2p.send_and_ping(msg_tx(spendtx))
assert spendtx.hash in self.nodes[0].getrawmempool()

# Now we verify that a block with this transaction is invalid.
Expand All @@ -123,23 +121,23 @@ def run_test(self):
block.rehash()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)

wait_until(lambda: "reject" in node0.last_message.keys(), lock=mininode_lock)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
with mininode_lock:
# We can receive different reject messages depending on whether
# bitcoind is running with multiple script check threads. If script
# check threads are not in use, then transaction script validation
# happens sequentially, and bitcoind produces more specific reject
# reasons.
assert node0.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(node0.last_message["reject"].data, block.sha256)
if node0.last_message["reject"].code == REJECT_INVALID:
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
if self.nodes[0].p2p.last_message["reject"].code == REJECT_INVALID:
# Generic rejection when a block is invalid
assert_equal(node0.last_message["reject"].reason, b'block-validation-failed')
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'block-validation-failed')
else:
assert b'Non-canonical DER signature' in node0.last_message["reject"].reason
assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason

self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
block.vtx[1] = create_transaction(self.nodes[0],
Expand All @@ -148,7 +146,7 @@ def run_test(self):
block.rehash()
block.solve()

node0.send_and_ping(msg_block(block))
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)

if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 32ae82f

Please sign in to comment.