The Bitcoin P2P protocol is comprised of messages over TCP. These messages are serialized using a custom format. Unlike RPC protocols, messages do not necessarily have a reply and there is no way to unambiguously connect a sent message to a reply, although many communications are often request/response pairs. High performance full node software may handle incoming messages in parallel, so it is not appropriate to assume a message reply order. Messages that cannot be fulfilled are sometimes dropped with no reply, and sometimes replied to via a REJECT message.
These legacy design decisions can make the protocol difficult to implement on the client side, but are generally needed when a robust implementation communicates with untrusted/uncooperative partners. A good strategy is to wait for any message that provides the required data, with a timeout, and then separately issue the request in a retry loop to multiple peers. If a timeout occurs, return to higher level software which should re-assess whether the data is still needed, since in nodes in the network may have converged to a competing block or transaction, and therefore not be serving the data you are requesting (nodes only serve data on the most-difficult chain, even if they have some data pertaining to lower-difficulty splits).
Bitcoin uses a custom serialization format that is generally little-endian.
The following table describes the message header:
network identifier | command | size | checksum | contents |
---|---|---|---|---|
0: 4 bytes | 4: 12 bytes | 16: 4 bytes | 20: 4 bytes | 24: size bytes |
BCH:E3,E1,F3,E8 BTC:F9,BE,B4,D9 tBCH:F4,E5,F3,F4 tBTC:0B,11,09,07 |
ascii null extended | little endian uint32 | little endian uint32 | depends on command |
The network identifier is used to separate blockchains and test networks. This reduces unnecessary load on peers, allowing them to rapidly ban nodes rather then forcing the peer to do a blockchain analysis before banning.
Unfortunately, the BCH and BSV blockchains use the same network identifier.
The command is the exact lowercase bytes in the titles of each subsection in the Message Types section below followed by zeros -- e.g. the INV message's command is literally the 12 bytes: 'i','n',v',0,0,0,0,0,0,0,0,0. This is not a "C" string. If a command was exactly 12 bytes, there would be no null terminator!
Size is the size of the contents field in bytes, not the size of the entire message.
This field is a message checksum. The checksum is calculated by first computing the double SHA256 of the contents portion of the message. The first 4 bytes of this hash is the checksum. See C++ generate, python verify, python generate.
Since TCP has message integrity checksums, and a peer can cause another node to waste processing power validating bad checksums, it is not recommended that nodes verify this checksum. That is, this field should be considered obsolete.
However, senders should calculate and fill this checksum field to be compatible with all software, unless the XVERSION message is used to tell peers that this checksum will not be verified (currently supported by Bitcoin Unlimited). In this case the field SHOULD be set to 0 (but not enforced as 0 on the receiver's side). This may allow a future reuse of this field.
The contents of messages are described in the next section.
Add a single item into an existing filter
Remove an existing filter
Inserts a transaction and merkle block filter into the peer
Notifies peers about the existence of some information (generally a block or transaction)
Communicates a change in peer capabilities
Requests block hash identifiers
Requests information (generally previously announced via an INV) from a peer
Requests block headers from a peer
Keep-alive
Describes peer capabilities
Describes peer capabilities in an extensible manner Currently supported by Bitcoin Unlimited only
Note that some of these "response" messages can also be sent without solicitation (i.e. without a request).
Provides a peer with the addresses of other peers
Provides a block
Provides a set of block headers (unsolicited or GETHEADERS response)
Provides a provable subset of a block's transactions, as filtered by FILTERADD
Reply to a ping message
General response by well-behaved clients if a message cannot be handled
Transaction object
Respond to a version message
Respond to an xversion message