Skip to content

Commit

Permalink
Convert undo.h to new serialization framework
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa authored and furszy committed Jul 3, 2021
1 parent a926ba3 commit e107a0c
Showing 1 changed file with 17 additions and 62 deletions.
79 changes: 17 additions & 62 deletions src/undo.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,90 +13,51 @@
#include "primitives/transaction.h"
#include "serialize.h"

/** Undo information for a CTxIn
/** Formatter for undo information for a CTxIn
*
* Contains the prevout's CTxOut being spent, and its metadata as well
* (coinbase/coinstake or not, height). The serialization contains a
* dummy value of zero. This is be compatible with older versions which
* expect to see the transaction version there.
*/
class TxInUndoSerializer
struct TxInUndoFormatter
{
const Coin* txout;

public:
template <typename Stream>
void Serialize(Stream& s) const {
::Serialize(s, VARINT(txout->nHeight * 4 + (txout->fCoinBase ? 2u : 0u) + (txout->fCoinStake ? 1u : 0u)));
if (txout->nHeight > 0) {
template<typename Stream>
void Ser(Stream &s, const Coin& txout) {
::Serialize(s, VARINT(txout.nHeight * 4 + (txout.fCoinBase ? 2u : 0u) + (txout.fCoinStake ? 1u : 0u)));
if (txout.nHeight > 0) {
// Required to maintain compatibility with older undo format.
::Serialize(s, (unsigned char)0);
}
::Serialize(s, Using<TxOutCompression>(REF(txout->out)));
::Serialize(s, Using<TxOutCompression>(txout.out));
}

TxInUndoSerializer(const Coin* coin) : txout(coin) {}
};

class TxInUndoDeserializer
{
Coin* txout;

public:
template <typename Stream>
void Unserialize(Stream& s)
{
template<typename Stream>
void Unser(Stream &s, Coin& txout) {
unsigned int nCode = 0;
::Unserialize(s, VARINT(nCode));
txout->nHeight = nCode >> 2;
txout->fCoinBase = nCode & 2;
txout->fCoinStake = nCode & 1;
if (txout->nHeight > 0) {
txout.nHeight = nCode >> 2;
txout.fCoinBase = nCode & 2;
txout.fCoinStake = nCode & 1;
if (txout.nHeight > 0) {
// Old versions stored the version number for the last spend of
// a transaction's outputs. Non-final spends were indicated with
// height = 0.
unsigned int nVersionDummy;
::Unserialize(s, VARINT(nVersionDummy));
}
::Unserialize(s, Using<TxOutCompression>(REF(txout->out)));
::Unserialize(s, Using<TxOutCompression>(txout.out));
}

TxInUndoDeserializer(Coin* coin) : txout(coin) {}
};

static const size_t MAX_INPUTS_PER_BLOCK = MAX_BLOCK_SIZE_CURRENT / ::GetSerializeSize(CTxIn(), PROTOCOL_VERSION);

/** Undo information for a CTransaction */
class CTxUndo
{
public:
// undo information for all txins
std::vector<Coin> vprevout;

template <typename Stream>
void Serialize(Stream& s) const
{
// TODO: avoid reimplementing vector serializer
uint64_t count = vprevout.size();
::Serialize(s, COMPACTSIZE(REF(count)));
for (const auto& prevout : vprevout) {
::Serialize(s, TxInUndoSerializer(&prevout));
}
}

template <typename Stream>
void Unserialize(Stream& s)
{
// TODO: avoid reimplementing vector deserializer
uint64_t count = 0;
::Unserialize(s, COMPACTSIZE(count));
if (count > MAX_INPUTS_PER_BLOCK) {
throw std::ios_base::failure("Too many input undo records");
}
vprevout.resize(count);
for (auto& prevout : vprevout) {
::Unserialize(s, TxInUndoDeserializer(&prevout));
}
}
SERIALIZE_METHODS(CTxUndo, obj) { READWRITE(Using<VectorFormatter<TxInUndoFormatter>>(obj.vprevout)); }
};

/** Undo information for a CBlock */
Expand All @@ -105,13 +66,7 @@ class CBlockUndo
public:
std::vector<CTxUndo> vtxundo; // for all but the coinbase

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(vtxundo);
}
SERIALIZE_METHODS(CBlockUndo, obj) { READWRITE(obj.vtxundo); }
};

#endif // BITCOIN_UNDO_H

0 comments on commit e107a0c

Please sign in to comment.