def run_test(self):
    test_node = self.nodes[0].add_p2p_connection(P2PInterface())
    min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
    network_thread_start()
    test_node.wait_for_verack()
    min_work_node.wait_for_verack()
    [n.generate(1) for n in self.nodes]
    tips = [int(('0x' + n.getbestblockhash()), 0) for n in self.nodes]
    blocks_h2 = []
    block_time = (int(time.time()) + 1)
    for i in range(2):
        blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
        blocks_h2[i].solve()
        block_time += 1
    test_node.send_message(msg_block(blocks_h2[0]))
    min_work_node.send_message(msg_block(blocks_h2[1]))
    for x in [test_node, min_work_node]:
        x.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 2)
    assert_equal(self.nodes[1].getblockcount(), 1)
    self.log.info('First height 2 block accepted by node0; correctly rejected by node1')
    block_h1f = create_block(int(('0x' + self.nodes[0].getblockhash(0)), 0), create_coinbase(1), block_time)
    block_time += 1
    block_h1f.solve()
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h1f.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, block_h1f.hash)
    block_h2f = create_block(block_h1f.sha256, create_coinbase(2), block_time)
    block_time += 1
    block_h2f.solve()
    test_node.send_message(msg_block(block_h2f))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h2f.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    self.nodes[0].getblock(block_h2f.hash)
    self.log.info("Second height 2 block accepted, but not reorg'ed to")
    block_h3 = create_block(block_h2f.sha256, create_coinbase(3), (block_h2f.nTime + 1))
    block_h3.solve()
    test_node.send_message(msg_block(block_h3))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h3.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    self.nodes[0].getblock(block_h3.hash)
    self.nodes[0].getblock(block_h3.hash)
    self.log.info('Unrequested more-work block accepted')
    tip = block_h3
    all_blocks = []
    for i in range(288):
        next_block = create_block(tip.sha256, create_coinbase((i + 4)), (tip.nTime + 1))
        next_block.solve()
        all_blocks.append(next_block)
        tip = next_block
    test_node.send_message(msg_block(all_blocks[1]))
    test_node.sync_with_ping()
    assert_raises_rpc_error((- 5), 'Block not found', self.nodes[0].getblock, all_blocks[1].hash)
    assert_raises_rpc_error((- 5), 'Block not found', self.nodes[0].getblockheader, all_blocks[1].hash)
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(all_blocks[0]))
    test_node.send_message(headers_message)
    test_node.send_message(msg_block(all_blocks[1]))
    test_node.sync_with_ping()
    self.nodes[0].getblock(all_blocks[1].hash)
    for i in range(288):
        test_node.send_message(msg_block(all_blocks[i]))
    test_node.sync_with_ping()
    for x in all_blocks[:(- 1)]:
        self.nodes[0].getblock(x.hash)
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, all_blocks[(- 1)].hash)
    self.nodes[0].disconnect_p2ps()
    self.nodes[1].disconnect_p2ps()
    network_thread_join()
    test_node = self.nodes[0].add_p2p_connection(P2PInterface())
    network_thread_start()
    test_node.wait_for_verack()
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 2)
    self.log.info('Unrequested block that would complete more-work chain was ignored')
    with mininode_lock:
        test_node.last_message.pop('getdata', None)
        test_node.send_message(msg_inv([CInv(2, block_h3.sha256)]))
    test_node.sync_with_ping()
    with mininode_lock:
        getdata = test_node.last_message['getdata']
    assert_equal(getdata.inv[0].hash, block_h1f.sha256)
    self.log.info('Inv at tip triggered getdata for unprocessed block')
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 290)
    self.nodes[0].getblock(all_blocks[286].hash)
    assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, all_blocks[287].hash)
    self.log.info('Successfully reorged to longer chain from non-whitelisted peer')
    block_289f = create_block(all_blocks[284].sha256, create_coinbase(289), (all_blocks[284].nTime + 1))
    block_289f.solve()
    block_290f = create_block(block_289f.sha256, create_coinbase(290), (block_289f.nTime + 1))
    block_290f.solve()
    block_291 = create_block(block_290f.sha256, create_coinbase(291), (block_290f.nTime + 1))
    block_291.vtx.append(create_transaction(block_290f.vtx[0], 0, b'42', 1))
    block_291.hashMerkleRoot = block_291.calc_merkle_root()
    block_291.solve()
    block_292 = create_block(block_291.sha256, create_coinbase(292), (block_291.nTime + 1))
    block_292.solve()
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(block_289f))
    headers_message.headers.append(CBlockHeader(block_290f))
    headers_message.headers.append(CBlockHeader(block_291))
    headers_message.headers.append(CBlockHeader(block_292))
    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_292.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, block_292.hash)
    test_node.send_message(msg_block(block_289f))
    test_node.send_message(msg_block(block_290f))
    test_node.sync_with_ping()
    self.nodes[0].getblock(block_289f.hash)
    self.nodes[0].getblock(block_290f.hash)
    test_node.send_message(msg_block(block_291))
    try:
        test_node.sync_with_ping(timeout=1)
    except AssertionError:
        test_node.wait_for_disconnect()
        self.nodes[0].disconnect_p2ps()
        test_node = self.nodes[0].add_p2p_connection(P2PInterface())
        network_thread_start()
        test_node.wait_for_verack()
    assert_equal(self.nodes[0].getblockcount(), 290)
    assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
    assert_equal(self.nodes[0].getblock(block_291.hash)['confirmations'], (- 1))
    block_293 = create_block(block_292.sha256, create_coinbase(293), (block_292.nTime + 1))
    block_293.solve()
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(block_293))
    test_node.send_message(headers_message)
    test_node.wait_for_disconnect()
    connect_nodes(self.nodes[0], 1)
    sync_blocks([self.nodes[0], self.nodes[1]])
    self.log.info('Successfully synced nodes 1 and 0')
