| 625 | } |
| 626 | |
| 627 | bool DisconnectBlock(CBlock &block, CCacheWrapper &cw, CBlockIndex *pIndex, CValidationState &state, bool *pfClean) { |
| 628 | auto bmTx = MAKE_BENCHMARK("DisconnectBlock"); |
| 629 | assert(pIndex->GetBlockHash() == cw.blockCache.GetBestBlockHash()); |
| 630 | |
| 631 | if (pfClean) |
| 632 | *pfClean = false; |
| 633 | |
| 634 | bool fClean = true; |
| 635 | |
| 636 | CBlockUndo blockUndo; |
| 637 | CDiskBlockPos pos = pIndex->GetUndoPos(); |
| 638 | if (pos.IsNull()) |
| 639 | return ERRORMSG("no undo data available"); |
| 640 | |
| 641 | if (!blockUndo.ReadFromDisk(pos, pIndex->pprev->GetBlockHash())) |
| 642 | return ERRORMSG("failure reading undo data"); |
| 643 | |
| 644 | if ((blockUndo.vtxundo.size() != block.vptx.size()) && (blockUndo.vtxundo.size() != (block.vptx.size() + 1))) |
| 645 | return ERRORMSG("block and undo data inconsistent"); |
| 646 | CBlockUndoExecutor undoExecutor(cw, blockUndo); |
| 647 | if (!undoExecutor.Execute()) { |
| 648 | return ERRORMSG("Undo all data in block failed"); |
| 649 | } |
| 650 | |
| 651 | // Set previous block as the best block |
| 652 | cw.blockCache.SetBestBlock(pIndex->pprev->GetBlockHash()); |
| 653 | |
| 654 | // Delete the disconnected block's transactions from transaction memory cache. |
| 655 | if (!cw.txCache.RemoveBlockTx(block)) { |
| 656 | return state.Abort(_("DisconnectBlock() : failed to delete block from transaction memory cache")); |
| 657 | } |
| 658 | |
| 659 | // Load transactions into transaction memory cache. |
| 660 | if (pIndex->height > SysCfg().GetTxCacheHeight()) { |
| 661 | CBlockIndex *pReLoadBlockIndex = pIndex; |
| 662 | int32_t nCacheHeight = SysCfg().GetTxCacheHeight(); |
| 663 | while (pReLoadBlockIndex && nCacheHeight-- > 0) { |
| 664 | pReLoadBlockIndex = pReLoadBlockIndex->pprev; |
| 665 | } |
| 666 | |
| 667 | CBlock reLoadblock; |
| 668 | if (!ReadBlockFromDisk(pReLoadBlockIndex, reLoadblock)) { |
| 669 | return state.Abort(_("DisconnectBlock() : failed to read block")); |
| 670 | } |
| 671 | |
| 672 | if (!cw.txCache.AddBlockTx(reLoadblock)) { |
| 673 | return state.Abort(_("DisconnectBlock() : failed to add block into transaction memory cache")); |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | // undo block prices of price point memory cache. |
| 678 | if (!cw.ppCache.UndoBlock(cw.sysParamCache, pIndex, block)) |
| 679 | return state.Abort(_("DisconnectBlock() : undo block prices of memory cache")); |
| 680 | |
| 681 | if (pfClean) { |
| 682 | *pfClean = fClean; |
| 683 | return true; |
| 684 | } else { |
no test coverage detected