Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-finalize-block.py
Show All 20 Lines | |||||
class FinalizeBlockTest(BitcoinTestFramework): | class FinalizeBlockTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 3 | self.num_nodes = 3 | ||||
self.extra_args = [["-finalizationdelay=0"], | self.extra_args = [["-finalizationdelay=0"], | ||||
["-finalizationdelay=0"], []] | ["-finalizationdelay=0"], []] | ||||
self.finalization_delay = 2 * 60 * 60 | self.finalization_delay = 2 * 60 * 60 | ||||
def skip_test_if_missing_module(self): | |||||
self.skip_if_no_wallet() | |||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
self.mocktime = int(time.time()) | self.mocktime = int(time.time()) | ||||
self.log.info("Test block finalization...") | self.log.info("Test block finalization...") | ||||
node.generate(10) | node.generatetoaddress(10, node.get_deterministic_priv_key().address) | ||||
tip = node.getbestblockhash() | tip = node.getbestblockhash() | ||||
node.finalizeblock(tip) | node.finalizeblock(tip) | ||||
assert_equal(node.getbestblockhash(), tip) | assert_equal(node.getbestblockhash(), tip) | ||||
assert_equal(node.getfinalizedblockhash(), tip) | assert_equal(node.getfinalizedblockhash(), tip) | ||||
def wait_for_tip(node, tip): | def wait_for_tip(node, tip): | ||||
def check_tip(): | def check_tip(): | ||||
return node.getbestblockhash() == tip | return node.getbestblockhash() == tip | ||||
Show All 32 Lines | def run_test(self): | ||||
for tip in node.getchaintips(): | for tip in node.getchaintips(): | ||||
if tip["hash"] == block: | if tip["hash"] == block: | ||||
assert tip["status"] != "active" | assert tip["status"] != "active" | ||||
return tip["status"] == status | return tip["status"] == status | ||||
return False | return False | ||||
wait_until(check_block) | wait_until(check_block) | ||||
# First block header is accepted as valid-header | # First block header is accepted as valid-header | ||||
alt_node.generate(1) | alt_node.generatetoaddress( | ||||
1, alt_node.get_deterministic_priv_key().address) | |||||
wait_for_block(node, alt_node.getbestblockhash(), "valid-headers") | wait_for_block(node, alt_node.getbestblockhash(), "valid-headers") | ||||
# Second block header is accepted but set invalid | # Second block header is accepted but set invalid | ||||
alt_node.generate(1) | alt_node.generatetoaddress( | ||||
1, alt_node.get_deterministic_priv_key().address) | |||||
invalid_block = alt_node.getbestblockhash() | invalid_block = alt_node.getbestblockhash() | ||||
wait_for_block(node, invalid_block) | wait_for_block(node, invalid_block) | ||||
# Later block headers are rejected | # Later block headers are rejected | ||||
for i in range(2, 9): | for i in range(2, 9): | ||||
alt_node.generate(1) | alt_node.generatetoaddress( | ||||
1, alt_node.get_deterministic_priv_key().address) | |||||
assert_raises_rpc_error(-5, RPC_BLOCK_NOT_FOUND_ERROR, | assert_raises_rpc_error(-5, RPC_BLOCK_NOT_FOUND_ERROR, | ||||
node.getblockheader, alt_node.getbestblockhash()) | node.getblockheader, alt_node.getbestblockhash()) | ||||
assert_equal(node.getbestblockhash(), tip) | assert_equal(node.getbestblockhash(), tip) | ||||
assert_equal(node.getfinalizedblockhash(), tip) | assert_equal(node.getfinalizedblockhash(), tip) | ||||
self.log.info("Test that an invalid block cannot be finalized...") | self.log.info("Test that an invalid block cannot be finalized...") | ||||
assert_raises_rpc_error(-20, RPC_FINALIZE_INVALID_BLOCK_ERROR, | assert_raises_rpc_error(-20, RPC_FINALIZE_INVALID_BLOCK_ERROR, | ||||
Show All 37 Lines | def run_test(self): | ||||
# (200)->(201)-> // ->(209 auto-finalized)->(210 invalid) | # (200)->(201)-> // ->(209 auto-finalized)->(210 invalid) | ||||
# | # | ||||
# On node: | # On node: | ||||
# >(210)->(211)->(212)-> // ->(218)->(219 tip) | # >(210)->(211)->(212)-> // ->(218)->(219 tip) | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209 finalized)->(210) | # (200)->(201)-> // ->(209 finalized)->(210) | ||||
node.reconsiderblock(invalid_block) | node.reconsiderblock(invalid_block) | ||||
alt_node_tip = alt_node.generate(1)[-1] | alt_node_tip = alt_node.generatetoaddress( | ||||
1, alt_node.get_deterministic_priv_key().address)[-1] | |||||
wait_for_tip(node, alt_node_tip) | wait_for_tip(node, alt_node_tip) | ||||
assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) | assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) | ||||
assert_equal(node.getfinalizedblockhash(), fork_block) | assert_equal(node.getfinalizedblockhash(), fork_block) | ||||
assert_equal(alt_node.getfinalizedblockhash(), fork_block) | assert_equal(alt_node.getfinalizedblockhash(), fork_block) | ||||
self.log.info("Trigger reorg via block finalization...") | self.log.info("Trigger reorg via block finalization...") | ||||
# Finalize node tip to reorg | # Finalize node tip to reorg | ||||
Show All 29 Lines | def run_test(self): | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209)->(210 invalid) | # (200)->(201)-> // ->(209)->(210 invalid) | ||||
# | # | ||||
# On node: | # On node: | ||||
# >(210)->(211)-> // ->(219 auto-finalized)-> // ->(229 tip) | # >(210)->(211)-> // ->(219 auto-finalized)-> // ->(229 tip) | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209)->(210 invalid) | # (200)->(201)-> // ->(209)->(210 invalid) | ||||
node.reconsiderblock(alt_node.getbestblockhash()) | node.reconsiderblock(alt_node.getbestblockhash()) | ||||
block_to_autofinalize = alt_node.generate(1)[-1] | block_to_autofinalize = alt_node.generatetoaddress( | ||||
alt_node_new_tip = alt_node.generate(9)[-1] | 1, alt_node.get_deterministic_priv_key().address)[-1] | ||||
alt_node_new_tip = alt_node.generatetoaddress( | |||||
9, alt_node.get_deterministic_priv_key().address)[-1] | |||||
wait_for_tip(node, alt_node_new_tip) | wait_for_tip(node, alt_node_new_tip) | ||||
assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) | assert_equal(node.getbestblockhash(), alt_node.getbestblockhash()) | ||||
assert_equal(node.getfinalizedblockhash(), alt_node_tip) | assert_equal(node.getfinalizedblockhash(), alt_node_tip) | ||||
assert_equal(alt_node.getfinalizedblockhash(), alt_node_tip) | assert_equal(alt_node.getfinalizedblockhash(), alt_node_tip) | ||||
self.log.info( | self.log.info( | ||||
"Try to finalize a block on an already finalized chain...") | "Try to finalize a block on an already finalized chain...") | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# (200)->(201)-> // ->(209)->(210 invalid) | # (200)->(201)-> // ->(209)->(210 invalid) | ||||
# | # | ||||
# On delay_node: | # On delay_node: | ||||
# >(220 auto-finalized)-> // ->(230 tip) | # >(220 auto-finalized)-> // ->(230 tip) | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209)->(210) | # (200)->(201)-> // ->(209)->(210) | ||||
self.mocktime += self.finalization_delay | self.mocktime += self.finalization_delay | ||||
set_node_times([delay_node], self.mocktime) | set_node_times([delay_node], self.mocktime) | ||||
new_tip = alt_node.generate(1)[-1] | new_tip = alt_node.generatetoaddress( | ||||
1, alt_node.get_deterministic_priv_key().address)[-1] | |||||
wait_for_tip(delay_node, new_tip) | wait_for_tip(delay_node, new_tip) | ||||
assert_equal(alt_node.getbestblockhash(), new_tip) | assert_equal(alt_node.getbestblockhash(), new_tip) | ||||
assert_equal(node.getfinalizedblockhash(), block_to_autofinalize) | assert_equal(node.getfinalizedblockhash(), block_to_autofinalize) | ||||
assert_equal(alt_node.getfinalizedblockhash(), block_to_autofinalize) | assert_equal(alt_node.getfinalizedblockhash(), block_to_autofinalize) | ||||
self.log.info( | self.log.info( | ||||
"Check that finalization delay is effective on node boot") | "Check that finalization delay is effective on node boot") | ||||
# Restart the new node, so the blocks have no header received time. | # Restart the new node, so the blocks have no header received time. | ||||
self.restart_node(2) | self.restart_node(2) | ||||
# There should be no finalized block (getfinalizedblockhash returns an | # There should be no finalized block (getfinalizedblockhash returns an | ||||
# empty string) | # empty string) | ||||
assert_equal(delay_node.getfinalizedblockhash(), str()) | assert_equal(delay_node.getfinalizedblockhash(), str()) | ||||
# Generate 20 blocks with no delay. This should not trigger auto-finalization. | # Generate 20 blocks with no delay. This should not trigger auto-finalization. | ||||
# | # | ||||
# Expected state: | # Expected state: | ||||
# | # | ||||
# On delay_node: | # On delay_node: | ||||
# >(220)-> // ->(250 tip) | # >(220)-> // ->(250 tip) | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209)->(210) | # (200)->(201)-> // ->(209)->(210) | ||||
blocks = delay_node.generate(20) | blocks = delay_node.generatetoaddress( | ||||
20, alt_node.get_deterministic_priv_key().address) | |||||
reboot_autofinalized_block = blocks[10] | reboot_autofinalized_block = blocks[10] | ||||
new_tip = blocks[-1] | new_tip = blocks[-1] | ||||
wait_for_tip(delay_node, new_tip) | wait_for_tip(delay_node, new_tip) | ||||
assert_equal(delay_node.getfinalizedblockhash(), str()) | assert_equal(delay_node.getfinalizedblockhash(), str()) | ||||
# Now let the finalization delay to expire, then generate one more block. | # Now let the finalization delay to expire, then generate one more block. | ||||
# This should resume auto-finalization. | # This should resume auto-finalization. | ||||
# | # | ||||
# Expected state: | # Expected state: | ||||
# | # | ||||
# On delay_node: | # On delay_node: | ||||
# >(220)-> // ->(241 auto-finalized)-> // ->(251 tip) | # >(220)-> // ->(241 auto-finalized)-> // ->(251 tip) | ||||
# / | # / | ||||
# (200)->(201)-> // ->(209)->(210) | # (200)->(201)-> // ->(209)->(210) | ||||
self.mocktime += self.finalization_delay | self.mocktime += self.finalization_delay | ||||
set_node_times([delay_node], self.mocktime) | set_node_times([delay_node], self.mocktime) | ||||
new_tip = delay_node.generate(1)[-1] | new_tip = delay_node.generatetoaddress( | ||||
1, delay_node.get_deterministic_priv_key().address)[-1] | |||||
wait_for_tip(delay_node, new_tip) | wait_for_tip(delay_node, new_tip) | ||||
assert_equal(delay_node.getfinalizedblockhash(), | assert_equal(delay_node.getfinalizedblockhash(), | ||||
reboot_autofinalized_block) | reboot_autofinalized_block) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
FinalizeBlockTest().main() | FinalizeBlockTest().main() |