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

Code before:
        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 (suggestion):
It feels a bit lacking to have `CHECKED_NOT_UNDER_ASSUMEVALID` when the block is based upon the assumevalid block. Would expect something like `CHECKED_EXCEEDS_ASSUMEVALID`. For *validation.cpp*:
```C++
        } else if (it->second.nHeight < pindex->nHeight) {
            assume_valid = CHECKED_EXCEEDS_ASSUMEVALID;
        } else if (it->second.GetAncestor(pindex->nHeight) != pindex) {
            assume_valid = CHECKED_NOT_UNDER_ASSUMEVALID;
```

Code after:
            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):
                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)


        # nodes[2]
        # Send blocks to node2. Block 102 will be rejected.
        with self.nodes[2].assert_debug_log(expected_msgs=[
            f"Enabling script verification at block #1 ({block_1_hash}): block too recent relative to best header.",
            "Block validation error: block-script-verify-flag-failed",
        ]):