Repository: bitcoin/bitcoin
File: test/functional/feature_assumevalid.py (Python)

Code before:
        height += 1

        # Bury the assumed valid block 2100 deep
        for _ in range(2100):
            block = create_block(self.tip, create_coinbase(height), self.block_time)
            block.solve()
            self.blocks.append(block)
            self.tip = block.hash_int
            self.block_time += 1
            height += 1

        # Start node1 and node2 with assumevalid so they accept a block with a bad signature.
        self.start_node(1, extra_args=["-assumevalid=" + block102.hash_hex])
        self.start_node(2, extra_args=["-assumevalid=" + block102.hash_hex])

        p2p0 = self.nodes[0].add_p2p_connection(BaseNode())
        p2p0.send_header_for_blocks(self.blocks[0:2000])
        p2p0.send_header_for_blocks(self.blocks[2000:])

        # Send blocks to node0. Block 102 will be rejected.
        self.send_blocks_until_disconnected(p2p0)
        self.wait_until(lambda: self.nodes[0].getblockcount() >= COINBASE_MATURITY + 1)
        assert_equal(self.nodes[0].getblockcount(), COINBASE_MATURITY + 1)

        p2p1 = self.nodes[1].add_p2p_connection(BaseNode())
        p2p1.send_header_for_blocks(self.blocks[0:2000])
        p2p1.send_header_for_blocks(self.blocks[2000:])
        with self.nodes[1].assert_debug_log(expected_msgs=['Disabling signature validations at block #1', 'Enabling signature validations at block #103']):
            # Send all blocks to node1. All blocks will be accepted.
            for i in range(2202):
                p2p1.send_without_ping(msg_block(self.blocks[i]))
            # Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync.
            p2p1.sync_with_ping(timeout=960)
        assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202)

        p2p2 = self.nodes[2].add_p2p_connection(BaseNode())
        p2p2.send_header_for_blocks(self.blocks[0:200])

        # Send blocks to node2. Block 102 will be rejected.
        self.send_blocks_until_disconnected(p2p2)
        self.wait_until(lambda: self.nodes[2].getblockcount() >= COINBASE_MATURITY + 1)
        assert_equal(self.nodes[2].getblockcount(), COINBASE_MATURITY + 1)


if __name__ == '__main__':
    AssumeValidTest(__file__).main()


