<p>They are part of Bitcoin Core's custom serialization framework.</p>
<p>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.</p>
<p>Deserialization is the reverse process, where an object is reconstructed from a byte array.</p>
<p>It is implemented using a number of classes, helper functions, and macros, in <code>serialize.h</code>.</p>
<p>Specifically the code you cite for <code>CBlockFileInfo</code> simply means:</p>
<ul>
<li>To serialize a <code>CBlockFileInfo</code> object <code>obj</code>, do the following:
<ul>
<li>Serialize <code>obj.nBlocks</code> in VARINT format</li>
<li>Serialize <code>obj.nSize</code> in VARINT format</li>
<li>...</li>
<li>Serialize <code>obj.nTimeLast</code> in VARINT format</li>
</ul>
</li>
<li>To deserialize, do the same (but with deserialize instead of serialize).</li>
</ul>
<p>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.</p>

CC BY-SA 4.0
2022-07-05T16:55:58.420Z
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?
Amir reza Riahi
CC BY-SA 4.0
2022-07-05T17:23:50.137Z
@AmirrezaRiahi Exactly, along with a few others.
Pieter Wuille
CC BY-SA 4.0
2022-07-05T16:45:07.903Z
2022-07-05T16:45:07.903Z
Pieter Wuille
<pre><code> * 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&lt;typename Stream&gt;                                                       \
    void Serialize(Stream&amp; s) const                                                 \
    {                                                                               \
        static_assert(std::is_same&lt;const cls&amp;, decltype(*this)&gt;::value, &quot;Serialize type mismatch&quot;); \
        Ser(s, *this);                                                              \
    }                                                                               \
    template&lt;typename Stream&gt;                                                       \
    void Unserialize(Stream&amp; s)                                                     \
    {                                                                               \
        static_assert(std::is_same&lt;cls&amp;, decltype(*this)&gt;::value, &quot;Unserialize type mismatch&quot;); \
        Unser(s, *this);                                                            \
    }                                                                               \
    FORMATTER_METHODS(cls, obj)
</code></pre>
<p>This macro is used frequently in the Bitcoin Core. As an example in <code>CBlockFileInfo</code>:</p>
<pre><code>class CBlockFileInfo
{
public:
    unsigned int nBlocks;      //!&lt; number of blocks stored in file
    unsigned int nSize;        //!&lt; number of used bytes of block file
    unsigned int nUndoSize;    //!&lt; number of used bytes in the undo file
    unsigned int nHeightFirst; //!&lt; lowest height of block in file
    unsigned int nHeightLast;  //!&lt; highest height of block in file
    uint64_t nTimeFirst;       //!&lt; earliest time of block in file
    uint64_t nTimeLast;        //!&lt; 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));
    }
</code></pre>
<p>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.</p>

<bitcoin-core><bitcoin-core-development>
what is SERIALIZE_METHODS macro in the Bitcoin Core?
Amir reza Riahi
# what is SERIALIZE_METHODS macro in the Bitcoin Core?

(Asked by: username_0 on 2022-07-05)

```
 * 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.

**Tags:** bitcoin-core, bitcoin-core-development


---

## 1 answers

### Answer by username_1 on 2022-07-05. Score: 3 | Accepted answer

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.

> **Comments:**
> **username_0**: 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?  
> **username_1**: @username_0 Exactly, along with a few others.  

---

