mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-28 16:36:04 +01:00
Merge #17896: Serialization improvements (step 2)
9b66083788Convert chain to new serialization (Pieter Wuille)2f1b2f4ed0Convert VARINT to the formatter/Using approach (Pieter Wuille)ca62563df3Add a generic approach for (de)serialization of objects using code in other classes (Pieter Wuille) Pull request description: This is a second carve-out from #10785. This introduces a const-correct generic approach for serializing objects using custom serializers (defined separately from the object being serialized), then converts VARINT to use that approach, and then converts chain.h to the new framework (including the new const-correct VARINT macro). ACKs for top commit: jamesob: ACK9b66083788([`jamesob/ackr/17896.1.sipa.serialization_improvemen`](https://github.com/jamesob/bitcoin/tree/ackr/17896.1.sipa.serialization_improvemen)) ryanofsky: Code review ACK9b66083788. Only change since last review is suggested lvalue reference tweak Tree-SHA512: 2da4af1754699cb223d6beae44c587555e39ef6951448488a04783c92e2dfd4a305934f71cc3a75d06faf6d722723d8cdbd5ccb12039783f8d62039b83987bb8
This commit is contained in:
56
src/chain.h
56
src/chain.h
@@ -48,17 +48,15 @@ public:
|
||||
uint64_t nTimeFirst; //!< earliest time of block in file
|
||||
uint64_t nTimeLast; //!< latest time of block in file
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(VARINT(nBlocks));
|
||||
READWRITE(VARINT(nSize));
|
||||
READWRITE(VARINT(nUndoSize));
|
||||
READWRITE(VARINT(nHeightFirst));
|
||||
READWRITE(VARINT(nHeightLast));
|
||||
READWRITE(VARINT(nTimeFirst));
|
||||
READWRITE(VARINT(nTimeLast));
|
||||
SERIALIZE_METHODS(CBlockFileInfo, obj)
|
||||
{
|
||||
READWRITE(VARINT(obj.nBlocks));
|
||||
READWRITE(VARINT(obj.nSize));
|
||||
READWRITE(VARINT(obj.nUndoSize));
|
||||
READWRITE(VARINT(obj.nHeightFirst));
|
||||
READWRITE(VARINT(obj.nHeightLast));
|
||||
READWRITE(VARINT(obj.nTimeFirst));
|
||||
READWRITE(VARINT(obj.nTimeLast));
|
||||
}
|
||||
|
||||
void SetNull() {
|
||||
@@ -332,31 +330,25 @@ public:
|
||||
hashPrev = (pprev ? pprev->GetBlockHash() : uint256());
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
SERIALIZE_METHODS(CDiskBlockIndex, obj)
|
||||
{
|
||||
int _nVersion = s.GetVersion();
|
||||
if (!(s.GetType() & SER_GETHASH))
|
||||
READWRITE(VARINT(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT(_nVersion, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
|
||||
READWRITE(VARINT(nHeight, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
READWRITE(VARINT(nStatus));
|
||||
READWRITE(VARINT(nTx));
|
||||
if (nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO))
|
||||
READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
if (nStatus & BLOCK_HAVE_DATA)
|
||||
READWRITE(VARINT(nDataPos));
|
||||
if (nStatus & BLOCK_HAVE_UNDO)
|
||||
READWRITE(VARINT(nUndoPos));
|
||||
READWRITE(VARINT(obj.nHeight, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
READWRITE(VARINT(obj.nStatus));
|
||||
READWRITE(VARINT(obj.nTx));
|
||||
if (obj.nStatus & (BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO)) READWRITE(VARINT(obj.nFile, VarIntMode::NONNEGATIVE_SIGNED));
|
||||
if (obj.nStatus & BLOCK_HAVE_DATA) READWRITE(VARINT(obj.nDataPos));
|
||||
if (obj.nStatus & BLOCK_HAVE_UNDO) READWRITE(VARINT(obj.nUndoPos));
|
||||
|
||||
// block header
|
||||
READWRITE(this->nVersion);
|
||||
READWRITE(hashPrev);
|
||||
READWRITE(hashMerkleRoot);
|
||||
READWRITE(nTime);
|
||||
READWRITE(nBits);
|
||||
READWRITE(nNonce);
|
||||
READWRITE(obj.nVersion);
|
||||
READWRITE(obj.hashPrev);
|
||||
READWRITE(obj.hashMerkleRoot);
|
||||
READWRITE(obj.nTime);
|
||||
READWRITE(obj.nBits);
|
||||
READWRITE(obj.nNonce);
|
||||
}
|
||||
|
||||
uint256 GetBlockHash() const
|
||||
|
||||
@@ -442,26 +442,48 @@ I ReadVarInt(Stream& is)
|
||||
}
|
||||
}
|
||||
|
||||
#define VARINT(obj, ...) WrapVarInt<__VA_ARGS__>(REF(obj))
|
||||
/** Simple wrapper class to serialize objects using a formatter; used by Using(). */
|
||||
template<typename Formatter, typename T>
|
||||
class Wrapper
|
||||
{
|
||||
static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
|
||||
protected:
|
||||
T m_object;
|
||||
public:
|
||||
explicit Wrapper(T obj) : m_object(obj) {}
|
||||
template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
|
||||
template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
|
||||
};
|
||||
|
||||
/** Cause serialization/deserialization of an object to be done using a specified formatter class.
|
||||
*
|
||||
* To use this, you need a class Formatter that has public functions Ser(stream, const object&) for
|
||||
* serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside
|
||||
* READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).
|
||||
*
|
||||
* This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is
|
||||
* const during serialization, and non-const during deserialization, which maintains const
|
||||
* correctness.
|
||||
*/
|
||||
template<typename Formatter, typename T>
|
||||
static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
|
||||
|
||||
#define VARINT(obj, ...) Using<VarIntFormatter<__VA_ARGS__>>(obj)
|
||||
#define COMPACTSIZE(obj) CCompactSize(REF(obj))
|
||||
#define LIMITED_STRING(obj,n) LimitedString< n >(REF(obj))
|
||||
|
||||
template<VarIntMode Mode, typename I>
|
||||
class CVarInt
|
||||
/** Serialization wrapper class for integers in VarInt format. */
|
||||
template<VarIntMode Mode=VarIntMode::DEFAULT>
|
||||
struct VarIntFormatter
|
||||
{
|
||||
protected:
|
||||
I &n;
|
||||
public:
|
||||
explicit CVarInt(I& nIn) : n(nIn) { }
|
||||
|
||||
template<typename Stream>
|
||||
void Serialize(Stream &s) const {
|
||||
WriteVarInt<Stream,Mode,I>(s, n);
|
||||
template<typename Stream, typename I> void Ser(Stream &s, I v)
|
||||
{
|
||||
WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
n = ReadVarInt<Stream,Mode,I>(s);
|
||||
template<typename Stream, typename I> void Unser(Stream& s, I& v)
|
||||
{
|
||||
v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -546,9 +568,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<VarIntMode Mode=VarIntMode::DEFAULT, typename I>
|
||||
CVarInt<Mode, I> WrapVarInt(I& n) { return CVarInt<Mode, I>{n}; }
|
||||
|
||||
template<typename I>
|
||||
BigEndian<I> WrapBigEndian(I& n) { return BigEndian<I>(n); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user