From: alexhz Date: Wed, 15 Jan 2014 14:34:46 +0000 (+0000) Subject: Add CTxUndo: transaction undo information X-Git-Tag: v0.4.4.7-nvc-next-testing~31 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=a19ee92bdbc1f99b2296a5af17164b36366c9fbc Add CTxUndo: transaction undo information The CTxUndo class encapsulates data necessary to undo the effects of a transaction on the txout set, namely the previous outputs consumed by it (script + amount), and potentially transaction meta-data when it is spent entirely. --- diff --git a/src/main.h b/src/main.h index 4f7e3f0..9db3dc6 100644 --- a/src/main.h +++ b/src/main.h @@ -738,6 +738,61 @@ 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 + 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 + 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 vprevout; + + IMPLEMENT_SERIALIZE( + READWRITE(vprevout); + ) +}; + + /** pruned version of CTransaction: only retains metadata and unspent transaction outputs * * Serialized format: @@ -939,21 +994,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