@@ -253,6 +253,61 @@ bool CBlockTreeDB::LoadBlockIndexGuts(std::function<CBlockIndex*(const uint256&)
253253 return true ;
254254}
255255
256+ namespace {
257+
258+ // ! Legacy class to deserialize pre-pertxout database entries without reindex.
259+ class CCoins
260+ {
261+ public:
262+ // ! whether transaction is a coinbase
263+ bool fCoinBase ;
264+
265+ // ! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
266+ std::vector<CTxOut> vout;
267+
268+ // ! at which height this transaction was included in the active block chain
269+ int nHeight;
270+
271+ // ! empty constructor
272+ CCoins () : fCoinBase (false ), vout(0 ), nHeight(0 ) { }
273+
274+ template <typename Stream>
275+ void Unserialize (Stream &s) {
276+ unsigned int nCode = 0 ;
277+ // version
278+ int nVersionDummy;
279+ ::Unserialize (s, VARINT(nVersionDummy));
280+ // header code
281+ ::Unserialize (s, VARINT(nCode));
282+ fCoinBase = nCode & 1 ;
283+ std::vector<bool > vAvail (2 , false );
284+ vAvail[0 ] = (nCode & 2 ) != 0 ;
285+ vAvail[1 ] = (nCode & 4 ) != 0 ;
286+ unsigned int nMaskCode = (nCode / 8 ) + ((nCode & 6 ) != 0 ? 0 : 1 );
287+ // spentness bitmask
288+ while (nMaskCode > 0 ) {
289+ unsigned char chAvail = 0 ;
290+ ::Unserialize (s, chAvail);
291+ for (unsigned int p = 0 ; p < 8 ; p++) {
292+ bool f = (chAvail & (1 << p)) != 0 ;
293+ vAvail.push_back (f);
294+ }
295+ if (chAvail != 0 )
296+ nMaskCode--;
297+ }
298+ // txouts themself
299+ vout.assign (vAvail.size (), CTxOut ());
300+ for (unsigned int i = 0 ; i < vAvail.size (); i++) {
301+ if (vAvail[i])
302+ ::Unserialize (s, REF(CTxOutCompressor(vout[i])));
303+ }
304+ // coinbase height
305+ ::Unserialize (s, VARINT(nHeight));
306+ }
307+ };
308+
309+ }
310+
256311/* * Upgrade the database from older formats.
257312 *
258313 * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
0 commit comments