diff --git a/test/functional/abc-finalize-block.py b/test/functional/abc-finalize-block.py --- a/test/functional/abc-finalize-block.py +++ b/test/functional/abc-finalize-block.py @@ -9,6 +9,7 @@ from test_framework.util import assert_equal, assert_raises_rpc_error, connect_nodes_bi, sync_blocks, wait_until RPC_FINALIZE_INVALID_BLOCK_ERROR = 'finalize-invalid-block' +RPC_FORK_PRIOR_FINALIZED_ERROR = 'bad-fork-prior-finalized' RPC_BLOCK_NOT_FOUND_ERROR = 'Block not found' AUTO_FINALIZATION_DEPTH = 10 @@ -37,13 +38,14 @@ tip = node.getbestblockhash() node.finalizeblock(tip) assert_equal(node.getbestblockhash(), tip) + assert_equal(node.getfinalizedblockhash(), tip) alt_node = self.nodes[1] connect_nodes_bi(self.nodes, 0, 1) sync_blocks(self.nodes[0:2]) alt_node.invalidateblock(tip) - # We will use this later to check auto-finalization during a reorg + # We will use this later fork_block = alt_node.getbestblockhash() # Node 0 should not accept the whole alt_node's chain due to tip being finalized, @@ -78,7 +80,6 @@ # First block header is accepted as valid-header alt_node.generate(1) - alt_210 = alt_node.getbestblockhash() wait_for_block(node, alt_node.getbestblockhash(), "valid-headers") # Second block header is accepted but set invalid @@ -92,6 +93,9 @@ assert_raises_rpc_error(-5, RPC_BLOCK_NOT_FOUND_ERROR, node.getblockheader, alt_node.getbestblockhash()) + assert_equal(node.getbestblockhash(), tip) + assert_equal(node.getfinalizedblockhash(), tip) + self.log.info("Test that an invalid block cannot be finalized...") assert_raises_rpc_error(-20, RPC_FINALIZE_INVALID_BLOCK_ERROR, node.finalizeblock, invalid_block) @@ -141,50 +145,66 @@ alt_node.generate(1) sync_blocks(self.nodes[0:2]) + alt_node_tip = alt_node.getbestblockhash() assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) assert_equal(node.getfinalizedblockhash(), fork_block) assert_equal(alt_node.getfinalizedblockhash(), fork_block) self.log.info("Trigger reorg via block finalization...") - # Finalize node tip to reorg + # Generate some more blockes on alt_node. Auto-finalization will occur on + # both chains. # # Expected state: # # On alt_node: - # >(210)->(211)-> // ->(218)->(219 tip) - # / - # (200)->(201)-> // ->(209 auto-finalized)->(210 invalid) + # >(210)->(211)-> // ->(219 auto-finalized)-> // ->(229 tip) + # / + # (200)->(201)-> // ->(209)->(210 invalid) # # On node: - # >(210 invalid)-> // ->(219 invalid) + # >(210)->(211)-> // ->(219 auto-finalized)-> // ->(229 tip) # / - # (200)->(201)-> // ->(209)->(210 finalized, tip) - node.finalizeblock(tip) - assert_equal(node.getfinalizedblockhash(), tip) + # (200)->(201)-> // ->(209)->(210 invalid) + for i in range(10): + alt_node.generate(1) + sync_blocks(self.nodes[0:2]) + + assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) + assert_equal(node.getfinalizedblockhash(), alt_node_tip) + assert_equal(alt_node.getfinalizedblockhash(), alt_node_tip) self.log.info("Try to finalize a block on a competiting fork...") - assert_raises_rpc_error(-20, RPC_FINALIZE_INVALID_BLOCK_ERROR, - node.finalizeblock, alt_node.getbestblockhash()) - assert node.getfinalizedblockhash() != alt_node.getbestblockhash(), \ - "Finalized block should not be alt_node's tip!" + # Finalizing the tip should not be allowed, because it would + # fork before a finalized block + assert_raises_rpc_error(-20, RPC_FORK_PRIOR_FINALIZED_ERROR, + node.finalizeblock, tip) + assert node.getfinalizedblockhash() != tip, \ + "Finalization should not occur: a competing chain is already finalized" + + self.log.info( + "Try to finalize a block on an already finalized chain...") + # Finalizing a block of an already finalized chain should have no effect + block_218 = node.getblockheader(alt_node_tip)['previousblockhash'] + node.finalizeblock(block_218) + assert_equal(node.getfinalizedblockhash(), alt_node_tip) self.log.info( "Make sure reconsidering block move the finalization point...") - # Reconsidering alt_node tip will move finalized block on node + # Reconsidering the tip will move back the finalized block on node # # Expected state: # # On alt_node: - # >(210)->(211)-> // ->(218)->(219 tip) - # / - # (200)->(201)-> // ->(209 auto-finalized)->(210 invalid) + # >(210)->(211)-> // ->(219 auto-finalized)-> // ->(229 tip) + # / + # (200)->(201)-> // ->(209)->(210 invalid) # # On node: - # >(210)-> // ->(219 tip) + # >(210)->(211)-> // ->(219)-> // ->(229 tip) # / # (200)->(201)-> // ->(209 finalized)->(210) - node.reconsiderblock(alt_node.getbestblockhash()) + node.reconsiderblock(tip) assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) assert_equal(node.getfinalizedblockhash(), fork_block)