Introducing Bitcoin nodes' boostrap process and its protocol
Table of Contents
Introduction #
During my undergraduate internship in the KAIST NetS&P lab, I needed to find out how Bitcoin nodes communicate when joining a distributed network for the first time. Specifically, I wanted to understand what information is exchanged between nodes and known hosts or seed nodes during this initial connection. To investigate this, I utilized Wireshark to capture packets and analyze the communication process. And find out that the handshake required for Bitcoin nodes involves a streamlined set of messages, as detailed above.
The commands and protocols exchanged during this process are critical for establishing reliable connections and data sharing. For a more in-depth understanding, I’ve referenced various Bitcoin Protocol and BEP official documentation throughout this exploration.
Bitcoin protocol #
Messages #
Bitcoin nodes communicate with Bitcoin protocol which follows the protocol documentation like below (which is built on top on TCP)
Messages which are bitcoin protocol have common structures like the table below +) Almost all integers are encoded in little endian. Only IP or port number are encoded big endian. All field sizes are numbers of bytes
Field Size | Description | Data type | Comments |
---|---|---|---|
4 | magic | uint32_t | for REGTEST: 0xDAB5BFFA |
12 | command | char[12] | NULL padded |
4 | length | uint32_t | Length of payload bytes |
4 | checksum | uint32_t | First 4 bytes of sha256(sha256(payload)) |
? | payload | uchar[] | Actual data |
version #
Advertise its version
wtxiderelay #
- Send prior to
verack
- For only protocol both
70016
or higher
Payload #
Empty payload for this command
sendaddrv2 #
BIP155
Prefer to receive addrv2
than addr
- Must send as response to
version
- and send prior to
verack
verack #
sent reply to version
getaddr #
asking information about active peers
sendcmpct #
- Payload length is 9
- For only protocol both
70014
or higher
Payload (9bytes) = 1byte (boolean) + 8bytes
Example Payload: 0 2 0 0 0 0 0 0
If first and second bytes are
1 and 1
→ new blocks bycmpctblock
(BIP130)0 and *
→ new blocks byinv
andheaders
(BIP130)* and not 1
→ not received any message
ping #
confirm TCP/IP connection is valid with random nonce
pong #
response to ping with nonce from ping
getheaders #
requests the peer for headers
message
Example Payload.
- version:
70016
- hash_count:
1
- block_locator_hashes:
[GENESIS_BLOCK_HASH]
In other words, starting hash - hash_stop:
0
In other words, stop_hash. When it is set to zero, get as many blocks as possible (Max. 2000)
So, for getheaders
message, it requests the opposite nodes to send block hashes starting from block_locator_hashes
until hash_stop
.
Payload #
Field Size | Description | Data type | Comments |
---|---|---|---|
4 | version | uint32_t | the protocol version |
1+ | hash count | var_int | number of block locator hash entries |
32+ | block locator hashes | char[32] | block locator object |
32 | hash_stop | char[32] | hash of the last desired block header |
feefilter #
Instruct peers not to send inv
s for transactions with fees below specific value.
→ due to limited memepool
- For only protocol both
70013
or higher
headers #
returns block header response to getheaders
message.
sendheaders #
prefer to receive headers
message than inv
- For only protocol both
70012
or higher