@@ -2023,46 +2023,43 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
20232023
20242024} // anon namespace
20252025
2026+ enum DisconnectResult
2027+ {
2028+ DISCONNECT_OK, // All good.
2029+ DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
2030+ DISCONNECT_FAILED // Something else went wrong.
2031+ };
2032+
20262033/* *
20272034 * Apply the undo operation of a CTxInUndo to the given chain state.
20282035 * @param undo The undo object.
20292036 * @param view The coins view to which to apply the changes.
20302037 * @param out The out point that corresponds to the tx input.
2031- * @return True on success.
2038+ * @return A DisconnectResult as an int
20322039 */
2033- bool ApplyTxInUndo (const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
2040+ int ApplyTxInUndo (const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
20342041{
20352042 bool fClean = true ;
20362043
20372044 CCoinsModifier coins = view.ModifyCoins (out.hash );
20382045 if (undo.nHeight != 0 ) {
20392046 // undo data contains height: this is the last output of the prevout tx being spent
2040- if (!coins->IsPruned ())
2041- fClean = fClean && error (" %s: undo data overwriting existing transaction" , __func__);
2042- coins->Clear ();
2047+ if (!coins->IsPruned ()) fClean = false ; // overwriting existing transaction
20432048 coins->fCoinBase = undo.fCoinBase ;
20442049 coins->fCoinStake = undo.fCoinStake ;
20452050 coins->nHeight = undo.nHeight ;
20462051 coins->nVersion = undo.nVersion ;
20472052 } else {
2048- if (coins->IsPruned ())
2049- fClean = fClean && error (" %s: undo data adding output to missing transaction" , __func__);
2053+ if (coins->IsPruned ()) fClean = false ; // adding output to missing transaction
20502054 }
2051- if (coins->IsAvailable (out.n ))
2052- fClean = fClean && error (" %s: undo data overwriting existing output" , __func__);
2055+ if (coins->IsAvailable (out.n )) fClean = false ; // overwriting existing output
20532056 if (coins->vout .size () < out.n +1 )
20542057 coins->vout .resize (out.n +1 );
20552058 coins->vout [out.n ] = undo.txout ;
20562059
2057- return fClean ;
2060+ return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
20582061}
20592062
2060- enum DisconnectResult
2061- {
2062- DISCONNECT_OK, // All good.
2063- DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
2064- DISCONNECT_FAILED // Something else went wrong.
2065- };
20662063
20672064/* * Undo the effects of this block (with given index) on the UTXO set represented by coins.
20682065 * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. */
@@ -2123,8 +2120,7 @@ DisconnectResult DisconnectBlock(CBlock& block, CBlockIndex* pindex, CCoinsViewC
21232120 // but it must be corrected before txout nversion ever influences a network rule.
21242121 if (outsBlock.nVersion < 0 )
21252122 outs->nVersion = outsBlock.nVersion ;
2126- if (*outs != outsBlock)
2127- fClean = fClean && error (" %s : added transaction mismatch? database corrupted" , __func__);
2123+ if (*outs != outsBlock) fClean = false ; // transaction mismatch
21282124
21292125 // remove outputs
21302126 outs->Clear ();
@@ -2144,8 +2140,9 @@ DisconnectResult DisconnectBlock(CBlock& block, CBlockIndex* pindex, CCoinsViewC
21442140 for (unsigned int j = tx.vin .size (); j-- > 0 ;) {
21452141 const COutPoint& out = tx.vin [j].prevout ;
21462142 const CTxInUndo& undo = txundo.vprevout [j];
2147- if (!ApplyTxInUndo (undo, view, out))
2148- fClean = false ;
2143+ int res = ApplyTxInUndo (undo, view, out);
2144+ if (res == DISCONNECT_FAILED) return DISCONNECT_FAILED;
2145+ fClean = fClean && res != DISCONNECT_UNCLEAN;
21492146 }
21502147
21512148 if (view.HaveInputs (tx))
0 commit comments