Bitcointalk · [PATCH] Automatic block validation

中本聪,2010 年 8 月 16 日

SN-2468 已核对来源,附原文与上下文。

阅读语言
中文译文

那是个麻烦的办法。

我们需要触发一次重组,把无效链断开。

这段代码几乎不会被测试到,而且相当繁复精巧,所以简单安全的做法最好。

我的想法是这样。(还没测试过)它检查主链上的所有区块。发现坏的,就把那条链的 bnChainWork 全部置 0,让它再也赢不了最佳链,并把最佳链工作量降到分叉点级别,如此这般分叉点之后的任何新区块都会触发重组。(不真正做一次重组,它改不了 pindexBest)

这还不完善。它仍需要收到一个有效区块来触发重组。

兴许可以在检查之后主动发起 AddToBlockIndex 或 Reorganize,但那需要更细致的推敲。我大抵应该把 AddToBlockIndex 里设置新区块最佳的部分拆出来。我最后很可能用那个做法,而非下面的代码。

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;
}
ORIGINAL · 英文原文
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;
}
来源
Bitcointalk 原始链接 ↗ 记录编号 SN-2468