For the complete documentation index, see llms.txt. This page is also available as Markdown.

SV Node Wire Protocol

Message framing and message types of the SV Node P2P wire protocol (non-consensus)

The reference node exchanges data with its peers over TCP using a message-based protocol descended from the original Bitcoin wire protocol. This page specifies the message framing, the connection handshake, the catalogue of message types, and the BSV-specific extensions that support unbounded block sizes and higher throughput.

Ground truth. The message framing, message-type names, protocol version, and size limits below derive from src/protocol.h and src/protocol.cpp, the protocol-version constants from src/version.h, and the network magic values from src/chainparams.cpp. The BSV-specific message extensions are also specified in the bitcoin-sv-specs/protocol documents referenced inline. All citations are pinned to release v1.2.2 (commit 879fc8b).

Conventions

  • Little-endian unless stated otherwise: integer header and payload fields are serialized least-significant byte first. The one exception is the network port inside an address, which is big-endian (network byte order).

  • char[n] fields are fixed-width and NULL-padded.

  • var_int (CompactSize) is the variable-length integer used for counts and lengths, identical to the encoding used throughout the consensus serialization — see CompactSize.

  • var_str is a var_int length followed by that many bytes of UTF-8 text.

  • var_bytes is a var_int length followed by that many raw bytes.

Message structure

Every message is a fixed-size header followed by a payload. There are two header forms: the basic 24-byte header used by all ordinary messages, and the extended header used to carry payloads larger than 4 GiB (see Extended messages).

Basic header

Field size
Name
Data type
Description

4

magic

char[4]

Network magic value identifying the network (see Network magic).

12

command

char[12]

Message type identifier, ASCII, NULL-padded (e.g. version, tx, block).

4

length

uint32_t

Byte length of payload.

4

checksum

char[4]

First 4 bytes of the double-SHA-256 of payload.

length

payload

uint8_t[]

The message body.

The header is 24 bytes (MESSAGE_START_SIZE 4 + COMMAND_SIZE 12 + length 4 + CHECKSUM_SIZE 4). Because length is a uint32_t, a basic message payload is limited to 0xFFFFFFFF (4 GiB − 1) bytes; larger payloads use the extended header.

Network magic

The 4-byte magic prefix identifies which network a message belongs to and frames the start of each message on the stream.

Network
Magic (bytes, in order)

Mainnet

e3 e1 f3 e8

Testnet

f4 e5 f3 f4

STN (scaling test network)

fb ce c4 f9

Regtest

da b5 bf fa

Protocol version

The current P2P protocol version is 70016 (PROTOCOL_VERSION). Each peer advertises its version in the version message during the handshake, and behaviour is gated on the negotiated minimum of the two peers' versions. Notable version thresholds:

Version
Meaning

70016

EXTENDED_PAYLOAD_VERSION — peer understands extended (large) messages. A node must not send extended-format messages to peers below this version.

70015

INVALID_CB_NO_BAN_VERSION

70014

SHORT_IDS_BLOCKS_VERSION — compact blocks.

70013

FEEFILTER_VERSION — feefilter message.

70012

SENDHEADERS_VERSION — sendheaders message.

70011

NO_BLOOM_VERSION — bloom filtering no longer advertised by default.

31800

GETHEADERS_VERSION = MIN_PEER_PROTO_VERSION; peers below this are not accepted.

The handshake

A connection begins with a version handshake before any other message is exchanged:

  1. Each side sends a version message describing itself.

  2. Each side replies with verack to acknowledge the peer's version.

  3. Only after both veracks may other message types be sent. Optionally, protoconf is sent immediately after verack to advertise relaxed limits.

version message

Field size
Name
Data type
Description

4

version

int32_t

Protocol version of the sending node.

8

services

uint64_t

Bitfield of services offered (see Service flags).

8

timestamp

int64_t

Current UNIX time in seconds.

26

addr_recv

net_addr

Address of the receiving node (as seen by the sender).

26

addr_from

net_addr

Address of the sending node.

8

nonce

uint64_t

Random nonce; used to detect connections to self.

1+

user_agent

var_str

Human-readable client identifier.

4

start_height

int32_t

Height of the sender's best block.

1

relay

bool

Whether the peer should relay transactions (BIP 37).

1+

association_id

var_bytes

Association identifier for multi-streams. Optional; absence signals a peer that does not support associations.

The association_id field is a BSV addition appended after relay; see Multi-streams. The version message uses the 26-byte net_addr form (services + IP + port, with no timestamp).

net_addr

