| 1700 | } |
| 1701 | |
| 1702 | bool ProcessForkedChain(const CBlock &block, CBlockIndex *pPreBlockIndex, CValidationState &state) { |
| 1703 | bool forkChainTipFound = false; |
| 1704 | uint256 forkChainTipBlockHash; |
| 1705 | vector<CBlock> vPreBlocks; |
| 1706 | std::shared_ptr<CCacheWrapper> spCW = nullptr; |
| 1707 | |
| 1708 | // If the block's previous block is not the active chain's tip, find the forked point. |
| 1709 | while (!chainActive.Contains(pPreBlockIndex)) { |
| 1710 | if (!forkChainTipFound) { |
| 1711 | if (mapForkCache.count(pPreBlockIndex->GetBlockHash())) { |
| 1712 | forkChainTipBlockHash = pPreBlockIndex->GetBlockHash(); |
| 1713 | forkChainTipFound = true; |
| 1714 | LogPrint(BCLog::INFO, "ProcessForkedChain() : fork chain's best block [%d]: %s\n", |
| 1715 | pPreBlockIndex->height, forkChainTipBlockHash.GetHex()); |
| 1716 | } else { |
| 1717 | CBlock block; |
| 1718 | if (!ReadBlockFromDisk(pPreBlockIndex, block)) |
| 1719 | return state.Abort(_("Failed to read block")); |
| 1720 | |
| 1721 | // Reserve the forked chain's blocks. |
| 1722 | vPreBlocks.push_back(block); |
| 1723 | } |
| 1724 | } |
| 1725 | |
| 1726 | pPreBlockIndex = pPreBlockIndex->pprev; |
| 1727 | |
| 1728 | // enable it to avoid forked chain attack. |
| 1729 | if (chainActive.Height() - pPreBlockIndex->height > SysCfg().GetMaxForkHeight(block.GetHeight())) |
| 1730 | return state.DoS(100, ERRORMSG("block at fork chain too earlier than tip block hash=%s block height=%d\n", |
| 1731 | block.GetHash().GetHex(), block.GetHeight())); |
| 1732 | |
| 1733 | if (mapBlockIndex.find(pPreBlockIndex->GetBlockHash()) == mapBlockIndex.end()) |
| 1734 | return state.DoS(10, ERRORMSG("prev block not found"), 0, "bad-prevblk"); |
| 1735 | } |
| 1736 | |
| 1737 | // enable it to avoid forked chain attack. |
| 1738 | if (chainActive.Height() - pPreBlockIndex->height > SysCfg().GetMaxForkHeight(block.GetHeight())) |
| 1739 | return state.DoS(100, ERRORMSG("block at fork chain too earlier than tip block hash=%s block height=%d\n", |
| 1740 | block.GetHash().GetHex(), block.GetHeight())); |
| 1741 | |
| 1742 | if (forkChainTipFound) { |
| 1743 | spCW = mapForkCache[forkChainTipBlockHash]; |
| 1744 | } else if (mapForkCache.count(pPreBlockIndex->GetBlockHash())) { |
| 1745 | forkChainTipBlockHash = pPreBlockIndex->GetBlockHash(); |
| 1746 | spCW = mapForkCache[forkChainTipBlockHash]; |
| 1747 | forkChainTipFound = true; |
| 1748 | LogPrint(BCLog::INFO, "[%d] found block(%s) in cache\n", pPreBlockIndex->height, forkChainTipBlockHash.GetHex()); |
| 1749 | } else { |
| 1750 | spCW = CCacheWrapper::NewCopyFrom(pCdMan); |
| 1751 | int64_t beginTime = GetTimeMillis(); |
| 1752 | CBlockIndex *pBlockIndex = chainActive.Tip(); |
| 1753 | |
| 1754 | while (pPreBlockIndex != pBlockIndex) { |
| 1755 | LogPrint(BCLog::INFO, "disconnect block [%d]: %s\n", pBlockIndex->height, |
| 1756 | pBlockIndex->GetBlockHash().GetHex()); |
| 1757 | |
| 1758 | CBlock block; |
| 1759 | if (!ReadBlockFromDisk(pBlockIndex, block)) |
no test coverage detected