Before a full node can validate unconfirmed transactions and recently-mined blocks, it must download and validate all blocks from block 1 (the block after the hardcoded genesis block) to the current tip of the best block chain. This is the Initial Block Download (IBD) or initial sync.

Although the word “initial” implies this method is only used once, it can also be used any time a large number of blocks need to be downloaded, such as when a previously-caught-up node has been offline for a long time. In this case, a node can use the IBD method to download all the blocks which were produced since the last time it was online.

dcrd uses the IBD method any time the last block on its local best block chain has a block header time more than 24 hours in the past. dcrd will also perform IBD if its local best block chain is more than 288 blocks lower than its local best header chain (that is, the local block chain is more than about 24 hours in the past).

## Blocks-First¶

dcrd uses a simple IBD method called blocks-first. The goal is to download the blocks from the best block chain in sequence. Below is a high-level diagram of the blocks-first method.

The first time a node is started, it only has a single block in its local best block chain, the hardcoded genesis block (block 0). We will refer to this as the “IBD node”. This node chooses a remote peer, called the “sync node”, and sends it the getblocks message illustrated below.

In the header hashes field in the payload of the getblocks message, this new node sends the header hash of the only block it has, the genesis block (6fe2…0000 in internal byte order). It also sets the stop hash field to all zeroes to request a maximum-size response.

Upon receipt of the getblocks message, the sync node takes the first (and only) header hash and searches its local best block chain for a block with that header hash. It finds that block 0 matches, so it replies with 500 block inventories (the maximum response to a getblocks message) starting from block 1. It sends these inventories in the inventory (inv) message illustrated below.

Inventories are unique identifiers for information on the network. Each inventory contains a type field and the unique identifier for an instance of the object. For blocks, the unique identifier is a hash of the block’s header.

The block inventories appear in the inv message in the same order they appear in the block chain. In our example, as illustrated above, the first inv message contains inventories for blocks 1 through 501. We can also see that the unique identifier for the first message is the hash of block 1 (4860…0000).

The IBD node uses the received inventories to request 128 blocks from the sync node in the getdata message illustrated below.

It’s important to blocks-first nodes that the blocks be requested and sent in order because each block header references the header hash of the preceding block. That means the IBD node can’t fully validate a block until its parent block has been received. Blocks that can’t be validated because their parents haven’t been received are called orphan blocks.

Upon receipt of the getdata message, the sync node replies with each of the blocks requested. Each block is put into serialized block format and sent in a separate block message. The first block message sent (for block 1) is illustrated below.

The IBD node downloads each block, validates it, and then requests the next block it hasn’t requested yet, maintaining a queue of up to 128 blocks to download. When it has requested every block for which it has an inventory, it sends another getblocks message to the sync node requesting the inventories of up to 500 more blocks. This second getblocks message contains multiple header hashes as illustrated below:

Upon receipt of the second getblocks message, the sync node searches its local best block chain for a block that matches one of the header hashes in the message, trying each hash in the order they were received. If it finds a matching hash, it replies with 500 block inventories starting with the next block from that point. But if there is no matching hash (besides the stop hash), it assumes the only block the two nodes have in common is block 0 and so it sends an inv starting with block 1 (the same inv message seen several illustrations above).

This repeated search allows the sync node to send useful inventories even if the IBD node’s local block chain forked from the sync node’s local block chain. This fork detection becomes increasingly useful the closer the IBD node gets to the tip of the block chain.

When the IBD node receives the second inv message, it will request those blocks using getdata messages. The sync node will respond with block messages. Then the IBD node will request more inventories with another getblocks message, and the cycle will repeat until the IBD node is synced to the tip of the block chain. At that point, the node will accept blocks sent through the regular block broadcasting mechanism.