Module chain_selector

Source
Available on non-WebAssembly only.
Expand description

A module that connects with multiple peers and finds the best chain.

§The theory

In Bitcoin, the history of transactions processed by the network is defined by a sequence of blocks, chainned by their cryptographic hash. A block commits the hash for the block right before it. Therefore, if we pick any given block, there’s exactly one history leading to the very first block, that commits to no one. However, if you go in the other way, starting at the first block and going up, there may not be only one history. Multiple blocks may commit to the same parent. We need a way to pick just one such chain, among all others.

To do that, we use the most work rule, sometimes called “Nakamoto Consensus” after Bitcoin’s creator, Satoshi Nakamoto. Every block has to solve a probabilistic challenge of finding a combination of data that hashes to a value smaller than a network-agreed value. Because hash functions are pseudorandom, one must make certain amount of hashes (on average) before finding a valid one. If we define the amount of hashes needed to find a block as this block’s “work”, by adding-up the work in each of a chain’s blocks, we arrive with the chainwork. The Nakamoto consensus consists in taking the chain with most work as the best one.

This works because anyone in the network will compute the same amount of work and pick the same one, regardless of where and when. Because work is a intrinsic and deterministic property of a block, everyone comparing the same chain, be on earth, on mars; in 2020 or 2100, they will choose the exact same chain, always.

The most critial part of syncing-up a Bitcoin node is making sure you know about the most-work chain. If someone can eclypse you, they can make you start following a chain that only you and the attacker care about. If you get paid in this chain, you can’t pay someone else outside this chain, because they will be following other chains. Luckily, we only need one honest peer, to find the best-work chain and avoid any attacker to fools us into accepting payments in a “fake Bitcoin”

§Implementation

In Floresta, we try to pick a good balance between data downloaded and security. We could simply download all chains from all peers and pick the most work one. But each header is 80 bytes-long, with ~800k blocks, that’s around 60 MBs. If we have 10 peers, that’s 600MBs (excluding overhead by the p2p messages). Moreover, it’s very uncommon to actually have peers in different chains. So we can optmistically download all headers from one random peer, and then check with the others if they agree. If they have another chain for us, we download that chain, and pick whichever has more work.

Most likely we’ll only download one chain and all peers will agree with it. Then we can start downloading the actual blocks and validating them.

Structs§

ChainSelector
A p2p driver that attempts to connect with multiple peers, ask which chain are them following and download and verify the headers, not the actual blocks. This is the first part of a loger IBD pipeline. The actual blocks should be downloaded by a SyncPeer.

Enums§

ChainSelectorState
FindAccResult