@ -1248,46 +1248,42 @@ bool AbortNode(CValidationState& state, const std::string& strMessage, const std
} // anon namespace
} // anon namespace
enum DisconnectResult
{
DISCONNECT_OK , // All good.
DISCONNECT_UNCLEAN , // Rolled back, but UTXO set was inconsistent with block.
DISCONNECT_FAILED // Something else went wrong.
} ;
/**
/**
* Apply the undo operation of a CTxInUndo to the given chain state .
* Apply the undo operation of a CTxInUndo to the given chain state .
* @ param undo The undo object .
* @ param undo The undo object .
* @ param view The coins view to which to apply the changes .
* @ param view The coins view to which to apply the changes .
* @ param out The out point that corresponds to the tx input .
* @ param out The out point that corresponds to the tx input .
* @ return True on success .
* @ return A DisconnectResult as an int
*/
*/
bool ApplyTxInUndo ( const CTxInUndo & undo , CCoinsViewCache & view , const COutPoint & out )
int ApplyTxInUndo ( const CTxInUndo & undo , CCoinsViewCache & view , const COutPoint & out )
{
{
bool fClean = true ;
bool fClean = true ;
CCoinsModifier coins = view . ModifyCoins ( out . hash ) ;
CCoinsModifier coins = view . ModifyCoins ( out . hash ) ;
if ( undo . nHeight ! = 0 ) {
if ( undo . nHeight ! = 0 ) {
// undo data contains height: this is the last output of the prevout tx being spent
// undo data contains height: this is the last output of the prevout tx being spent
if ( ! coins - > IsPruned ( ) )
if ( ! coins - > IsPruned ( ) ) fClean = false ; // overwriting existing transaction
fClean = fClean & & error ( " %s: undo data overwriting existing transaction " , __func__ ) ;
coins - > Clear ( ) ;
coins - > fCoinBase = undo . fCoinBase ;
coins - > fCoinBase = undo . fCoinBase ;
coins - > nHeight = undo . nHeight ;
coins - > nHeight = undo . nHeight ;
coins - > nVersion = undo . nVersion ;
coins - > nVersion = undo . nVersion ;
} else {
} else {
if ( coins - > IsPruned ( ) )
if ( coins - > IsPruned ( ) ) fClean = false ; // adding output to missing transaction
fClean = fClean & & error ( " %s: undo data adding output to missing transaction " , __func__ ) ;
}
}
if ( coins - > IsAvailable ( out . n ) )
if ( coins - > IsAvailable ( out . n ) ) fClean = false ; // overwriting existing output
fClean = fClean & & error ( " %s: undo data overwriting existing output " , __func__ ) ;
if ( coins - > vout . size ( ) < out . n + 1 )
if ( coins - > vout . size ( ) < out . n + 1 )
coins - > vout . resize ( out . n + 1 ) ;
coins - > vout . resize ( out . n + 1 ) ;
coins - > vout [ out . n ] = undo . txout ;
coins - > vout [ out . n ] = undo . txout ;
return fClean ;
return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN ;
}
}
enum DisconnectResult
{
DISCONNECT_OK , // All good.
DISCONNECT_UNCLEAN , // Rolled back, but UTXO set was inconsistent with block.
DISCONNECT_FAILED // Something else went wrong.
} ;
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
* When UNCLEAN or FAILED is returned , view is left in an indeterminate state . */
* When UNCLEAN or FAILED is returned , view is left in an indeterminate state . */
static DisconnectResult DisconnectBlock ( const CBlock & block , const CBlockIndex * pindex , CCoinsViewCache & view )
static DisconnectResult DisconnectBlock ( const CBlock & block , const CBlockIndex * pindex , CCoinsViewCache & view )
@ -1329,8 +1325,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex*
// but it must be corrected before txout nversion ever influences a network rule.
// but it must be corrected before txout nversion ever influences a network rule.
if ( outsBlock . nVersion < 0 )
if ( outsBlock . nVersion < 0 )
outs - > nVersion = outsBlock . nVersion ;
outs - > nVersion = outsBlock . nVersion ;
if ( * outs ! = outsBlock )
if ( * outs ! = outsBlock ) fClean = false ; // transaction mismatch
fClean = fClean & & error ( " DisconnectBlock(): added transaction mismatch? database corrupted " ) ;
// remove outputs
// remove outputs
outs - > Clear ( ) ;
outs - > Clear ( ) ;
@ -1346,8 +1341,9 @@ static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex*
for ( unsigned int j = tx . vin . size ( ) ; j - - > 0 ; ) {
for ( unsigned int j = tx . vin . size ( ) ; j - - > 0 ; ) {
const COutPoint & out = tx . vin [ j ] . prevout ;
const COutPoint & out = tx . vin [ j ] . prevout ;
const CTxInUndo & undo = txundo . vprevout [ j ] ;
const CTxInUndo & undo = txundo . vprevout [ j ] ;
if ( ! ApplyTxInUndo ( undo , view , out ) )
int res = ApplyTxInUndo ( undo , view , out ) ;
fClean = false ;
if ( res = = DISCONNECT_FAILED ) return DISCONNECT_FAILED ;
fClean = fClean & & res ! = DISCONNECT_UNCLEAN ;
}
}
}
}
}
}