Disconnect chainActive'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 UpdateMempoolForReorg. * with cs_main held. * * If disconnectpool is nullptr, then no disconnected transactions are added to * disconnectpool (note that the c
| 2347 | * in any case). |
| 2348 | */ |
| 2349 | bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) |
| 2350 | { |
| 2351 | CBlockIndex *pindexDelete = chainActive.Tip(); |
| 2352 | assert(pindexDelete); |
| 2353 | // Read block from disk. |
| 2354 | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); |
| 2355 | CBlock& block = *pblock; |
| 2356 | if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus())) |
| 2357 | return AbortNode(state, "Failed to read block"); |
| 2358 | // Apply the block atomically to the chain state. |
| 2359 | int64_t nStart = GetTimeMicros(); |
| 2360 | { |
| 2361 | CCoinsViewCache view(pcoinsTip.get()); |
| 2362 | assert(view.GetBestBlock() == pindexDelete->GetBlockHash()); |
| 2363 | if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK) |
| 2364 | return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString()); |
| 2365 | bool flushed = view.Flush(); |
| 2366 | assert(flushed); |
| 2367 | } |
| 2368 | LogPrint(BCLog::BENCH, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * MILLI); |
| 2369 | // Write the chain state to disk, if necessary. |
| 2370 | if (!FlushStateToDisk(chainparams, state, FlushStateMode::IF_NEEDED)) |
| 2371 | return false; |
| 2372 | |
| 2373 | if (disconnectpool) { |
| 2374 | // Save transactions to re-add to mempool at end of reorg |
| 2375 | for (auto it = block.vtx.rbegin(); it != block.vtx.rend(); ++it) { |
| 2376 | disconnectpool->addTransaction(*it); |
| 2377 | } |
| 2378 | while (disconnectpool->DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) { |
| 2379 | // Drop the earliest entry, and remove its children from the mempool. |
| 2380 | auto it = disconnectpool->queuedTx.get<insertion_order>().begin(); |
| 2381 | mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); |
| 2382 | disconnectpool->removeEntry(it); |
| 2383 | } |
| 2384 | } |
| 2385 | |
| 2386 | // If the tip is finalized, then undo it. |
| 2387 | if (pindexFinalized == pindexDelete) { |
| 2388 | pindexFinalized = pindexDelete->pprev; |
| 2389 | } |
| 2390 | |
| 2391 | chainActive.SetTip(pindexDelete->pprev); |
| 2392 | |
| 2393 | UpdateTip(pindexDelete->pprev, chainparams); |
| 2394 | // Let wallets know transactions went from 1-confirmed to |
| 2395 | // 0-confirmed or conflicted: |
| 2396 | GetMainSignals().BlockDisconnected(pblock); |
| 2397 | return true; |
| 2398 | } |
| 2399 | |
| 2400 | static int64_t nTimeReadFromDisk = 0; |
| 2401 | static int64_t nTimeConnectTotal = 0; |
nothing calls this directly
no test coverage detected