p2p-acceptblock: add steps 8, 9 to confirm node disconnects
This commit is contained in:
parent
fe1bca68da
commit
fb194d7319
|
@ -7,7 +7,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 *
|
||||||
import time
|
import time
|
||||||
from test_framework.blocktools import create_block, create_coinbase
|
from test_framework.blocktools import create_block, create_coinbase, create_transaction
|
||||||
|
|
||||||
'''
|
'''
|
||||||
AcceptBlockTest -- test processing of unrequested blocks.
|
AcceptBlockTest -- test processing of unrequested blocks.
|
||||||
|
@ -54,6 +54,14 @@ The test:
|
||||||
|
|
||||||
7. Send Node0 the missing block again.
|
7. Send Node0 the missing block again.
|
||||||
Node0 should process and the tip should advance.
|
Node0 should process and the tip should advance.
|
||||||
|
|
||||||
|
8. Create a fork which is invalid at a height longer than the current chain
|
||||||
|
(ie to which the node will try to reorg) but which has headers built on top
|
||||||
|
of the invalid block. Check that we get disconnected if we send more headers
|
||||||
|
on the chain the node now knows to be invalid.
|
||||||
|
|
||||||
|
9. Test Node1 is able to sync when connected to node0 (which should have sufficient
|
||||||
|
work on its chain).
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
|
# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
|
||||||
|
@ -271,8 +279,85 @@ class AcceptBlockTest(BitcoinTestFramework):
|
||||||
|
|
||||||
test_node.sync_with_ping()
|
test_node.sync_with_ping()
|
||||||
assert_equal(self.nodes[0].getblockcount(), 1442)
|
assert_equal(self.nodes[0].getblockcount(), 1442)
|
||||||
|
self.nodes[0].getblock(all_blocks[1438].hash)
|
||||||
|
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[1438].hash)
|
||||||
|
assert_raises_jsonrpc(-1, "Block not found on disk", self.nodes[0].getblock, all_blocks[1439].hash)
|
||||||
print("Successfully reorged to longer chain from non-whitelisted peer")
|
print("Successfully reorged to longer chain from non-whitelisted peer")
|
||||||
|
|
||||||
|
# 8. Create a chain which is invalid at a height longer than the
|
||||||
|
# current chain, but which has more blocks on top of that
|
||||||
|
block_1441f = create_block(all_blocks[1436].sha256, create_coinbase(1441), all_blocks[1436].nTime+1)
|
||||||
|
block_1441f.solve()
|
||||||
|
block_1442f = create_block(block_1441f.sha256, create_coinbase(1440), block_1441f.nTime+1)
|
||||||
|
block_1442f.solve()
|
||||||
|
block_1443 = create_block(block_1442f.sha256, create_coinbase(1441), block_1442f.nTime+1)
|
||||||
|
# block_1443 spends a coinbase below maturity!
|
||||||
|
block_1443.vtx.append(create_transaction(block_1442f.vtx[0], 0, b"42", 1))
|
||||||
|
block_1443.hashMerkleRoot = block_1443.calc_merkle_root()
|
||||||
|
block_1443.solve()
|
||||||
|
block_1444 = create_block(block_1443.sha256, create_coinbase(1444), block_1443.nTime+1)
|
||||||
|
block_1444.solve()
|
||||||
|
|
||||||
|
# Now send all the headers on the chain and enough blocks to trigger reorg
|
||||||
|
headers_message = msg_headers()
|
||||||
|
headers_message.headers.append(CBlockHeader(block_1441f))
|
||||||
|
headers_message.headers.append(CBlockHeader(block_1442f))
|
||||||
|
headers_message.headers.append(CBlockHeader(block_1443))
|
||||||
|
headers_message.headers.append(CBlockHeader(block_1444))
|
||||||
|
test_node.send_message(headers_message)
|
||||||
|
|
||||||
|
test_node.sync_with_ping()
|
||||||
|
tip_entry_found = False
|
||||||
|
for x in self.nodes[0].getchaintips():
|
||||||
|
if x['hash'] == block_1444.hash:
|
||||||
|
assert_equal(x['status'], "headers-only")
|
||||||
|
tip_entry_found = True
|
||||||
|
assert(tip_entry_found)
|
||||||
|
assert_raises_jsonrpc(-1, "Block not found on disk", self.nodes[0].getblock, block_1444.hash)
|
||||||
|
|
||||||
|
test_node.send_message(msg_block(block_1441f))
|
||||||
|
test_node.send_message(msg_block(block_1442f))
|
||||||
|
|
||||||
|
test_node.sync_with_ping()
|
||||||
|
self.nodes[0].getblock(block_1441f.hash)
|
||||||
|
self.nodes[0].getblock(block_1442f.hash)
|
||||||
|
|
||||||
|
test_node.send_message(msg_block(block_1443))
|
||||||
|
|
||||||
|
# At this point we've sent an obviously-bogus block, wait for full processing
|
||||||
|
# without assuming whether we will be disconnected or not
|
||||||
|
try:
|
||||||
|
# Only wait a short while so the test doesn't take forever if we do get
|
||||||
|
# disconnected
|
||||||
|
test_node.sync_with_ping(timeout=1)
|
||||||
|
except AssertionError:
|
||||||
|
test_node.wait_for_disconnect()
|
||||||
|
|
||||||
|
test_node = TestNode() # connects to node (not whitelisted)
|
||||||
|
connections[0] = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node)
|
||||||
|
test_node.add_connection(connections[0])
|
||||||
|
|
||||||
|
NetworkThread().start() # Start up network handling in another thread
|
||||||
|
test_node.wait_for_verack()
|
||||||
|
|
||||||
|
# We should have failed reorg and switched back to 1442 (but have block 1443)
|
||||||
|
assert_equal(self.nodes[0].getblockcount(), 1442)
|
||||||
|
assert_equal(self.nodes[0].getbestblockhash(), all_blocks[1438].hash)
|
||||||
|
assert_equal(self.nodes[0].getblock(block_1443.hash)["confirmations"], -1)
|
||||||
|
|
||||||
|
# Now send a new header on the invalid chain, indicating we're forked off, and expect to get disconnected
|
||||||
|
block_1445 = create_block(block_1444.sha256, create_coinbase(1445), block_1444.nTime+1)
|
||||||
|
block_1445.solve()
|
||||||
|
headers_message = msg_headers()
|
||||||
|
headers_message.headers.append(CBlockHeader(block_1445))
|
||||||
|
test_node.send_message(headers_message)
|
||||||
|
test_node.wait_for_disconnect()
|
||||||
|
|
||||||
|
# 9. Connect node1 to node0 and ensure it is able to sync
|
||||||
|
connect_nodes(self.nodes[0], 1)
|
||||||
|
sync_blocks([self.nodes[0], self.nodes[1]])
|
||||||
|
self.log.info("Successfully synced nodes 1 and 0")
|
||||||
|
|
||||||
[ c.disconnect_node() for c in connections ]
|
[ c.disconnect_node() for c in connections ]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in a new issue