Skip to content

Latest commit

 

History

History
77 lines (53 loc) · 5.11 KB

README.md

File metadata and controls

77 lines (53 loc) · 5.11 KB

netsync

ISC License

Overview

This package implements a concurrency safe block syncing protocol. The SyncManager communicates with connected peers to perform an initial block download, keep the chain and unconfirmed transaction pool in sync, and announce new blocks connected to the dag. Currently the sync manager selects a single sync peer that it downloads all blocks from until it is up to date with the longest chain the sync peer is aware of.

netsync package provides a 'manager' (goroutine) that is started when soterd is run. Managers communicate with other managers via message passing over channels associated with them. For example, the mining manager can pass a newly-generated block to the netsync manager, so that this soterd node can advertise the new block to its peers.

Sync flow

The sync manager works by reacting to messages it receives, and ends up with synchronization behaviour due to how the sync manager on each node will react to each other's messages. The end result of their interaction is that the node that initiated the flow has a copy of blocks it was previously missing from its sync peer.

There are multiple ways that a nodes trigger sync flow:

  1. When a block received from a peer is being processed and our dag height is still below our peers', a getblocks message is sent for blocks ranging from our maximum dag height to the tip of our peer's dag.
  2. When a block received from a peer is being processed and its determined that it is an orphan (we don't have their parent blocks), a getdata message is sent to retrieve the parents of the orphan block.
  3. When a block received from a peer is being processed and its determined that its is a parent of an orphan, a getblocks message is generated from the parent's height to the hash of the orphan.
  4. When a block is generated by a miner, a node will advertise it to its peers with an inventory message. If peers don't have this block, they will respond with a getdata message.

Description of messages

Here's a quick reference for the messages involved in sync flow:

Message Response to Description
getblocks None Asks for block inventory, for a range of blocks. Range is specified as (start block height, end block hash). A special zero-hash is used to indicate "end at tips". Responses will contain hashes and height of blocks, but no further information.
getdata None Asks for the full block data
inventory getblocks A message containing an array of inventory. Each inventory element consists of Type (block, tx, etc), Hash, Height fields.
block getdata Contains a full block

Sync mode

Sync mode is where a node detects that it is behind its peer(s), and needs to concentrate on downloading blocks from a peer it selects (called a sync peer) before expanding the scope of its node communication. While in sync mode, a node will drop block-related messages from non-sync nodes.

When a node is started and gets its first sync-eligible peer, SyncManager.handleNewPeerMsg() is called, which calls SyncManager.startSync(). The node is also now in sync mode.

startSync() issues a getblocks message to the peer for blocks from its tips of dag to the tips of the peer's dag.

The sync peer receives the getblocks message, and responds with an inventory message containing an array of inventory. Each inventory element consists of:

Type (block, transaction, etc)
Hash
Height (currently only meaningful for block type)

The node receives the inventory message, and processes it with SyncManager.handleInvMsg(). handleInvMsg does three main tasks:

  1. Issues getdata messages for blocks the node doesn't have (if not in headers-first mode)
  2. Requests more inventory with another getblocks message, if the maximum height of the blocks in the inventory are higher than our current dag tips. It asks for blocks from the height of the block after the maxHeight block in the inventory to the tips of the sync peer.
  3. Looks through orphans, and issues getdata messages for orphan block's parents if the node doesn't have them.

The sync peer receives the getdata message, and and replies with block message.

The node receives the block message, and processes it with SyncManager.handleBlockMsg(). handleBlockMsg does four main tasks:

  1. Attempts to process the block, for inclusion into the node's dag.
    • If the block is an orphan (parents missing from node's dag), it's added to the orphan pool and the node issues getdata requests for the parents.
  2. If the node isn't in headers-first mode and its tips are now current with peers, the node exits sync mode.
  3. If the block processed is the parent of an orphan, getblocks message is sent for blocks between the parent's height and the child orphans' hash.
  4. If the node is in headers-first mode, getblocks message for blocks after this block's height to the tips of the peer is sent.

Installation and Updating

$ go get -u github.com/soteria-dag/soterd/netsync

License

Package netsync is licensed under the copyfree ISC License.