Peer-to-Peer Network Protocol
The P2P protocol transports blocks, transactions, headers, addresses, filters, and relay-control messages between nodes. This section specifies interoperable wire behavior.
Message envelope
Legacy unencrypted Bitcoin P2P messages use a 24-byte header followed by a payload:
| Field | Type | Meaning |
|---|---|---|
start | byte[4] | Network magic identifying mainnet, testnet, signet, or regtest. |
command | byte[12] | ASCII command name padded with zero bytes. |
payloadSize | uint32 | Number of payload bytes. |
checksum | byte[4] | First four bytes of $H(payload)$. |
payload | byte[] | Command-specific serialized payload of length payloadSize. |
BIP324 defines an encrypted v2 transport that changes transport framing after negotiation, but command payload semantics remain command-specific (sources: bip-0324,bitcoin-core-v31).
Handshake
A connection becomes usable after version negotiation:
-
each side sends
version; -
each side validates network, protocol version, services, timestamp, nonce, and user-agent limits;
-
each side sends
verack; and -
optional relay, compact-block, address-relay, filter, and transport features are negotiated by later messages.
version field | Type | Meaning |
|---|---|---|
version | int32 | Protocol version offered by the sender. |
services | uint64 | Service bits offered by the sender. |
timestamp | int64 | Sender Unix time in seconds. |
addrRecv | network address | Address of the receiving peer as understood by the sender. |
addrFrom | network address | Address of the sender. |
nonce | uint64 | Random connection nonce used to detect self-connections. |
userAgent | string | BIP14 user-agent string. |
startHeight | int32 | Sender’s current best height estimate. |
relay | bool, optional | BIP37 transaction-inventory relay preference when present. |
Control and negotiation payloads
| Message | Payload | Meaning |
|---|---|---|
verack | empty | Completes version negotiation. |
sendheaders | empty | Requests direct headers announcements instead of block inventory announcements. |
wtxidrelay | empty | Negotiates transaction relay by witness transaction identifier. |
sendaddrv2 | empty | Negotiates BIP155 address relay. |
ping | uint64 nonce | Liveness probe. |
pong | uint64 nonce | Response echoing the received ping nonce. |
feefilter | uint64 feerate | Asks the peer not to announce transactions below the feerate in satoshis per 1000 virtual bytes. |
Service flags
| Flag | Bit | Meaning |
|---|---|---|
NODE_NETWORK | 0 | Peer can serve the full block chain. |
NODE_BLOOM | 2 | Peer supports BIP37 bloom-filter service. |
NODE_WITNESS | 3 | Peer supports witness transaction and block relay. |
NODE_COMPACT_FILTERS | 6 | Peer supports BIP157 compact block filter service. |
NODE_NETWORK_LIMITED | 10 | Peer can serve at least a limited recent block window. |
Service flags advertise capability. A node must still validate responses and apply local resource limits.
Inventory and object retrieval
Inventory relay announces objects by type and hash. A peer requests announced objects with getdata; the responder sends the corresponding object or a notfound response when unavailable.
| Record | Fields | Meaning |
|---|---|---|
InventoryVector | type:uint32, hash:uint256 | Identifies a transaction, block, filtered block, compact block, witness transaction, or witness block. |
inv | vector< InventoryVector> | Announces available objects. |
getdata | vector< InventoryVector> | Requests announced objects. |
notfound | vector< InventoryVector> | Reports requested objects not available from the responder. |
Witness inventory types request serialization that includes witness data. A peer that has not negotiated witness support must not rely on receiving witness objects from that connection (sources: bip-0144).
| Inventory type | Value | Object requested or announced |
|---|---|---|
MSG_TX | 1 | Transaction by txid. |
MSG_BLOCK | 2 | Block without requiring witness serialization. |
MSG_FILTERED_BLOCK | 3 | BIP37 filtered block. |
MSG_CMPCT_BLOCK | 4 | BIP152 compact block. |
MSG_WITNESS_TX | $2^30 + 1$ | Transaction including witness data, identified by txid request type with witness flag. |
MSG_WITNESS_BLOCK | $2^30 + 2$ | Block including witness data. |
MSG_FILTERED _WITNESS_BLOCK | $2^30 + 3$ | Filtered block including witness data. |
Header and block synchronization
Headers synchronize chain work before full block data. A locator is a sequence of block hashes, newest first, stepping back from a known tip toward genesis.
Messages getheaders and getblocks carry a locator and stop hash. Message headers returns block headers in forward order, each followed by CompactSize zero. Message block carries serialized full block data. A node must validate proof of work, linkage, target, timestamp, and deployment context for received headers before using them for chain selection.
| Record | Fields | Encoding rule |
|---|---|---|
BlockLocator | version, hashes | int32 version followed by vector<uint256> locator hashes. |
getheaders/ getblocks | version, locator, stopHash | int32, locator vector, then uint256 stop hash. |
headers item | header, txCount | 80-byte block header followed by CompactSize zero. A nonzero count is invalid for headers. |
Compact block relay
BIP152 compact blocks reduce block-relay bandwidth by sending a header, short transaction identifiers, selected prefilled transactions, and requesting any missing transactions (sources: bip-0152).
Message sendcmpct negotiates compact-block mode and announcement preference. Messages cmpctblock, getblocktxn, and blocktxn carry the compact block and missing-transaction exchange. Compact reconstruction is an optimization only. The reconstructed full block must pass the same block validation rules as any received block message.
| Record | Fields | Encoding rule |
|---|---|---|
Compact Block | header, nonce, shortIds, prefilledTx | Header, uint64 nonce, CompactSize count plus 6-byte short ids, then vector<PrefilledTx>. |
PrefilledTx | indexDelta, tx | CompactSize differential index from the previous prefilled transaction, then full transaction. |
getblocktxn | blockHash, indexes | Block hash followed by CompactSize differential transaction indexes. |
blocktxn | blockHash, transactions | Block hash followed by transaction vector. |
Address relay
Legacy address records and BIP155 address records use different encodings:
| Record | Fields | Encoding rule |
|---|---|---|
NetAddress NoTime | services, address, port | uint64 services, 16 address bytes, then uint16 port in big-endian network byte order. Used inside version. |
NetAddress Legacy | time, services, address, port | uint32 time plus NetAddressNoTime. Used by addr. |
AddrV2 | time, services, networkId, address, port | uint32 time, CompactSize services, uint8 network id, CompactSize address length, address bytes, then big-endian port. |
Messages addr and addrv2 relay legacy and BIP155 address records. Message sendaddrv2 announces BIP155 address-relay support, and getaddr requests known peer addresses subject to local rate limits. Address relay is unauthenticated gossip. Received addresses are hints, not validated reachability claims (sources: bip-0155).
Light-client services
Bitcoin P2P includes two optional light-client service families:
| Service | Messages | Status |
|---|---|---|
| BIP37 bloom filters | filterload, filteradd, filterclear, merkleblock | Optional peer service; disabled unless a node chooses to provide bloom-filter support. |
| BIP157/158 compact filters | getcfilters, cfilter, getcfheaders, cfheaders, getcfcheckpt, cfcheckpt | Optional compact-filter service for clients that verify filters against block-filter headers. |
These services do not change block or transaction validity (sources: bip-0037,bip-0157,bip-0158).
| Message | Payload fields | Encoding rule |
|---|---|---|
filterload | filter, hashFuncs, tweak, flags | varbytes, uint32, uint32, uint8. |
filteradd | data | varbytes. |
filterclear | empty | Clears the peer’s BIP37 filter state. |
merkleblock | header, total, hashes, flags | Block header, uint32 total transactions, vector<uint256> hashes, and flag bytes. |
getcfilters | type, startHeight, stopHash | uint8, uint32, uint256. |
cfilter | type, blockHash, filter | uint8, uint256, varbytes. |
getcfheaders | type, startHeight, stopHash | uint8, uint32, uint256. |
cfheaders | type, stopHash, prevHeader, filterHashes | uint8, two uint256 values, then vector<uint256>. |
getcfcheckpt | type, stopHash | uint8, uint256. |
cfcheckpt | type, stopHash, headers | uint8, uint256, vector<uint256>. |