@@ -2023,41 +2023,55 @@ static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const CO
20232023 return fClean ;
20242024}
20252025
2026- bool DisconnectBlock (CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool * pfClean)
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+
2033+ /* * Undo the effects of this block (with given index) on the UTXO set represented by coins.
2034+ * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. */
2035+ DisconnectResult DisconnectBlock (CBlock& block, CBlockIndex* pindex, CCoinsViewCache& view)
20272036{
20282037 AssertLockHeld (cs_main);
20292038
20302039 if (pindex->GetBlockHash () != view.GetBestBlock ())
20312040 LogPrintf (" %s : pindex=%s view=%s\n " , __func__, pindex->GetBlockHash ().GetHex (), view.GetBestBlock ().GetHex ());
20322041 assert (pindex->GetBlockHash () == view.GetBestBlock ());
20332042
2034- if (pfClean)
2035- *pfClean = false ;
2036-
20372043 bool fClean = true ;
20382044
20392045 CBlockUndo blockUndo;
20402046 CAmount nValueOut = 0 ;
20412047 CAmount nValueIn = 0 ;
20422048 CDiskBlockPos pos = pindex->GetUndoPos ();
2043- if (pos.IsNull ())
2044- return error (" DisconnectBlock() : no undo data available" );
2045- if (!UndoReadFromDisk (blockUndo, pos, pindex->pprev ->GetBlockHash ()))
2046- return error (" DisconnectBlock() : failure reading undo data" );
2049+ if (pos.IsNull ()) {
2050+ error (" DisconnectBlock() : no undo data available" );
2051+ return DISCONNECT_FAILED;
2052+ }
2053+ if (!UndoReadFromDisk (blockUndo, pos, pindex->pprev ->GetBlockHash ())) {
2054+ error (" DisconnectBlock() : failure reading undo data" );
2055+ return DISCONNECT_FAILED;
2056+ }
20472057
2048- if (blockUndo.vtxundo .size () + 1 != block.vtx .size ())
2049- return error (" DisconnectBlock() : block and undo data inconsistent" );
2058+ if (blockUndo.vtxundo .size () + 1 != block.vtx .size ()) {
2059+ error (" DisconnectBlock() : block and undo data inconsistent" );
2060+ return DISCONNECT_FAILED;
2061+ }
20502062
20512063 // Track zPIV money supply
2052- if (!UpdateZPIVSupplyDisconnect (block, pindex))
2053- return error (" %s: Failed to calculate new zPIV supply" , __func__);
2064+ if (!UpdateZPIVSupplyDisconnect (block, pindex)) {
2065+ error (" %s: Failed to calculate new zPIV supply" , __func__);
2066+ return DISCONNECT_FAILED;
2067+ }
20542068
20552069 // undo transactions in reverse order
20562070 for (int i = block.vtx .size () - 1 ; i >= 0 ; i--) {
20572071 const CTransaction& tx = block.vtx [i];
20582072
20592073 if (!DisconnectZerocoinTx (tx, nValueIn, zerocoinDB))
2060- return false ;
2074+ return DISCONNECT_FAILED ;
20612075
20622076 nValueOut += tx.GetValueOut ();
20632077 uint256 hash = tx.GetHash ();
@@ -2088,8 +2102,11 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
20882102
20892103 // restore inputs
20902104 const CTxUndo& txundo = blockUndo.vtxundo [i - 1 ];
2091- if (txundo.vprevout .size () != tx.vin .size ())
2092- return error (" DisconnectBlock() : transaction and undo data inconsistent - txundo.vprevout.siz=%d tx.vin.siz=%d" , txundo.vprevout .size (), tx.vin .size ());
2105+ if (txundo.vprevout .size () != tx.vin .size ()) {
2106+ error (" DisconnectBlock() : transaction and undo data inconsistent - txundo.vprevout.siz=%d tx.vin.siz=%d" ,
2107+ txundo.vprevout .size (), tx.vin .size ());
2108+ return DISCONNECT_FAILED;
2109+ }
20932110 for (unsigned int j = tx.vin .size (); j-- > 0 ;) {
20942111 const COutPoint& out = tx.vin [j].prevout ;
20952112 const CTxInUndo& undo = txundo.vprevout [j];
@@ -2114,12 +2131,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
21142131 DataBaseAccChecksum (pindex, false );
21152132 }
21162133
2117- if (pfClean) {
2118- *pfClean = fClean ;
2119- return true ;
2120- }
2121-
2122- return fClean ;
2134+ return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
21232135}
21242136
21252137void static FlushBlockFile (bool fFinalize = false )
@@ -2665,7 +2677,7 @@ bool static DisconnectTip(CValidationState& state)
26652677 int64_t nStart = GetTimeMicros ();
26662678 {
26672679 CCoinsViewCache view (pcoinsTip);
2668- if (! DisconnectBlock (block, state, pindexDelete, view))
2680+ if (DisconnectBlock (block, pindexDelete, view) != DISCONNECT_OK )
26692681 return error (" DisconnectTip() : DisconnectBlock %s failed" , pindexDelete->GetBlockHash ().ToString ());
26702682 assert (view.Flush ());
26712683 }
@@ -4430,15 +4442,18 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth
44304442 }
44314443 // check level 3: check for inconsistencies during memory-only disconnect of tip blocks
44324444 if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage () + pcoinsTip->DynamicMemoryUsage ()) <= nCoinCacheUsage) {
4433- bool fClean = true ;
4434- if (!DisconnectBlock (block, state, pindex, coins, &fClean ))
4435- return error (" %s: *** irrecoverable inconsistency in block data at %d, hash=%s" , __func__, pindex->nHeight , pindex->GetBlockHash ().ToString ());
4445+ DisconnectResult res = DisconnectBlock (block, pindex, coins);
4446+ if (res == DISCONNECT_FAILED) {
4447+ return error (" %s: *** irrecoverable inconsistency in block data at %d, hash=%s" , __func__,
4448+ pindex->nHeight , pindex->GetBlockHash ().ToString ());
4449+ }
44364450 pindexState = pindex->pprev ;
4437- if (! fClean ) {
4451+ if (res == DISCONNECT_UNCLEAN ) {
44384452 nGoodTransactions = 0 ;
44394453 pindexFailure = pindex;
4440- } else
4454+ } else {
44414455 nGoodTransactions += block.vtx .size ();
4456+ }
44424457 }
44434458 if (ShutdownRequested ())
44444459 return true ;
0 commit comments