From 177d07f65915ffce0c52818934e3ceddf574fd84 Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Thu, 14 Mar 2024 13:53:09 -0400 Subject: [PATCH] test: Adds block tiebreak over restarts tests Adds tests to make sure we are consistent on activating the same chain over a node restart if two or more candidates have the same work when the node is shutdown --- test/functional/feature_chain_tiebreaks.py | 50 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/test/functional/feature_chain_tiebreaks.py b/test/functional/feature_chain_tiebreaks.py index a18d9a8cdb9..f75f7983f77 100755 --- a/test/functional/feature_chain_tiebreaks.py +++ b/test/functional/feature_chain_tiebreaks.py @@ -23,7 +23,7 @@ class ChainTiebreaksTest(BitcoinTestFramework): # announcement. node.submitheader(hexdata=CBlockHeader(block).serialize().hex()) - def run_test(self): + def test_chain_split_in_memory(self): node = self.nodes[0] # Add P2P connection to bitcoind peer = node.add_p2p_connection(P2PDataStore()) @@ -99,5 +99,53 @@ class ChainTiebreaksTest(BitcoinTestFramework): # B7 is now active. assert_equal(node.getbestblockhash(), blocks[7].hash) + # Invalidate blocks to start fresh on the next test + node.invalidateblock(blocks[0].hash) + + def test_chain_split_from_disk(self): + node = self.nodes[0] + peer = node.add_p2p_connection(P2PDataStore()) + + self.log.info('Precomputing blocks') + # + # A1 + # / + # G + # \ + # A2 + # + blocks = [] + + # Construct two blocks building from genesis. + start_height = node.getblockcount() + genesis_block = node.getblock(node.getblockhash(start_height)) + prev_time = genesis_block["time"] + + for i in range(0, 2): + blocks.append(create_block( + hashprev=int(genesis_block["hash"], 16), + tmpl={"height": start_height + 1, + # Make sure each block has a different hash. + "curtime": prev_time + i + 1, + } + )) + blocks[-1].solve() + + # Send blocks and test the last one is not connected + self.log.info('Send A1 and A2. Make sure than only the former connects') + peer.send_blocks_and_test([blocks[0]], node, success=True) + peer.send_blocks_and_test([blocks[1]], node, success=False) + + self.log.info('Restart the node and check that the best tip before restarting matched the ones afterwards') + # Restart and check enough times to this to eventually fail if the logic is broken + for _ in range(10): + self.restart_node(0) + assert_equal(blocks[0].hash, node.getbestblockhash()) + + def run_test(self): + self.test_chain_split_in_memory() + self.test_chain_split_from_disk() + + if __name__ == '__main__': ChainTiebreaksTest(__file__).main()