Glossary / Developer reference
MSG_CMPCT_BLOCK
- Definition
- MSG_CMPCT_BLOCK, inventory type 4, is a request-only code: it never appears in an announcement and is legal only inside a getdata message sent to a peer that agreed to it first.
Specified in BIP-152.
Compact blocks are negotiated, not advertised. A peer sends sendcmpct once to say it will accept them, and only then may the other side answer a new block with type 4 rather than type 2. BIP152 arrived with Bitcoin Core 0.13.0 in August 2016, and the saving is the entire point: six bytes to name a transaction the receiver already holds, instead of the two hundred or more it takes to ship it twice.
How it works
MSG_CMPCT_BLOCK asks for a description of a block instead of the block, and the description is worth having only when the two nodes hold similar mempools.
Negotiation comes first. The sendcmpct message carries a flag and a version number: version 1 identifies transactions by txid, version 2 by witness txid and is the only one in use since segregated witness. A node must never put type 4 in a getdata to a peer that has not sent sendcmpct, because that peer is under no obligation to understand it.
The reply is a cmpctblock message holding the 80 byte header, an eight byte nonce, one six byte short identifier per transaction, and a handful of transactions supplied in full, always including the coinbase, which the receiver cannot possibly have seen already. Short identifiers are produced with SipHash keyed from the header and that nonce, so they differ for every block and every request. The randomization is a defense: a fixed scheme would let an attacker precompute two transactions that collide and jam reconstruction across the whole network at once.
The receiver matches identifiers against its mempool, asks for anything missing with getblocktxn, and rebuilds the block locally. Validation afterwards is ordinary, and no consensus rule is touched.
Depth is limited. Bitcoin Core serves a compact block only for the five most recent blocks and answers a request for anything older with a full block, because a receiver that far behind has no useful mempool and would end up asking for every transaction in it.
Where you see it
The clearest view of MSG_CMPCT_BLOCK is Bitcoin Core's own logging, which reports how well each reconstruction went.
Start the node with -debug=cmpctblock and every new block produces a line stating how many transactions were prefilled, how many were found in the mempool, and how many had to be fetched. On a machine that has been running for hours the fetched count is usually zero, and the block arrives as tens of kilobytes rather than a megabyte and a half. A block carrying 3,000 transactions needs 18,000 bytes of short identifiers plus the header and the coinbase.
That arithmetic collapses on a freshly started node. An empty mempool means every identifier misses, the follow-up request asks for the entire block, and the extra round trip makes the compact path slower than simply asking for the block outright. This is why the code belongs to nodes sitting at the tip and never appears during an initial sync.
For anyone running a node at home, this is the feature that decides whether an ordinary connection keeps pace with the network or falls behind each time a block is found.