6

In trying to implement a client, I am wondering what is the most efficient approach to figure out if you are on a fork.

Let's say you pick a peer at random and go through IBD using the headers-first approach. After reaching the tip of the chain, what is the most efficient way to check whether this is the longest chain?

I'm guessing you have to ask your peers what their best header is, and based on the response and some heuristic, decide whether you are on the longest chain or not. Is this simply done via getheaders? What is the heuristic? And what do you do if you find out you're on a fork?

Pointers to the relevant code in bitcoin or btcd would also be appreciated.

Thanks

EDIT: In case this isn't obvious, I'm not asking whether it can know with certaintiy that it is on the longest chain (it can't), but rather what is the best effort attempt to remain on the longest chain at all times.

5

First of all, finding the longest chain is not the goal, but the chain with the most accumulated proof-of-work [1]

Now, finding the most-work chain is the entire goal of the full node. The whole meaning of its existence is finding the most-work chain, and so you can pick almost any line out of the networking and validation modules of the code and explain it in those terms.

To be a bit more specific:

  • The full node connects to at least 8 peers. More recent versions connect to 2 extra peers in 'blocks only' mode. Peers are chosen to be as diverse as possible (by IP subnet or AS map). If a new block has not been added within a certain timeout (I think it's 40 minutes) Bitcoin Core adds one more outgoing peer.
  • The full node sends a getheaders request to each peer and keeps track of the best block each peer knows about.
  • If a peer has a valid block header with greater accumulated work than our current tip, we ask it for the corresponding blocks. If those blocks are valid, it becomes our new chain tip. A reorganization may or may not be necessary to get to that state.

If you understand conceptually how headers-first sync works, the function FindNextBlocksToDownload() is the next step. This is where the node decides if a peer has headers with greater work than its current chain tip, and requests those blocks from that peer.

So all we can do is connect to a lot of peers and assume that at least one of them knows about the most-work chain. This makes peer discovery and choosing which peers to connect to of critical importance.

| improve this answer | |
  • Thanks, this is really helpful. Looking at FindNextBlocksToDownload, the part I'm still trying to understand is: if after finishing your header sync, a peer gives you headers you've never seen, and which don't connect to your chain, how are you going to judge whether they have more accumulated work? – cloudhead Aug 25 at 20:46
  • 1
    Since we can not verify "orphan" headers, we do not request those blocks. The getheaders message includes something called a locator that the receiving peer uses to determine where their chain connects to your chain, and sends you headers from that point: en.bitcoin.it/wiki/Protocol_documentation#getheaders – pinhead Aug 25 at 20:55
  • 1
    I see, so peers will end up sending chains that connect, by using the locators.. makes sense! – cloudhead Aug 25 at 21:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.