Network addresses appear in version and addr messages.

Field size
Name
Data type
Description

4

time

uint32_t

UNIX timestamp the address was last seen. Present in addr only, not in version.

8

services

uint64_t

Service bits advertised by that address.

16

ip

char[16]

IPv6 address, or an IPv4 address mapped into IPv6 (::ffff:a.b.c.d).

2

port

uint16_t

TCP port, big-endian (network byte order).

Service flags

Bit
Name
Meaning

1 << 0

NODE_NETWORK

Node serves the full blockchain. Set by all reference nodes; unset by SPV/light clients.

1 << 1

NODE_GETUTXO

BIP 64 getutxo. Not supported by the reference node.

1 << 2

NODE_BLOOM

Willing to serve bloom-filtered connections. No longer advertised by default as of version 70011.

1 << 4

NODE_XTHIN

Xtreme Thinblocks support.

1 << 5

NODE_BITCOIN_CASH

Legacy UAHF-era separation bit.

Service bits are unauthenticated advertisements; implementations must be robust against peers that advertise services they do not actually provide.

Message types

The reference node recognises the following message types (allNetMessageTypes in protocol.cpp). Message types not on this list are ignored, which is what allows optional messages like protoconf to be introduced without a protocol-version bump.

Connection and control

Command
Description

version

Opening handshake; advertises version, services, and address.

verack

Acknowledges a received version.

ping / pong

Liveness check; pong echoes the ping nonce (BIP 31, version ≥ 60000).

reject

Reports rejection of a previous message.

protoconf

Advertises relaxed protocol limits (see protoconf).

createstrm

Opens an additional stream within an association.

streamack

Acknowledges a createstrm.

Peer discovery

Command
Description

getaddr

Requests known peer addresses.

addr

Advertises peer addresses (each a net_addr with time).

Inventory and data transfer

Command
Description

inv

Announces available objects by type and hash.

getdata

Requests objects previously announced in an inv.

notfound

Reports that requested objects are unavailable.

tx

A transaction.

block

A full block.

mempool

Requests the peer's mempool contents (see mempool message).

feefilter

Requests that the peer not relay transactions below a fee rate (version ≥ 70013).

An inv/getdata/notfound entry pairs a 4-byte type with a 32-byte hash. The object types are:

Value
Name
Object

1

MSG_TX

Transaction.

2

MSG_BLOCK

Block.

3

MSG_FILTERED_BLOCK

Bloom-filtered block (merkleblock).

4

MSG_CMPCT_BLOCK

Compact block.

5

MSG_DATAREF_TX

Dataref transaction.

Headers and block synchronisation

Command
Description

getblocks

Requests an inv of block hashes from a locator.

getheaders

Requests block headers from a locator.

headers

Delivers block headers.

sendheaders

Requests that new blocks be announced via headers rather than inv (version ≥ 70012).

gethdrsen

Requests enriched headers.

hdrsen

Delivers enriched headers.

sendhdrsen

Requests enriched-header announcements.

Compact blocks

Command
Description

sendcmpct

Negotiates compact-block relay (version ≥ 70014).

cmpctblock

A compact block (short transaction IDs).

getblocktxn

Requests the full transactions missing from a compact block.

blocktxn

Delivers the requested transactions.

Bloom filtering (BIP 37)

Command
Description

filterload

Installs a bloom filter on the connection.

filteradd

Adds an element to the current filter.

filterclear

Removes the current filter.

merkleblock

A block reduced to the transactions matching the filter, plus a partial Merkle branch.

Large-message framing

Command
Description

extmsg

Envelope indicating an extended (large) payload follows.

The reference node also defines message types for features outside the wire protocol proper — Miner ID (revokemid), node authentication (authch, authresp), dataref transactions (datareftx), and double-spend detection (dsdetected). These are not part of the core wire protocol and are not documented here.

BSV extensions

The following extensions distinguish the BSV wire protocol from the original Bitcoin protocol. All are designed for backward compatibility: a peer that does not understand an extension either negotiates it away during the handshake or simply ignores the unknown message.

Extended (large) messages

The basic header's length field is a uint32_t, capping a basic payload at 4 GiB. To carry blocks (and potentially other objects) larger than that, an extended header is used. It is signalled by the special command extmsg, after which the real command and a 64-bit length follow before the payload.

Field size
Name
Data type
Description

4

magic

char[4]

Network magic.

12

command

char[12]

Set to extmsg.

4

length

uint32_t

Set to 0xFFFFFFFF to mark an extended message. The real length is in ext_length.

