LCOV - code coverage report
Current view: top level - src - serialize.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 418 474 88.2 %
Date: 2025-02-23 09:33:43 Functions: 1202 1402 85.7 %

          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     8744347 : inline char* CharCast(unsigned char* c) { return (char*)c; }
      73             : inline const char* CharCast(const char* c) { return c; }
      74      419705 : 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    30478900 : template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
      81             : {
      82   640669794 :     s.write((char*)&obj, 1);
      83           0 : }
      84    15339534 : template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
      85             : {
      86     7950211 :     obj = htole16(obj);
      87    15212325 :     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   139924554 : template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
      95             : {
      96   137704771 :     obj = htole32(obj);
      97   123797368 :     s.write((char*)&obj, 4);
      98           0 : }
      99    67383271 : template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
     100             : {
     101    67374745 :     obj = htole64(obj);
     102    65586504 :     s.write((char*)&obj, 8);
     103           0 : }
     104    86515791 : template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
     105             : {
     106             :     uint8_t obj;
     107    70822094 :     s.read((char*)&obj, 1);
     108    86515336 :     return obj;
     109             : }
     110     1937973 : template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
     111             : {
     112             :     uint16_t obj;
     113      400446 :     s.read((char*)&obj, 2);
     114     1894773 :     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     5433073 : template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
     123             : {
     124             :     uint32_t obj;
     125       39233 :     s.read((char*)&obj, 4);
     126     3254833 :     return le32toh(obj);
     127             : }
     128     2149795 : template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
     129             : {
     130             :     uint64_t obj;
     131        4252 :     s.read((char*)&obj, 8);
     132     3163153 :     return le64toh(obj);
     133             : }
     134      738996 : inline uint64_t ser_double_to_uint64(double x)
     135             : {
     136      738996 :     uint64_t tmp;
     137      737994 :     std::memcpy(&tmp, &x, sizeof(x));
     138      738996 :     static_assert(sizeof(tmp) == sizeof(x), "double and uint64_t assumed to have the same size");
     139      738994 :     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      175138 : inline double ser_uint64_to_double(uint64_t y)
     149             : {
     150      175138 :     double tmp;
     151      174138 :     std::memcpy(&tmp, &y, sizeof(y));
     152      175138 :     static_assert(sizeof(tmp) == sizeof(y), "double and uint64_t assumed to have the same size");
     153        1090 :     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     5286753 : template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
     181   103447180 : 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      370128 : 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   937833041 : template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
     240     7918335 : template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
     241       16880 : template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
     242    20253265 : template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
     243    43025895 : template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
     244    78267278 : template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
     245      727965 : 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        1356 : template<typename Stream> inline void Serialize(Stream& s, double a  ) { ser_writedata64(s, ser_double_to_uint64(a)); }
     248      658938 : template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
     249      451717 : template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
     250       66123 : template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
     251     1574535 : template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
     252             : 
     253       22825 : 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     8732248 : template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
     256     1853058 : template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
     257       71482 : template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
     258      692696 : template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
     259     2378943 : template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
     260      147425 : template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
     261       14700 : 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      175132 : template<typename Stream> inline void Unserialize(Stream& s, double& a  ) { a = ser_uint64_to_double(ser_readdata64(s)); }
     264      758315 : template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
     265       16363 : template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
     266     7167592 : template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }
     267             : 
     268       34997 : template<typename Stream> inline void Serialize(Stream& s, bool a)    { char f=a; ser_writedata8(s, f); }
     269       10594 : 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         699 : inline void Serialize(Stream& s, libzerocoin::CoinDenomination a)
     274             : {
     275         699 :     int f = libzerocoin::ZerocoinDenominationToInt(a);
     276         699 :     ser_writedata32(s, f);
     277         699 : }
     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        8164 : inline void Serialize(Stream& s, SporkId sporkID)
     304             : {
     305        8164 :     int32_t f = static_cast<int32_t>(sporkID);
     306        6386 :     ser_writedata32(s, f);
     307             : }
     308             : 
     309             : template <typename Stream>
     310        2173 : inline void Unserialize(Stream& s, SporkId& sporkID)
     311             : {
     312        2173 :     int32_t f = ser_readdata32(s);
     313        2173 :     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    23228847 : inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
     325             : {
     326    22628869 :     if (nSize < 253)             return sizeof(unsigned char);
     327       18937 :     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   107330682 : void WriteCompactSize(Stream& os, uint64_t nSize)
     336             : {
     337   107330682 :     if (nSize < 253) {
     338   107301648 :         ser_writedata8(os, nSize);
     339       29105 :     } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
     340       29008 :         ser_writedata8(os, 253);
     341       29008 :         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   107330681 :     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     8010172 : uint64_t ReadCompactSize(Stream& is, bool range_check = true)
     360             : {
     361     8010167 :     uint8_t chSize = ser_readdata8(is);
     362     8010167 :     uint64_t nSizeRet = 0;
     363     8010167 :     if (chSize < 253) {
     364     7999933 :         nSizeRet = chSize;
     365       10236 :     } else if (chSize == 253) {
     366       10173 :         nSizeRet = ser_readdata16(is);
     367       10173 :         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     8010161 :     if (range_check && nSizeRet > MAX_SIZE) {
     379           0 :         throw std::ios_base::failure("ReadCompactSize(): size too large");
     380             :     }
     381     8010161 :     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    46759636 :     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    17727432 : void WriteVarInt(Stream& os, I n)
     448             : {
     449             :     CheckVarIntMode<Mode, I>();
     450             :     unsigned char tmp[(sizeof(n)*8+6)/7];
     451    17727432 :     int len=0;
     452    24190115 :     while(true) {
     453    39855410 :         tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
     454    41917518 :         if (n <= 0x7F)
     455             :             break;
     456    24190115 :         n = (n >> 7) - 1;
     457    24190115 :         len++;
     458             :     }
     459    41917519 :     do {
     460    41917519 :         ser_writedata8(os, tmp[len]);
     461             :     } while (len--);
     462    17727432 : }
     463             : 
     464             : template<typename Stream, VarIntMode Mode, typename I>
     465    29032186 : I ReadVarInt(Stream& is)
     466             : {
     467             :     CheckVarIntMode<Mode, I>();
     468    29032186 :     I n = 0;
     469    36264946 :     while (true) {
     470    65297084 :         unsigned char chData = ser_readdata8(is);
     471    65297084 :         if (n > (std::numeric_limits<I>::max() >> 7)) {
     472           0 :            throw std::ios_base::failure("ReadVarInt(): size too large");
     473             :         }
     474    65297084 :         n = (n << 7) | (chData & 0x7F);
     475    65297084 :         if (chData & 0x80) {
     476    36264946 :             if (n == std::numeric_limits<I>::max()) {
     477           0 :                 throw std::ios_base::failure("ReadVarInt(): size too large");
     478             :             }
     479    36264946 :             n++;
     480             :         } else {
     481    29032186 :             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    86327974 :     explicit Wrapper(T obj) : m_object(obj) {}
     495    68597785 :     template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
     496     9649268 :     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    47101155 : 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    17727436 :     template<typename Stream, typename I> void Ser(Stream &s, I v)
     522             :     {
     523    17727436 :         WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
     524             :     }
     525             : 
     526    29032159 :     template<typename Stream, typename I> void Unser(Stream& s, I& v)
     527             :     {
     528    57534105 :         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        3897 :     void Ser(Stream& s, const std::vector<bool>& vec)
     544             :     {
     545        3897 :         size_t size = (N == 0 ? vec.size() : N);
     546             :         if (N == 0) {
     547        4493 :             WriteCompactSize(s, size);
     548             :         }
     549        3897 :         std::vector<unsigned char> vBytes((size + 7) / 8);
     550        3897 :         size_t ms = std::min(size, vec.size());
     551       15706 :         for (size_t p = 0; p < ms; p++)
     552       11809 :             vBytes[p / 8] |= vec[p] << (p % 8);
     553        5714 :         s.write((char*)vBytes.data(), vBytes.size());
     554        3897 :     }
     555             : 
     556             :     template<typename Stream>
     557       21472 :     void Unser(Stream& s, std::vector<bool>& vec)
     558             :     {
     559       21472 :         size_t size = (N == 0 ? ReadCompactSize(s) : N);
     560       21472 :         vec.resize(size);
     561       21472 :         std::vector<unsigned char> vBytes((size + 7) / 8);
     562       21472 :         s.read((char*)vBytes.data(), vBytes.size());
     563       86006 :         for (size_t p = 0; p < size; p++)
     564      129068 :             vec[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0;
     565       21472 :         if (vBytes.size() * 8 != size) {
     566       21472 :             size_t rem = vBytes.size() * 8 - size;
     567       21472 :             uint8_t m = ~(uint8_t)(0xff >> rem);
     568       21472 :             if (vBytes[vBytes.size() - 1] & m) {
     569           0 :                 throw std::ios_base::failure("Out-of-range bits set");
     570             :             }
     571             :         }
     572       21472 :     }
     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       74573 :     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       19545 :             uint64_t raw = htobe64(v);
     679       70754 :             s.write(((const char*)&raw) + 8 - Bytes, Bytes);
     680             :         } else {
     681        2937 :             uint64_t raw = htole64(v);
     682        2937 :             s.write((const char*)&raw, Bytes);
     683             :         }
     684          11 :     }
     685             : 
     686       16040 :     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       16040 :         uint64_t raw = 0;
     691             :         if (BigEndian) {
     692       16945 :             s.read(((char*)&raw) + 8 - Bytes, Bytes);
     693       10747 :             v = static_cast<I>(be64toh(raw));
     694             :         } else {
     695        5293 :             s.read((char*)&raw, Bytes);
     696        5293 :             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        6536 :     void Unser(Stream& s, I& v)
     709             :     {
     710       13072 :         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        5499 :         v = n;
     715             :     }
     716             : 
     717             :     template<typename Stream, typename I>
     718       17983 :     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       17983 :         WriteCompactSize<Stream>(s, v);
     724             :     }
     725             : };
     726             : 
     727             : template<size_t Limit>
     728             : struct LimitedStringFormatter
     729             : {
     730             :     template<typename Stream>
     731        1711 :     void Unser(Stream& s, std::string& v)
     732             :     {
     733        1711 :         size_t size = ReadCompactSize(s);
     734        1710 :         if (size > Limit) {
     735           0 :             throw std::ios_base::failure("String length limit exceeded");
     736             :         }
     737        1710 :         v.resize(size);
     738        1710 :         if (size != 0) s.read((char*)v.data(), size);
     739        1710 :     }
     740             : 
     741             :     template<typename Stream>
     742         597 :     void Ser(Stream& s, const std::string& v)
     743             :     {
     744         597 :         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    17703502 :     void Ser(Stream& s, const V& v)
     766             :     {
     767             :         Formatter formatter;
     768    25422283 :         WriteCompactSize(s, v.size());
     769   100419826 :         for (const typename V::value_type& elem : v) {
     770    82277052 :             formatter.Ser(s, elem);
     771             :         }
     772    17703502 :     }
     773             : 
     774             :     template<typename Stream, typename V>
     775     2794340 :     void Unser(Stream& s, V& v)
     776             :     {
     777             :         Formatter formatter;
     778     2794340 :         v.clear();
     779     2794340 :         size_t size = ReadCompactSize(s);
     780     2794336 :         size_t allocated = 0;
     781     5521772 :         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     2727447 :             allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
     787     2727447 :             v.reserve(allocated);
     788     9406666 :             while (v.size() < allocated) {
     789     6679221 :                 v.emplace_back();
     790    11302096 :                 formatter.Unser(s, v.back());
     791             :             }
     792             :         }
     793     2794334 :     };
     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      183534 : 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      183534 :     if (item) {
     862      176370 :         unsigned char discriminant = 0x01;
     863      176370 :         Serialize(os, discriminant);
     864      355390 :         Serialize(os, *item);
     865             :     } else {
     866        7164 :         unsigned char discriminant = 0x00;
     867       73182 :         Serialize(os, discriminant);
     868             :     }
     869      183534 : }
     870             : 
     871             : template<typename Stream, typename T>
     872       26468 : void Unserialize(Stream& is, Optional<T>& item)
     873             : {
     874       26468 :     unsigned char discriminant = 0x00;
     875       26468 :     Unserialize(is, discriminant);
     876             : 
     877       26468 :     if (discriminant == 0x00) {
     878         417 :         item = boost::none;
     879             :     } else {
     880       11635 :         T object;
     881       26051 :         Unserialize(is, object);
     882       26051 :         item = object;
     883             :     }
     884       26468 : }
     885             : 
     886             : 
     887             : template<typename Stream, typename T, std::size_t N>
     888     1905496 : void Serialize(Stream& os, const std::array<T, N>& item)
     889             : {
     890   510456022 :     for (size_t i = 0; i < N; i++) {
     891   508550039 :         Serialize(os, item[i]);
     892             :     }
     893     1905496 : }
     894             : 
     895             : template<typename Stream, typename T, std::size_t N>
     896       47517 : void Unserialize(Stream& is, std::array<T, N>& item)
     897             : {
     898     6726465 :     for (size_t i = 0; i < N; i++) {
     899     6678950 :         Unserialize(is, item[i]);
     900             :     }
     901       47517 : }
     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    53097167 : inline void Serialize(Stream& os, const T& a)
     950             : {
     951   137142942 :     a.Serialize(os);
     952     8701653 : }
     953             : 
     954             : template<typename Stream, typename T>
     955    29547249 : inline void Unserialize(Stream& is, T&& a)
     956             : {
     957    36197594 :     a.Unserialize(is);
     958       14492 : }
     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    80394537 :     static void Ser(Stream& s, const T& t) { Serialize(s, t); }
     969             : 
     970             :     template<typename Stream, typename T>
     971     8868972 :     static void Unser(Stream& s, T& t) { Unserialize(s, t); }
     972             : };
     973             : 
     974             : 
     975             : /**
     976             :  * string
     977             :  */
     978             : template <typename Stream, typename C>
     979     2779372 : void Serialize(Stream& os, const std::basic_string<C>& str)
     980             : {
     981     2779374 :     WriteCompactSize(os, str.size());
     982     2779371 :     if (!str.empty())
     983     2439107 :         os.write((char*)str.data(), str.size() * sizeof(C));
     984     2779371 : }
     985             : 
     986             : template <typename Stream, typename C>
     987       88049 : void Unserialize(Stream& is, std::basic_string<C>& str)
     988             : {
     989       88049 :     unsigned int nSize = ReadCompactSize(is);
     990       88049 :     str.resize(nSize);
     991       88049 :     if (nSize != 0)
     992       81062 :         is.read((char*)str.data(), nSize * sizeof(C));
     993       88047 : }
     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        2255 : void Serialize(Stream& os, const std::list<T, A>& l)
    1013             : {
    1014        2255 :     WriteCompactSize(os, l.size());
    1015        3091 :     for (typename std::list<T, A>::const_iterator it = l.begin(); it != l.end(); ++it)
    1016         836 :         Serialize(os, (*it));
    1017        2255 : }
    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   102819728 : void Serialize_impl(Stream& os, const prevector<N, T>& v, const unsigned char&)
    1038             : {
    1039   118187335 :     WriteCompactSize(os, v.size());
    1040   102819728 :     if (!v.empty())
    1041   161035154 :         os.write((char*)v.data(), v.size() * sizeof(T));
    1042   102819728 : }
    1043             : 
    1044             : template<typename Stream, unsigned int N, typename T, typename V>
    1045      219648 : void Serialize_impl(Stream& os, const prevector<N, T>& v, const V&)
    1046             : {
    1047      219648 :     Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1048      219648 : }
    1049             : 
    1050             : template<typename Stream, unsigned int N, typename T>
    1051   103039377 : inline void Serialize(Stream& os, const prevector<N, T>& v)
    1052             : {
    1053   199340077 :     Serialize_impl(os, v, T());
    1054             : }
    1055             : 
    1056             : 
    1057             : template<typename Stream, unsigned int N, typename T>
    1058     4932033 : 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     4932033 :     v.clear();
    1062     4932033 :     unsigned int nSize = ReadCompactSize(is);
    1063     4932033 :     unsigned int i = 0;
    1064     9510353 :     while (i < nSize)
    1065             :     {
    1066     4578321 :         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1067     4578321 :         v.resize_uninitialized(i + blk);
    1068     4578321 :         is.read((char*)&v[i], blk * sizeof(T));
    1069     4578321 :         i += blk;
    1070             :     }
    1071     4932032 : }
    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     4932030 : inline void Unserialize(Stream& is, prevector<N, T>& v)
    1081             : {
    1082     9864059 :     Unserialize_impl(is, v, T());
    1083             : }
    1084             : 
    1085             : 
    1086             : 
    1087             : /**
    1088             :  * vector
    1089             :  */
    1090             : template <typename Stream, typename T, typename A>
    1091      239261 : void Serialize_impl(Stream& os, const std::vector<T, A>& v, const unsigned char&)
    1092             : {
    1093      289962 :     WriteCompactSize(os, v.size());
    1094      239261 :     if (!v.empty())
    1095      237489 :         os.write((char*)v.data(), v.size() * sizeof(T));
    1096      239261 : }
    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    16448158 : void Serialize_impl(Stream& os, const std::vector<T, A>& v, const V&)
    1112             : {
    1113    16448158 :     Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));
    1114    16448158 : }
    1115             : 
    1116             : template <typename Stream, typename T, typename A>
    1117    16619992 : inline void Serialize(Stream& os, const std::vector<T, A>& v)
    1118             : {
    1119    16218339 :     Serialize_impl(os, v, T());
    1120    15340785 : }
    1121             : 
    1122             : 
    1123             : template <typename Stream, typename T, typename A>
    1124      131208 : 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      131208 :     v.clear();
    1128      131208 :     unsigned int nSize = ReadCompactSize(is);
    1129      131208 :     unsigned int i = 0;
    1130      208930 :     while (i < nSize) {
    1131       77722 :         unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
    1132       77722 :         v.resize(i + blk);
    1133       77722 :         is.read((char*)&v[i], blk * sizeof(T));
    1134       77722 :         i += blk;
    1135             :     }
    1136      131208 : }
    1137             : 
    1138             : template <typename Stream, typename T, typename A, typename V>
    1139     2664350 : void Unserialize_impl(Stream& is, std::vector<T, A>& v, const V&)
    1140             : {
    1141     2664350 :     Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));
    1142     2664344 : }
    1143             : 
    1144             : template <typename Stream, typename T, typename A>
    1145     2737235 : inline void Unserialize(Stream& is, std::vector<T, A>& v)
    1146             : {
    1147     2779478 :     Unserialize_impl(is, v, T());
    1148     2416836 : }
    1149             : 
    1150             : 
    1151             : 
    1152             : /**
    1153             :  * pair
    1154             :  */
    1155             : template <typename Stream, typename K, typename T>
    1156     2018558 : void Serialize(Stream& os, const std::pair<K, T>& item)
    1157             : {
    1158     2018558 :     Serialize(os, item.first);
    1159     2018558 :     Serialize(os, item.second);
    1160     2018558 : }
    1161             : 
    1162             : template <typename Stream, typename K, typename T>
    1163       55928 : void Unserialize(Stream& is, std::pair<K, T>& item)
    1164             : {
    1165       55928 :     Unserialize(is, item.first);
    1166       55931 :     Unserialize(is, item.second);
    1167       55632 : }
    1168             : 
    1169             : /**
    1170             :  * tuple
    1171             :  */
    1172             : template<typename Stream, int index, typename... Ts>
    1173             : struct SerializeTuple {
    1174      120395 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1175      120395 :         SerializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1176      120395 :         s << std::get<index>(t);
    1177      120395 :     }
    1178             : };
    1179             : 
    1180             : template<typename Stream, typename... Ts>
    1181             : struct SerializeTuple<Stream, 0, Ts...> {
    1182       63355 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1183       63355 :         s << std::get<0>(t);
    1184             :     }
    1185             : };
    1186             : 
    1187             : template<typename Stream, int index, typename... Ts>
    1188             : struct DeserializeTuple {
    1189       35970 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1190       35970 :         DeserializeTuple<Stream, index - 1, Ts...>{}(s, t);
    1191       35970 :         s >> std::get<index>(t);
    1192       35044 :     }
    1193             : };
    1194             : 
    1195             : template<typename Stream, typename... Ts>
    1196             : struct DeserializeTuple<Stream, 0, Ts...> {
    1197       17522 :     void operator() (Stream&s, std::tuple<Ts...>& t) {
    1198       17522 :         s >> std::get<0>(t);
    1199             :     }
    1200             : };
    1201             : 
    1202             : 
    1203             : template<typename Stream, typename... Elements>
    1204       63355 : void Serialize(Stream& os, const std::tuple<Elements...>& item)
    1205             : {
    1206       63355 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1207       63355 :     SerializeTuple<Stream, size - 1, Elements...>{}(os, const_cast<std::tuple<Elements...>&>(item));
    1208       63355 : }
    1209             : 
    1210             : template<typename Stream, typename... Elements>
    1211       17522 : void Unserialize(Stream& is, std::tuple<Elements...>& item)
    1212             : {
    1213       17522 :     const auto size = std::tuple_size<std::tuple<Elements...>>::value;
    1214       17377 :     DeserializeTuple<Stream, size - 1, Elements...>{}(is, item);
    1215       17377 : }
    1216             : 
    1217             : 
    1218             : /**
    1219             :  * map
    1220             :  */
    1221             : template <typename Stream, typename K, typename T, typename Pred, typename A>
    1222      348531 : void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
    1223             : {
    1224      348531 :     WriteCompactSize(os, m.size());
    1225     1365655 :     for (const auto& entry : m)
    1226     1017130 :         Serialize(os, entry);
    1227      348531 : }
    1228             : 
    1229             : template <typename Stream, typename K, typename T, typename Pred, typename A>
    1230        8475 : void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
    1231             : {
    1232        8475 :     m.clear();
    1233        8475 :     unsigned int nSize = ReadCompactSize(is);
    1234        8475 :     typename std::map<K, T, Pred, A>::iterator mi = m.begin();
    1235       28921 :     for (unsigned int i = 0; i < nSize; i++) {
    1236       40786 :         std::pair<K, T> item;
    1237       20446 :         Unserialize(is, item);
    1238       20446 :         mi = m.insert(mi, item);
    1239             :     }
    1240        8475 : }
    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     2558677 : Serialize(Stream& os, const std::shared_ptr<const T>& p)
    1291             : {
    1292     2558677 :     Serialize(os, *p);
    1293     2558677 : }
    1294             : 
    1295             : template<typename Stream, typename T>
    1296      900602 : void Unserialize(Stream& is, std::shared_ptr<const T>& p)
    1297             : {
    1298      907366 :     p = std::make_shared<const T>(deserialize, is);
    1299      900602 : }
    1300             : 
    1301             : template<typename Stream, typename T> void
    1302          34 : Serialize(Stream& os, const std::shared_ptr<T>& p)
    1303             : {
    1304          34 :     Serialize(os, *p);
    1305          34 : }
    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     2738778 :     explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
    1344             : 
    1345    87164348 :     void write(const char* psz, size_t _nSize)
    1346             :     {
    1347    42156429 :         this->nSize += _nSize;
    1348    15089592 :     }
    1349             : 
    1350             :     /** Pretend _nSize bytes are written, without specifying them. */
    1351    23172404 :     void seek(size_t _nSize)
    1352             :     {
    1353    23172404 :         this->nSize += _nSize;
    1354             :     }
    1355             : 
    1356             :     template <typename T>
    1357    14850387 :     CSizeComputer& operator<<(const T& obj)
    1358             :     {
    1359     5071632 :         ::Serialize(*this, obj);
    1360       20855 :         return (*this);
    1361             :     }
    1362             : 
    1363     2738778 :     size_t size() const
    1364             :     {
    1365     2738778 :         return nSize;
    1366             :     }
    1367             : 
    1368         906 :     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   490030576 : void SerializeMany(Stream& s, const Arg& arg, const Args&... args)
    1378             : {
    1379   490030576 :     ::Serialize(s, arg);
    1380   213119654 :     ::SerializeMany(s, args...);
    1381   490030576 : }
    1382             : 
    1383             : template<typename Stream>
    1384    14225898 : inline void UnserializeMany(Stream& s)
    1385             : {
    1386             : }
    1387             : 
    1388             : template<typename Stream, typename Arg, typename... Args>
    1389    45994618 : inline void UnserializeMany(Stream& s, Arg&& arg, Args&&... args)
    1390             : {
    1391    32760665 :     ::Unserialize(s, arg);
    1392    32794088 :     ::UnserializeMany(s, args...);
    1393    22752921 : }
    1394             : 
    1395             : template<typename Stream, typename... Args>
    1396   276256490 : inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, const Args&... args)
    1397             : {
    1398   275012801 :     ::SerializeMany(s, args...);
    1399        4814 : }
    1400             : 
    1401             : template<typename Stream, typename... Args>
    1402    15197123 : inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&... args)
    1403             : {
    1404    13841195 :     ::UnserializeMany(s, args...);
    1405         896 : }
    1406             : 
    1407             : template<typename Stream, typename Type, typename Fn>
    1408       47063 : inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
    1409             : {
    1410             : }
    1411             : 
    1412             : template<typename Stream, typename Type, typename Fn>
    1413       12067 : inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
    1414             : {
    1415       12067 :     fn(s, std::forward<Type>(obj));
    1416         168 : }
    1417             : 
    1418             : template<typename Stream, typename Type, typename Fn>
    1419       18151 : inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
    1420             : {
    1421       18151 :     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    23172404 : inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
    1436             : {
    1437    23191219 :     s.seek(GetSizeOfCompactSize(nSize));
    1438             : }
    1439             : 
    1440             : template <typename T>
    1441     2738778 : size_t GetSerializeSize(const T& t, int nVersion = 0)
    1442             : {
    1443     2738778 :     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         188 : unsigned int GetSerializeSize(const Optional<T> &item)
    1459             : {
    1460         188 :     if (item) {
    1461         188 :         return 1 + GetSerializeSize(*item);
    1462             :     } else {
    1463             :         return 1;
    1464             :     }
    1465             : }
    1466             : 
    1467             : #endif // PIVX_SERIALIZE_H

Generated by: LCOV version 1.14