def run_test(self):
    test_node = self.nodes[0].add_p2p_connection(P2PInterface())
    min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
    network_thread_start()
    test_node.wait_for_verack()
    min_work_node.wait_for_verack()
    [n.generate(1) for n in self.nodes]
    tips = [int(('0x' + n.getbestblockhash()), 0) for n in self.nodes]
    blocks_h2 = []
    block_time = (int(time.time()) + 1)
    for i in range(2):
        blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
        blocks_h2[i].solve()
        block_time += 1
    test_node.send_message(msg_block(blocks_h2[0]))
    min_work_node.send_message(msg_block(blocks_h2[1]))
    for x in [test_node, min_work_node]:
        x.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 2)
    assert_equal(self.nodes[1].getblockcount(), 1)
    self.log.info('First height 2 block accepted by node0; correctly rejected by node1')
    block_h1f = create_block(int(('0x' + self.nodes[0].getblockhash(0)), 0), create_coinbase(1), block_time)
    block_time += 1
    block_h1f.solve()
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h1f.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, block_h1f.hash)
    block_h2f = create_block(block_h1f.sha256, create_coinbase(2), block_time)
    block_time += 1
    block_h2f.solve()
    test_node.send_message(msg_block(block_h2f))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h2f.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    self.nodes[0].getblock(block_h2f.hash)
    self.log.info("Second height 2 block accepted, but not reorg'ed to")
    block_h3 = create_block(block_h2f.sha256, create_coinbase(3), (block_h2f.nTime + 1))
    block_h3.solve()
    test_node.send_message(msg_block(block_h3))
    test_node.sync_with_ping()
    tip_entry_found = False
    for x in self.nodes[0].getchaintips():
        if (x['hash'] == block_h3.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    self.nodes[0].getblock(block_h3.hash)
    self.nodes[0].getblock(block_h3.hash)
    self.log.info('Unrequested more-work block accepted')
    tip = block_h3
    all_blocks = []
    for i in range(288):
        next_block = create_block(tip.sha256, create_coinbase((i + 4)), (tip.nTime + 1))
        next_block.solve()
        all_blocks.append(next_block)
        tip = next_block
    test_node.send_message(msg_block(all_blocks[1]))
    test_node.sync_with_ping()
    assert_raises_rpc_error((- 5), 'Block not found', self.nodes[0].getblock, all_blocks[1].hash)
    assert_raises_rpc_error((- 5), 'Block not found', self.nodes[0].getblockheader, all_blocks[1].hash)
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(all_blocks[0]))
    test_node.send_message(headers_message)
    test_node.send_message(msg_block(all_blocks[1]))
    test_node.sync_with_ping()
    self.nodes[0].getblock(all_blocks[1].hash)
    for i in range(288):
        test_node.send_message(msg_block(all_blocks[i]))
    test_node.sync_with_ping()
    for x in all_blocks[:(- 1)]:
        self.nodes[0].getblock(x.hash)
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, all_blocks[(- 1)].hash)
    self.nodes[0].disconnect_p2ps()
    self.nodes[1].disconnect_p2ps()
    network_thread_join()
    test_node = self.nodes[0].add_p2p_connection(P2PInterface())
    network_thread_start()
    test_node.wait_for_verack()
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 2)
    self.log.info('Unrequested block that would complete more-work chain was ignored')
    with mininode_lock:
        test_node.last_message.pop('getdata', None)
        test_node.send_message(msg_inv([CInv(2, block_h3.sha256)]))
    test_node.sync_with_ping()
    with mininode_lock:
        getdata = test_node.last_message['getdata']
    assert_equal(getdata.inv[0].hash, block_h1f.sha256)
    self.log.info('Inv at tip triggered getdata for unprocessed block')
    test_node.send_message(msg_block(block_h1f))
    test_node.sync_with_ping()
    assert_equal(self.nodes[0].getblockcount(), 290)
    self.nodes[0].getblock(all_blocks[286].hash)
    assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, all_blocks[287].hash)
    self.log.info('Successfully reorged to longer chain from non-whitelisted peer')
    block_289f = create_block(all_blocks[284].sha256, create_coinbase(289), (all_blocks[284].nTime + 1))
    block_289f.solve()
    block_290f = create_block(block_289f.sha256, create_coinbase(290), (block_289f.nTime + 1))
    block_290f.solve()
    block_291 = create_block(block_290f.sha256, create_coinbase(291), (block_290f.nTime + 1))
    block_291.vtx.append(create_transaction(block_290f.vtx[0], 0, b'42', 1))
    block_291.hashMerkleRoot = block_291.calc_merkle_root()
    block_291.solve()
    block_292 = create_block(block_291.sha256, create_coinbase(292), (block_291.nTime + 1))
    block_292.solve()
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(block_289f))
    headers_message.headers.append(CBlockHeader(block_290f))
    headers_message.headers.append(CBlockHeader(block_291))
    headers_message.headers.append(CBlockHeader(block_292))
    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_292.hash):
            assert_equal(x['status'], 'headers-only')
            tip_entry_found = True
    assert tip_entry_found
    assert_raises_rpc_error((- 1), 'Block not found on disk', self.nodes[0].getblock, block_292.hash)
    test_node.send_message(msg_block(block_289f))
    test_node.send_message(msg_block(block_290f))
    test_node.sync_with_ping()
    self.nodes[0].getblock(block_289f.hash)
    self.nodes[0].getblock(block_290f.hash)
    test_node.send_message(msg_block(block_291))
    try:
        test_node.sync_with_ping(timeout=1)
    except AssertionError:
        test_node.wait_for_disconnect()
        self.nodes[0].disconnect_p2ps()
        test_node = self.nodes[0].add_p2p_connection(P2PInterface())
        network_thread_start()
        test_node.wait_for_verack()
    assert_equal(self.nodes[0].getblockcount(), 290)
    assert_equal(self.nodes[0].getbestblockhash(), all_blocks[286].hash)
    assert_equal(self.nodes[0].getblock(block_291.hash)['confirmations'], (- 1))
    block_293 = create_block(block_292.sha256, create_coinbase(293), (block_292.nTime + 1))
    block_293.solve()
    headers_message = msg_headers()
    headers_message.headers.append(CBlockHeader(block_293))
    test_node.send_message(headers_message)
    test_node.wait_for_disconnect()
    connect_nodes(self.nodes[0], 1)
    sync_blocks([self.nodes[0], self.nodes[1]])
    self.log.info('Successfully synced nodes 1 and 0')