Skip to content

Commit

Permalink
Convert undo.h to new serialization framework
Browse files Browse the repository at this point in the history
Summary:
This is a partial backport of Core [[bitcoin/bitcoin#18021 | PR18021]] [4/4]
bitcoin/bitcoin@3c94b00

Depends on D8744

There are some important differences in the deserialization, due to  differences in how the  `Coin` object is implemented (coins.h)

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, majcosta

Reviewed By: #bitcoin_abc, majcosta

Subscribers: majcosta

Differential Revision: https://reviews.bitcoinabc.org/D8745
  • Loading branch information
sipa authored and PiRK committed Dec 23, 2020
1 parent 295f251 commit 74eb604
Showing 1 changed file with 13 additions and 51 deletions.
64 changes: 13 additions & 51 deletions src/undo.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,25 @@ class CCoinsViewCache;
class BlockValidationState;

/**
* 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
* or not, height). The serialization contains a dummy value of zero. This is
* compatible with older versions which expect to see the transaction version
* there.
*/
class TxInUndoSerializer {
const Coin *pcoin;

public:
explicit TxInUndoSerializer(const Coin *pcoinIn) : pcoin(pcoinIn) {}

template <typename Stream> void Serialize(Stream &s) const {
struct TxInUndoFormatter {
template <typename Stream> void Ser(Stream &s, const Coin &txout) {
::Serialize(
s, VARINT(pcoin->GetHeight() * 2 + (pcoin->IsCoinBase() ? 1 : 0)));
if (pcoin->GetHeight() > 0) {
s, VARINT(txout.GetHeight() * 2 + (txout.IsCoinBase() ? 1 : 0)));
if (txout.GetHeight() > 0) {
// Required to maintain compatibility with older undo format.
::Serialize(s, uint8_t(0));
}
::Serialize(s, Using<TxOutCompression>(REF(pcoin->GetTxOut())));
::Serialize(s, Using<TxOutCompression>(txout.GetTxOut()));
}
};

class TxInUndoDeserializer {
Coin *pcoin;

public:
explicit TxInUndoDeserializer(Coin *pcoinIn) : pcoin(pcoinIn) {}

template <typename Stream> void Unserialize(Stream &s) {
template <typename Stream> void Unser(Stream &s, Coin &txout) {
uint32_t nCode = 0;
::Unserialize(s, VARINT(nCode));
uint32_t nHeight = nCode / 2;
Expand All @@ -63,42 +51,21 @@ class TxInUndoDeserializer {
::Unserialize(s, VARINT(nVersionDummy));
}

CTxOut txout;
::Unserialize(s, Using<TxOutCompression>(REF(txout)));
CTxOut out;
::Unserialize(s, Using<TxOutCompression>(out));

*pcoin = Coin(std::move(txout), nHeight, fCoinBase);
txout = Coin(std::move(out), nHeight, fCoinBase);
}
};

static const size_t MAX_INPUTS_PER_TX =
MAX_TX_SIZE / ::GetSerializeSize(CTxIn(), PROTOCOL_VERSION);

/** Restore the UTXO in a Coin at a given COutPoint */
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_TX) {
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));
}
};

Expand All @@ -108,12 +75,7 @@ class CBlockUndo {
// For all but the coinbase
std::vector<CTxUndo> vtxundo;

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); }
};

/**
Expand Down

0 comments on commit 74eb604

Please sign in to comment.