From 86d98b94e5469e6476dc87f54b8ac25074603f0c Mon Sep 17 00:00:00 2001 From: stratospher <44024636+stratospher@users.noreply.github.com> Date: Fri, 28 Feb 2025 23:45:53 +0530 Subject: [PATCH] test: verify that ancestors of a reconsidered block can become the chain tip when we reconsiderblock, previously only block and it's descendants were considered as chain tip candidates/inserted into setBlockIndexCandidates ex: on this chain, with block 4 invalidated 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> header 7 blocks 4, 5, 6, header 7 have BLOCK_FAILED_* flags set previously: - if we reconsiderblock header 7, the chain would have all the BLOCK_FAILED_* flags cleared but would report chain tip as block 3. - after restart, it reports correct chain tip block 6. now: - if we reconsiderblock header 7, the correct chain tip block 6 is reported since ancestors are also considered as chain tip candidates/inserted into setBlockIndexCandidates. Co-authored-by: Martin Zumsande --- test/functional/rpc_invalidateblock.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py index e2eb033f09..031f1dd86c 100755 --- a/test/functional/rpc_invalidateblock.py +++ b/test/functional/rpc_invalidateblock.py @@ -85,6 +85,23 @@ class InvalidateTest(BitcoinTestFramework): self.wait_until(lambda: self.nodes[0].getblockcount() == 4, timeout=5) self.wait_until(lambda: self.nodes[1].getblockcount() == 4, timeout=5) + self.log.info("Verify that ancestors can become chain tip candidates when we reconsider blocks") + # Invalidate node0's current chain (1' -> 2' -> 3' -> 4') so that we don't reorg back to it in this test + badhash = self.nodes[0].getblockhash(1) + self.nodes[0].invalidateblock(badhash) + # Reconsider the tip so that node0's chain becomes this chain again : 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> header 7 + self.nodes[0].reconsiderblock(tip) + blockhash_3 = self.nodes[0].getblockhash(3) + blockhash_4 = self.nodes[0].getblockhash(4) + blockhash_6 = self.nodes[0].getblockhash(6) + assert_equal(self.nodes[0].getbestblockhash(), blockhash_6) + + # Invalidate block 4 so that chain becomes : 1 -> 2 -> 3 + self.nodes[0].invalidateblock(blockhash_4) + assert_equal(self.nodes[0].getbestblockhash(), blockhash_3) + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 3) + assert_equal(self.nodes[0].getblockchaininfo()['headers'], 3) + self.log.info("Verify that we reconsider all ancestors as well") blocks = self.generatetodescriptor(self.nodes[1], 10, ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR, sync_fun=self.no_op) assert_equal(self.nodes[1].getbestblockhash(), blocks[-1]) @@ -111,6 +128,14 @@ class InvalidateTest(BitcoinTestFramework): # Should report consistent blockchain info assert_equal(self.nodes[1].getblockchaininfo()["headers"], self.nodes[1].getblockchaininfo()["blocks"]) + # Reconsider the header + self.nodes[0].reconsiderblock(block.hash) + # Since header doesn't have block data, it can't be chain tip + # Check if it's possible for an ancestor (with block data) to be the chain tip + assert_equal(self.nodes[0].getbestblockhash(), blockhash_6) + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 6) + assert_equal(self.nodes[0].getblockchaininfo()['headers'], 7) + self.log.info("Verify that invalidating an unknown block throws an error") assert_raises_rpc_error(-5, "Block not found", self.nodes[1].invalidateblock, "00" * 32) assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])