20 stable releases

1.3.17 Oct 25, 2021
1.3.14 Aug 23, 2021
1.3.12 Jul 30, 2021
1.2.0 Feb 28, 2021
1.1.4 Aug 27, 2020

#21 in #peer-connection

27 downloads per month
Used in 2 crates

GPL-3.0 license

2.5MB
11K SLoC

snarkos-network

Crates.io Authors License: GPL v3

The snarkOS network protocol establishes a peer-to-peer network of nodes that maintains ledger liveness by actively exchanging transactions and blocks.

Overview

snarkOS uses TCP connections to facilitate data transfers over the network. Networking on snarkOS is built with asynchronous calls in Rust and tokio.rs. Tokio tasks are spawned to handle new connections and send messages to the main event loop.

snarkOS downloads, verifies, and stores the history of valid blocks and transactions prior to becoming an active node on the network.

Peer Discovery

When a node joins the network for the first time, it needs to populate a list of active peers in the network. In order to bootstrap peer discovery, snarkOS includes a set of optional specialised "beacon" nodes. Once connected, these provide an initial set of peers which includes the address of a sync provider. The sync provider will supply the node with an initial sync of the chainstate. To allow users flexibility, snarkOS provides allows users to configure the initial set of nodes in the configuration file, or as a input via a command-line flag.

Once a node is connected to one or more nodes, it may scan the network to discover more peers. This processes starts by asking peers for more connected nodes in the network with a GetPeers message, followed by attempts to establish a connection with each newly discovered peer.

Upon success, snarkOS will store the new peer address to allow it to connect directly with this peer in the future, without needing to use beacons to startup in the future.

Connecting to Peers

Peer connections are established with an XX noise handshake.

Peer connections are maintained with a ping-pong protocol that periodically relays Ping / Pong messages to verify that peers are still connected. snarkOS will update its peer book to account for newly-connected peers, and disconnected peers.

Block Download/Sync

Before a node can participate in the network, it must sync itself to the latest state of the ledger. Whether a node is newly connecting to the network or simply has stale state, it must sync with its peers, and download its missing blocks and transactions.

snarkOS uses a "Header-First" approach to syncing blocks, where a node downloads and validates each block header before downloading the corresponding full block, in parallel.

When a node determines it needs to download state, it selects a peer as the sync-node and sends it a GetSync message. The GetSync message contains information about the current block state of the node, so the sync-node is able to determine which block headers are necessary to send as a response.

Upon receiving a GetSync message, the sync-node sends back at most 100 block headers via a Sync message. The requester then validates these headers and downloads the blocks in parallel by sending out GetBlock messages. After these blocks have been downloaded, the requester sends another GetSync message, and repeats this process until its chain state is fully up to date.

Here is a basic iteration of the sync protocol:

Message Sender Receiver Data
GetSync Node Sync Node 1 or more block hashes
Sync Sync Node Node Up to 100 new block headers
GetBlocks Node Any Peer Block headers of the requested blocks
Block Any Peer Node A serialized block

Transaction Broadcasting

A node may broadcast a transaction to the network by sending a Transaction message to its connected peers. The peers receiving this transaction verify the transaction and further propagate the transaction by broadcasting it to its connected peers. This transaction continues through the network until it is propagated to every connected peer in the network.

Block Broadcasting

A node may broadcast a block using a Block message, in the same manner as broadcasting a transaction.

Block

Send a block to a peer.

Message Name

block

Payload

The serialized bytes of the block.

GetBlocks

A request for blocks with the specified hashes.

Message Name

getblocks

Payload

Parameter Type Description
block_hashes array A list of hashes of blocks to request

GetMemoryPool

A request for a peer's memory pool transactions.

Message Name

getmemorypool

Payload

None

GetPeers

A request for a list of the peer's connected peer addresses.

Message Name

getpeers

Payload

None

GetSync

A request for knowledge of specified block locator hashes.

Message Name

getsync

Payload

Parameter Type Description
block_locator_hashes array A list of block hashes describing the state of the requester's chain

MemoryPool

A response to a GetMemoryPool request.

Message Name

memorypool

Payload

Parameter Type Description
transactions array A list of serialized memory pool transactions

Peers

A response to a GetPeers request.

Message Name

peers

Payload

Parameter Type Description
addresses array A list of listening addresses of connected peers

Ping

A message used to check if a peer is active and calculate their RTT.

Message Name

ping

Payload

Parameter Type Description
block_height number The current height of the chain

Pong

A response to a Ping request.

Message Name

pong

Payload

None

Sync

A response to a GetSync message.

Message Name

sync

Payload

Parameter Type Description
block_hashes array A list of block hashes to share with the requester

SyncBlock

A response to a GetBlock request.

Message Name

syncblock

Payload

Parameter Type Description
data bytes The serialized bytes of the requested block

Transaction

A transaction sent by a peer.

Message Name

transaction

Payload

Parameter Type Description
data bytes The serialized bytes of a transaction

Version

Sent during the handshake.

Message Name

version

Payload

Parameter Type Description
version number The version of the network protocol
listening_port number The node's listening port

Contributing

How to Update this README

This README is auto-generated during continuous integration. To update this README, submit a pull request updating the appropriate Markdown file in documentation and the configuration file.

Dependencies

~73MB
~875K SLoC