回复:[补丁] 自动区块验证
原始发布页
打开来源页面查看 1 个交叉存档
那是一种很难实现的方法。
我们需要触发一次重组,从而断开无效链。
这段代码几乎永远不会得到测试,而且相当复杂,所以最好采用简单而安全的做法。
这是我的设想。(我还没有测试)它会检查主链中的所有区块。如果发现坏区块,就把该链所有区块的 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; }
英文原文
展开英文原文
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; }