diff options
Diffstat (limited to 'src/db.cpp')
| -rw-r--r-- | src/db.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
| @@ -435,6 +435,47 @@ bool CTxDB::LoadBlockIndex() | |||
| 435 | nBestHeight = pindexBest->nHeight; | 435 | nBestHeight = pindexBest->nHeight; |
| 436 | printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight); | 436 | printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight); |
| 437 | 437 | ||
| 438 | // Verify the tail of the best chain, and fall back to the last good block | ||
| 439 | // if any of it fails. | ||
| 440 | // | ||
| 441 | // A node that accepted blocks its current rules would reject -- because it | ||
| 442 | // was running an older build, or because the tip it landed on was never | ||
| 443 | // valid -- has no way to notice on its own. It keeps the branch, keeps | ||
| 444 | // building on it, and keeps mining coins that the rest of the network | ||
| 445 | // throws away. The only cure used to be deleting blk*.dat by hand, which | ||
| 446 | // requires knowing something is wrong in the first place. That is how a | ||
| 447 | // node here once mined a 323-block fork for five days. | ||
| 448 | // | ||
| 449 | // Checking every block on every start would mean a RandomX hash per block, | ||
| 450 | // so only the tail is checked by default. /checkblocks=0 does the lot. | ||
| 451 | int nCheckBlocks = nCheckBlocksOnLoad; | ||
| 452 | CBlockIndex* pindexFork = NULL; | ||
| 453 | int nChecked = 0; | ||
| 454 | for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) | ||
| 455 | { | ||
| 456 | if (nCheckBlocks > 0 && nChecked >= nCheckBlocks) | ||
| 457 | break; | ||
| 458 | nChecked++; | ||
| 459 | CBlock block; | ||
| 460 | if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true)) | ||
| 461 | return error("LoadBlockIndex() : ReadFromDisk failed at height %d", pindex->nHeight); | ||
| 462 | if (!block.CheckBlock()) | ||
| 463 | { | ||
| 464 | printf("LoadBlockIndex() : *** bad block at height %d, hash=%s\n", | ||
| 465 | pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,14).c_str()); | ||
| 466 | // Keep going: an older bad block further back wins, because | ||
| 467 | // everything after it has to come off too. | ||
| 468 | pindexFork = pindex->pprev; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | printf("LoadBlockIndex(): verified %d block(s)\n", nChecked); | ||
| 472 | |||
| 473 | // The repair itself happens in the caller, after this handle is closed. | ||
| 474 | // The cursor above is still open and holds read locks, so a write | ||
| 475 | // transaction opened here waits on it forever -- measured: the node came | ||
| 476 | // up, printed the diagnosis, and hung with no error anywhere. | ||
| 477 | pindexBadChainFork = pindexFork; | ||
| 478 | |||
| 438 | return true; | 479 | return true; |
| 439 | } | 480 | } |
| 440 | 481 | ||