I have google a lot, there exists little information, confused with the code comments

Retrieve the range of blocks that may have been only partially written. If the database is in a consistent state, the result is the empty vector. Otherwise, a two-element vector is returned consisting of the new and the old block hash, in that order.

why there exists old & new block, their function?

2 Answers 2


Bitcoin Core does this thing called non-atomic flushing. What that means is that the database, instead of being updated atomically (i.e. everything is written at the same time, or nothing is written), has data written to it over time. If the database crashes, with non-atomic flushing, there will be some data written, and some data that is not written. This is different from atomic flushing where either all of the data was written, or none of it was.

Non-atomic flushing allows Bitcoin Core to skip validation of things it has already validated and then just flush things to the database later after a crash or unclean shutdown. But in order to know where it has validated up to, it has to store that block hash (where it has validated up to and where it is flushing up to). It also has to store the block it started at (the block the database knew up to when flushing began).

This is where GetHeadBlocks() comes in. When Bitcoin Core begins flushing, it first writes those two blocks, the old one where the database head was at, and the new one, where the database head will be once flushing finishes. In the event of an unclean shutdown or database crash, these values are already written to the database so it can pull those out of the database, know where its last known good database state was at, and know where it has validated up to so it can skip full validation and just build the database data and flush it. If there was no unclean shutdown or crash, GetHeadBlocks() would return an empty vector.

For example, suppose the database was at block 50, and it is flushing to block 60. When it begins flushing, the hashes of blocks 50 and 60 are written to the database. Suppose that the computer suddenly loses power when it has only flushed up to block 55. When the node comes back on, it will call GetHeadBlocks() and get the hashes of blocks 50 and 60. Now it knows that it was mid-flush when it uncleanly shutdown. So it then rebuilds what the database would be from blocks 50 to 60 but does not perform full validation. It then flushes the remaining data and removes the hashes of blocks 50 and 60 from where they were written.

  • When a crash happens during the flush from 50 to 60, it will have some changes from every block between 50 and 60, not neatly everything up to 55 and nothing above. This is a detail and doesn't impact the rest of the explanation, but it otherwise raises a question: if you've synced everything to 55, why not write that to the db, to avoid processing of blocks 50-54? If it's a mix of changes from all, you can't do that. Jan 30, 2018 at 16:37

Your answer lies in the code.

Check where GetHeadBlocks is being used.. https://dev.visucore.com/bitcoin/doxygen/class_c_coins_view_d_b.html

The caller graph indicates that it's being used by CCoinsViewDB::BatchWrite. The assert statement in BatchWrite will abort the function execution if the latest head does not match the hashblock passed as an argument.

My 30 second research seems to indicate that it will return the block hashes of the old & new block when it's in a syncing state. The BatchWrite is also responsible for updating the best block hash (check doxygen).

  • you answer too mindless..... why there exists old & new block, their function?
    – xiedeacc
    Dec 29, 2017 at 15:05

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.