| 2378 | bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock); |
| 2379 | |
| 2380 | static DisconnectResult DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) |
| 2381 | { |
| 2382 | if (pfClean) |
| 2383 | *pfClean = false; |
| 2384 | |
| 2385 | bool fClean = true; |
| 2386 | |
| 2387 | CBlockUndo blockUndo; |
| 2388 | CDiskBlockPos pos = pindex->GetUndoPos(); |
| 2389 | if (pos.IsNull()) { |
| 2390 | error("DisconnectBlock() : no undo data available"); |
| 2391 | return DISCONNECT_FAILED; |
| 2392 | } |
| 2393 | if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) { |
| 2394 | error("DisconnectBlock() : failure reading undo data"); |
| 2395 | return DISCONNECT_FAILED; |
| 2396 | } |
| 2397 | |
| 2398 | if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) { |
| 2399 | error("DisconnectBlock() : block and undo data inconsistent"); |
| 2400 | return DISCONNECT_FAILED; |
| 2401 | } |
| 2402 | |
| 2403 | std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; |
| 2404 | std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > addressUnspentIndex; |
| 2405 | std::vector<std::pair<CSpentIndexKey, CSpentIndexValue> > spentIndex; |
| 2406 | |
| 2407 | // undo transactions in reverse order |
| 2408 | for (int i = block.vtx.size() - 1; i >= 0; i--) { |
| 2409 | const CTransaction& tx = block.vtx[i]; |
| 2410 | uint256 hash = tx.GetHash(); |
| 2411 | |
| 2412 | // Check that all outputs are available and match the outputs in the block itself |
| 2413 | // exactly. Note that transactions with only provably unspendable outputs won't |
| 2414 | // have outputs available even in the block itself, so we handle that case |
| 2415 | // specially with outsEmpty. |
| 2416 | { |
| 2417 | CCoinsModifier outs = view.ModifyCoins(hash); |
| 2418 | outs->ClearUnspendable(); |
| 2419 | |
| 2420 | CCoins outsBlock(tx, pindex->nHeight); |
| 2421 | // The CCoins serialization does not serialize negative numbers. |
| 2422 | // No network rules currently depend on the version here, so an inconsistency is harmless |
| 2423 | // but it must be corrected before txout nversion ever influences a network rule. |
| 2424 | if (outsBlock.nVersion < 0) |
| 2425 | outs->nVersion = outsBlock.nVersion; |
| 2426 | if (*outs != outsBlock) |
| 2427 | fClean = false; |
| 2428 | |
| 2429 | // remove outputs |
| 2430 | outs->Clear(); |
| 2431 | } |
| 2432 | |
| 2433 | if (fAddressIndex) |
| 2434 | { |
| 2435 | for (size_t k = tx.vout.size(); k-- > 0;) |
| 2436 | { |
| 2437 | CTxDestination dest; uint160 hashDest; |
no test coverage detected