@ -673,6 +673,60 @@ public:
} ) ; )
} ;
/** Undo information for a CTxIn
*
* Contains the prevout ' s CTxOut being spent , and if this was the
* last output of the affected transaction , its metadata as well
* ( coinbase or not , height , transaction version )
*/
class CTxInUndo
{
public :
CTxOut txout ; // the txout data before being spent
bool fCoinBase ; // if the outpoint was the last unspent: whether it belonged to a coinbase
unsigned int nHeight ; // if the outpoint was the last unspent: its height
int nVersion ; // if the outpoint was the last unspent: its version
CTxInUndo ( ) : txout ( ) , fCoinBase ( false ) , nHeight ( 0 ) , nVersion ( 0 ) { }
CTxInUndo ( const CTxOut & txoutIn , bool fCoinBaseIn = false , unsigned int nHeightIn = 0 , int nVersionIn = 0 ) : txout ( txoutIn ) , fCoinBase ( fCoinBaseIn ) , nHeight ( nHeightIn ) , nVersion ( nVersionIn ) { }
unsigned int GetSerializeSize ( int nType , int nVersion ) const {
return : : GetSerializeSize ( VARINT ( nHeight * 2 + ( fCoinBase ? 1 : 0 ) ) , nType , nVersion ) +
( nHeight > 0 ? : : GetSerializeSize ( VARINT ( this - > nVersion ) , nType , nVersion ) : 0 ) +
: : GetSerializeSize ( CTxOutCompressor ( REF ( txout ) ) , nType , nVersion ) ;
}
template < typename Stream >
void Serialize ( Stream & s , int nType , int nVersion ) const {
: : Serialize ( s , VARINT ( nHeight * 2 + ( fCoinBase ? 1 : 0 ) ) , nType , nVersion ) ;
if ( nHeight > 0 )
: : Serialize ( s , VARINT ( this - > nVersion ) , nType , nVersion ) ;
: : Serialize ( s , CTxOutCompressor ( REF ( txout ) ) , nType , nVersion ) ;
}
template < typename Stream >
void Unserialize ( Stream & s , int nType , int nVersion ) {
unsigned int nCode = 0 ;
: : Unserialize ( s , VARINT ( nCode ) , nType , nVersion ) ;
nHeight = nCode / 2 ;
fCoinBase = nCode & 1 ;
if ( nHeight > 0 )
: : Unserialize ( s , VARINT ( this - > nVersion ) , nType , nVersion ) ;
: : Unserialize ( s , REF ( CTxOutCompressor ( REF ( txout ) ) ) , nType , nVersion ) ;
}
} ;
/** Undo information for a CTransaction */
class CTxUndo
{
public :
std : : vector < CTxInUndo > vprevout ;
IMPLEMENT_SERIALIZE (
READWRITE ( vprevout ) ;
)
} ;
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
*
* Serialized format :
@ -874,21 +928,28 @@ public:
Cleanup ( ) ;
}
// mark an outpoint spent
bool Spend ( const COutPoint & out ) {
// mark an outpoint spent , and construct undo information
bool Spend ( const COutPoint & out , CTxInUndo & undo ) {
if ( out . n > = vout . size ( ) )
return false ;
if ( vout [ out . n ] . IsNull ( ) )
return false ;
undo = CTxInUndo ( vout [ out . n ] ) ;
vout [ out . n ] . SetNull ( ) ;
Cleanup ( ) ;
if ( vout . size ( ) = = 0 ) {
undo . nHeight = nHeight ;
undo . fCoinBase = fCoinBase ;
undo . nVersion = this - > nVersion ;
}
return true ;
}
// mark a vout spent
bool Spend ( int nPos ) {
CTxInUndo undo ;
COutPoint out ( 0 , nPos ) ;
return Spend ( out );
return Spend ( out , undo );
}
// check whether a particular output is still available