4

checksum

char[4]

Set to 0x00000000 and not checked; computing a checksum over multi-gigabyte payloads has little utility.

12

ext_command

char[12]

The real message type (e.g. block).

8

ext_length

uint64_t

The real payload length.

ext_length

payload

uint8_t[]

The message body.

Extended messages require protocol version 70016 (EXTENDED_PAYLOAD_VERSION). A node must not send an extended-format message to a peer advertising a lower version, or it risks being banned. See the large-message specification.

protoconf

By default a peer will accept messages up to DEFAULT_MAX_PROTOCOL_RECV_PAYLOAD_LENGTH (2 MiB), falling back to LEGACY_MAX_PROTOCOL_PAYLOAD_LENGTH (1 MiB) for peers that predate this message. The optional protoconf message lets a peer advertise relaxed limits so larger non-block messages can be exchanged.

Field size
Name
Data type
Description

variable

numberOfFields

var_int

Number of fields that follow; also serves as the message version. Must be ≥ 1 (version 0 is invalid); this specification is version 2.

4

maxRecvPayloadLength

uint32_t

Maximum non-block message payload the sender is willing to receive. Minimum (and default) 1 MiB; advertising less is a protocol violation.

variable

streamPolicies

var_str

Comma-separated list of supported stream policies.

Rules of use:

  • protoconf may only be sent after verack, at most once per connection, and should be sent immediately after verack.

  • It can only relax limits, never tighten them below the defaults — this preserves compatibility with peers that ignore the message.

  • The protoconf payload itself is capped at 1 MiB.

  • Advertising maxRecvPayloadLength also lifts the legacy MAX_INV_SZ (50 000) cap on inv/getdata element counts; those are then bounded only by the advertised payload length.

See the protoconf specification.

Multi-streams

A single TCP connection to a peer suffers head-of-line blocking: a newly-arrived block can be stuck behind a large batch of transactions already being transmitted. Multi-streams lets peers open several TCP connections (streams) grouped into one logical association, and dedicate streams to particular traffic categories (for example, a high-priority stream for blocks).

An association is identified by the association_id a peer includes in its version message. If the responding node echoes the same association_id, both peers support associations and further streams can be opened.

createstrm — sent as the first message on a new connection (in place of version) to attach it as a stream to an existing association:

Field size
Name
Data type
Description

1+

association_id

var_bytes

The association this stream joins.

1

stream_type

byte

Stream category (1–4).

0+

stream_policy

var_str

(Optional) name of the stream policy to use.

streamack — the response confirming the stream, echoing the association ID and stream type:

Field size
Name
Data type
Description

1+

association_id

var_bytes

The association being acknowledged.

1

stream_type

byte

The stream type being acknowledged.

A failed createstrm yields a reject and the connection is closed.

Two stream policies are implemented: Default (no additional streams; behaves like a single traditional connection) and BlockPriority (one extra stream carrying block and control messages, so they are prioritised over bulk transaction traffic). Supported policy names are exchanged via the streamPolicies field of protoconf. See the multi-streams specification.

Extended mempool message

The mempool message may carry an optional age field. A node responding to a mempool request restricts the transactions it reports to those that have been in its mempool for at least the given number of seconds.

Field size
Name
Data type
Description

0+

age

uint64_t

Minimum mempool age (seconds) for a transaction to be included in the response.

Old nodes continue to use the field-less form unchanged. See the mempool message specification.

Message-size limits

The reference node applies per-message size limits as a transport-layer defence. These are policy limits on the network layer, not consensus rules; exceeding them causes a peer to be disconnected or banned but says nothing about the validity of any transaction or block.

Limit
Value
Applies to

LEGACY_MAX_PROTOCOL_PAYLOAD_LENGTH

1 MiB

Peers that do not support protoconf; also the protoconf payload cap.

DEFAULT_MAX_PROTOCOL_RECV_PAYLOAD_LENGTH

2 MiB

Default cap for non-block messages, overridable upward via protoconf.

MAX_PROTOCOL_RECV_PAYLOAD_LENGTH

1 GiB

Ceiling for the configurable receive limit.

Block-like messages

Max block size

block, cmpctblock, blocktxn, hdrsen are bounded by the configured maximum block size, not the protocol payload limit.

tx

Max post-Genesis transaction size

A tx (and datareftx) is bounded by the consensus maximum transaction size.

Because block-like and transaction messages are exempt from the general payload limit, block and transaction propagation scales with the configured block size rather than a fixed network cap.

Last updated