LCOV - code coverage report
Current view: top level - src - serialize.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 408 474 86.1 %
Date: 2026-08-09 10:51:41 Functions: 1115 1402 79.5 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2015-2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #ifndef PIVX_SERIALIZE_H
       8             : #define PIVX_SERIALIZE_H
       9             : 
      10             : #include <algorithm>
      11             : #include <array>
      12             : #include <assert.h>
      13             : #include <cstring>
      14             : #include <cstdint>
      15             : #include <ios>
      16             : #include <limits>
      17             : #include <list>
      18             : #include <map>
      19             : #include <memory>
      20             : #include <set>
      21             : #include <string.h>
      22             : #include <string>
      23             : #include <utility>
      24             : #include <vector>
      25             : 
      26             : #include "compat/endian.h"
      27             : #include "libzerocoin/Denominations.h"
      28             : #include "libzerocoin/SpendType.h"
      29             : #include "optional.h"
      30             : #include "prevector.h"
      31             : #include "span.h"
      32             : #include "sporkid.h"
      33             : 
      34             : class CScript;
      35             : 
      36             : /**
      37             :  * The maximum size of a serialized object in bytes or number of elements
      38             :  * (for eg vectors) when the size is encoded as CompactSize.
      39             :  */
      40             : static constexpr uint64_t MAX_SIZE = 0x02000000;
      41             : 
      42             : /** Maximum amount of memory (in bytes) to allocate at once when deserializing vectors. */
      43             : static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
      44             : 
      45             : /**
      46             :  * Dummy data type to identify deserializing constructors.
      47             :  *
      48             :  * By convention, a constructor of a type T with signature
      49             :  *
      50             :  *   template <typename Stream> T::T(deserialize_type, Stream& s)
      51             :  *
      52             :  * is a deserializing constructor, which builds the type by
      53             :  * deserializing it from s. If T contains const fields, this
      54             :  * is likely the only way to do so.
      55             :  */
      56             : struct deserialize_type {};
      57             : constexpr deserialize_type deserialize {};
      58             : 
      59             : /**
      60             :  * Used to bypass the rule against non-const reference to temporary
      61             :  * where it makes sense with wrappers such as CFlatData or CTxDB
      62             :  */
      63             : 
      64             : template <typename T>
      65           0 : inline T& REF(const T& val)
      66             : {
      67             :     return const_cast<T&>(val);
      68             : }
      69             : 
      70             : //! Safely convert odd char pointer types to standard ones.
      71             : inline char* CharCast(char* c) { return c; }
      72      865234 : inline char* CharCast(unsigned char* c) { return (char*)c; }
      73             : inline const char* CharCast(const char* c) { return c; }
      74      145697 : inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
      75             : 
      76             : /*
      77             :  * Lowest-level serialization and conversion.
      78             :  * @note Sizes of these types are verified in the tests
      79             :  */
      80    10457249 : template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
      81             : {
      82   515384243 :     s.write((char*)&obj, 1);
      83           0 : }
      84     5421404 : template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
      85             : {
      86     2959200 :     obj = htole16(obj);
      87     5343530 :     s.write((char*)&obj, 2);
      88           0 : }
      89             : template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
      90             : {
      91             :     obj = htobe16(obj);
      92             :     s.write((char*)&obj, 2);
      93             : }
      94   101301262 : template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
      95             : {
      96   100030888 :     obj = htole32(obj);
      97    97104815 :     s.write((char*)&obj, 4);
      98           0 : }
      99    48789816 : template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
     100             : {
     101    48787415 :     obj = htole64(obj);
     102    48726285 :     s.write((char*)&obj, 8);
     103           0 : }
     104    10346125 : template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
     105             : {
     106             :     uint8_t obj;
     107     6706068 :     s.read((char*)&obj, 1);
     108    10345660 :     return obj;
     109             : }
     110      485065 : template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
     111             : {
     112             :     uint16_t obj;
     113      155684 :     s.read((char*)&obj, 2);
     114      621598 :     return le16toh(obj);
     115             : }
     116             : template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
     117             : {
     118             :     uint16_t obj;
     119             :     s.read((char*)&obj, 2);
     120             :     return be16toh(obj);
     121             : }
     122     1561265 : template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
     123             : {
     124             :     uint32_t obj;
     125       36985 :     s.read((char*)&obj, 4);
     126     1180117 :     return le32toh(obj);
     127             : }
     128      717283 : template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
     129             : {
     130             :     uint64_t obj;
     131        2396 :     s.read((char*)&obj, 8);
     132     1093186 :     return le64toh(obj);
     133             : }
     134      610470 : inline uint64_t ser_double_to_uint64(double x)
     135             : {
     136      610470 :     uint64_t tmp;
     137      609468 :     std::memcpy(&tmp, &x, sizeof(x));
     138      610470 :     static_assert(sizeof(tmp) == sizeof(x), "double and uint64_t assumed to have the same size");
     139      610468 :     return tmp;
     140             : }
     141        1008 : inline uint32_t ser_float_to_uint32(float x)
     142             : {
     143        1008 :     uint32_t tmp;
     144           6 :     std::memcpy(&tmp, &x, sizeof(x));
     145        1008 :     static_assert(sizeof(tmp) == sizeof(x), "float and uint32_t assumed to have the same size");
     146        1006 :     return tmp;
     147             : }
     148      160627 : inline double ser_uint64_to_double(uint64_t y)
     149             : {
     150      160627 :     double tmp;
     151      159627 :     std::memcpy(&tmp, &y, sizeof(y));
     152      160627 :     static_assert(sizeof(tmp) == sizeof(y), "double and uint64_t assumed to have the same size");
     153        1083 :     return tmp;
     154             : }
     155        1006 : inline float ser_uint32_to_float(uint32_t y)
     156             : {
     157        1006 :     float tmp;
     158           6 :     std::memcpy(&tmp, &y, sizeof(y));
     159        1006 :     static_assert(sizeof(tmp) == sizeof(y), "float and uint32_t assumed to have the same size");
     160        1006 :     return tmp;
     161             : }
     162             : 
     163             : 
     164             : /////////////////////////////////////////////////////////////////
     165             : //
     166             : // Templates for serializing to anything that looks like a stream,
     167             : // i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
     168             : //
     169             : 
     170             : class CSizeComputer;
     171             : 
     172             : enum {
     173             :     // primary actions
     174             :     SER_NETWORK = (1 << 0),
     175             :     SER_DISK = (1 << 1),
     176             :     SER_GETHASH = (1 << 2),
     177             : };
     178             : 
     179             : //! Convert the reference base type to X, without changing constness or reference type.
     180     1609391 : template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
     181    72914666 : template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
     182             : 
     183             : #define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
     184             : #define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
     185             : #define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
     186             : #define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
     187             : 
     188             : /**
     189             :  * Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
     190             :  *
     191             :  * Both Ser and Unser are delegated to a single static method SerializationOps, which is polymorphic
     192             :  * in the serialized/deserialized type (allowing it to be const when serializing, and non-const when
     193             :  * deserializing).
     194             :  *
     195             :  * Example use:
     196             :  *   struct FooFormatter {
     197             :  *     FORMATTER_METHODS(Class, obj) { READWRITE(obj.val1, VARINT(obj.val2)); }
     198             :  *   }
     199             :  *   would define a class FooFormatter that defines a serialization of Class objects consisting
     200             :  *   of serializing its val1 member using the default serialization, and its val2 member using
     201             :  *   VARINT serialization. That FooFormatter can then be used in statements like
     202             :  *   READWRITE(Using<FooFormatter>(obj.bla)).
     203             :  */
     204             : #define FORMATTER_METHODS(cls, obj) \
     205             :     template<typename Stream> \
     206             :     static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, CSerActionSerialize()); } \
     207             :     template<typename Stream> \
     208             :     static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, CSerActionUnserialize()); } \
     209             :     template<typename Stream, typename Type, typename Operation> \
     210             :     static inline void SerializationOps(Type& obj, Stream& s, Operation ser_action) \
     211             : 
     212             : /**
     213             :  * Implement the Serialize and Unserialize methods by delegating to a single templated
     214             :  * static method that takes the to-be-(de)serialized object as a parameter. This approach
     215             :  * has the advantage that the constness of the object becomes a template parameter, and
     216             :  * thus allows a single implementation that sees the object as const for serializing
     217             :  * and non-const for deserializing, without casts.
     218             :  */
     219             : #define SERIALIZE_METHODS(cls, obj)                                                 \
     220             :     template<typename Stream>                                                       \
     221             :     void Serialize(Stream& s) const                                                 \
     222             :     {                                                                               \
     223             :         static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
     224             :         Ser(s, *this);                                                              \
     225             :     }                                                                               \
     226             :     template<typename Stream>                                                       \
     227             :     void Unserialize(Stream& s)                                                     \
     228             :     {                                                                               \
     229             :         static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
     230             :         Unser(s, *this);                                                            \
     231             :     }                                                                               \
     232             :     FORMATTER_METHODS(cls, obj)
     233             : 
     234             : /*
     235             :  * Basic Types
     236             :  */
     237       42378 : template<typename Stream> inline void Serialize(Stream& s, char a    ) { ser_writedata8(s, a); } // TODO Get rid of bare char
     238           2 : template<typename Stream> inline void Serialize(Stream& s, int8_t a  ) { ser_writedata8(s, a); }
     239   851304603 : template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
     240     2946091 : template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
     241        3262 : template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
     242    11234123 : template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
     243    22809427 : template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
     244    49962745 : template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
     245      139337 : template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
     246        1000 : template<typename Stream> inline void Serialize(Stream& s, float a   ) { ser_writedata32(s, ser_float_to_uint32(a)); }
     247        1294 : template<typename Stream> inline void Serialize(Stream& s, double a  ) { ser_writedata64(s, ser_double_to_uint64(a)); }
     248      132352 : template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
     249      145001 : template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
     250       62046 : template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
     251      462508 : template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
     252             : 
     253       22436 : template<typename Stream> inline void Unserialize(Stream& s, char& a    ) { a = ser_readdata8(s); } // TODO Get rid of bare char
     254             : template<typename Stream> inline void Unserialize(Stream& s, int8_t& a  ) { a = ser_readdata8(s); }
     255     3859079 : template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
     256      614969 : template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
     257       13764 : template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
     258      195620 : template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
     259     1057544 : template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
     260      132860 : template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
     261        7755 : template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
     262        1000 : template<typename Stream> inline void Unserialize(Stream& s, float& a   ) { a = ser_uint32_to_float(ser_readdata32(s)); }
     263      160621 : template<typename Stream> inline void Unserialize(Stream& s, double& a  ) { a = ser_uint64_to_double(ser_readdata64(s)); }
     264      233521 : template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
     265       14575 : template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
     266      400503 : template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }
     267             : 
     268       29620 : template<typename Stream> inline void Serialize(Stream& s, bool a)    { char f=a; ser_writedata8(s, f); }
     269        6535 : template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
     270             : 
     271             : // Serializatin for libzerocoin::CoinDenomination
     272             : template <typename Stream>
     273         622 : inline void Serialize(Stream& s, libzerocoin::CoinDenomination a)
     274             : {
     275         622 :     int f = libzerocoin::ZerocoinDenominationToInt(a);
     276         622 :     ser_writedata32(s, f);
     277         622 : }
     278             : 
     279             : template <typename Stream>
     280         320 : inline void Unserialize(Stream& s, libzerocoin::CoinDenomination& a)
     281             : {
     282         320 :     int f = ser_readdata32(s);
     283         320 :     a = libzerocoin::IntToZerocoinDenomination(f);
     284         320 : }
     285             : 
     286             : // Serialization for libzerocoin::SpendType
     287             : template <typename Stream>
     288           0 : inline void Serialize(Stream& s, libzerocoin::SpendType a)
     289             : {
     290           0 :     uint8_t f = static_cast<uint8_t>(a);
     291           0 :     ser_writedata8(s, f);
     292             : }
     293             : 
     294             : template <typename Stream>
     295           0 : inline void Unserialize(Stream& s, libzerocoin::SpendType & a)
     296             : {
     297           0 :     uint8_t f = ser_readdata8(s);
     298           0 :     a = static_cast<libzerocoin::SpendType>(f);
     299             : }
     300             : 
     301             : // Serialization for SporkId
     302             : template <typename Stream>
     303        4646 : inline void Serialize(Stream& s, SporkId sporkID)
     304             : {
     305        4646 :     int32_t f = static_cast<int32_t>(sporkID);
     306        4082 :     ser_writedata32(s, f);
     307             : }
     308             : 
     309             : template <typename Stream>
     310         760 : inline void Unserialize(Stream& s, SporkId& sporkID)
     311             : {
     312         760 :     int32_t f = ser_readdata32(s);
     313         760 :     sporkID = (SporkId) f;
     314             : }
     315             : 
     316             : 
     317             : /**
     318             :  * Compact Size
     319             :  * size <  253        -- 1 byte
     320             :  * size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
     321             :  * size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
     322             :  * size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
     323             :  */
     324     7436416 : inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
     325             : {
     326     7147408 :     if (nSize < 253)             return sizeof(unsigned char);
     327        3352 :     else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);
     328          91 :     else if (nSize <= std::numeric_limits<unsigned int>::max())  return sizeof(unsigned char) + sizeof(unsigned int);
     329           0 :     else                         return sizeof(unsigned char) + sizeof(uint64_t);
     330             : }
     331             : 
     332             : inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
     333             : 
     334             : template <typename Stream>
     335    73865695 : void WriteCompactSize(Stream& os, uint64_t nSize)
     336             : {
     337    73865695 :     if (nSize < 253) {
     338    73853788 :         ser_writedata8(os, nSize);
     339       11914 :     } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
     340       11817 :         ser_writedata8(os, 253);
     341       11817 :         ser_writedata16(os, nSize);
     342          97 :     } else if (nSize <= std::numeric_limits<unsigned int>::max()) {
     343          97 :         ser_writedata8(os, 254);
     344          97 :         ser_writedata32(os, nSize);
     345             :     } else {
     346           0 :         ser_writedata8(os, 255);
     347           0 :         ser_writedata64(os, nSize);
     348             :     }
     349    73865694 :     return;
     350             : }
     351             : 
     352             : /**
     353             :  * Decode a CompactSize-encoded variable-length integer.
     354             :  *
     355             :  * As these are primarily used to encode the size of vector-like serializations, by default a range
     356             :  * check is performed. When used as a generic number encoding, range_check should be set to false.
     357             :  */
     358             : template<typename Stream>
     359     2708217 : uint64_t ReadCompactSize(Stream& is, bool range_check = true)
     360             : {
     361     2708212 :     uint8_t chSize = ser_readdata8(is);
     362     2708212 :     uint64_t nSizeRet = 0;
     363     2708212 :     if (chSize < 253) {
     364     2707132 :         nSizeRet = chSize;
     365        1087 :     } else if (chSize == 253) {
     366        1024 :         nSizeRet = ser_readdata16(is);
     367        1024 :         if (nSizeRet < 253)
     368           2 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     369          63 :     } else if (chSize == 254) {
     370          61 :         nSizeRet = ser_readdata32(is);
     371          61 :         if (nSizeRet < 0x10000u)
     372           2 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     373             :     } else {
     374           2 :         nSizeRet = ser_readdata64(is);
     375           2 :         if (nSizeRet < 0x100000000ULL)
     376           2 :             throw std::ios_base::failure("non-canonical ReadCompactSize()");
     377             :     }
     378     2708206 :     if (range_check && nSizeRet > MAX_SIZE) {
     379           0 :         throw std::ios_base::failure("ReadCompactSize(): size too large");
     380             :     }
     381     2708206 :     return nSizeRet;
     382             : }
     383             : 
     384             : /**
     385             :  * Variable-length integers: bytes are a MSB base-128 encoding of the number.
     386             :  * The high bit in each byte signifies whether another digit follows. To make
     387             :  * sure the encoding is one-to-one, one is subtracted from all but the last digit.
     388             :  * Thus, the byte sequence a[] with length len, where all but the last byte
     389             :  * has bit 128 set, encodes the number:
     390             :  *
     391             :  *  (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))
     392             :  *
     393             :  * Properties:
     394             :  * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)
     395             :  * * Every integer has exactly one encoding
     396             :  * * Encoding does not depend on size of original integer type
     397             :  * * No redundancy: every (infinite) byte sequence corresponds to a list
     398             :  *   of encoded integers.
     399             :  *
     400             :  * 0:         [0x00]  256:        [0x81 0x00]
     401             :  * 1:         [0x01]  16383:      [0xFE 0x7F]
     402             :  * 127:       [0x7F]  16384:      [0xFF 0x00]
     403             :  * 128:  [0x80 0x00]  16511: [0x80 0xFF 0x7F]
     404             :  * 255:  [0x80 0x7F]  65535: [0x82 0xFD 0x7F]
     405             :  * 2^32:           [0x8E 0xFE 0xFE 0xFF 0x00]
     406             :  */
     407             : 
     408             : /**
     409             :  * Mode for encoding VarInts.
     410             :  *
     411             :  * Currently there is no support for signed encodings. The default mode will not
     412             :  * compile with signed values, and the legacy "nonnegative signed" mode will
     413             :  * accept signed values, but improperly encode and decode them if they are
     414             :  * negative. In the future, the DEFAULT mode could be extended to support
     415             :  * negative numbers in a backwards compatible way, and additional modes could be
     416             :  * added to support different varint formats (e.g. zigzag encoding).
     417             :  */
     418             : enum class VarIntMode { DEFAULT, NONNEGATIVE_SIGNED };
     419             : 
     420             : template <VarIntMode Mode, typename I>
     421             : struct CheckVarIntMode {
     422     5137401 :     constexpr CheckVarIntMode()
     423             :     {
     424             :         static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value, "Unsigned type required with mode DEFAULT.");
     425             :         static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed<I>::value, "Signed type required with mode NONNEGATIVE_SIGNED.");
     426             :     }
     427             : };
     428             : 
     429             : template<VarIntMode Mode, typename I>
     430             : inline unsigned int GetSizeOfVarInt(I n)
     431             : {
     432             :     CheckVarIntMode<Mode, I>();
     433             :     int nRet = 0;
     434             :     while (true) {
     435             :         nRet++;
     436             :         if (n <= 0x7F)
     437             :             break;
     438             :         n = (n >> 7) - 1;
     439             :     }
     440             :     return nRet;
     441             : }
     442             : 
     443             : template<typename I>
     444             : inline void WriteVarInt(CSizeComputer& os, I n);
     445             : 
     446             : template<typename Stream, VarIntMode Mode, typename I>
     447     3292747 : void WriteVarInt(Stream& os, I n)
     448             : {
     449             :     CheckVarIntMode<Mode, I>();
     450             :     unsigned char tmp[(sizeof(n)*8+6)/7];
     451     3292747 :     int len=0;
     452     5271104 :     while(true) {
     453     7608917 :         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
     454     8563845 :         if (n <= 0x7F)
     455             :             break;
     456     5271104 :         n = (n >> 7) - 1;
     457     5271104 :         len++;
     458             :     }
     459     8563846 :     do {
     460     8563846 :         ser_writedata8(os, tmp[len]);
     461             :     } while (len--);
     462     3292747 : }
     463             : 
     464             : template<typename Stream, VarIntMode Mode, typename I>
     465     1844653 : I ReadVarInt(Stream& is)
     466             : {
     467             :     CheckVarIntMode<Mode, I>();
     468     1844653 :     I n = 0;
     469     2113606 :     while (true) {
     470     3958243 :         unsigned char chData = ser_readdata8(is);
     471     3958243 :         if (n > (std::numeric_limits<I>::max() >> 7)) {
     472           0 :            throw std::ios_base::failure("ReadVarInt(): size too large");
     473             :         }
     474     3958243 :         n = (n << 7) | (chData & 0x7F);
     475     3958243 :         if (chData & 0x80) {
     476     2113606 :             if (n == std::numeric_limits<I>::max()) {
     477           0 :                 throw std::ios_base::failure("ReadVarInt(): size too large");
     478             :             }
     479     2113606 :             n++;
     480             :         } else {
     481     1844643 :             return n;
     482             :         }
     483             :     }
     484             : }
     485             : 
     486             : /** Simple wrapper class to serialize objects using a formatter; used by Using(). */
     487             : template<typename Formatter, typename T>
     488             : class Wrapper
     489             : {
     490             :     static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
     491             : protected:
     492             :     T m_object;
     493             : public:
     494    15736374 :     explicit Wrapper(T obj) : m_object(obj) {}
     495    21541171 :     template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
     496     1423531 :     template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
     497             : };
     498             : 
     499             : /** Cause serialization/deserialization of an object to be done using a specified formatter class.
     500             :  *
     501             :  * To use this, you need a class Formatter that has public functions Ser(stream, const object&) for
     502             :  * serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside
     503             :  * READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).
     504             :  *
     505             :  * This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is
     506             :  * const during serialization, and non-const during deserialization, which maintains const
     507             :  * correctness.
     508             :  */
     509             : template<typename Formatter, typename T>
     510     8479151 : static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
     511             : 
     512             : #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
     513             : #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
     514             : #define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
     515             : #define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
     516             : 
     517             : /** Serialization wrapper class for integers in VarInt format. */
     518             : template<VarIntMode Mode>
     519             : struct VarIntFormatter
     520             : {
     521     3292755 :     template<typename Stream, typename I> void Ser(Stream &s, I v)
     522             :     {
     523     3292755 :         WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
     524             :     }
     525             : 
     526     1844657 :     template<typename Stream, typename I> void Unser(Stream& s, I& v)
     527             :     {
     528     3489280 :         v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
     529             :     }
     530             : };
     531             : 
     532             : #define FIXEDBITSET(obj, size) Using<BitSetFormatter<size>>(obj)
     533             : #define DYNBITSET(obj) Using<BitSetFormatter<0>>(obj)
     534             : #define FIXEDVARINTSBITSET(obj, size) REF(CFixedVarIntsBitSet(REF(obj), (size)))
     535             : #define AUTOBITSET(obj, size) REF(CAutoBitSet(REF(obj), (size)))
     536             : 
     537             : /* Formatter for fixed (size N), or dynamic (size 0) bitsets */
     538             : 
     539             : template<size_t N>
     540             : struct BitSetFormatter
     541             : {
     542             :     template<typename Stream>
     543         257 :     void Ser(Stream& s, const std::vector<bool>& vec)
     544             :     {
     545         257 :         size_t size = (N == 0 ? vec.size() : N);
     546             :         if (N == 0) {
     547         265 :             WriteCompactSize(s, size);
     548             :         }
     549         257 :         std::vector<unsigned char> vBytes((size + 7) / 8);
     550         257 :         size_t ms = std::min(size, vec.size());
     551        1986 :         for (size_t p = 0; p < ms; p++)
     552        1729 :             vBytes[p / 8] |= vec[p] << (p % 8);
     553         300 :         s.write((char*)vBytes.data(), vBytes.size());
     554         257 :     }
     555             : 
     556             :     template<typename Stream>
     557        2778 :     void Unser(Stream& s, std::vector<bool>& vec)
     558             :     {
     559        2778 :         size_t size = (N == 0 ? ReadCompactSize(s) : N);
     560        2778 :         vec.resize(size);
     561        2778 :         std::vector<unsigned char> vBytes((size + 7) / 8);
     562        2778 :         s.read((char*)vBytes.data(), vBytes.size());
     563       12070 :         for (size_t p = 0; p < size; p++)
     564       18584 :             vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
     565        2778 :         if (vBytes.size() * 8 != size) {
     566        2778 :             size_t rem = vBytes.size() * 8 - size;
     567        2778 :             uint8_t m = ~(uint8_t)(0xff >> rem);
     568        2778 :             if (vBytes[vBytes.size() - 1] & m) {
     569           0 :                 throw std::ios_base::failure("Out-of-range bits set");
     570             :             }
     571             :         }
     572        2778 :     }
     573             : };
     574             : 
     575             : /**
     576             :  * Stores a fixed size bitset as a series of VarInts. Each VarInt is an offset from the last entry and the sum of the
     577             :  * last entry and the offset gives an index into the bitset for a set bit. The series of VarInts ends with a 0.
     578             :  */
     579             : 
     580             : class CFixedVarIntsBitSet
     581             : {
     582             : protected:
     583             :     std::vector<bool>& vec;
     584             :     size_t size;
     585             : 
     586             : public:
     587           0 :     CFixedVarIntsBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
     588             : 
     589             :     template <typename Stream>
     590           0 :     void Serialize(Stream& s) const
     591             :     {
     592           0 :         int32_t last = -1;
     593           0 :         for (int32_t i = 0; i < (int32_t)vec.size(); i++) {
     594           0 :             if (vec[i]) {
     595           0 :                 WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, (uint32_t)(i - last));
     596           0 :                 last = i;
     597             :             }
     598             :         }
     599           0 :         WriteVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s, 0); // stopper
     600           0 :     }
     601             : 
     602             :     template <typename Stream>
     603           0 :     void Unserialize(Stream& s)
     604             :     {
     605           0 :         vec.assign(size, false);
     606             : 
     607             :         int32_t last = -1;
     608           0 :         while (true) {
     609           0 :             uint32_t offset = ReadVarInt<Stream, VarIntMode::DEFAULT, uint32_t>(s);
     610           0 :             if (offset == 0) {
     611             :                 break;
     612             :             }
     613           0 :             int32_t idx = last + offset;
     614           0 :             if (idx >= size) {
     615           0 :                 throw std::ios_base::failure("out of bounds index");
     616             :             }
     617           0 :             if (last != -1 && idx <= last) {
     618           0 :                 throw std::ios_base::failure("offset overflow");
     619             :             }
     620           0 :             vec[idx] = true;
     621           0 :             last = idx;
     622             :         }
     623           0 :     }
     624             : };
     625             : 
     626             : /**
     627             :  * Serializes either as a or CFixedVarIntsBitSet
     628             :  */
     629             : 
     630             : class CAutoBitSet
     631             : {
     632             : protected:
     633             :     std::vector<bool>& vec;
     634             :     size_t size;
     635             : 
     636             : public:
     637           0 :     explicit CAutoBitSet(std::vector<bool>& vecIn, size_t sizeIn) : vec(vecIn), size(sizeIn) {}
     638             : 
     639             :     template <typename Stream>
     640           0 :     void Serialize(Stream& s) const
     641             :     {
     642           0 :         assert(vec.size() == size);
     643             : 
     644           0 :         ser_writedata8(s, 0);
     645           0 :         s << FIXEDVARINTSBITSET(vec, vec.size());
     646           0 :     }
     647             : 
     648             :     template <typename Stream>
     649           0 :     void Unserialize(Stream& s)
     650             :     {
     651           0 :         uint8_t isVarInts = ser_readdata8(s);
     652           0 :         if (isVarInts != 0) {
     653           0 :             throw std::ios_base::failure("invalid value for isVarInts byte");
     654             :         }
     655           0 :         s >> FIXEDVARINTSBITSET(vec, size);
     656           0 :     }
     657             : };
     658             : 
     659             : /** Serialization wrapper class for custom integers and enums.
     660             :  *
     661             :  * It permits specifying the serialized size (1 to 8 bytes) and endianness.
     662             :  *
     663             :  * Use the big endian mode for values that are stored in memory in native
     664             :  * byte order, but serialized in big endian notation. This is only intended
     665             :  * to implement serializers that are compatible with existing formats, and
     666             :  * its use is not recommended for new data structures.
     667             :  */
     668             : template<int Bytes, bool BigEndian = false>
     669             : struct CustomUintFormatter
     670             : {
     671             :     static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
     672             :     static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
     673             : 
     674       25448 :     template <typename Stream, typename I> void Ser(Stream& s, I v)
     675             :     {
     676             :         if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
     677             :         if (BigEndian) {
     678       18650 :             uint64_t raw = htobe64(v);
     679       23869 :             s.write(((const char*)&raw) + 8 - Bytes, Bytes);
     680             :         } else {
     681        1343 :             uint64_t raw = htole64(v);
     682        1343 :             s.write((const char*)&raw, Bytes);
     683             :         }
     684          11 :     }
     685             : 
     686        9895 :     template <typename Stream, typename I> void Unser(Stream& s, I& v)
     687             :     {
     688             :         using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
     689             :         static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
     690        9895 :         uint64_t raw = 0;
     691             :         if (BigEndian) {
     692       10833 :             s.read(((char*)&raw) + 8 - Bytes, Bytes);
     693        6119 :             v = static_cast<I>(be64toh(raw));
     694             :         } else {
     695        3776 :             s.read((char*)&raw, Bytes);
     696        3776 :             v = static_cast<I>(le64toh(raw));
     697             :         }
     698             :     }
     699             : };
     700             : 
     701             : template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
     702             : 
     703             : /** Formatter for integers in CompactSize format. */
     704             : template<bool RangeCheck>
     705             : struct CompactSizeFormatter
     706             : {
     707             :     template<typename Stream, typename I>
     708        3452 :     void Unser(Stream& s, I& v)
     709             :     {
     710        6904 :         uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
     711             :         if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
     712             :             throw std::ios_base::failure("CompactSize exceeds limit of type");
     713             :         }
     714        2415 :         v = n;
     715             :     }
     716             : 
     717             :     template<typename Stream, typename I>
     718       18083 :     void Ser(Stream& s, I v)
     719             :     {
     720             :         static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
     721             :         static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
     722             : 
     723       18083 :         WriteCompactSize<Stream>(s, v);
     724             :     }
     725             : };
     726             : 
     727             : template<size_t Limit>
     728             : struct LimitedStringFormatter
     729             : {
     730             :     template<typename Stream>
     731         671 :     void Unser(Stream& s, std::string& v)
     732             :     {
     733         671 :         size_t size = ReadCompactSize(s);
     734         670 :         if (size > Limit) {
     735           0 :             throw std::ios_base::failure("String length limit exceeded");
     736             :         }
     737         670 :         v.resize(size);
     738         670 :         if (size != 0) s.read((char*)v.data(), size);
     739         670 :     }
     740             : 
     741             :     template<typename Stream>
     742         169 :     void Ser(Stream& s, const std::string& v)
     743             :     {
     744         169 :         s << v;
     745             :     }
     746             : };
     747             : 
     748             : /** Formatter to serialize/deserialize vector elements using another formatter
     749             :  *
     750             :  * Example:
     751             :  *   struct X {
     752             :  *     std::vector<uint64_t> v;
     753             :  *     SERIALIZE_METHODS(X, obj) { READWRITE(Using<VectorFormatter<VarInt>>(obj.v)); }
     754             :  *   };
     755             :  * will define a struct that contains a vector of uint64_t, which is serialized
     756             :  * as a vector of VarInt-encoded integers.
     757             :  *
     758             :  * V is not required to be an std::vector type. It works for any class that
     759             :  * exposes a value_type, size, reserve, emplace_back, back, and const iterators.
     760             :  */
     761             : template<class Formatter>
     762             : struct VectorFormatter
     763             : {
     764             :     template<typename Stream, typename V>
     765     7096581 :     void Ser(Stream& s, const V& v)
     766             :     {
     767             :         Formatter formatter;
     768     9949898 :         WriteCompactSize(s, v.size());
     769    63995867 :         for (const typename V::value_type& elem : v) {
     770    56471496 :             formatter.Ser(s, elem);
     771             :         }
     772     7096581 :     }
     773             : 
     774             :     template<typename Stream, typename V>
     775      974671 :     void Unser(Stream& s, V& v)
     776             :     {
     777             :         Formatter formatter;
     778      974671 :         v.clear();
     779      974671 :         size_t size = ReadCompactSize(s);
     780      974667 :         size_t allocated = 0;
     781     1921380 :         while (allocated < size) {
     782             :             // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
     783             :             // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
     784             :             // X MiB of data to make us allocate X+5 Mib.
     785             :             static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
     786      946715 :             allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
     787      946715 :             v.reserve(allocated);
     788     3482512 :             while (v.size() < allocated) {
     789     2535799 :                 v.emplace_back();
     790     4073974 :                 formatter.Unser(s, v.back());
     791             :             }
     792             :         }
     793      974665 :     };
     794             : };
     795             : 
     796             : /**
     797             :  * Forward declarations
     798             :  */
     799             : 
     800             : /**
     801             :  *  std::string
     802             :  */
     803             : template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
     804             : template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
     805             : 
     806             : /**
     807             :  * prevector
     808             :  * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
     809             :  */
     810             : template<typename Stream, unsigned int N, typename T> void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&);
     811             : template<typename Stream, unsigned int N, typename T, typename V> void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&);
     812             : template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
     813             : template<typename Stream, unsigned int N, typename T> void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&);
     814             : template<typename Stream, unsigned int N, typename T, typename V> void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&);
     815             : template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
     816             : 
     817             : /**
     818             :  * vector
     819             :  * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob.
     820             :  */
     821             : template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&);
     822             : template<typename Stream, typename T, typename A> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const bool&);
     823             : template<typename Stream, typename T, typename A, typename V> void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&);
     824             : template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
     825             : template<typename Stream, typename T, typename A> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&);
     826             : template<typename Stream, typename T, typename A, typename V> void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&);
     827             : template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
     828             : 
     829             : /**
     830             :  * array
     831             :  */
     832             : template<typename T, std::size_t N> unsigned int GetSerializeSize(const std::array<T, N> &item);
     833             : template<typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& item);
     834             : template<typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, std::array<T, N>& item);
     835             : 
     836             : /**
     837             :  * optional
     838             :  */
     839             : template<typename T> unsigned int GetSerializeSize(const Optional<T> &item);
     840             : template<typename Stream, typename T> void Serialize(Stream& os, const Optional<T>& item);
     841             : template<typename Stream, typename T> void Unserialize(Stream& is, Optional<T>& item);
     842             : 
     843             : /**
     844             :  * array
     845             :  */
     846             : template<typename T, std::size_t N>
     847             : unsigned int GetSerializeSize(const std::array<T, N> &item)
     848             : {
     849             :     unsigned int size = 0;
     850             :     for (size_t i = 0; i < N; i++) {
     851             :         size += GetSerializeSize(item[0]);
     852             :     }
     853             :     return size;
     854             : }
     855             : 
     856             : template<typename Stream, typename T>
     857       73318 : void Serialize(Stream& os, const Optional<T>& item)
     858             : {
     859             :     // If the value is there, put 0x01 and then serialize the value.
     860             :     // If it's not, put 0x00.
     861       73318 :     if (item) {
     862       69342 :         unsigned char discriminant = 0x01;
     863       69342 :         Serialize(os, discriminant);
     864      141358 :         Serialize(os, *item);
     865             :     } else {
     866        3976 :         unsigned char discriminant = 0x00;
     867       17590 :         Serialize(os, discriminant);
     868             :     }
     869       73318 : }
     870             : 
     871             : template<typename Stream, typename T>
     872        5132 : void Unserialize(Stream& is, Optional<T>& item)
     873             : {
     874        5132 :     unsigned char discriminant = 0x00;
     875        5132 :     Unserialize(is, discriminant);
     876             : 
     877        5132 :     if (discriminant == 0x00) {
     878         417 :         item = boost::none;
     879             :     } else {
     880        1899 :         T object;
     881        4715 :         Unserialize(is, object);
     882        4715 :         item = object;
     883             :     }
     884        5132 : }
     885             : 
     886             : 
     887             : template<typename Stream, typename T, std::size_t N>
     888     1614089 : void Serialize(Stream& os, const std::array<T, N>& item)
     889             : {
     890   442550583 :     for (size_t i = 0; i < N; i++) {
     891   440935791 :         Serialize(os, item[i]);
     892             :     }
     893     1614089 : }
     894             : 
     895             : template<typename Stream, typename T, std::size_t N>
     896       25634 : void Unserialize(Stream& is, std::array<T, N>& item)
     897             : {
     898     3396229 :     for (size_t i = 0; i < N; i++) {
     899     3370594 :         Unserialize(is, item[i]);
     900             :     }
     901       25634 : }
     902             : 
     903             : 
     904             : /**
     905             :  * pair
     906             :  */
     907             : template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
     908             : template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
     909             : 
     910             : /**
     911             :  * tuple
     912             :  */
     913             : template<typename Stream, typename... Elements> void Serialize(Stream& os, const std::tuple<Elements...>& item);
     914             : template<typename Stream, typename... Elements> void Unserialize(Stream& is, std::tuple<Elements...>& item);
     915             : 
     916             : /**
     917             :  * map
     918             :  */
     919             : template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
     920             : template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
     921             : 
     922             : /**
     923             :  * set
     924             :  */
     925             : template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
     926             : template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
     927             : 
     928             : /**
     929             :  * shared_ptr
     930             :  */
     931             : template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
     932             : template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
     933             : 
     934             : template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<T>& p);
     935             : template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<T>& p);
     936             : 
     937             : /**
     938             :  * unique_ptr
     939             :  */
     940             : template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
     941             : template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
     942             : 
     943             : 
     944             : 
     945             : /**
     946             :  * If none of the specialized versions above matched, default to calling member function.
     947             :  */
     948             : template <typename Stream, typename T>
     949    30050195 : inline void Serialize(Stream& os, const T& a)
     950             : {
     951    74226032 :     a.Serialize(os);
     952     1562438 : }
     953             : 
     954             : template<typename Stream, typename T>
     955     1996447 : inline void Unserialize(Stream& is, T&& a)
     956             : {
     957     2123728 :     a.Unserialize(is);
     958        2892 : }
     959             : 
     960             : /** Default formatter. Serializes objects as themselves.
     961             :  *
     962             :  * The vector/prevector serialization code passes this to VectorFormatter
     963             :  * to enable reusing that logic. It shouldn't be needed elsewhere.
     964             :  */
     965             : struct DefaultFormatter
     966             : {
     967             :     template<typename Stream, typename T>
     968    55664312 :     static void Ser(Stream& s, const T& t) { Serialize(s, t); }
     969             : 
     970             :     template<typename Stream, typename T>
     971     3196235 :     static void Unser(Stream& s, T& t) { Unserialize(s, t); }
     972             : };
     973             : 
     974             : 
     975             : /**
     976             :  * string
     977             :  */
     978             : template <typename Stream, typename C>
     979      234438 : void Serialize(Stream& os, const std::basic_string<C>& str)
     980             : {
     981      234440 :     WriteCompactSize(os, str.size());
     982      234437 :     if (!str.empty())
     983      220826 :         os.write((char*)str.data(), str.size() * sizeof(C));
     984      234437 : }
     985             : 
     986             : template <typename Stream, typename C>
     987       67063 : void Unserialize(Stream& is, std::basic_string<C>& str)
     988             : {
     989       67063 :     unsigned int nSize = ReadCompactSize(is);
     990       67063 :     str.resize(nSize);
     991       67063 :     if (nSize != 0)
     992       60451 :         is.read((char*)str.data(), nSize * sizeof(C));
     993       67060 : }
     994             : 
     995             : /**
     996             :   * list
     997             :   */
     998             : template<typename T, typename A> unsigned int GetSerializeSize(const std::list<T, A>& m);
     999             : template<typename Stream, typename T, typename A> void Serialize(Stream& os, const std::list<T, A>& m);
    1000             : template<typename Stream, typename T, typename A> void Unserialize(Stream& is, std::list<T, A>& m);
    1001             : 
    1002             : template<typename T, typename A>
    1003             : unsigned int GetSerializeSize(const std::list<T, A>& l)
    1004             : {
    1005             :     unsigned int nSize = GetSizeOfCompactSize(l.size());
    1006             :     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
    1007             :         nSize += GetSerializeSize((*it));
    1008             :     return nSize;
    1009             : }
    1010             : 
    1011             : template<typename Stream, typename T, typename A>
    1012         649 : void Serialize(Stream& os, const std::list<T, A>& l)
    1013             : {
    1014         649 :     WriteCompactSize(os, l.size());
    1015        1485 :     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
    1016         836 :         Serialize(os, (*it));
    1017         649 : }
    1018             : 
    1019             : template<typename Stream, typename T, typename A>
    1020          23 : void Unserialize(Stream& is, std::list<T, A>& l)
    1021             : {
    1022          23 :     l.clear();
    1023          23 :     unsigned int nSize = ReadCompactSize(is);
    1024          24 :     for (unsigned int i = 0; i < nSize; i++)
    1025             :     {
    1026           1 :         T item;
    1027           1 :         Unserialize(is, item);
    1028           1 :         l.push_back(item);
    1029             :     }
    1030          23 : }
    1031             : 
    1032             : 
    1033             : /**
    1034             :  * prevector
    1035             :  */
    1036             : template<typename Stream, unsigned int N, typename T>
    1037    72578281 : void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
    1038             : {
    1039    77106098 :     WriteCompactSize(os, v.size());
    1040    72578281 :     if (!v.empty())
    1041   116090092 :         os.write((char*)v.data(), v.size() * sizeof(T));
    1042    72578281 : }
    1043             : 
    1044             : template<typename Stream, unsigned int N, typename T, typename V>
    1045      213888 : void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
    1046             : {
    1047      213888 :     Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1048      213888 : }
    1049             : 
    1050             : template<typename Stream, unsigned int N, typename T>
    1051    72792166 : inline void Serialize(Stream& os, const prevector<N, T>& v)
    1052             : {
    1053   144868075 :     Serialize_impl(os, v, T());
    1054             : }
    1055             : 
    1056             : 
    1057             : template<typename Stream, unsigned int N, typename T>
    1058     1533492 : void Unserialize_impl(Stream& is, prevector<N, T>& v, const unsigned char&)
    1059             : {
    1060             :     // Limit size per read so bogus size value won't cause out of memory
    1061     1533492 :     v.clear();
    1062     1533492 :     unsigned int nSize = ReadCompactSize(is);
    1063     1533492 :     unsigned int i = 0;
    1064     2936663 :     while (i < nSize)
    1065             :     {
    1066     1403172 :         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1067     1403172 :         v.resize_uninitialized(i + blk);
    1068     1403172 :         is.read((char*)&v[i], blk * sizeof(T));
    1069     1403172 :         i += blk;
    1070             :     }
    1071     1533491 : }
    1072             : 
    1073             : template<typename Stream, unsigned int N, typename T, typename V>
    1074             : void Unserialize_impl(Stream& is, prevector<N, T>& v, const V&)
    1075             : {
    1076             :     Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
    1077             : }
    1078             : 
    1079             : template<typename Stream, unsigned int N, typename T>
    1080     1533492 : inline void Unserialize(Stream& is, prevector<N, T>& v)
    1081             : {
    1082     3066987 :     Unserialize_impl(is, v, T());
    1083             : }
    1084             : 
    1085             : 
    1086             : 
    1087             : /**
    1088             :  * vector
    1089             :  */
    1090             : template <typename Stream, typename T, typename A>
    1091      134010 : void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
    1092             : {
    1093      151329 :     WriteCompactSize(os, v.size());
    1094      134010 :     if (!v.empty())
    1095      133162 :         os.write((char*)v.data(), v.size() * sizeof(T));
    1096      134010 : }
    1097             : 
    1098             : template <typename Stream, typename T, typename A>
    1099          22 : void Serialize_impl(Stream& os, const std::vector<T, A>& v, const bool&)
    1100             : {
    1101             :     // A special case for std::vector<bool>, as dereferencing
    1102             :     // std::vector<bool>::const_iterator does not result in a const bool&
    1103             :     // due to std::vector's special casing for bool arguments.
    1104          22 :     WriteCompactSize(os, v.size());
    1105       10514 :     for (bool elem : v) {
    1106        9939 :         ::Serialize(os, elem);
    1107             :     }
    1108          22 : }
    1109             : 
    1110             : template <typename Stream, typename T, typename A, typename V>
    1111     6402297 : void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
    1112             : {
    1113     6402297 :     Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1114     6402297 : }
    1115             : 
    1116             : template <typename Stream, typename T, typename A>
    1117     6482458 : inline void Serialize(Stream& os, const std::vector<T, A>& v)
    1118             : {
    1119     6447265 :     Serialize_impl(os, v, T());
    1120     6114748 : }
    1121             : 
    1122             : 
    1123             : template <typename Stream, typename T, typename A>
    1124       95765 : void Unserialize_impl(Stream& is, std::vector<T, A>& v, const unsigned char&)
    1125             : {
    1126             :     // Limit size per read so bogus size value won't cause out of memory
    1127       95765 :     v.clear();
    1128       95765 :     unsigned int nSize = ReadCompactSize(is);
    1129       95765 :     unsigned int i = 0;
    1130      139883 :     while (i < nSize) {
    1131       44118 :         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1132       44118 :         v.resize(i + blk);
    1133       44118 :         is.read((char*)&v[i], blk * sizeof(T));
    1134       44118 :         i += blk;
    1135             :     }
    1136       95765 : }
    1137             : 
    1138             : template <typename Stream, typename T, typename A, typename V>
    1139      903907 : void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
    1140             : {
    1141      903907 :     Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
    1142      903901 : }
    1143             : 
    1144             : template <typename Stream, typename T, typename A>
    1145      946811 : inline void Unserialize(Stream& is, std::vector<T, A>& v)
    1146             : {
    1147     1002203 :     Unserialize_impl(is, v, T());
    1148      848150 : }
    1149             : 
    1150             : 
    1151             : 
    1152             : /**
    1153             :  * pair
    1154             :  */
    1155             : template <typename Stream, typename K, typename T>
    1156      277898 : void Serialize(Stream& os, const std::pair<K, T>& item)
    1157             : {
    1158      277898 :     Serialize(os, item.first);
    1159      277898 :     Serialize(os, item.second);
    1160      277898 : }
    1161             : 
    1162             : template <typename Stream, typename K, typename T>
    1163       49717 : void Unserialize(Stream& is, std::pair<K, T>& item)
    1164             : {
    1165       49717 :     Unserialize(is, item.first);
    1166       49720 :     Unserialize(is, item.second);
    1167       49430 : }
    1168             : 
    1169             : /**
    1170             :  * tuple
    1171             :  */
    1172             : template<typename Stream, int index, typename... Ts>
    1173             : struct SerializeTuple {
    1174       11151 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1175       11151 :         SerializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1176       11151 :         s << std::get<index>(t);
    1177       11151 :     }
    1178             : };
    1179             : 
    1180             : template<typename Stream, typename... Ts>
    1181             : struct SerializeTuple<Stream, 0, Ts...> {
    1182        3740 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1183        3740 :         s << std::get<0>(t);
    1184             :     }
    1185             : };
    1186             : 
    1187             : template<typename Stream, int index, typename... Ts>
    1188             : struct DeserializeTuple {
    1189           0 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1190           0 :         DeserializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1191           0 :         s >> std::get<index>(t);
    1192           0 :     }
    1193             : };
    1194             : 
    1195             : template<typename Stream, typename... Ts>
    1196             : struct DeserializeTuple<Stream, 0, Ts...> {
    1197           0 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1198           0 :         s >> std::get<0>(t);
    1199             :     }
    1200             : };
    1201             : 
    1202             : 
    1203             : template<typename Stream, typename... Elements>
    1204        3740 : void Serialize(Stream& os, const std::tuple<Elements...>& item)
    1205             : {
    1206        3740 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1207        3740 :     SerializeTuple<Stream, size - 1, Elements...>{}(os, const_cast<std::tuple<Elements...>&>(item));
    1208        3740 : }
    1209             : 
    1210             : template<typename Stream, typename... Elements>
    1211           0 : void Unserialize(Stream& is, std::tuple<Elements...>& item)
    1212             : {
    1213           0 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1214           0 :     DeserializeTuple<Stream, size - 1, Elements...>{}(is, item);
    1215           0 : }
    1216             : 
    1217             : 
    1218             : /**
    1219             :  * map
    1220             :  */
    1221             : template <typename Stream, typename K, typename T, typename Pred, typename A>
    1222       18392 : void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
    1223             : {
    1224       18392 :     WriteCompactSize(os, m.size());
    1225       53629 :     for (const auto& entry : m)
    1226       35237 :         Serialize(os, entry);
    1227       18392 : }
    1228             : 
    1229             : template <typename Stream, typename K, typename T, typename Pred, typename A>
    1230        7945 : void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
    1231             : {
    1232        7945 :     m.clear();
    1233        7945 :     unsigned int nSize = ReadCompactSize(is);
    1234        7945 :     typename std::map<K, T, Pred, A>::iterator mi = m.begin();
    1235       27199 :     for (unsigned int i = 0; i < nSize; i++) {
    1236       38444 :         std::pair<K, T> item;
    1237       19254 :         Unserialize(is, item);
    1238       19254 :         mi = m.insert(mi, item);
    1239             :     }
    1240        7945 : }
    1241             : 
    1242             : 
    1243             : /**
    1244             :  * set
    1245             :  */
    1246             : template <typename Stream, typename K, typename Pred, typename A>
    1247             : void Serialize(Stream& os, const std::set<K, Pred, A>& m)
    1248             : {
    1249             :     WriteCompactSize(os, m.size());
    1250             :     for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
    1251             :         Serialize(os, (*it));
    1252             : }
    1253             : 
    1254             : template <typename Stream, typename K, typename Pred, typename A>
    1255             : void Unserialize(Stream& is, std::set<K, Pred, A>& m)
    1256             : {
    1257             :     m.clear();
    1258             :     unsigned int nSize = ReadCompactSize(is);
    1259             :     typename std::set<K, Pred, A>::iterator it = m.begin();
    1260             :     for (unsigned int i = 0; i < nSize; i++) {
    1261             :         K key;
    1262             :         Unserialize(is, key);
    1263             :         it = m.insert(it, key);
    1264             :     }
    1265             : }
    1266             : 
    1267             : 
    1268             : 
    1269             : /**
    1270             :  * unique_ptr
    1271             :  */
    1272             : template<typename Stream, typename T> void
    1273             : Serialize(Stream& os, const std::unique_ptr<const T>& p)
    1274             : {
    1275             :     Serialize(os, *p);
    1276             : }
    1277             : 
    1278             : template<typename Stream, typename T>
    1279             : void Unserialize(Stream& is, std::unique_ptr<const T>& p)
    1280             : {
    1281             :     p.reset(new T(deserialize, is));
    1282             : }
    1283             : 
    1284             : 
    1285             : 
    1286             : /**
    1287             :  * shared_ptr
    1288             :  */
    1289             : template<typename Stream, typename T> void
    1290      906461 : Serialize(Stream& os, const std::shared_ptr<const T>& p)
    1291             : {
    1292      906461 :     Serialize(os, *p);
    1293      906461 : }
    1294             : 
    1295             : template<typename Stream, typename T>
    1296      368438 : void Unserialize(Stream& is, std::shared_ptr<const T>& p)
    1297             : {
    1298      374827 :     p = std::make_shared<const T>(deserialize, is);
    1299      368438 : }
    1300             : 
    1301             : template<typename Stream, typename T> void
    1302          25 : Serialize(Stream& os, const std::shared_ptr<T>& p)
    1303             : {
    1304          25 :     Serialize(os, *p);
    1305          25 : }
    1306             : 
    1307             : template<typename Stream, typename T>
    1308           0 : void Unserialize(Stream& is, std::shared_ptr<T>& p)
    1309             : {
    1310           0 :     p = std::make_shared<T>(deserialize, is);
    1311           0 : }
    1312             : 
    1313             : /**
    1314             :  * Support for SERIALIZE_METHODS and READWRITE macro.
    1315             :  */
    1316             : struct CSerActionSerialize {
    1317             :     constexpr bool ForRead() const { return false; }
    1318             : };
    1319             : struct CSerActionUnserialize {
    1320             :     constexpr bool ForRead() const { return true; }
    1321             : };
    1322             : 
    1323             : 
    1324             : /* ::GetSerializeSize implementations
    1325             :  *
    1326             :  * Computing the serialized size of objects is done through a special stream
    1327             :  * object of type CSizeComputer, which only records the number of bytes written
    1328             :  * to it.
    1329             :  *
    1330             :  * If your Serialize or SerializationOp method has non-trivial overhead for
    1331             :  * serialization, it may be worthwhile to implement a specialized version for
    1332             :  * CSizeComputer, which uses the s.seek() method to record bytes that would
    1333             :  * be written instead.
    1334             :  */
    1335             : class CSizeComputer
    1336             : {
    1337             : protected:
    1338             :     size_t nSize;
    1339             : 
    1340             :     const int nVersion;
    1341             : 
    1342             : public:
    1343      912147 :     explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
    1344             : 
    1345    28646981 :     void write(const char* psz, size_t _nSize)
    1346             :     {
    1347    14847180 :         this->nSize += _nSize;
    1348     4245702 :     }
    1349             : 
    1350             :     /** Pretend _nSize bytes are written, without specifying them. */
    1351     7401724 :     void seek(size_t _nSize)
    1352             :     {
    1353     7401724 :         this->nSize += _nSize;
    1354             :     }
    1355             : 
    1356             :     template <typename T>
    1357     5346749 :     CSizeComputer& operator<<(const T& obj)
    1358             :     {
    1359     1825330 :         ::Serialize(*this, obj);
    1360        3579 :         return (*this);
    1361             :     }
    1362             : 
    1363      912147 :     size_t size() const
    1364             :     {
    1365      912147 :         return nSize;
    1366             :     }
    1367             : 
    1368         260 :     int GetVersion() const { return nVersion; }
    1369             : };
    1370             : 
    1371             : template<typename Stream>
    1372             : void SerializeMany(Stream& s)
    1373             : {
    1374             : }
    1375             : 
    1376             : template<typename Stream, typename Arg, typename... Args>
    1377   356993494 : void SerializeMany(Stream& s, const Arg& arg, const Args&... args)
    1378             : {
    1379   356993494 :     ::Serialize(s, arg);
    1380   156113385 :     ::SerializeMany(s, args...);
    1381   356993494 : }
    1382             : 
    1383             : template<typename Stream>
    1384     4501705 : inline void UnserializeMany(Stream& s)
    1385             : {
    1386             : }
    1387             : 
    1388             : template<typename Stream, typename Arg, typename... Args>
    1389     7400427 : inline void UnserializeMany(Stream& s, Arg&& arg, Args&&... args)
    1390             : {
    1391     5077226 :     ::Unserialize(s, arg);
    1392     5034612 :     ::UnserializeMany(s, args...);
    1393     3610338 : }
    1394             : 
    1395             : template<typename Stream, typename... Args>
    1396   200749939 : inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, const Args&... args)
    1397             : {
    1398   200101534 :     ::SerializeMany(s, args...);
    1399        4031 : }
    1400             : 
    1401             : template<typename Stream, typename... Args>
    1402     2993995 : inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&... args)
    1403             : {
    1404     2645003 :     ::UnserializeMany(s, args...);
    1405         829 : }
    1406             : 
    1407             : template<typename Stream, typename Type, typename Fn>
    1408       38866 : inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
    1409             : {
    1410             : }
    1411             : 
    1412             : template<typename Stream, typename Type, typename Fn>
    1413        6225 : inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
    1414             : {
    1415        6225 :     fn(s, std::forward<Type>(obj));
    1416         168 : }
    1417             : 
    1418             : template<typename Stream, typename Type, typename Fn>
    1419       18251 : inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
    1420             : {
    1421       18251 :     fn(s, std::forward<Type>(obj));
    1422         169 : }
    1423             : 
    1424             : template<typename Stream, typename Type, typename Fn>
    1425        1205 : inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
    1426             : {
    1427             : }
    1428             : 
    1429             : template<typename I>
    1430             : inline void WriteVarInt(CSizeComputer &s, I n)
    1431             : {
    1432             :     s.seek(GetSizeOfVarInt<I>(n));
    1433             : }
    1434             : 
    1435     7401724 : inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
    1436             : {
    1437     7405037 :     s.seek(GetSizeOfCompactSize(nSize));
    1438             : }
    1439             : 
    1440             : template <typename T>
    1441      912147 : size_t GetSerializeSize(const T& t, int nVersion = 0)
    1442             : {
    1443      912147 :     return (CSizeComputer(nVersion) << t).size();
    1444             : }
    1445             : 
    1446             : template <typename... T>
    1447             : size_t GetSerializeSizeMany(int nVersion, const T&... t)
    1448             : {
    1449             :     CSizeComputer sc(nVersion);
    1450             :     SerializeMany(sc, t...);
    1451             :     return sc.size();
    1452             : }
    1453             : 
    1454             : /**
    1455             : * optional
    1456             : */
    1457             : template<typename T>
    1458          84 : unsigned int GetSerializeSize(const Optional<T> &item)
    1459             : {
    1460          84 :     if (item) {
    1461          84 :         return 1 + GetSerializeSize(*item);
    1462             :     } else {
    1463             :         return 1;
    1464             :     }
    1465             : }
    1466             : 
    1467             : #endif // PIVX_SERIALIZE_H

Generated by: LCOV version 1.14