LCOV - code coverage report
Current view: top level - src - serialize.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 479 508 94.3 %
Date: 2026-06-25 07:23:43 Functions: 3768 4214 89.4 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_SERIALIZE_H
       7             : #define BITCOIN_SERIALIZE_H
       8             : 
       9             : #include <compat/endian.h>
      10             : 
      11             : #include <algorithm>
      12             : #include <atomic>
      13             : #include <concepts>
      14             : #include <cstdint>
      15             : #include <cstring>
      16             : #include <ios>
      17             : #include <limits>
      18             : #include <list>
      19             : #include <map>
      20             : #include <memory>
      21             : #include <optional>
      22             : #include <set>
      23             : #include <string>
      24             : #include <string.h>
      25             : #include <unordered_map>
      26             : #include <unordered_set>
      27             : #include <utility>
      28             : #include <vector>
      29             : 
      30             : #include <support/allocators/secure.h>
      31             : #include <prevector.h>
      32             : #include <span.h>
      33             : 
      34             : /**
      35             :  * The maximum size of a serialized object in bytes or number of elements
      36             :  * (for eg vectors) when the size is encoded as CompactSize.
      37             :  */
      38             : static constexpr uint64_t MAX_SIZE = 0x02000000;
      39             : 
      40             : /** Maximum amount of memory (in bytes) to allocate at once when deserializing vectors. */
      41             : static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
      42             : 
      43             : /**
      44             :  * Dummy data type to identify deserializing constructors.
      45             :  *
      46             :  * By convention, a constructor of a type T with signature
      47             :  *
      48             :  *   template <typename Stream> T::T(deserialize_type, Stream& s)
      49             :  *
      50             :  * is a deserializing constructor, which builds the type by
      51             :  * deserializing it from s. If T contains const fields, this
      52             :  * is likely the only way to do so.
      53             :  */
      54             : struct deserialize_type {};
      55             : constexpr deserialize_type deserialize {};
      56             : 
      57             : /*
      58             :  * Lowest-level serialization and conversion.
      59             :  */
      60   136065528 : template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
      61             : {
      62   136065528 :     s.write(AsBytes(Span{&obj, 1}));
      63   136065528 : }
      64     1872001 : template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
      65             : {
      66     1872001 :     obj = htole16_internal(obj);
      67     1872001 :     s.write(AsBytes(Span{&obj, 1}));
      68     1872001 : }
      69             : template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
      70             : {
      71             :     obj = htobe16_internal(obj);
      72             :     s.write(AsBytes(Span{&obj, 1}));
      73             : }
      74   122879265 : template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
      75             : {
      76   122879265 :     obj = htole32_internal(obj);
      77   122879265 :     s.write(AsBytes(Span{&obj, 1}));
      78   122879265 : }
      79      304821 : template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
      80             : {
      81      304821 :     obj = htobe32_internal(obj);
      82      304821 :     s.write(AsBytes(Span{&obj, 1}));
      83      304821 : }
      84   115322470 : template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
      85             : {
      86   115322470 :     obj = htole64_internal(obj);
      87   115322470 :     s.write(AsBytes(Span{&obj, 1}));
      88   115322470 : }
      89    30577560 : template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
      90             : {
      91             :     uint8_t obj;
      92    30577560 :     s.read(AsWritableBytes(Span{&obj, 1}));
      93    30577560 :     return obj;
      94             : }
      95     4304397 : template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
      96             : {
      97             :     uint16_t obj;
      98     4304397 :     s.read(AsWritableBytes(Span{&obj, 1}));
      99     4304397 :     return le16toh_internal(obj);
     100             : }
     101             : template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
     102             : {
     103             :     uint16_t obj;
     104             :     s.read(AsWritableBytes(Span{&obj, 1}));
     105             :     return be16toh_internal(obj);
     106             : }
     107    19585613 : template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
     108             : {
     109             :     uint32_t obj;
     110    19585613 :     s.read(AsWritableBytes(Span{&obj, 1}));
     111    19585613 :     return le32toh_internal(obj);
     112             : }
     113       11114 : template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
     114             : {
     115             :     uint32_t obj;
     116       11114 :     s.read(AsWritableBytes(Span{&obj, 1}));
     117       11114 :     return be32toh_internal(obj);
     118             : }
     119    46697726 : template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
     120             : {
     121             :     uint64_t obj;
     122    46697726 :     s.read(AsWritableBytes(Span{&obj, 1}));
     123    46697726 :     return le64toh_internal(obj);
     124             : }
     125             : 
     126             : 
     127             : /////////////////////////////////////////////////////////////////
     128             : //
     129             : // Templates for serializing to anything that looks like a stream,
     130             : // i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>)
     131             : //
     132             : 
     133             : class CSizeComputer;
     134             : 
     135             : enum
     136             : {
     137             :     // primary actions
     138             :     SER_NETWORK         = (1 << 0),
     139             :     SER_DISK            = (1 << 1),
     140             :     SER_GETHASH         = (1 << 2),
     141             : };
     142             : 
     143             : //! Convert the reference base type to X, without changing constness or reference type.
     144     5506789 : template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
     145    49303140 : template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
     146             : 
     147             : #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
     148             : #define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
     149             : #define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
     150             : #define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
     151             : 
     152             : /**
     153             :  * Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
     154             :  *
     155             :  * Both Ser and Unser are delegated to a single static method SerializationOps, which is polymorphic
     156             :  * in the serialized/deserialized type (allowing it to be const when serializing, and non-const when
     157             :  * deserializing).
     158             :  *
     159             :  * Example use:
     160             :  *   struct FooFormatter {
     161             :  *     FORMATTER_METHODS(Class, obj) { READWRITE(obj.val1, VARINT(obj.val2)); }
     162             :  *   }
     163             :  *   would define a class FooFormatter that defines a serialization of Class objects consisting
     164             :  *   of serializing its val1 member using the default serialization, and its val2 member using
     165             :  *   VARINT serialization. That FooFormatter can then be used in statements like
     166             :  *   READWRITE(Using<FooFormatter>(obj.bla)).
     167             :  */
     168             : #define FORMATTER_METHODS(cls, obj) \
     169             :     template<typename Stream> \
     170             :     static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, CSerActionSerialize()); } \
     171             :     template<typename Stream> \
     172             :     static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, CSerActionUnserialize()); } \
     173             :     template<typename Stream, typename Type, typename Operation> \
     174             :     static inline void SerializationOps(Type& obj, Stream& s, Operation ser_action) \
     175             : 
     176             : /**
     177             :  * Implement the Serialize and Unserialize methods by delegating to a single templated
     178             :  * static method that takes the to-be-(de)serialized object as a parameter. This approach
     179             :  * has the advantage that the constness of the object becomes a template parameter, and
     180             :  * thus allows a single implementation that sees the object as const for serializing
     181             :  * and non-const for deserializing, without casts.
     182             :  */
     183             : #define SERIALIZE_METHODS(cls, obj)                                                 \
     184             :     template<typename Stream>                                                       \
     185             :     void Serialize(Stream& s) const                                                 \
     186             :     {                                                                               \
     187             :         static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
     188             :         Ser(s, *this);                                                              \
     189             :     }                                                                               \
     190             :     template<typename Stream>                                                       \
     191             :     void Unserialize(Stream& s)                                                     \
     192             :     {                                                                               \
     193             :         static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
     194             :         Unser(s, *this);                                                            \
     195             :     }                                                                               \
     196             :     FORMATTER_METHODS(cls, obj)
     197             : 
     198             : // clang-format off
     199             : 
     200             : // Typically int8_t and char are distinct types, but some systems may define int8_t
     201             : // in terms of char. Forbid serialization of char in the typical case, but allow it if
     202             : // it's the only way to describe an int8_t.
     203             : template<class T>
     204             : concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
     205             : 
     206             : template <typename Stream, CharNotInt8 V> void Serialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
     207           1 : template <typename Stream> void Serialize(Stream& s, std::byte a) { ser_writedata8(s, uint8_t(a)); }
     208           2 : template<typename Stream> inline void Serialize(Stream& s, int8_t a  ) { ser_writedata8(s, a); }
     209    22570065 : template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
     210      130902 : template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
     211      412996 : template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
     212    32754067 : template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
     213    90107555 : template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
     214    23928219 : template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
     215    91425465 : template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
     216     3153763 : template <typename Stream, BasicByte B, int N> void Serialize(Stream& s, const B (&a)[N]) { s.write(MakeByteSpan(a)); }
     217             : template <typename Stream, BasicByte B, std::size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { s.write(MakeByteSpan(a)); }
     218     1219270 : template <typename Stream, BasicByte B> void Serialize(Stream& s, Span<B> span) { s.write(AsBytes(span)); }
     219             : 
     220             : template <typename Stream, CharNotInt8 V> void Unserialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
     221           1 : template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte{ser_readdata8(s)}; }
     222           1 : template<typename Stream> inline void Unserialize(Stream& s, int8_t& a  ) { a = ser_readdata8(s); }
     223     3345916 : template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
     224      573952 : template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
     225     2821333 : template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
     226     6078531 : template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
     227    13489182 : template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
     228     3475313 : template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
     229    43253378 : template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
     230     2543910 : template <typename Stream, BasicByte B, int N> void Unserialize(Stream& s, B (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
     231             : template <typename Stream, BasicByte B, std::size_t N> void Unserialize(Stream& s, std::array<B, N>& a) { s.read(MakeWritableByteSpan(a)); }
     232      588441 : template <typename Stream, BasicByte B> void Unserialize(Stream& s, Span<B> span) { s.read(AsWritableBytes(span)); }
     233             : 
     234      402067 : template <typename Stream> inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); }
     235      194695 : template <typename Stream> inline void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; }
     236             : // clang-format on
     237             : 
     238             : 
     239             : /**
     240             :  * Compact Size
     241             :  * size <  253        -- 1 byte
     242             :  * size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
     243             :  * size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
     244             :  * size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
     245             :  */
     246    37558773 : inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
     247             : {
     248    37558773 :     if (nSize < 253)             return sizeof(unsigned char);
     249     1966382 :     else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);
     250       51037 :     else if (nSize <= std::numeric_limits<unsigned int>::max())  return sizeof(unsigned char) + sizeof(unsigned int);
     251           0 :     else                         return sizeof(unsigned char) + sizeof(uint64_t);
     252    37558773 : }
     253             : 
     254             : inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
     255             : 
     256             : template<typename Stream>
     257    54293422 : void WriteCompactSize(Stream& os, uint64_t nSize)
     258             : {
     259    54293422 :     if (nSize < 253)
     260             :     {
     261    52928456 :         ser_writedata8(os, nSize);
     262    52928456 :     }
     263     1364966 :     else if (nSize <= std::numeric_limits<uint16_t>::max())
     264             :     {
     265     1328070 :         ser_writedata8(os, 253);
     266     1328070 :         ser_writedata16(os, nSize);
     267     1328070 :     }
     268       36896 :     else if (nSize <= std::numeric_limits<unsigned int>::max())
     269             :     {
     270       36896 :         ser_writedata8(os, 254);
     271       36896 :         ser_writedata32(os, nSize);
     272       36896 :     }
     273             :     else
     274             :     {
     275           0 :         ser_writedata8(os, 255);
     276           0 :         ser_writedata64(os, nSize);
     277             :     }
     278    54293422 :     return;
     279             : }
     280             : 
     281             : /**
     282             :  * Decode a CompactSize-encoded variable-length integer.
     283             :  *
     284             :  * As these are primarily used to encode the size of vector-like serializations, by default a range
     285             :  * check is performed. When used as a generic number encoding, range_check should be set to false.
     286             :  */
     287             : template<typename Stream>
     288    18135877 : uint64_t ReadCompactSize(Stream& is, bool range_check = true)
     289             : {
     290    18135877 :     uint8_t chSize = ser_readdata8(is);
     291    18135877 :     uint64_t nSizeRet = 0;
     292    18135877 :     if (chSize < 253)
     293             :     {
     294    17209064 :         nSizeRet = chSize;
     295    17209064 :     }
     296      926813 :     else if (chSize == 253)
     297             :     {
     298      909111 :         nSizeRet = ser_readdata16(is);
     299      909111 :         if (nSizeRet < 253)
     300           2 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     301      909109 :     }
     302       17702 :     else if (chSize == 254)
     303             :     {
     304       17695 :         nSizeRet = ser_readdata32(is);
     305       17695 :         if (nSizeRet < 0x10000u)
     306           2 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     307       17693 :     }
     308             :     else
     309             :     {
     310           7 :         nSizeRet = ser_readdata64(is);
     311           7 :         if (nSizeRet < 0x100000000ULL)
     312           5 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     313             :     }
     314    18135868 :     if (range_check && nSizeRet > MAX_SIZE) {
     315           2 :         throw std::ios_base::failure("ReadCompactSize(): size too large");
     316             :     }
     317    18135866 :     return nSizeRet;
     318           0 : }
     319             : 
     320             : /**
     321             :  * Variable-length integers: bytes are a MSB base-128 encoding of the number.
     322             :  * The high bit in each byte signifies whether another digit follows. To make
     323             :  * sure the encoding is one-to-one, one is subtracted from all but the last digit.
     324             :  * Thus, the byte sequence a[] with length len, where all but the last byte
     325             :  * has bit 128 set, encodes the number:
     326             :  *
     327             :  *  (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
     328             :  *
     329             :  * Properties:
     330             :  * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
     331             :  * * Every integer has exactly one encoding
     332             :  * * Encoding does not depend on size of original integer type
     333             :  * * No redundancy: every (infinite) byte sequence corresponds to a list
     334             :  *   of encoded integers.
     335             :  *
     336             :  * 0:         [0x00]  256:        [0x81 0x00]
     337             :  * 1:         [0x01]  16383:      [0xFE 0x7F]
     338             :  * 127:       [0x7F]  16384:      [0xFF 0x00]
     339             :  * 128:  [0x80 0x00]  16511:      [0xFF 0x7F]
     340             :  * 255:  [0x80 0x7F]  65535: [0x82 0xFE 0x7F]
     341             :  * 2^32:           [0x8E 0xFE 0xFE 0xFF 0x00]
     342             :  */
     343             : 
     344             : /**
     345             :  * Mode for encoding VarInts.
     346             :  *
     347             :  * Currently there is no support for signed encodings. The default mode will not
     348             :  * compile with signed values, and the legacy "nonnegative signed" mode will
     349             :  * accept signed values, but improperly encode and decode them if they are
     350             :  * negative. In the future, the DEFAULT mode could be extended to support
     351             :  * negative numbers in a backwards compatible way, and additional modes could be
     352             :  * added to support different varint formats (e.g. zigzag encoding).
     353             :  */
     354             : enum class VarIntMode { DEFAULT, NONNEGATIVE_SIGNED };
     355             : 
     356             : template <VarIntMode Mode, typename I>
     357             : struct CheckVarIntMode {
     358    56887712 :     constexpr CheckVarIntMode()
     359    28443856 :     {
     360             :         static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value, "Unsigned type required with mode DEFAULT.");
     361             :         static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed<I>::value, "Signed type required with mode NONNEGATIVE_SIGNED.");
     362    56887712 :     }
     363             : };
     364             : 
     365             : template<VarIntMode Mode, typename I>
     366             : inline unsigned int GetSizeOfVarInt(I n)
     367             : {
     368             :     CheckVarIntMode<Mode, I>();
     369             :     int nRet = 0;
     370             :     while(true) {
     371             :         nRet++;
     372             :         if (n <= 0x7F)
     373             :             break;
     374             :         n = (n >> 7) - 1;
     375             :     }
     376             :     return nRet;
     377             : }
     378             : 
     379             : template<typename I>
     380             : inline void WriteVarInt(CSizeComputer& os, I n);
     381             : 
     382             : template<typename Stream, VarIntMode Mode, typename I>
     383    23587816 : void WriteVarInt(Stream& os, I n)
     384             : {
     385    23587816 :     CheckVarIntMode<Mode, I>();
     386             :     unsigned char tmp[(sizeof(n)*8+6)/7];
     387    23587816 :     int len=0;
     388    58466707 :     while(true) {
     389    58466707 :         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
     390    58466707 :         if (n <= 0x7F)
     391    23587816 :             break;
     392    34878891 :         n = (n >> 7) - 1;
     393    34878891 :         len++;
     394             :     }
     395    23587816 :     do {
     396    58466693 :         ser_writedata8(os, tmp[len]);
     397    58466693 :     } while(len--);
     398    23587816 : }
     399             : 
     400             : template<typename Stream, VarIntMode Mode, typename I>
     401     4856060 : I ReadVarInt(Stream& is)
     402             : {
     403     4856060 :     CheckVarIntMode<Mode, I>();
     404     4856060 :     I n = 0;
     405     8874960 :     while(true) {
     406     8874960 :         unsigned char chData = ser_readdata8(is);
     407     8874960 :         if (n > (std::numeric_limits<I>::max() >> 7)) {
     408           0 :            throw std::ios_base::failure("ReadVarInt(): size too large");
     409             :         }
     410     8874960 :         n = (n << 7) | (chData & 0x7F);
     411     8874960 :         if (chData & 0x80) {
     412     4018900 :             if (n == std::numeric_limits<I>::max()) {
     413           0 :                 throw std::ios_base::failure("ReadVarInt(): size too large");
     414             :             }
     415     4018900 :             n++;
     416     4018900 :         } else {
     417     4856060 :             return n;
     418             :         }
     419             :     }
     420           0 : }
     421             : 
     422             : /** TODO: describe FixedBitSet */
     423       15346 : inline unsigned int GetSizeOfFixedBitSet(size_t size)
     424             : {
     425       15346 :     return (size + 7) / 8;
     426             : }
     427             : 
     428             : template<typename Stream>
     429      276964 : void WriteFixedBitSet(Stream& s, const std::vector<bool>& vec, size_t size)
     430             : {
     431      276964 :     std::vector<uint8_t> vBytes((size + 7) / 8);
     432      276964 :     size_t ms = std::min(size, vec.size());
     433     1333308 :     for (size_t p = 0; p < ms; p++)
     434     1056343 :         vBytes[p / 8] |= vec[p] << (p % 8);
     435      276965 :     s.write(AsBytes(Span{vBytes}));
     436      276966 : }
     437             : 
     438             : template<typename Stream>
     439     2189437 : void ReadFixedBitSet(Stream& s, std::vector<bool>& vec, size_t size)
     440             : {
     441     2189437 :     vec.resize(size);
     442             : 
     443     2189437 :     std::vector<uint8_t> vBytes((size + 7) / 8);
     444     2189437 :     s.read(AsWritableBytes(Span{vBytes}));
     445    10131440 :     for (size_t p = 0; p < size; p++)
     446     7942003 :         vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
     447     2189437 :     if (vBytes.size() * 8 != size) {
     448     2189395 :         size_t rem = vBytes.size() * 8 - size;
     449     2189395 :         uint8_t m = ~(uint8_t)(0xff >> rem);
     450     2189395 :         if (vBytes[vBytes.size() - 1] & m) {
     451           0 :             throw std::ios_base::failure("Out-of-range bits set");
     452             :         }
     453     2189395 :     }
     454     2189445 : }
     455             : 
     456             : /**
     457             :  * Stores a fixed size bitset as a series of VarInts. Each VarInt is an offset from the last entry and the sum of the
     458             :  * last entry and the offset gives an index into the bitset for a set bit. The series of VarInts ends with a 0.
     459             :  */
     460             : template<typename Stream>
     461       15346 : void WriteFixedVarIntsBitSet(Stream& s, const std::vector<bool>& vec, size_t size)
     462             : {
     463       15346 :     std::optional<size_t> last;
     464       78692 :     for (size_t i = 0; i < vec.size(); i++) {
     465       63346 :         if (vec[i]) {
     466       17808 :             WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, static_cast<uint32_t>(last ? (i - *last) : (i + 1)));
     467       17808 :             last = i;
     468       17808 :         }
     469       63346 :     }
     470       15346 :     WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, 0); // stopper
     471       15346 : }
     472             : 
     473             : template<typename Stream>
     474           0 : void ReadFixedVarIntsBitSet(Stream& s, std::vector<bool>& vec, size_t size)
     475             : {
     476           0 :     vec.assign(size, false);
     477             : 
     478           0 :     std::optional<size_t> last;
     479           0 :     while(true) {
     480           0 :         uint32_t offset = ReadVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s);
     481           0 :         if (offset == 0) {
     482           0 :             break;
     483             :         }
     484           0 :         size_t idx = last ? (*last + offset) : (static_cast<size_t>(offset) - 1);
     485           0 :         if (idx >= size) {
     486           0 :             throw std::ios_base::failure("out of bounds index");
     487             :         }
     488           0 :         if (last.has_value() && idx <= *last) {
     489           0 :             throw std::ios_base::failure("offset overflow");
     490             :         }
     491           0 :         vec[idx] = true;
     492           0 :         last = idx;
     493             :     }
     494           0 : }
     495             : 
     496             : /**
     497             :  * Serializes either as a CFixedBitSet or CFixedVarIntsBitSet, depending on which would give a smaller size
     498             :  */
     499             : typedef std::pair<std::vector<bool>, size_t> autobitset_t;
     500             : 
     501             : struct CFixedBitSet
     502             : {
     503             :     const std::vector<bool>& vec;
     504             :     size_t size;
     505       30692 :     CFixedBitSet(const std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
     506             :     template<typename Stream>
     507       15346 :     void Serialize(Stream& s) const { WriteFixedBitSet(s, vec, size); }
     508             : };
     509             : 
     510             : struct CFixedVarIntsBitSet
     511             : {
     512             :     const std::vector<bool>& vec;
     513             :     size_t size;
     514       30692 :     CFixedVarIntsBitSet(const std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
     515             :     template<typename Stream>
     516       15346 :     void Serialize(Stream& s) const { WriteFixedVarIntsBitSet(s, vec, vec.size()); }
     517             : };
     518             : 
     519             : /* Forward declaration for WriteAutoBitSet */
     520             : template <typename T> size_t GetSerializeSize(const T& t, int nVersion = 0);
     521             : 
     522             : template<typename Stream>
     523       15346 : void WriteAutoBitSet(Stream& s, const autobitset_t& item)
     524             : {
     525       15346 :     auto& vec = item.first;
     526       15346 :     auto& size = item.second;
     527             : 
     528       15346 :     assert(vec.size() == size);
     529             : 
     530       15346 :     size_t size1 = ::GetSerializeSize(CFixedBitSet(vec, size), s.GetVersion());
     531       15346 :     size_t size2 = ::GetSerializeSize(CFixedVarIntsBitSet(vec, size), s.GetVersion());
     532             : 
     533       15346 :     assert(size1 == GetSizeOfFixedBitSet(size));
     534             : 
     535       15346 :     if (size1 < size2) {
     536       15346 :         ser_writedata8(s, 0);
     537       15346 :         WriteFixedBitSet(s, vec, vec.size());
     538       15346 :     } else {
     539           0 :         ser_writedata8(s, 1);
     540           0 :         WriteFixedVarIntsBitSet(s, vec, vec.size());
     541             :     }
     542       15346 : }
     543             : 
     544             : template<typename Stream>
     545       15333 : void ReadAutoBitSet(Stream& s, autobitset_t& item)
     546             : {
     547       15333 :     uint8_t isVarInts = ser_readdata8(s);
     548       15333 :     if (isVarInts != 0 && isVarInts != 1) {
     549           0 :         throw std::ios_base::failure("invalid value for isVarInts byte");
     550             :     }
     551             : 
     552       15333 :     auto& vec = item.first;
     553       15333 :     auto& size = item.second;
     554             : 
     555       15333 :     if (!isVarInts) {
     556       15333 :         ReadFixedBitSet(s, vec, size);
     557       15333 :     } else {
     558           0 :         ReadFixedVarIntsBitSet(s, vec, size);
     559             :     }
     560       15333 : }
     561             : 
     562             : /** Simple wrapper class to serialize objects using a formatter; used by Using(). */
     563             : template<typename Formatter, typename T>
     564             : class Wrapper
     565             : {
     566             :     static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
     567             : protected:
     568             :     T m_object;
     569             : public:
     570   141676791 :     explicit Wrapper(T obj) : m_object(obj) {}
     571    55034004 :     template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
     572    15804429 :     template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
     573             : };
     574             : 
     575             : /** Cause serialization/deserialization of an object to be done using a specified formatter class.
     576             :  *
     577             :  * To use this, you need a class Formatter that has public functions Ser(stream, const object&) for
     578             :  * serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside
     579             :  * READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).
     580             :  *
     581             :  * This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is
     582             :  * const during serialization, and non-const during deserialization, which maintains const
     583             :  * correctness.
     584             :  */
     585             : template<typename Formatter, typename T>
     586    70838497 : static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
     587             : 
     588             : #define DYNBITSET(obj) Using<DynamicBitSetFormatter>(obj)
     589             : #define AUTOBITSET(obj) Using<AutoBitSetFormatter>(obj)
     590             : #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
     591             : #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
     592             : #define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
     593             : #define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
     594             : 
     595             : /** TODO: describe DynamicBitSet */
     596             : struct DynamicBitSetFormatter
     597             : {
     598             :     template<typename Stream>
     599      241337 :     void Ser(Stream& s, const std::vector<bool>& vec) const
     600             :     {
     601      241337 :         WriteCompactSize(s, vec.size());
     602      241337 :         WriteFixedBitSet(s, vec, vec.size());
     603      241337 :     }
     604             : 
     605             :     template<typename Stream>
     606     2173057 :     void Unser(Stream& s, std::vector<bool>& vec)
     607             :     {
     608     2173057 :         ReadFixedBitSet(s, vec, ReadCompactSize(s));
     609     2173057 :     }
     610             : };
     611             : 
     612             : /**
     613             :  * Serializes either as a CFixedBitSet or CFixedVarIntsBitSet, depending on which would give a smaller size
     614             :  */
     615             : struct AutoBitSetFormatter
     616             : {
     617             :     template<typename Stream>
     618       15346 :     void Ser(Stream& s, const autobitset_t& item) const
     619             :     {
     620       15346 :         WriteAutoBitSet(s, item);
     621       15346 :     }
     622             : 
     623             :     template<typename Stream>
     624       15333 :     void Unser(Stream& s, autobitset_t& item)
     625             :     {
     626       15333 :         ReadAutoBitSet(s, item);
     627       15333 :     }
     628             : };
     629             : 
     630             : /** Serialization wrapper class for integers in VarInt format. */
     631             : template<VarIntMode Mode>
     632             : struct VarIntFormatter
     633             : {
     634    23239129 :     template<typename Stream, typename I> void Ser(Stream &s, I v)
     635             :     {
     636    23239129 :         WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
     637    23239129 :     }
     638             : 
     639     4797324 :     template<typename Stream, typename I> void Unser(Stream& s, I& v)
     640             :     {
     641     4797324 :         v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
     642     4797324 :     }
     643             : };
     644             : 
     645             : /** Serialization wrapper class for custom integers and enums.
     646             :  *
     647             :  * It permits specifying the serialized size (1 to 8 bytes) and endianness.
     648             :  *
     649             :  * Use the big endian mode for values that are stored in memory in native
     650             :  * byte order, but serialized in big endian notation. This is only intended
     651             :  * to implement serializers that are compatible with existing formats, and
     652             :  * its use is not recommended for new data structures.
     653             :  */
     654             : template<int Bytes, bool BigEndian = false>
     655             : struct CustomUintFormatter
     656             : {
     657             :     static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
     658             :     static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
     659             : 
     660      546756 :     template <typename Stream, typename I> void Ser(Stream& s, I v)
     661             :     {
     662      546756 :         if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
     663             :         if (BigEndian) {
     664      338279 :             uint64_t raw = htobe64_internal(v);
     665      338279 :             s.write(AsBytes(Span{&raw, 1}).last(Bytes));
     666             :         } else {
     667      208477 :             uint64_t raw = htole64_internal(v);
     668      208477 :             s.write(AsBytes(Span{&raw, 1}).first(Bytes));
     669             :         }
     670      546756 :     }
     671             : 
     672      277366 :     template <typename Stream, typename I> void Unser(Stream& s, I& v)
     673             :     {
     674             :         using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
     675             :         static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
     676      277366 :         uint64_t raw = 0;
     677             :         if (BigEndian) {
     678      108174 :             s.read(AsWritableBytes(Span{&raw, 1}).last(Bytes));
     679      108174 :             v = static_cast<I>(be64toh_internal(raw));
     680             :         } else {
     681      169192 :             s.read(AsWritableBytes(Span{&raw, 1}).first(Bytes));
     682      169192 :             v = static_cast<I>(le64toh_internal(raw));
     683             :         }
     684      277366 :     }
     685             : };
     686             : 
     687             : template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
     688             : 
     689             : /** Formatter for integers in CompactSize format. */
     690             : template<bool RangeCheck>
     691             : struct CompactSizeFormatter
     692             : {
     693             :     template<typename Stream, typename I>
     694      637000 :     void Unser(Stream& s, I& v)
     695             :     {
     696      637000 :         uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
     697      637000 :         if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
     698           0 :             throw std::ios_base::failure("CompactSize exceeds limit of type");
     699             :         }
     700      637000 :         v = n;
     701      637000 :     }
     702             : 
     703             :     template<typename Stream, typename I>
     704      319641 :     void Ser(Stream& s, I v)
     705             :     {
     706             :         static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
     707             :         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
     708             : 
     709      319641 :         WriteCompactSize<Stream>(s, v);
     710      319641 :     }
     711             : };
     712             : 
     713             : template <typename U, bool LOSSY = false>
     714             : struct ChronoFormatter {
     715             :     template <typename Stream, typename Tp>
     716       95181 :     void Unser(Stream& s, Tp& tp)
     717             :     {
     718             :         U u;
     719       95181 :         s >> u;
     720             :         // Lossy deserialization does not make sense, so force Wnarrowing
     721       95181 :         tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
     722       95181 :     }
     723             :     template <typename Stream, typename Tp>
     724      260968 :     void Ser(Stream& s, Tp tp)
     725             :     {
     726             :         if constexpr (LOSSY) {
     727      149466 :             s << U(tp.time_since_epoch().count());
     728             :         } else {
     729      111502 :             s << U{tp.time_since_epoch().count()};
     730             :         }
     731      260968 :     }
     732             : };
     733             : template <typename U>
     734             : using LossyChronoFormatter = ChronoFormatter<U, true>;
     735             : 
     736             : class CompactSizeWriter
     737             : {
     738             : protected:
     739             :     uint64_t n;
     740             : public:
     741        6960 :     explicit CompactSizeWriter(uint64_t n_in) : n(n_in) { }
     742             : 
     743             :     template<typename Stream>
     744        5892 :     void Serialize(Stream &s) const {
     745        5892 :         WriteCompactSize<Stream>(s, n);
     746        5892 :     }
     747             : };
     748             : 
     749             : template<size_t Limit>
     750             : struct LimitedStringFormatter
     751             : {
     752             :     template<typename Stream>
     753        9010 :     void Unser(Stream& s, std::string& v)
     754             :     {
     755        9010 :         size_t size = ReadCompactSize(s);
     756        9010 :         if (size > Limit) {
     757           0 :             throw std::ios_base::failure("String length limit exceeded");
     758             :         }
     759        9010 :         v.resize(size);
     760        9010 :         if (size != 0) s.read(MakeWritableByteSpan(v));
     761        9010 :     }
     762             : 
     763             :     template<typename Stream>
     764           3 :     void Ser(Stream& s, const std::string& v)
     765             :     {
     766           3 :         s << v;
     767           3 :     }
     768             : };
     769             : 
     770             : /** Formatter to serialize/deserialize vector elements using another formatter
     771             :  *
     772             :  * Example:
     773             :  *   struct X {
     774             :  *     std::vector<uint64_t> v;
     775             :  *     SERIALIZE_METHODS(X, obj) { READWRITE(Using<VectorFormatter<VarInt>>(obj.v)); }
     776             :  *   };
     777             :  * will define a struct that contains a vector of uint64_t, which is serialized
     778             :  * as a vector of VarInt-encoded integers.
     779             :  *
     780             :  * V is not required to be an std::vector type. It works for any class that
     781             :  * exposes a value_type, size, reserve, emplace_back, back, and const iterators.
     782             :  */
     783             : template<class Formatter>
     784             : struct VectorFormatter
     785             : {
     786             :     template<typename Stream, typename V>
     787    27230065 :     void Ser(Stream& s, const V& v)
     788             :     {
     789       29258 :         Formatter formatter;
     790    27230065 :         WriteCompactSize(s, v.size());
     791   156739935 :         for (const typename V::value_type& elem : v) {
     792   129509870 :             formatter.Ser(s, elem);
     793             :         }
     794    27230065 :     }
     795             : 
     796             :     template<typename Stream, typename V>
     797     6528343 :     void Unser(Stream& s, V& v)
     798             :     {
     799       29141 :         Formatter formatter;
     800     6528343 :         v.clear();
     801     6528343 :         size_t size = ReadCompactSize(s);
     802     6528343 :         size_t allocated = 0;
     803    10651375 :         while (allocated < size) {
     804             :             // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
     805             :             // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
     806             :             // X MiB of data to make us allocate X+5 Mib.
     807             :             static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
     808     4123032 :             allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
     809     4123032 :             v.reserve(allocated);
     810    55407426 :             while (v.size() < allocated) {
     811    51284394 :                 v.emplace_back();
     812    51284394 :                 formatter.Unser(s, v.back());
     813             :             }
     814             :         }
     815     6528343 :     };
     816             : };
     817             : 
     818             : /**
     819             :  * Forward declarations
     820             :  */
     821             : 
     822             : /**
     823             :  *  string
     824             :  */
     825             : template<typename Stream, typename A, typename B, typename C> void Serialize(Stream& os, const std::basic_string<A, B, C>& str);
     826             : template<typename Stream, typename A, typename B, typename C> void Unserialize(Stream& is, std::basic_string<A, B, C>& str);
     827             : 
     828             : /**
     829             :  * prevector
     830             :  * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
     831             :  */
     832             : template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
     833             : template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
     834             : 
     835             : /**
     836             :  * vector
     837             :  * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
     838             :  */
     839             : template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
     840             : template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
     841             : 
     842             : /**
     843             :  * pair
     844             :  */
     845             : template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
     846             : template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
     847             : 
     848             : /**
     849             :  * pair
     850             :  */
     851             : template<typename Stream, typename... Elements> void Serialize(Stream& os, const std::tuple<Elements...>& item);
     852             : template<typename Stream, typename... Elements> void Unserialize(Stream& is, std::tuple<Elements...>& item);
     853             : 
     854             : /**
     855             :  * map
     856             :  */
     857             : template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
     858             : template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
     859             : template<typename Stream, typename K, typename T, typename Hash, typename Pred, typename A> void Serialize(Stream& os, const std::unordered_map<K, T, Hash, Pred, A>& m);
     860             : template<typename Stream, typename K, typename T, typename Hash, typename Pred, typename A> void Unserialize(Stream& is, std::unordered_map<K, T, Hash, Pred, A>& m);
     861             : 
     862             : /**
     863             :  * set
     864             :  */
     865             : template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
     866             : template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
     867             : template<typename Stream, typename K, typename Hash, typename Pred, typename A> void Serialize(Stream& os, const std::unordered_set<K, Hash, Pred, A>& m);
     868             : template<typename Stream, typename K, typename Hash, typename Pred, typename A> void Unserialize(Stream& is, std::unordered_set<K, Hash, Pred, A>& m);
     869             : 
     870             : /**
     871             :  * shared_ptr
     872             :  */
     873             : template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<T>& p);
     874             : template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<T>& p);
     875             : 
     876             : /**
     877             :  * unique_ptr
     878             :  */
     879             : template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
     880             : template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
     881             : 
     882             : /**
     883             :  * atomic
     884             :  */
     885             : template<typename Stream, typename T> void Serialize(Stream& os, const std::atomic<T>& a);
     886             : template<typename Stream, typename T> void Unserialize(Stream& is, std::atomic<T>& a);
     887             : 
     888             : 
     889             : /**
     890             :  * If none of the specialized versions above matched and T is a class, default to calling member function.
     891             :  */
     892             : template <class T, class Stream, typename std::enable_if<std::is_class<T>::value>::type* = nullptr >
     893             : concept Serializable = requires(T a, Stream s) { a.Serialize(s); };
     894             : template <typename Stream, typename T>
     895             :     requires Serializable<T, Stream>
     896   278238186 : void Serialize(Stream& os, const T& a)
     897             : {
     898   278238186 :     a.Serialize(os);
     899   278238186 : }
     900             : 
     901             : template <class T, class Stream, typename std::enable_if<std::is_class<std::remove_reference<T> >::value>::type* = nullptr>
     902             : concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };
     903             : template <typename Stream, typename T>
     904             :     requires Unserializable<T, Stream>
     905    50356801 : void Unserialize(Stream& is, T&& a)
     906             : {
     907    50356801 :     a.Unserialize(is);
     908    50356801 : }
     909             : 
     910             : /**
     911             :  * If none of the specialized versions above matched and T is an enum, default to calling
     912             :  * Serialize/Unserialze with the underlying type. This is only allowed when a specialized struct of is_serializable_enum<Enum>
     913             :  * is found which derives from std::true_type. This is to ensure that enums are not serialized with the wrong type by
     914             :  * accident.
     915             :  */
     916             : 
     917             : template<typename T> struct is_serializable_enum;
     918             : template<typename T> struct is_serializable_enum : std::false_type {};
     919             : 
     920             : template<typename Stream, typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
     921     3177250 : inline void Serialize(Stream& s, const T& a )
     922             : {
     923             :     // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type
     924             :     static_assert(is_serializable_enum<T>::value, "Missing declararion of is_serializable_enum");
     925             : 
     926             :     typedef typename std::underlying_type<T>::type T2;
     927     3177250 :     T2 b = (T2)a;
     928     3177250 :     Serialize(s, b);
     929     3177250 : }
     930             : 
     931             : template<typename Stream, typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
     932     2943453 : inline void Unserialize(Stream& s, T& a )
     933             : {
     934             :     // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type
     935             :     static_assert(is_serializable_enum<T>::value, "Missing declararion of is_serializable_enum");
     936             : 
     937             :     typedef typename std::underlying_type<T>::type T2;
     938             :     T2 b;
     939     2943453 :     Unserialize(s, b);
     940     2943453 :     a = (T)b;
     941     2943453 : }
     942             : 
     943             : /** Default formatter. Serializes objects as themselves.
     944             :  *
     945             :  * The vector/prevector serialization code passes this to VectorFormatter
     946             :  * to enable reusing that logic. It shouldn't be needed elsewhere.
     947             :  */
     948             : struct DefaultFormatter
     949             : {
     950             :     template<typename Stream, typename T>
     951    37848593 :     static void Ser(Stream& s, const T& t) { Serialize(s, t); }
     952             : 
     953             : 
     954             :     template<typename Stream, typename T>
     955     7807975 :     static void Unser(Stream& s, T& t) { Unserialize(s, t); }
     956             : };
     957             : 
     958             : /**
     959             :  * string
     960             :  */
     961             : template<typename Stream, typename A, typename B, typename C>
     962     5701736 : void Serialize(Stream& os, const std::basic_string<A, B, C>& str)
     963             : {
     964     5701736 :     WriteCompactSize(os, str.size());
     965     5701736 :     if (!str.empty())
     966     5585173 :         os.write(MakeByteSpan(str));
     967     5701736 : }
     968             : 
     969             : template<typename Stream, typename A, typename B, typename C>
     970     1755975 : void Unserialize(Stream& is, std::basic_string<A, B, C>& str)
     971             : {
     972     1755975 :     unsigned int nSize = ReadCompactSize(is);
     973     1755975 :     str.resize(nSize);
     974     1755975 :     if (nSize != 0)
     975     1697112 :         is.read(MakeWritableByteSpan(str));
     976     1755975 : }
     977             : 
     978             : /**
     979             :  * string_view
     980             :  */
     981             : template<typename Stream, typename C>
     982     1587049 : void Serialize(Stream& os, const std::basic_string_view<C>& str)
     983             : {
     984     1587049 :     WriteCompactSize(os, str.size());
     985     1587049 :     if (!str.empty())
     986     1587049 :         os.write(AsBytes(Span{str.data(), str.size() * sizeof(C)}));
     987     1587049 : }
     988             : 
     989             : template<typename Stream, typename C>
     990             : void Unserialize(Stream& is, std::basic_string_view<C>& str)
     991             : {
     992             :     unsigned int nSize = ReadCompactSize(is);
     993             :     str.resize(nSize);
     994             :     if (nSize != 0)
     995             :         is.read(AsWritableBytes(Span{str.data(), nSize * sizeof(C)}));
     996             : }
     997             : 
     998             : 
     999             : /**
    1000             :  * prevector
    1001             :  */
    1002             : template <typename Stream, unsigned int N, typename T>
    1003    46724485 : void Serialize(Stream& os, const prevector<N, T>& v)
    1004             : {
    1005             :     if constexpr (std::is_same_v<T, unsigned char>) {
    1006    46452933 :         WriteCompactSize(os, v.size());
    1007    46452933 :         if (!v.empty())
    1008    30925850 :             os.write(MakeByteSpan(v));
    1009             :     } else {
    1010      271552 :         Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1011             :     }
    1012    46724485 : }
    1013             : 
    1014             : 
    1015             : template <typename Stream, unsigned int N, typename T>
    1016     4494380 : void Unserialize(Stream& is, prevector<N, T>& v)
    1017             : {
    1018             :     if constexpr (std::is_same_v<T, unsigned char>) {
    1019             :         // Limit size per read so bogus size value won't cause out of memory
    1020     4494380 :         v.clear();
    1021     4494380 :         unsigned int nSize = ReadCompactSize(is);
    1022     4494380 :         unsigned int i = 0;
    1023     8871534 :         while (i < nSize) {
    1024     4377154 :             unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1025     4377154 :             v.resize_uninitialized(i + blk);
    1026     4377154 :             is.read(AsWritableBytes(Span{&v[i], blk}));
    1027     4377154 :             i += blk;
    1028             :         }
    1029             :     } else {
    1030             :         Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
    1031             :     }
    1032     4494380 : }
    1033             : 
    1034             : 
    1035             : /**
    1036             :  * vector
    1037             :  */
    1038             : template <typename Stream, typename T, typename A>
    1039    31911772 : void Serialize(Stream& os, const std::vector<T, A>& v)
    1040             : {
    1041             :     if constexpr (std::is_same_v<T, unsigned char>) {
    1042     6825060 :         WriteCompactSize(os, v.size());
    1043     6825060 :         if (!v.empty())
    1044     6626763 :             os.write(MakeByteSpan(v));
    1045             :     } else if constexpr (std::is_same_v<T, bool>) {
    1046             :         // A special case for std::vector<bool>, as dereferencing
    1047             :         // std::vector<bool>::const_iterator does not result in a const bool&
    1048             :         // due to std::vector's special casing for bool arguments.
    1049          48 :         WriteCompactSize(os, v.size());
    1050       22259 :         for (bool elem : v) {
    1051       22211 :             ::Serialize(os, elem);
    1052             :         }
    1053             :     } else {
    1054    25086664 :         Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1055             :     }
    1056    31911774 : }
    1057             : 
    1058             : 
    1059             : template <typename Stream, typename T, typename A>
    1060     7428944 : void Unserialize(Stream& is, std::vector<T, A>& v)
    1061             : {
    1062             :     if constexpr (std::is_same_v<T, unsigned char>) {
    1063             :         // Limit size per read so bogus size value won't cause out of memory
    1064     1635948 :         v.clear();
    1065     1635948 :         unsigned int nSize = ReadCompactSize(is);
    1066     1635948 :         unsigned int i = 0;
    1067     3261971 :         while (i < nSize) {
    1068     1626023 :             unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1069     1626023 :             v.resize(i + blk);
    1070     1626023 :             is.read(AsWritableBytes(Span{&v[i], blk}));
    1071     1626023 :             i += blk;
    1072             :         }
    1073             :     } else {
    1074     5792996 :         Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
    1075             :     }
    1076     7428944 : }
    1077             : 
    1078             : 
    1079             : /**
    1080             :  * pair
    1081             :  */
    1082             : template<typename Stream, typename K, typename T>
    1083     3352732 : void Serialize(Stream& os, const std::pair<K, T>& item)
    1084             : {
    1085     3352732 :     Serialize(os, item.first);
    1086     3352732 :     Serialize(os, item.second);
    1087     3352732 : }
    1088             : 
    1089             : template<typename Stream, typename K, typename T>
    1090      679492 : void Unserialize(Stream& is, std::pair<K, T>& item)
    1091             : {
    1092      679492 :     Unserialize(is, item.first);
    1093      679492 :     Unserialize(is, item.second);
    1094      679492 : }
    1095             : 
    1096             : /**
    1097             :  * tuple
    1098             :  */
    1099             : template<typename Stream, int index, typename... Ts>
    1100             : struct SerializeTuple {
    1101     8221576 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1102     8221576 :         SerializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1103     8221576 :         s << std::get<index>(t);
    1104     8221576 :     }
    1105             : };
    1106             : 
    1107             : template<typename Stream, typename... Ts>
    1108             : struct SerializeTuple<Stream, 0, Ts...> {
    1109     4466361 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1110     4466361 :         s << std::get<0>(t);
    1111     4466361 :     }
    1112             : };
    1113             : 
    1114             : template<typename Stream, int index, typename... Ts>
    1115             : struct DeserializeTuple {
    1116     2640280 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1117     2640280 :         DeserializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1118     2640280 :         s >> std::get<index>(t);
    1119     2640280 :     }
    1120             : };
    1121             : 
    1122             : template<typename Stream, typename... Ts>
    1123             : struct DeserializeTuple<Stream, 0, Ts...> {
    1124     1242515 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1125     1242515 :         s >> std::get<0>(t);
    1126     1242515 :     }
    1127             : };
    1128             : 
    1129             : 
    1130             : template<typename Stream, typename... Elements>
    1131     4466362 : void Serialize(Stream& os, const std::tuple<Elements...>& item)
    1132             : {
    1133     4466362 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1134     4466362 :     SerializeTuple<Stream, size - 1, Elements...>{}(os, const_cast<std::tuple<Elements...>&>(item));
    1135     4466362 : }
    1136             : 
    1137             : template<typename Stream, typename... Elements>
    1138     1242515 : void Unserialize(Stream& is, std::tuple<Elements...>& item)
    1139             : {
    1140     1242515 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1141     1242515 :     DeserializeTuple<Stream, size - 1, Elements...>{}(is, item);
    1142     1242515 : }
    1143             : 
    1144             : 
    1145             : /**
    1146             :  * map
    1147             :  */
    1148             : template<typename Stream, typename Map>
    1149      399655 : void SerializeMap(Stream& os, const Map& m)
    1150             : {
    1151      399655 :     WriteCompactSize(os, m.size());
    1152      808415 :     for (const auto& entry : m)
    1153      408760 :         Serialize(os, entry);
    1154      399655 : }
    1155             : 
    1156             : template<typename Stream, typename Map>
    1157      117948 : void UnserializeMap(Stream& is, Map& m)
    1158             : {
    1159      117948 :     m.clear();
    1160      117948 :     unsigned int nSize = ReadCompactSize(is);
    1161      117948 :     auto mi = m.begin();
    1162      287929 :     for (unsigned int i = 0; i < nSize; i++)
    1163             :     {
    1164      169981 :         std::pair<typename std::remove_const<typename Map::key_type>::type, typename std::remove_const<typename Map::mapped_type>::type> item;
    1165      169981 :         Unserialize(is, item);
    1166      169981 :         mi = m.insert(mi, item);
    1167      169981 :     }
    1168      117948 : }
    1169             : 
    1170             : template<typename Stream, typename K, typename T, typename Pred, typename A>
    1171      139448 : void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
    1172             : {
    1173      139448 :     SerializeMap(os, m);
    1174      139448 : }
    1175             : 
    1176             : template<typename Stream, typename K, typename T, typename Pred, typename A>
    1177       67721 : void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
    1178             : {
    1179       67721 :     UnserializeMap(is, m);
    1180       67721 : }
    1181             : 
    1182             : template<typename Stream, typename K, typename T, typename Hash, typename Pred, typename A>
    1183      260207 : void Serialize(Stream& os, const std::unordered_map<K, T, Hash, Pred, A>& m)
    1184             : {
    1185      260207 :     SerializeMap(os, m);
    1186      260207 : }
    1187             : 
    1188             : template<typename Stream, typename K, typename T, typename Hash, typename Pred, typename A>
    1189       50227 : void Unserialize(Stream& is, std::unordered_map<K, T, Hash, Pred, A>& m)
    1190             : {
    1191       50227 :     UnserializeMap(is, m);
    1192       50227 : }
    1193             : 
    1194             : /**
    1195             :  * set
    1196             :  */
    1197             : 
    1198             : template<typename Stream, typename Set>
    1199        2877 : void SerializeSet(Stream& os, const Set& m)
    1200             : {
    1201        2877 :     WriteCompactSize(os, m.size());
    1202        3855 :     for (auto it = m.begin(); it != m.end(); ++it)
    1203         978 :         Serialize(os, (*it));
    1204        2877 : }
    1205             : 
    1206             : template<typename Stream, typename Set>
    1207        1256 : void UnserializeSet(Stream& is, Set& m)
    1208             : {
    1209        1256 :     m.clear();
    1210        1256 :     unsigned int nSize = ReadCompactSize(is);
    1211        1256 :     auto it = m.begin();
    1212        1478 :     for (unsigned int i = 0; i < nSize; i++)
    1213             :     {
    1214         222 :         typename std::remove_const<typename Set::key_type>::type key;
    1215         222 :         Unserialize(is, key);
    1216         222 :         it = m.insert(it, key);
    1217         222 :     }
    1218        1256 : }
    1219             : 
    1220             : template<typename Stream, typename K, typename Pred, typename A>
    1221        2877 : void Serialize(Stream& os, const std::set<K, Pred, A>& m)
    1222             : {
    1223        2877 :     SerializeSet(os, m);
    1224        2877 : }
    1225             : 
    1226             : template<typename Stream, typename K, typename Pred, typename A>
    1227        1256 : void Unserialize(Stream& is, std::set<K, Pred, A>& m)
    1228             : {
    1229        1256 :     UnserializeSet(is, m);
    1230        1256 : }
    1231             : 
    1232             : template<typename Stream, typename K, typename Hash, typename Pred, typename A>
    1233             : void Serialize(Stream& os, const std::unordered_set<K, Hash, Pred, A>& m)
    1234             : {
    1235             :     SerializeSet(os, m);
    1236             : }
    1237             : 
    1238             : template<typename Stream, typename K, typename Hash, typename Pred, typename A>
    1239             : void Unserialize(Stream& is, std::unordered_set<K, Hash, Pred, A>& m)
    1240             : {
    1241             :     UnserializeSet(is, m);
    1242             : }
    1243             : 
    1244             : /**
    1245             :  * list
    1246             :  */
    1247             : template<typename Stream, typename T, typename A>
    1248        7674 : void Serialize(Stream& os, const std::list<T, A>& l)
    1249             : {
    1250        7674 :     WriteCompactSize(os, l.size());
    1251        8893 :     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
    1252        1219 :         Serialize(os, (*it));
    1253        7674 : }
    1254             : 
    1255             : template<typename Stream, typename T, typename A>
    1256        6822 : void Unserialize(Stream& is, std::list<T, A>& l)
    1257             : {
    1258        6822 :     l.clear();
    1259        6822 :     unsigned int nSize = ReadCompactSize(is);
    1260        6841 :     for (unsigned int i = 0; i < nSize; i++)
    1261             :     {
    1262          19 :         T val;
    1263          19 :         Unserialize(is, val);
    1264          19 :         l.push_back(val);
    1265          19 :     }
    1266        6822 : }
    1267             : 
    1268             : 
    1269             : 
    1270             : /**
    1271             :  * unique_ptr
    1272             :  */
    1273             : template<typename Stream, typename T> void
    1274             : Serialize(Stream& os, const std::unique_ptr<const T>& p)
    1275             : {
    1276             :     Serialize(os, *p);
    1277             : }
    1278             : 
    1279             : template<typename Stream, typename T>
    1280             : void Unserialize(Stream& is, std::unique_ptr<const T>& p)
    1281             : {
    1282             :     p.reset(new T(deserialize, is));
    1283             : }
    1284             : 
    1285             : 
    1286             : 
    1287             : /**
    1288             :  * shared_ptr
    1289             :  */
    1290             : template<typename Stream, typename T> void
    1291     4247618 : Serialize(Stream& os, const std::shared_ptr<T>& p)
    1292             : {
    1293     4247618 :     Serialize(os, *p);
    1294     4247618 : }
    1295             : 
    1296             : template<typename Stream, typename T>
    1297     2091055 : void Unserialize(Stream& is, std::shared_ptr<T>& p)
    1298             : {
    1299     2091055 :     p = std::make_shared<T>(deserialize, is);
    1300     2091055 : }
    1301             : 
    1302             : 
    1303             : 
    1304             : /**
    1305             :  * atomic
    1306             :  */
    1307             : template<typename Stream, typename T>
    1308             : void Serialize(Stream& os, const std::atomic<T>& a)
    1309             : {
    1310             :     Serialize(os, a.load());
    1311             : }
    1312             : 
    1313             : template<typename Stream, typename T>
    1314             : void Unserialize(Stream& is, std::atomic<T>& a)
    1315             : {
    1316             :     T val;
    1317             :     Unserialize(is, val);
    1318             :     a.store(val);
    1319             : }
    1320             : 
    1321             : 
    1322             : 
    1323             : /**
    1324             :  * Support for SERIALIZE_METHODS and READWRITE macro.
    1325             :  */
    1326             : struct CSerActionSerialize
    1327             : {
    1328             :     constexpr bool ForRead() const { return false; }
    1329             : };
    1330             : struct CSerActionUnserialize
    1331             : {
    1332             :     constexpr bool ForRead() const { return true; }
    1333             : };
    1334             : 
    1335             : 
    1336             : 
    1337             : 
    1338             : 
    1339             : 
    1340             : 
    1341             : 
    1342             : /* ::GetSerializeSize implementations
    1343             :  *
    1344             :  * Computing the serialized size of objects is done through a special stream
    1345             :  * object of type CSizeComputer, which only records the number of bytes written
    1346             :  * to it.
    1347             :  *
    1348             :  * If your Serialize or SerializationOp method has non-trivial overhead for
    1349             :  * serialization, it may be worthwhile to implement a specialized version for
    1350             :  * CSizeComputer, which uses the s.seek() method to record bytes that would
    1351             :  * be written instead.
    1352             :  */
    1353             : class CSizeComputer
    1354             : {
    1355             : protected:
    1356     8033898 :     size_t nSize{0};
    1357             : 
    1358             :     const int nVersion;
    1359             : public:
    1360    24101696 :     explicit CSizeComputer(int nVersionIn) : nVersion(nVersionIn) {}
    1361             : 
    1362    77695276 :     void write(Span<const std::byte> src)
    1363             :     {
    1364    77695276 :         this->nSize += src.size();
    1365    77695276 :     }
    1366             : 
    1367             :     /** Pretend _nSize bytes are written, without specifying them. */
    1368    37263358 :     void seek(size_t _nSize)
    1369             :     {
    1370    37263358 :         this->nSize += _nSize;
    1371    37263358 :     }
    1372             : 
    1373             :     template<typename T>
    1374    36356200 :     CSizeComputer& operator<<(const T& obj)
    1375             :     {
    1376    36356200 :         ::Serialize(*this, obj);
    1377    36356200 :         return (*this);
    1378             :     }
    1379             : 
    1380     8033889 :     size_t size() const {
    1381     8033889 :         return nSize;
    1382             :     }
    1383             : 
    1384       16999 :     int GetVersion() const { return nVersion; }
    1385             : };
    1386             : 
    1387             : template <typename Stream, typename... Args>
    1388   149410432 : void SerializeMany(Stream& s, const Args&... args)
    1389             : {
    1390   149410432 :     (::Serialize(s, args), ...);
    1391   149410432 : }
    1392             : 
    1393             : template <typename Stream, typename... Args>
    1394    34964632 : inline void UnserializeMany(Stream& s, Args&&... args)
    1395             : {
    1396    34964632 :     (::Unserialize(s, args), ...);
    1397    34964632 : }
    1398             : 
    1399             : template<typename Stream, typename... Args>
    1400   147894521 : inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, const Args&... args)
    1401             : {
    1402   147894521 :     ::SerializeMany(s, args...);
    1403   147894521 : }
    1404             : 
    1405             : template<typename Stream, typename... Args>
    1406    34963340 : inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&... args)
    1407             : {
    1408    34963340 :     ::UnserializeMany(s, args...);
    1409    34963340 : }
    1410             : 
    1411             : template<typename Stream, typename Type, typename Fn>
    1412     1334273 : inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
    1413             : {
    1414     1334273 : }
    1415             : 
    1416             : template<typename Stream, typename Type, typename Fn>
    1417     4319588 : inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
    1418             : {
    1419     4319588 :     fn(s, std::forward<Type>(obj));
    1420     4319588 : }
    1421             : 
    1422             : template<typename Stream, typename Type, typename Fn>
    1423      696921 : inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
    1424             : {
    1425      696921 :     fn(s, std::forward<Type>(obj));
    1426      696921 : }
    1427             : 
    1428             : template<typename Stream, typename Type, typename Fn>
    1429     2146459 : inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
    1430             : {
    1431     2146459 : }
    1432             : 
    1433             : template<typename I>
    1434             : inline void WriteVarInt(CSizeComputer &s, I n)
    1435             : {
    1436             :     s.seek(GetSizeOfVarInt<I>(n));
    1437             : }
    1438             : 
    1439    37256907 : inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
    1440             : {
    1441    37256907 :     s.seek(GetSizeOfCompactSize(nSize));
    1442    37256907 : }
    1443             : 
    1444             : template <typename T>
    1445     8029629 : size_t GetSerializeSize(const T& t, int nVersion)
    1446             : {
    1447     8029629 :     return (CSizeComputer(nVersion) << t).size();
    1448             : }
    1449             : 
    1450             : template <typename... T>
    1451        4287 : size_t GetSerializeSizeMany(int nVersion, const T&... t)
    1452             : {
    1453        4287 :     CSizeComputer sc(nVersion);
    1454        4287 :     SerializeMany(sc, t...);
    1455        4287 :     return sc.size();
    1456             : }
    1457             : 
    1458             : #endif // BITCOIN_SERIALIZE_H

Generated by: LCOV version 1.16