Disconnect m_chain's tip. * After calling, the mempool will be in an inconsistent state, with * transactions from disconnected blocks being added to disconnectpool. You * should make the mempool consistent again by calling MaybeUpdateMempoolForReorg. * with cs_main held. * * If disconnectpool is nullptr, then no disconnected transactions are added to * disconnectpool (note that the
| 2799 | * in any case). |
| 2800 | */ |
| 2801 | bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTransactions* disconnectpool) |
| 2802 | { |
| 2803 | AssertLockHeld(cs_main); |
| 2804 | if (m_mempool) AssertLockHeld(m_mempool->cs); |
| 2805 | |
| 2806 | CBlockIndex *pindexDelete = m_chain.Tip(); |
| 2807 | assert(pindexDelete); |
| 2808 | // Read block from disk. |
| 2809 | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); |
| 2810 | CBlock& block = *pblock; |
| 2811 | if (!ReadBlockFromDisk(block, pindexDelete, m_params.GetConsensus())) { |
| 2812 | return error("DisconnectTip(): Failed to read block"); |
| 2813 | } |
| 2814 | // Apply the block atomically to the chain state. |
| 2815 | int64_t nStart = GetTimeMicros(); |
| 2816 | { |
| 2817 | CCoinsViewCache view(&CoinsTip()); |
| 2818 | assert(view.GetBestBlock() == pindexDelete->GetBlockHash()); |
| 2819 | if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK) |
| 2820 | return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); |
| 2821 | bool flushed = view.Flush(); |
| 2822 | assert(flushed); |
| 2823 | } |
| 2824 | LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * MILLI); |
| 2825 | // Write the chain state to disk, if necessary. |
| 2826 | if (!FlushStateToDisk(state, FlushStateMode::IF_NEEDED)) { |
| 2827 | return false; |
| 2828 | } |
| 2829 | |
| 2830 | if (disconnectpool && m_mempool) { |
| 2831 | // Save transactions to re-add to mempool at end of reorg |
| 2832 | for (auto it = block.vtx.rbegin(); it != block.vtx.rend(); ++it) { |
| 2833 | disconnectpool->addTransaction(*it); |
| 2834 | } |
| 2835 | while (disconnectpool->DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) { |
| 2836 | // Drop the earliest entry, and remove its children from the mempool. |
| 2837 | auto it = disconnectpool->queuedTx.get<insertion_order>().begin(); |
| 2838 | m_mempool->removeRecursive(**it, MemPoolRemovalReason::REORG); |
| 2839 | disconnectpool->removeEntry(it); |
| 2840 | } |
| 2841 | } |
| 2842 | |
| 2843 | m_chain.SetTip(pindexDelete->pprev); |
| 2844 | |
| 2845 | UpdateTip(pindexDelete->pprev); |
| 2846 | // Let wallets know transactions went from 1-confirmed to |
| 2847 | // 0-confirmed or conflicted: |
| 2848 | GetMainSignals().BlockDisconnected(pblock, pindexDelete); |
| 2849 | return true; |
| 2850 | } |
| 2851 | |
| 2852 | static int64_t nTimeReadFromDisk = 0; |
| 2853 | static int64_t nTimeConnectTotal = 0; |
nothing calls this directly
no test coverage detected