1#!/usr/bin/env python3 2# Copyright (c) 2014-2018 The Bitcoin Core developers 3# Distributed under the MIT software license, see the accompanying 4# file COPYING or http://www.opensource.org/licenses/mit-license.php. 5"""Test the invalidateblock RPC.""" 6 7from test_framework.test_framework import BitcoinTestFramework 8from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE 9from test_framework.util import ( 10 assert_equal, 11 connect_nodes_bi, 12 sync_blocks, 13 wait_until, 14) 15 16 17class InvalidateTest(BitcoinTestFramework): 18 def set_test_params(self): 19 self.setup_clean_chain = True 20 self.num_nodes = 3 21 22 def setup_network(self): 23 self.setup_nodes() 24 25 def run_test(self): 26 self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:") 27 self.log.info("Mine 4 blocks on Node 0") 28 self.nodes[0].generatetoaddress(4, self.nodes[0].get_deterministic_priv_key().address) 29 assert_equal(self.nodes[0].getblockcount(), 4) 30 besthash_n0 = self.nodes[0].getbestblockhash() 31 32 self.log.info("Mine competing 6 blocks on Node 1") 33 self.nodes[1].generatetoaddress(6, self.nodes[1].get_deterministic_priv_key().address) 34 assert_equal(self.nodes[1].getblockcount(), 6) 35 36 self.log.info("Connect nodes to force a reorg") 37 connect_nodes_bi(self.nodes, 0, 1) 38 sync_blocks(self.nodes[0:2]) 39 assert_equal(self.nodes[0].getblockcount(), 6) 40 badhash = self.nodes[1].getblockhash(2) 41 42 self.log.info("Invalidate block 2 on node 0 and verify we reorg to node 0's original chain") 43 self.nodes[0].invalidateblock(badhash) 44 assert_equal(self.nodes[0].getblockcount(), 4) 45 assert_equal(self.nodes[0].getbestblockhash(), besthash_n0) 46 47 self.log.info("Make sure we won't reorg to a lower work chain:") 48 connect_nodes_bi(self.nodes, 1, 2) 49 self.log.info("Sync node 2 to node 1 so both have 6 blocks") 50 sync_blocks(self.nodes[1:3]) 51 assert_equal(self.nodes[2].getblockcount(), 6) 52 self.log.info("Invalidate block 5 on node 1 so its tip is now at 4") 53 self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5)) 54 assert_equal(self.nodes[1].getblockcount(), 4) 55 self.log.info("Invalidate block 3 on node 2, so its tip is now 2") 56 self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3)) 57 assert_equal(self.nodes[2].getblockcount(), 2) 58 self.log.info("..and then mine a block") 59 self.nodes[2].generatetoaddress(1, self.nodes[2].get_deterministic_priv_key().address) 60 self.log.info("Verify all nodes are at the right height") 61 wait_until(lambda: self.nodes[2].getblockcount() == 3, timeout=5) 62 wait_until(lambda: self.nodes[0].getblockcount() == 4, timeout=5) 63 wait_until(lambda: self.nodes[1].getblockcount() == 4, timeout=5) 64 65 self.log.info("Verify that we reconsider all ancestors as well") 66 blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE) 67 assert_equal(self.nodes[1].getbestblockhash(), blocks[-1]) 68 # Invalidate the two blocks at the tip 69 self.nodes[1].invalidateblock(blocks[-1]) 70 self.nodes[1].invalidateblock(blocks[-2]) 71 assert_equal(self.nodes[1].getbestblockhash(), blocks[-3]) 72 # Reconsider only the previous tip 73 self.nodes[1].reconsiderblock(blocks[-1]) 74 # Should be back at the tip by now 75 assert_equal(self.nodes[1].getbestblockhash(), blocks[-1]) 76 77 self.log.info("Verify that we reconsider all descendants") 78 blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE) 79 assert_equal(self.nodes[1].getbestblockhash(), blocks[-1]) 80 # Invalidate the two blocks at the tip 81 self.nodes[1].invalidateblock(blocks[-2]) 82 self.nodes[1].invalidateblock(blocks[-4]) 83 assert_equal(self.nodes[1].getbestblockhash(), blocks[-5]) 84 # Reconsider only the previous tip 85 self.nodes[1].reconsiderblock(blocks[-4]) 86 # Should be back at the tip by now 87 assert_equal(self.nodes[1].getbestblockhash(), blocks[-1]) 88 89 90if __name__ == '__main__': 91 InvalidateTest().main() 92