rpc_preciousblock.py
1 #!/usr/bin/env python3 2 # Copyright (c) 2015-2021 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 preciousblock RPC.""" 6 7 from test_framework.test_framework import BitcoinTestFramework 8 from test_framework.util import ( 9 assert_equal, 10 ) 11 12 def unidirectional_node_sync_via_rpc(node_src, node_dest): 13 blocks_to_copy = [] 14 blockhash = node_src.getbestblockhash() 15 while True: 16 try: 17 assert len(node_dest.getblock(blockhash, False)) > 0 18 break 19 except Exception: 20 blocks_to_copy.append(blockhash) 21 blockhash = node_src.getblockheader(blockhash, True)['previousblockhash'] 22 blocks_to_copy.reverse() 23 for blockhash in blocks_to_copy: 24 blockdata = node_src.getblock(blockhash, False) 25 assert node_dest.submitblock(blockdata) in (None, 'inconclusive') 26 27 def node_sync_via_rpc(nodes): 28 for node_src in nodes: 29 for node_dest in nodes: 30 if node_src is node_dest: 31 continue 32 unidirectional_node_sync_via_rpc(node_src, node_dest) 33 34 class PreciousTest(BitcoinTestFramework): 35 def set_test_params(self): 36 self.setup_clean_chain = True 37 self.num_nodes = 3 38 self.supports_cli = False 39 40 def setup_network(self): 41 self.setup_nodes() 42 43 def run_test(self): 44 self.log.info("Ensure submitblock can in principle reorg to a competing chain") 45 self.generate(self.nodes[0], 1, sync_fun=self.no_op) 46 assert_equal(self.nodes[0].getblockcount(), 1) 47 hashZ = self.generate(self.nodes[1], 2, sync_fun=self.no_op)[-1] 48 assert_equal(self.nodes[1].getblockcount(), 2) 49 node_sync_via_rpc(self.nodes[0:3]) 50 assert_equal(self.nodes[0].getbestblockhash(), hashZ) 51 52 self.log.info("Mine blocks A-B-C on Node 0") 53 hashC = self.generate(self.nodes[0], 3, sync_fun=self.no_op)[-1] 54 assert_equal(self.nodes[0].getblockcount(), 5) 55 self.log.info("Mine competing blocks E-F-G on Node 1") 56 hashG = self.generate(self.nodes[1], 3, sync_fun=self.no_op)[-1] 57 assert_equal(self.nodes[1].getblockcount(), 5) 58 assert hashC != hashG 59 self.log.info("Connect nodes and check no reorg occurs") 60 # Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync) 61 node_sync_via_rpc(self.nodes[0:2]) 62 self.connect_nodes(0, 1) 63 assert_equal(self.nodes[0].getbestblockhash(), hashC) 64 assert_equal(self.nodes[1].getbestblockhash(), hashG) 65 self.log.info("Make Node0 prefer block G") 66 self.nodes[0].preciousblock(hashG) 67 assert_equal(self.nodes[0].getbestblockhash(), hashG) 68 self.log.info("Make Node0 prefer block C again") 69 self.nodes[0].preciousblock(hashC) 70 assert_equal(self.nodes[0].getbestblockhash(), hashC) 71 self.log.info("Make Node1 prefer block C") 72 self.nodes[1].preciousblock(hashC) 73 self.sync_blocks(self.nodes[0:2]) # wait because node 1 may not have downloaded hashC 74 assert_equal(self.nodes[1].getbestblockhash(), hashC) 75 self.log.info("Make Node1 prefer block G again") 76 self.nodes[1].preciousblock(hashG) 77 assert_equal(self.nodes[1].getbestblockhash(), hashG) 78 self.log.info("Make Node0 prefer block G again") 79 self.nodes[0].preciousblock(hashG) 80 assert_equal(self.nodes[0].getbestblockhash(), hashG) 81 self.log.info("Make Node1 prefer block C again") 82 self.nodes[1].preciousblock(hashC) 83 assert_equal(self.nodes[1].getbestblockhash(), hashC) 84 self.log.info("Mine another block (E-F-G-)H on Node 0 and reorg Node 1") 85 self.generate(self.nodes[0], 1, sync_fun=self.no_op) 86 assert_equal(self.nodes[0].getblockcount(), 6) 87 self.sync_blocks(self.nodes[0:2]) 88 hashH = self.nodes[0].getbestblockhash() 89 assert_equal(self.nodes[1].getbestblockhash(), hashH) 90 self.log.info("Node1 should not be able to prefer block C anymore") 91 self.nodes[1].preciousblock(hashC) 92 assert_equal(self.nodes[1].getbestblockhash(), hashH) 93 self.log.info("Mine competing blocks I-J-K-L on Node 2") 94 self.generate(self.nodes[2], 4, sync_fun=self.no_op) 95 assert_equal(self.nodes[2].getblockcount(), 6) 96 hashL = self.nodes[2].getbestblockhash() 97 self.log.info("Connect nodes and check no reorg occurs") 98 node_sync_via_rpc(self.nodes[1:3]) 99 self.connect_nodes(1, 2) 100 self.connect_nodes(0, 2) 101 assert_equal(self.nodes[0].getbestblockhash(), hashH) 102 assert_equal(self.nodes[1].getbestblockhash(), hashH) 103 assert_equal(self.nodes[2].getbestblockhash(), hashL) 104 self.log.info("Make Node1 prefer block L") 105 self.nodes[1].preciousblock(hashL) 106 assert_equal(self.nodes[1].getbestblockhash(), hashL) 107 self.log.info("Make Node2 prefer block H") 108 self.nodes[2].preciousblock(hashH) 109 assert_equal(self.nodes[2].getbestblockhash(), hashH) 110 111 if __name__ == '__main__': 112 PreciousTest().main()