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

Code before:
        comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
        msg = msg_cmpctblock(comp_block.to_p2p())
        test_node.send_and_ping(msg)

        # Check that the tip didn't advance
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

        # Re-establish a proper witness commitment with the coinbase witness, but
        # invalidate the last tx in the block.
        block.vtx[4].vin[0].scriptSig = CScript([OP_RETURN])
        block.hashMerkleRoot = block.calc_merkle_root()
        add_witness_commitment(block)
        block.solve()

        # This will lead to a consensus failure for which we also won't be disconnected but which
        # will be cached.
        comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
        msg = msg_cmpctblock(comp_block.to_p2p())
        test_node.send_and_ping(msg)

        # The tip still didn't advance.
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

        # The failure above was cached. Submitting the compact block again will returned a cached
        # consensus error (the code path is different) and still not get us disconnected (nor
        # advance the tip).
        test_node.send_and_ping(msg)
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

    # Helper for enabling cb announcements
    # Send the sendcmpct request and sync headers
    def request_cb_announcements(self, peer):
        node = self.nodes[0]
        tip = node.getbestblockhash()
        peer.get_headers(locator=[int(tip, 16)], hashstop=0)
        peer.send_and_ping(msg_sendcmpct(announce=True, version=2))

    def test_compactblock_reconstruction_stalling_peer(self, stalling_peer, delivery_peer):
        node = self.nodes[0]
        assert len(self.utxos)

        def announce_cmpct_block(node, peer):
            utxo = self.utxos.pop(0)
            block = self.build_block_with_transactions(node, utxo, 5)

            cmpct_block = HeaderAndShortIDs()
            cmpct_block.initialize_from_block(block)
            msg = msg_cmpctblock(cmpct_block.to_p2p())

Review comment (bug):
Small nit

```suggestion 
        # The failure above was cached. Submitting the compact block again will return a cached
```

Code after:
        comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
        msg = msg_cmpctblock(comp_block.to_p2p())
        test_node.send_and_ping(msg)

        # Check that the tip didn't advance
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

        # Re-establish a proper witness commitment with the coinbase witness, but
        # invalidate the last tx in the block.
        block.vtx[4].vin[0].scriptSig = CScript([OP_RETURN])
        block.hashMerkleRoot = block.calc_merkle_root()
        add_witness_commitment(block)
        block.solve()

        # This will lead to a consensus failure for which we also won't be disconnected but which
        # will be cached.
        comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
        msg = msg_cmpctblock(comp_block.to_p2p())
        test_node.send_and_ping(msg)

        # The tip still didn't advance.
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

        # The failure above was cached. Submitting the compact block again will returned a cached
        # consensus error (the code path is different) and still not get us disconnected (nor
        # advance the tip).
        test_node.send_and_ping(msg)
        assert_not_equal(node.getbestblockhash(), block.hash_hex)
        test_node.sync_with_ping()

        # Now, announcing a second block building on top of the invalid one will get us disconnected.
        block.hashPrevBlock = block.hash_int
        block.solve()
        comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
        msg = msg_cmpctblock(comp_block.to_p2p())
        test_node.send_await_disconnect(msg)

    # Helper for enabling cb announcements
    # Send the sendcmpct request and sync headers
    def request_cb_announcements(self, peer):
        node = self.nodes[0]
        tip = node.getbestblockhash()
        peer.get_headers(locator=[int(tip, 16)], hashstop=0)
        peer.send_and_ping(msg_sendcmpct(announce=True, version=2))

    def test_compactblock_reconstruction_stalling_peer(self, stalling_peer, delivery_peer):
        node = self.nodes[0]
        assert len(self.utxos)