@@ -1990,6 +1990,39 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
19901990
19911991} // anon namespace
19921992
1993+ /* *
1994+ * Apply the undo operation of a CTxInUndo to the given chain state.
1995+ * @param undo The undo object.
1996+ * @param view The coins view to which to apply the changes.
1997+ * @param out The out point that corresponds to the tx input.
1998+ * @return True on success.
1999+ */
2000+ static bool ApplyTxInUndo (const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
2001+ {
2002+ bool fClean = true ;
2003+
2004+ CCoinsModifier coins = view.ModifyCoins (out.hash );
2005+ if (undo.nHeight != 0 ) {
2006+ // undo data contains height: this is the last output of the prevout tx being spent
2007+ if (!coins->IsPruned ())
2008+ fClean = fClean && error (" %s: undo data overwriting existing transaction" , __func__);
2009+ coins->Clear ();
2010+ coins->fCoinBase = undo.fCoinBase ;
2011+ coins->nHeight = undo.nHeight ;
2012+ coins->nVersion = undo.nVersion ;
2013+ } else {
2014+ if (coins->IsPruned ())
2015+ fClean = fClean && error (" %s: undo data adding output to missing transaction" , __func__);
2016+ }
2017+ if (coins->IsAvailable (out.n ))
2018+ fClean = fClean && error (" %s: undo data overwriting existing output" , __func__);
2019+ if (coins->vout .size () < out.n +1 )
2020+ coins->vout .resize (out.n +1 );
2021+ coins->vout [out.n ] = undo.txout ;
2022+
2023+ return fClean ;
2024+ }
2025+
19932026bool DisconnectBlock (CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool * pfClean)
19942027{
19952028 AssertLockHeld (cs_main);
@@ -2031,11 +2064,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
20312064
20322065
20332066 // Check that all outputs are available and match the outputs in the block itself
2034- // exactly. Note that transactions with only provably unspendable outputs won't
2035- // have outputs available even in the block itself, so we handle that case
2036- // specially with outsEmpty.
2067+ // exactly.
20372068 {
2038- CCoins outsEmpty;
20392069 CCoinsModifier outs = view.ModifyCoins (hash);
20402070 outs->ClearUnspendable ();
20412071
@@ -2063,24 +2093,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
20632093 for (unsigned int j = tx.vin .size (); j-- > 0 ;) {
20642094 const COutPoint& out = tx.vin [j].prevout ;
20652095 const CTxInUndo& undo = txundo.vprevout [j];
2066- CCoinsModifier coins = view.ModifyCoins (out.hash );
2067- if (undo.nHeight != 0 ) {
2068- // undo data contains height: this is the last output of the prevout tx being spent
2069- if (!coins->IsPruned ())
2070- fClean = fClean && error (" DisconnectBlock() : undo data overwriting existing transaction" );
2071- coins->Clear ();
2072- coins->fCoinBase = undo.fCoinBase ;
2073- coins->nHeight = undo.nHeight ;
2074- coins->nVersion = undo.nVersion ;
2075- } else {
2076- if (coins->IsPruned ())
2077- fClean = fClean && error (" DisconnectBlock() : undo data adding output to missing transaction" );
2078- }
2079- if (coins->IsAvailable (out.n ))
2080- fClean = fClean && error (" DisconnectBlock() : undo data overwriting existing output" );
2081- if (coins->vout .size () < out.n + 1 )
2082- coins->vout .resize (out.n + 1 );
2083- coins->vout [out.n ] = undo.txout ;
2096+ if (!ApplyTxInUndo (undo, view, out))
2097+ fClean = false ;
20842098 }
20852099
20862100 if (view.HaveInputs (tx))
@@ -2103,9 +2117,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
21032117 if (pfClean) {
21042118 *pfClean = fClean ;
21052119 return true ;
2106- } else {
2107- return fClean ;
21082120 }
2121+
2122+ return fClean ;
21092123}
21102124
21112125void static FlushBlockFile (bool fFinalize = false )
0 commit comments