diff --git a/src/core.h b/src/core.h index 9ee8b2edce3..70e62716f34 100644 --- a/src/core.h +++ b/src/core.h @@ -421,6 +421,9 @@ public: // equality test friend bool operator==(const CCoins &a, const CCoins &b) { + // Empty CCoins objects are always equal. + if (a.IsPruned() && b.IsPruned()) + return true; return a.fCoinBase == b.fCoinBase && a.nHeight == b.nHeight && a.nVersion == b.nVersion && diff --git a/src/main.cpp b/src/main.cpp index 56bd7a5cfd0..49fc7abbaf2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1750,12 +1750,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex const CTransaction &tx = block.vtx[i]; uint256 hash = tx.GetHash(); - // check that all outputs are available - if (!view.HaveCoins(hash)) { - fClean = fClean && error("DisconnectBlock() : outputs still spent? database corrupted"); - view.SetCoins(hash, CCoins()); - } - CCoins &outs = view.GetCoins(hash); + // Check that all outputs are available and match the outputs in the block itself + // exactly. Note that transactions with only provably unspendable outputs won't + // have outputs available even in the block itself, so we handle that case + // specially with outsEmpty. + CCoins outsEmpty; + CCoins &outs = view.HaveCoins(hash) ? view.GetCoins(hash) : outsEmpty; outs.ClearUnspendable(); CCoins outsBlock = CCoins(tx, pindex->nHeight);