2
 * Implement the Serialize and Unserialize methods by delegating to a single templated
 * static method that takes the to-be-(de)serialized object as a parameter. This approach
 * has the advantage that the constness of the object becomes a template parameter, and
 * thus allows a single implementation that sees the object as const for serializing
 * and non-const for deserializing, without casts.
 */
#define SERIALIZE_METHODS(cls, obj)                                                 \
    template<typename Stream>                                                       \
    void Serialize(Stream& s) const                                                 \
    {                                                                               \
        static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
        Ser(s, *this);                                                              \
    }                                                                               \
    template<typename Stream>                                                       \
    void Unserialize(Stream& s)                                                     \
    {                                                                               \
        static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
        Unser(s, *this);                                                            \
    }                                                                               \
    FORMATTER_METHODS(cls, obj)

This macro is used frequently in the Bitcoin Core. As an example in CBlockFileInfo:

class CBlockFileInfo
{
public:
    unsigned int nBlocks;      //!< number of blocks stored in file
    unsigned int nSize;        //!< number of used bytes of block file
    unsigned int nUndoSize;    //!< number of used bytes in the undo file
    unsigned int nHeightFirst; //!< lowest height of block in file
    unsigned int nHeightLast;  //!< highest height of block in file
    uint64_t nTimeFirst;       //!< earliest time of block in file
    uint64_t nTimeLast;        //!< latest time of block in file

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

Can someone explain in simple language what does this macro actually do? I tried to figure out what it does by reading the comments above it and its implementation but didn't understand anything useful.

1 Answer 1

3

They are part of Bitcoin Core's custom serialization framework.

Serialization is the process of converting objects to byte arrays, for the purpose of storing them on disk, transferring them over the network, or computing their hash.

Deserialization is the reverse process, where an object is reconstructed from a byte array.

It is implemented using a number of classes, helper functions, and macros, in serialize.h.

Specifically the code you cite for CBlockFileInfo simply means:

  • To serialize a CBlockFileInfo object obj, do the following:
    • Serialize obj.nBlocks in VARINT format
    • Serialize obj.nSize in VARINT format
    • ...
    • Serialize obj.nTimeLast in VARINT format
  • To deserialize, do the same (but with deserialize instead of serialize).

This approach makes it possible to have a single definition in the class on how to serialize/deserialize is, without needing to duplicate the code multiple times.

2
  • Thanks for your explanation. So by adding this macro to the class, we implicitly define Serialize and Unserialize member functions? Now the class CBlockFileInfo has these two members? Jul 5, 2022 at 16:55
  • 1
    @AmirrezaRiahi Exactly, along with a few others. Jul 5, 2022 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.