TeachMeBitcoin

The P2P Version Message Payload

From TeachMeBitcoin, the free encyclopedia ⏱️ 3 min read

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_t Nonce during startup. * This Nonce is included in every outgoing version packet. * If an incoming version packet contains the node’s own active Nonce, it detects the self-connection and closes the socket immediately.

☕ Help support TeachMeBitcoin

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:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!