The P2P Version Message: Byte Layout and Payload Specifications
The P2P Version Message: Byte Layout and Payload Specifications
The version message is the foundational payload that initiating peers transmit upon opening a TCP connection. It acts as the negotiation contract, detailing the node’s protocol capabilities, system time, network addresses, user-agent details, and block synchronization heights.
This guide details the complete byte serialization layout and field specifications of the standard version message payload.
1. The Serialization Blueprint
The version payload contains 11 distinct fields, varying in size. Below is the precise sequential schema:
| Offset (Bytes) | Field Name | Data Type | Endianness | Description |
|---|---|---|---|---|
0 - 3 |
Version | int32_t |
Little Endian | Identifies the protocol version (e.g., 70016). |
4 - 11 |
Services | uint64_t |
Little Endian | Bitfield of service capabilities (e.g., NODE_NETWORK = 1). |
12 - 19 |
Timestamp | int64_t |
Little Endian | Epoch system timestamp in seconds of the sending node. |
20 - 45 |
Addr Recv | net_addr |
Big Endian | Network address details of the receiving node (peer). |
46 - 71 |
Addr From | net_addr |
Big Endian | Network address details of the sending node (self). |
72 - 79 |
Nonce | uint64_t |
Little Endian | Cryptographic random number to identify self-connections. |
80 - ? |
User Agent | var_str |
Raw (ASCII) | The name of the client software (e.g., /Satoshi:25.0.0/). |
? - ? |
Start Height | int32_t |
Little Endian | Current active tip block height of the sending node. |
? |
Relay | bool |
Raw | Flag (0 or 1) indicating if node should receive unconfirmed txs. |
2. Detailed Field Analysis
A. Network Address Serialization (net_addr)
To support unified IPv4 and IPv6 networks inside a standard schema, net addresses are always serialized as 26-byte structs:
-
Services:
8 Bytes(uint64, little-endian) outlining recipient capabilities. -
IP Address:
16 Bytes(big-endian). -
Port:
2 Bytes(uint16, big-endian network byte order).
IPv4-to-IPv6 Mapping Format
IPv4 addresses are padded inside the 16-byte IP field using the standard mapping syntax:
-
First 10 bytes: set to
\x00 -
Next 2 bytes: set to
\xFF\xFF -
Last 4 bytes: the actual IPv4 address.
$$\text{IPv4 Mapping: } \underbrace{\texttt{00 00 ... 00}}{10\text{ bytes}} \underbrace{\texttt{FF FF}}{2\text{ bytes}} \underbrace{\text{IP Address}}_{4\text{ bytes}}$$
For example, 127.0.0.1 is serialized as:
$$\texttt{00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01}$$
B. User Agent Variable String (var_str)
The User Agent is stored as a variable-length string. It starts with a CompactSize integer (1–9 bytes) defining the length of the string, followed by the ASCII characters.
For example, the string /Satoshi:25.0.0/ is 16 bytes:
-
Length:
0x10(16) -
Value (Hex):
2f 53 61 74 6f 73 68 69 3a 32 35 2e 30 2e 30 2f
C. Self-Connection Detection via Nonce
When a node broadcasts its IP, it might accidentally initiate a connection to itself. To prevent infinite loops:
-
The node generates a cryptographically secure random
uint64_tNonce during startup. -
This Nonce is included in every outgoing
versionpacket. -
If an incoming
versionpacket contains the node’s own active Nonce, it detects the self-connection and closes the socket immediately.
TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation: