Chapter 10. Networking
Jimmy Song, "Programming Bitcoin: Chapter 10. Networking", 2019. 03
Source: https://github.com/jimmysong/programmingbitcoin/tree/master/code-ch10
The peer-to-peer network that Bitcoin runs on is what gives it a lot of its robustness. More than 65,000 nodes are running on the network as of this writing and are communicating constantly. The Bitcoin network is a broadcast network, or gossip network. Every node is announcing different transactions, blocks, and peers that it knows about.
One thing to note about the networking protocol is that it is not consensus-critical. The same data can be sent from one node to another using some other protocol and the blockchain itself will not be affected.

Network Messages
The envelope that contains the actual payload (The example of common network message below.)
network magic (4 bytes): Magic value indicating message origin network, and used to seek to next message when stream state is unknown
command (12 bytes): ASCII string identifying the packet content, NULL padded (non-NULL padding results in packet rejected)
payload length (4 bytes): Length of payload in number of bytes
payload checksum (4 bytes): First 4 bytes of sha256 (= sha256(payload))
payload


The code to handle network messages requires us to create a new class:
Exercise 1
Write the parse method for NetworkEnvelope.
Exercise 2
Determine what this network message is: f9beb4d976657261636b000000000000000000005df6e0e2
Exercise 3
Write the serialize method for NetworkEnvelope.
Parsing the Payload
The below figure is the parsed payload for version message. The fields are meant to give enough information for two nodes to be able to communicate.

The following network services are currently assigned:

NODE_GETUTXO: Supported "getutxo" message that query UTXOs for verifying double spending on SPV nodes
NODE_BLOOM: Supported Bloom Filter
NODE_WITNESS: Supported Segwit
NODE_NETWORK_LIMITED: Supported relaying and verifying of all TXs and the most recent 288 blocks
Setting some reasonable defaults, our VersionMessage class looks like this:
Exercise 4
Write the serialize method for VersionMessage.
Network Handshake
The network handshake is how nodes establish communication:
A wants to connect to B and sends a version message.
B receives the version message, responds with a verack message, and sends its own version message.
A receives the version and verack messages and sends back a verack message.
B receives the verack message and continues communication.

Once the handshake is finished, A and B can communicate however they want. Note that there is no authentication here, and it’s up to the nodes to verify all data that they receive. If a node sends a bad transaction or block, it can expect to get banned or disconnected.
Connecting to the Network
Network communication is tricky due to its asynchronous nature. To experiment, we can establish a connection to a node on the network synchronously:
Connecting in this way, we can’t send until we’ve received and can’t respond intelligently to more than one message at a time. A more robust implementation would use an asynchronous library (like asyncio in Python 3) to send and receive without being blocked.
We also need a verack message class, which we’ll create here:
Let’s now automate this by creating a class that will handle the communication for us:
Now that we have a node, we can handshake with another node:
Exercise 5
Write the handshake method for SimpleNode.
Getting Block Headers
When any node first connects to the network, the data that’s most crucial to get and verify is the block headers.
For full nodes, downloading the block headers allows them to asynchronously ask for full blocks from multiple nodes, parallelizing the download of the blocks.
For light clients, downloading headers allows them to verify the proof-of-work in each block.
Nodes can give us the block headers without taking up much bandwidth. The command to get the block headers is called getheaders (the following figure is parsed getheaders)

Here's what the GetHeadersMessage class looks like:
Exercise 6
Write the serialize method for GetHeadersMessage.
Headers Response
We can now create a node, handshake, and then ask for some headers:
Now we need a way to receive the headers from the other node. The other node will send back the headers command. The below figure is parsed block headers.

We can use the same parsing engine as when parsing a full block:
Given the network connection that we’ve set up, we can download the headers, check their proof-of-work, and validate the block header difficulty adjustments as follows:
Last updated