Re: [PATCH] Automatic block validation

I’ve written a patch to help automatically validate cached blocks after validation fixes such as the one that was pushed out today. You can find it at

http://fushizen.net/~bd/blockverify.patch

or

http://github.com/bdonlan/bitcoin/commit/b205251959448ca99123f2bc95b088bf06d4ef3b

Upon first run with this patch, all blocks will be verified, and any invalid blocks, as well as blocks orphaned by removal of such blocks, will be removed from the block index. A version stamp
(BLOCK_VERIFY_TOKEN in db.cpp) will be then written to the db; this will cause the next run to skip the verification pass. Any future validation fixes can then simply bump BLOCK_VERIFY_TOKEN to force a revalidation of the block chain.

Note that I may be missing some important steps when deleting the old blocks – in particular, no attempt is made to update the wallet, or to prune stored uncommitted transactions. Review would be helpful.

That’s a difficult approach.

We need to cause a reorg, which will disconnect the invalid chain.

This is code that will rarely ever get tested, and is fairly intricate, so something simple and safe is best.

Here’s what I was thinking of.  (I haven’t tested this yet)  It checks all the blocks in the main chain.  If it finds a bad one, it sets all that chain’s bnChainWork to 0 so it can’t win best chain again, and it reduces best chain work to the fork level so any new block after the fork will cause a reorg.  (It can’t change pindexBest without actually doing a reorg)

This isn’t perfect yet.  It still needs to receive one valid block to trigger the reorg.

It would probably be possible to initiate an AddToBlockIndex or Reorganize after the check, but it would require a lot more careful attention.  I probably should break out part of AddToBlockIndex that sets the new best block.  I’ll probably end up doing that instead of the code below.

Code:
bool CTxDB::LoadBlockIndex()
{
    ...

    // Verify blocks in the main chain
    vector<CBlockIndex*> vChain;
    for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
    {
        vChain.push_back(pindex);
        CBlock block;
        if (!block.ReadFromDisk(pindex))
            return error("LoadBlockIndex() : block.ReadFromDisk failed");
        if (!block.CheckBlock())
        {
            bnBestChainWork = pindex->pprev->bnChainWork;
            foreach(CBlockIndex* pindex2, vChain)
                pindex2->bnChainWork = 0;
        }
    }

    return true;
}

42,112 total views, 4 views today

https://bitcointalk.org/index.php?topic=832.msg9754#msg9754