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

Code before:
            cltv_invalidate(spendtx, i)

            expected_cltv_reject_reason = [
                "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)",
                "mandatory-script-verify-flag-failed (Negative locktime)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
            ][i]
            # First we show that this tx is valid except for CLTV by getting it
            # rejected from the mempool for exactly that reason.
            assert_equal(
                [{
                    'txid': spendtx.hash,
                    'wtxid': spendtx.getwtxid(),
                    'allowed': False,
                    'reject-reason': expected_cltv_reject_reason,
                }],
                self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0),
            )

            # Now we verify that a block with this transaction is also invalid.
            block.vtx[1] = spendtx
            block.hashMerkleRoot = block.calc_merkle_root()
            block.solve()

            with self.nodes[0].assert_debug_log(expected_msgs=[f'CheckInputScripts on {block.vtx[-1].hash} failed with {expected_cltv_reject_reason}']):
                peer.send_and_ping(msg_block(block))
                assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
                peer.sync_with_ping()

        self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
        cltv_validate(spendtx, CLTV_HEIGHT - 1)

        block.vtx.pop(1)
        block.vtx.append(spendtx)
        block.hashMerkleRoot = block.calc_merkle_root()
        block.solve()

        self.test_cltv_info(is_active=True)  # Not active as of current tip, but next block must obey rules
        peer.send_and_ping(msg_block(block))
        self.test_cltv_info(is_active=True)  # Active as of current tip
        assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)


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


Review comment (bug):
asserting on logging is subpar I know, but we could do tighter assertions now if we want to check we're formatting properly:
```
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index 557fcc7cea..220a6f8b25 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -172,11 +172,13 @@ class BIP65Test(BitcoinTestFramework):
             # Now we verify that a block with this transaction is also invalid.
             block.vtx[1] = spendtx
             block.hashMerkleRoot = block.calc_merkle_root()
             block.solve()
 
-            with self.nodes[0].assert_debug_log(expected_msgs=[f'Block validation error: {expected_cltv_reject_reason}']):
+            input_idx = 0
+            expanded_expected_cltv_reject_reason = f"{expected_cltv_reject_reason}, input {input_idx} of {spendtx.hash}, spending {spendtx.vin[input_idx].prevout.hash:064x}:{spendtx.vin[input_idx].prevout.n}"
+            with self.nodes[0].assert_debug_log(expected_msgs=[f'Block validation error: {expanded_expected_cltv_reject_reason}']):
                 peer.send_and_ping(msg_block(block))
                 assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
                 peer.sync_with_ping()
 
         self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
```

Code after:

            expected_cltv_reject_reason = [
                "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)",
                "mandatory-script-verify-flag-failed (Negative locktime)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
                "mandatory-script-verify-flag-failed (Locktime requirement not satisfied)",
            ][i]
            # First we show that this tx is valid except for CLTV by getting it
            # rejected from the mempool for exactly that reason.
            assert_equal(
                [{
                    'txid': spendtx.hash,
                    'wtxid': spendtx.getwtxid(),
                    'allowed': False,
                    'reject-reason': expected_cltv_reject_reason,
                }],
                self.nodes[0].testmempoolaccept(rawtxs=[spendtx.serialize().hex()], maxfeerate=0),
            )

            # Now we verify that a block with this transaction is also invalid.
            block.vtx[1] = spendtx
            block.hashMerkleRoot = block.calc_merkle_root()
            block.solve()

            with self.nodes[0].assert_debug_log(expected_msgs=[f'Block validation error: {expected_cltv_reject_reason}']):
                peer.send_and_ping(msg_block(block))
                assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
                peer.sync_with_ping()

        self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
        cltv_validate(spendtx, CLTV_HEIGHT - 1)

        block.vtx.pop(1)
        block.vtx.append(spendtx)
        block.hashMerkleRoot = block.calc_merkle_root()
        block.solve()

        self.test_cltv_info(is_active=True)  # Not active as of current tip, but next block must obey rules
        peer.send_and_ping(msg_block(block))
        self.test_cltv_info(is_active=True)  # Active as of current tip
        assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)


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