Review comment (bug):
Could be more precise in that these strings are on the same log line:
```diff
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 544edfdb99..9ebaddb74f 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -150,8 +150,9 @@ class AssumeValidTest(BitcoinTestFramework):
         p2p0.send_header_for_blocks(self.blocks[2000:])
 
         # Send blocks to node0. Block 102 will be rejected.
-        with self.nodes[0].assert_debug_log(expected_msgs=['Enabling signature validations at block #1',
-                                                           'assumevalid=0 (always verify)']):  # AssumeValid::CHECKED
+        block_1_hash = self.blocks[0].hash_hex
+        with self.nodes[0].assert_debug_log(expected_msgs=[f'Enabling signature validations at block #1 ({block_1_hash}): assumevalid=0 (always verify)',  # AssumeValid::CHECKED
+                                                           'Block validation error: block-script-verify-flag-failed']):
             self.send_blocks_until_disconnected(p2p0)
             self.wait_until(lambda: self.nodes[0].getblockcount() >= COINBASE_MATURITY + 1)
         assert_equal(self.nodes[0].getblockcount(), COINBASE_MATURITY + 1)
@@ -162,8 +163,7 @@ class AssumeValidTest(BitcoinTestFramework):
         p2p1.send_header_for_blocks(self.blocks[0:2000])
         p2p1.send_header_for_blocks(self.blocks[2000:])
         with self.nodes[1].assert_debug_log(expected_msgs=['Disabling signature validations at block #1',  # AssumeValid::SKIPPED
-                                                           'Enabling signature validations at block #103',
-                                                           'block not part of assumevalid chain']):  # AssumeValid::CHECKED_NOT_UNDER_ASSUMEVALID
+                                                           f'Enabling signature validations at block #103 ({self.blocks[102].hash_hex}): block not part of assumevalid chain']):  # AssumeValid::CHECKED_NOT_UNDER_ASSUMEVALID
             # Send all blocks to node1. All blocks will be accepted.
             for i in range(2202):
                 p2p1.send_without_ping(msg_block(self.blocks[i]))
@@ -177,8 +177,8 @@ class AssumeValidTest(BitcoinTestFramework):
         p2p2.send_header_for_blocks(self.blocks[0:200])
 
         # Send blocks to node2. Block 102 will be rejected.
-        with self.nodes[2].assert_debug_log(expected_msgs=["Enabling signature validations at block #1",
-                                                           "too recent relative to best header"]):  # AssumeValid::CHECKED_NOT_BURIED_ENOUGH
+        with self.nodes[2].assert_debug_log(expected_msgs=[f"Enabling signature validations at block #1 ({block_1_hash}): too recent relative to best header",  # AssumeValid::CHECKED_NOT_BURIED_ENOUGH
+                                                           "Block validation error: block-script-verify-flag-failed"]):
             self.send_blocks_until_disconnected(p2p2)
             self.wait_until(lambda: self.nodes[2].getblockcount() >= COINBASE_MATURITY + 1)
         assert_equal(self.nodes[2].getblockcount(), COINBASE_MATURITY + 1)
@@ -191,13 +191,11 @@ class AssumeValidTest(BitcoinTestFramework):
         self.wait_until(lambda: self.nodes[3].getblockcount())
 
         # Reindex to deterministically hit specific assumevalid gates (no races with header downloads/chainwork during startup).
-        with self.nodes[3].assert_debug_log(expected_msgs=["Enabling signature validations at block #1",
-                                                           "assumevalid hash not in headers"]):  # AssumeValid::CHECKED_HASH_NOT_IN_HEADERS
+        with self.nodes[3].assert_debug_log(expected_msgs=[f"Enabling signature validations at block #1 ({block_1_hash}): assumevalid hash not in headers"]):  # AssumeValid::CHECKED_HASH_NOT_IN_HEADERS
             self.restart_node(3, extra_args=["-reindex-chainstate", "-assumevalid=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"])
         assert_equal(self.nodes[3].getblockcount(), 1)
 
-        with self.nodes[3].assert_debug_log(expected_msgs=["Enabling signature validations at block #1",
-                                                           "best header chainwork below minimumchainwork"]):  # AssumeValid::CHECKED_BELOW_MIN_CHAINWORK
+        with self.nodes[3].assert_debug_log(expected_msgs=[f"Enabling signature validations at block #1 ({block_1_hash}): best header chainwork below minimumchainwork"]):  # AssumeValid::CHECKED_BELOW_MIN_CHAINWORK
             self.restart_node(3, extra_args=["-reindex-chainstate", "-assumevalid=" + block102.hash_hex, "-minimumchainwork=0xffff"])
         assert_equal(self.nodes[3].getblockcount(), 1)
 
```
(Also adds check for "Block validation error").

Code after:
        self.block_time += 1
        block102.solve()
        self.blocks.append(block102)
        self.tip = block102.hash_int
        self.block_time += 1
        height += 1

        # Bury the assumed valid block 2100 deep
        for _ in range(2100):
            block = create_block(self.tip, create_coinbase(height), self.block_time)
            block.solve()
            self.blocks.append(block)
            self.tip = block.hash_int
            self.block_time += 1
            height += 1
        block_1_hash = self.blocks[0].hash_hex

        self.start_node(1, extra_args=[f"-assumevalid={block102.hash_hex}"])
        self.start_node(2, extra_args=[f"-assumevalid={block102.hash_hex}"])
        self.start_node(3, extra_args=[f"-assumevalid={block102.hash_hex}"])
        self.start_node(4, extra_args=[f"-assumevalid={block102.hash_hex}"])
        self.start_node(5)


        # nodes[0]
        # Send blocks to node0. Block 102 will be rejected.
        with self.nodes[0].assert_debug_log(expected_msgs=[
            f"Enabling script verification at block #1 ({block_1_hash}): assumevalid=0 (always verify).",
            "Block validation error: block-script-verify-flag-failed",
        ]):
            p2p0 = self.nodes[0].add_p2p_connection(BaseNode())

            p2p0.send_header_for_blocks(self.blocks[0:2000])
            p2p0.send_header_for_blocks(self.blocks[2000:])

            self.send_blocks_until_disconnected(p2p0)
            self.wait_until(lambda: self.nodes[0].getblockcount() >= COINBASE_MATURITY + 1)
            assert_equal(self.nodes[0].getblockcount(), COINBASE_MATURITY + 1)


        # nodes[1]
        with self.nodes[1].assert_debug_log(expected_msgs=[
            f"Disabling script verification at block #1 ({self.blocks[0].hash_hex}).",
            f"Enabling script verification at block #103 ({self.blocks[102].hash_hex}): block height above assumevalid height.",
        ]):
            p2p1 = self.nodes[1].add_p2p_connection(BaseNode())

            p2p1.send_header_for_blocks(self.blocks[0:2000])
            p2p1.send_header_for_blocks(self.blocks[2000:])
            # Send all blocks to node1. All blocks will be accepted.
            for i in range(2202):