Bitcoin Core  26.1.0
P2P Digital Currency
serialize.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef BITCOIN_SERIALIZE_H
7 #define BITCOIN_SERIALIZE_H
8 
9 #include <attributes.h>
10 #include <compat/endian.h>
11 
12 #include <algorithm>
13 #include <cstdint>
14 #include <cstring>
15 #include <ios>
16 #include <limits>
17 #include <map>
18 #include <memory>
19 #include <set>
20 #include <string>
21 #include <string.h>
22 #include <utility>
23 #include <vector>
24 
25 #include <prevector.h>
26 #include <span.h>
27 
32 static constexpr uint64_t MAX_SIZE = 0x02000000;
33 
35 static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
36 
48 struct deserialize_type {};
50 
51 /*
52  * Lowest-level serialization and conversion.
53  */
54 template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj)
55 {
56  s.write(AsBytes(Span{&obj, 1}));
57 }
58 template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
59 {
60  obj = htole16(obj);
61  s.write(AsBytes(Span{&obj, 1}));
62 }
63 template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
64 {
65  obj = htobe16(obj);
66  s.write(AsBytes(Span{&obj, 1}));
67 }
68 template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
69 {
70  obj = htole32(obj);
71  s.write(AsBytes(Span{&obj, 1}));
72 }
73 template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj)
74 {
75  obj = htobe32(obj);
76  s.write(AsBytes(Span{&obj, 1}));
77 }
78 template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj)
79 {
80  obj = htole64(obj);
81  s.write(AsBytes(Span{&obj, 1}));
82 }
83 template<typename Stream> inline uint8_t ser_readdata8(Stream &s)
84 {
85  uint8_t obj;
86  s.read(AsWritableBytes(Span{&obj, 1}));
87  return obj;
88 }
89 template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
90 {
91  uint16_t obj;
92  s.read(AsWritableBytes(Span{&obj, 1}));
93  return le16toh(obj);
94 }
95 template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
96 {
97  uint16_t obj;
98  s.read(AsWritableBytes(Span{&obj, 1}));
99  return be16toh(obj);
100 }
101 template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
102 {
103  uint32_t obj;
104  s.read(AsWritableBytes(Span{&obj, 1}));
105  return le32toh(obj);
106 }
107 template<typename Stream> inline uint32_t ser_readdata32be(Stream &s)
108 {
109  uint32_t obj;
110  s.read(AsWritableBytes(Span{&obj, 1}));
111  return be32toh(obj);
112 }
113 template<typename Stream> inline uint64_t ser_readdata64(Stream &s)
114 {
115  uint64_t obj;
116  s.read(AsWritableBytes(Span{&obj, 1}));
117  return le64toh(obj);
118 }
119 
120 
122 //
123 // Templates for serializing to anything that looks like a stream,
124 // i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>)
125 //
126 
127 class CSizeComputer;
128 
129 enum
130 {
131  // primary actions
132  SER_NETWORK = (1 << 0),
133  SER_DISK = (1 << 1),
134 };
135 
156 template <class Out, class In>
158 {
159  static_assert(std::is_base_of_v<Out, In>);
160  return x;
161 }
162 template <class Out, class In>
163 const Out& AsBase(const In& x)
164 {
165  static_assert(std::is_base_of_v<Out, In>);
166  return x;
167 }
168 
169 #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
170 #define SER_READ(obj, code) ser_action.SerRead(s, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
171 #define SER_WRITE(obj, code) ser_action.SerWrite(s, obj, [&](Stream& s, const Type& obj) { code; })
172 
189 #define FORMATTER_METHODS(cls, obj) \
190  template<typename Stream> \
191  static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, ActionSerialize{}); } \
192  template<typename Stream> \
193  static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, ActionUnserialize{}); } \
194  template<typename Stream, typename Type, typename Operation> \
195  static void SerializationOps(Type& obj, Stream& s, Operation ser_action)
196 
230 #define FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
231  template <typename Stream> \
232  static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, ActionSerialize{}, s.GetParams()); } \
233  template <typename Stream> \
234  static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, ActionUnserialize{}, s.GetParams()); } \
235  template <typename Stream, typename Type, typename Operation> \
236  static void SerializationOps(Type& obj, Stream& s, Operation ser_action, const paramcls& paramobj)
237 
238 #define BASE_SERIALIZE_METHODS(cls) \
239  template <typename Stream> \
240  void Serialize(Stream& s) const \
241  { \
242  static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
243  Ser(s, *this); \
244  } \
245  template <typename Stream> \
246  void Unserialize(Stream& s) \
247  { \
248  static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
249  Unser(s, *this); \
250  }
251 
259 #define SERIALIZE_METHODS(cls, obj) \
260  BASE_SERIALIZE_METHODS(cls) \
261  FORMATTER_METHODS(cls, obj)
262 
268 #define SERIALIZE_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
269  BASE_SERIALIZE_METHODS(cls) \
270  FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj)
271 
272 // clang-format off
273 #ifndef CHAR_EQUALS_INT8
274 template <typename Stream> void Serialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t
275 #endif
276 template <typename Stream> void Serialize(Stream& s, std::byte a) { ser_writedata8(s, uint8_t(a)); }
277 template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
278 template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
279 template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
280 template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
281 template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
282 template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
283 template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
284 template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
285 template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(MakeByteSpan(a)); }
286 template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(MakeByteSpan(a)); }
287 template <typename Stream, typename B, std::size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { (void)/* force byte-type */UCharCast(a.data()); s.write(MakeByteSpan(a)); }
288 template <typename Stream, typename B> void Serialize(Stream& s, Span<B> span) { (void)/* force byte-type */UCharCast(span.data()); s.write(AsBytes(span)); }
289 
290 #ifndef CHAR_EQUALS_INT8
291 template <typename Stream> void Unserialize(Stream&, char) = delete; // char serialization forbidden. Use uint8_t or int8_t
292 #endif
293 template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte{ser_readdata8(s)}; }
294 template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
295 template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
296 template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
297 template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
298 template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
299 template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
300 template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
301 template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
302 template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
303 template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
304 template <typename Stream, typename B, std::size_t N> void Unserialize(Stream& s, std::array<B, N>& a) { (void)/* force byte-type */UCharCast(a.data()); s.read(MakeWritableByteSpan(a)); }
305 template <typename Stream, typename B> void Unserialize(Stream& s, Span<B> span) { (void)/* force byte-type */UCharCast(span.data()); s.read(AsWritableBytes(span)); }
306 
307 template <typename Stream> inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); }
308 template <typename Stream> inline void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; }
309 // clang-format on
310 
311 
319 constexpr inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
320 {
321  if (nSize < 253) return sizeof(unsigned char);
322  else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);
323  else if (nSize <= std::numeric_limits<unsigned int>::max()) return sizeof(unsigned char) + sizeof(unsigned int);
324  else return sizeof(unsigned char) + sizeof(uint64_t);
325 }
326 
327 inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
328 
329 template<typename Stream>
330 void WriteCompactSize(Stream& os, uint64_t nSize)
331 {
332  if (nSize < 253)
333  {
334  ser_writedata8(os, nSize);
335  }
336  else if (nSize <= std::numeric_limits<uint16_t>::max())
337  {
338  ser_writedata8(os, 253);
339  ser_writedata16(os, nSize);
340  }
341  else if (nSize <= std::numeric_limits<unsigned int>::max())
342  {
343  ser_writedata8(os, 254);
344  ser_writedata32(os, nSize);
345  }
346  else
347  {
348  ser_writedata8(os, 255);
349  ser_writedata64(os, nSize);
350  }
351  return;
352 }
353 
360 template<typename Stream>
361 uint64_t ReadCompactSize(Stream& is, bool range_check = true)
362 {
363  uint8_t chSize = ser_readdata8(is);
364  uint64_t nSizeRet = 0;
365  if (chSize < 253)
366  {
367  nSizeRet = chSize;
368  }
369  else if (chSize == 253)
370  {
371  nSizeRet = ser_readdata16(is);
372  if (nSizeRet < 253)
373  throw std::ios_base::failure("non-canonical ReadCompactSize()");
374  }
375  else if (chSize == 254)
376  {
377  nSizeRet = ser_readdata32(is);
378  if (nSizeRet < 0x10000u)
379  throw std::ios_base::failure("non-canonical ReadCompactSize()");
380  }
381  else
382  {
383  nSizeRet = ser_readdata64(is);
384  if (nSizeRet < 0x100000000ULL)
385  throw std::ios_base::failure("non-canonical ReadCompactSize()");
386  }
387  if (range_check && nSizeRet > MAX_SIZE) {
388  throw std::ios_base::failure("ReadCompactSize(): size too large");
389  }
390  return nSizeRet;
391 }
392 
428 
429 template <VarIntMode Mode, typename I>
431  constexpr CheckVarIntMode()
432  {
433  static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value, "Unsigned type required with mode DEFAULT.");
434  static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed<I>::value, "Signed type required with mode NONNEGATIVE_SIGNED.");
435  }
436 };
437 
438 template<VarIntMode Mode, typename I>
439 inline unsigned int GetSizeOfVarInt(I n)
440 {
442  int nRet = 0;
443  while(true) {
444  nRet++;
445  if (n <= 0x7F)
446  break;
447  n = (n >> 7) - 1;
448  }
449  return nRet;
450 }
451 
452 template<typename I>
453 inline void WriteVarInt(CSizeComputer& os, I n);
454 
455 template<typename Stream, VarIntMode Mode, typename I>
456 void WriteVarInt(Stream& os, I n)
457 {
459  unsigned char tmp[(sizeof(n)*8+6)/7];
460  int len=0;
461  while(true) {
462  tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
463  if (n <= 0x7F)
464  break;
465  n = (n >> 7) - 1;
466  len++;
467  }
468  do {
469  ser_writedata8(os, tmp[len]);
470  } while(len--);
471 }
472 
473 template<typename Stream, VarIntMode Mode, typename I>
474 I ReadVarInt(Stream& is)
475 {
477  I n = 0;
478  while(true) {
479  unsigned char chData = ser_readdata8(is);
480  if (n > (std::numeric_limits<I>::max() >> 7)) {
481  throw std::ios_base::failure("ReadVarInt(): size too large");
482  }
483  n = (n << 7) | (chData & 0x7F);
484  if (chData & 0x80) {
485  if (n == std::numeric_limits<I>::max()) {
486  throw std::ios_base::failure("ReadVarInt(): size too large");
487  }
488  n++;
489  } else {
490  return n;
491  }
492  }
493 }
494 
496 template<typename Formatter, typename T>
497 class Wrapper
498 {
499  static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
500 protected:
501  T m_object;
502 public:
503  explicit Wrapper(T obj) : m_object(obj) {}
504  template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
505  template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
506 };
507 
518 template<typename Formatter, typename T>
519 static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
520 
521 #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
522 #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
523 #define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
524 #define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
525 
527 template<VarIntMode Mode>
529 {
530  template<typename Stream, typename I> void Ser(Stream &s, I v)
531  {
532  WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
533  }
534 
535  template<typename Stream, typename I> void Unser(Stream& s, I& v)
536  {
537  v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
538  }
539 };
540 
550 template<int Bytes, bool BigEndian = false>
552 {
553  static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
554  static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
555 
556  template <typename Stream, typename I> void Ser(Stream& s, I v)
557  {
558  if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
559  if (BigEndian) {
560  uint64_t raw = htobe64(v);
561  s.write(AsBytes(Span{&raw, 1}).last(Bytes));
562  } else {
563  uint64_t raw = htole64(v);
564  s.write(AsBytes(Span{&raw, 1}).first(Bytes));
565  }
566  }
567 
568  template <typename Stream, typename I> void Unser(Stream& s, I& v)
569  {
570  using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
571  static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
572  uint64_t raw = 0;
573  if (BigEndian) {
574  s.read(AsWritableBytes(Span{&raw, 1}).last(Bytes));
575  v = static_cast<I>(be64toh(raw));
576  } else {
577  s.read(AsWritableBytes(Span{&raw, 1}).first(Bytes));
578  v = static_cast<I>(le64toh(raw));
579  }
580  }
581 };
582 
584 
586 template<bool RangeCheck>
588 {
589  template<typename Stream, typename I>
590  void Unser(Stream& s, I& v)
591  {
592  uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
593  if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
594  throw std::ios_base::failure("CompactSize exceeds limit of type");
595  }
596  v = n;
597  }
598 
599  template<typename Stream, typename I>
600  void Ser(Stream& s, I v)
601  {
602  static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
603  static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
604 
605  WriteCompactSize<Stream>(s, v);
606  }
607 };
608 
609 template <typename U, bool LOSSY = false>
611  template <typename Stream, typename Tp>
612  void Unser(Stream& s, Tp& tp)
613  {
614  U u;
615  s >> u;
616  // Lossy deserialization does not make sense, so force Wnarrowing
617  tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
618  }
619  template <typename Stream, typename Tp>
620  void Ser(Stream& s, Tp tp)
621  {
622  if constexpr (LOSSY) {
623  s << U(tp.time_since_epoch().count());
624  } else {
625  s << U{tp.time_since_epoch().count()};
626  }
627  }
628 };
629 template <typename U>
631 
633 {
634 protected:
635  uint64_t n;
636 public:
637  explicit CompactSizeWriter(uint64_t n_in) : n(n_in) { }
638 
639  template<typename Stream>
640  void Serialize(Stream &s) const {
641  WriteCompactSize<Stream>(s, n);
642  }
643 };
644 
645 template<size_t Limit>
647 {
648  template<typename Stream>
649  void Unser(Stream& s, std::string& v)
650  {
651  size_t size = ReadCompactSize(s);
652  if (size > Limit) {
653  throw std::ios_base::failure("String length limit exceeded");
654  }
655  v.resize(size);
656  if (size != 0) s.read(MakeWritableByteSpan(v));
657  }
658 
659  template<typename Stream>
660  void Ser(Stream& s, const std::string& v)
661  {
662  s << v;
663  }
664 };
665 
679 template<class Formatter>
681 {
682  template<typename Stream, typename V>
683  void Ser(Stream& s, const V& v)
684  {
685  Formatter formatter;
686  WriteCompactSize(s, v.size());
687  for (const typename V::value_type& elem : v) {
688  formatter.Ser(s, elem);
689  }
690  }
691 
692  template<typename Stream, typename V>
693  void Unser(Stream& s, V& v)
694  {
695  Formatter formatter;
696  v.clear();
697  size_t size = ReadCompactSize(s);
698  size_t allocated = 0;
699  while (allocated < size) {
700  // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
701  // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
702  // X MiB of data to make us allocate X+5 Mib.
703  static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
704  allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
705  v.reserve(allocated);
706  while (v.size() < allocated) {
707  v.emplace_back();
708  formatter.Unser(s, v.back());
709  }
710  }
711  };
712 };
713 
721 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
722 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
723 
728 template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
729 template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
730 
735 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
736 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
737 
741 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
742 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
743 
747 template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
748 template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
749 
753 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
754 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
755 
759 template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
760 template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
761 
765 template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
766 template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
767 
768 
769 
773 template<typename Stream, typename T>
774 inline void Serialize(Stream& os, const T& a)
775 {
776  a.Serialize(os);
777 }
778 
779 template<typename Stream, typename T>
780 inline void Unserialize(Stream& is, T&& a)
781 {
782  a.Unserialize(is);
783 }
784 
791 {
792  template<typename Stream, typename T>
793  static void Ser(Stream& s, const T& t) { Serialize(s, t); }
794 
795  template<typename Stream, typename T>
796  static void Unser(Stream& s, T& t) { Unserialize(s, t); }
797 };
798 
799 
800 
801 
802 
806 template<typename Stream, typename C>
807 void Serialize(Stream& os, const std::basic_string<C>& str)
808 {
809  WriteCompactSize(os, str.size());
810  if (!str.empty())
811  os.write(MakeByteSpan(str));
812 }
813 
814 template<typename Stream, typename C>
815 void Unserialize(Stream& is, std::basic_string<C>& str)
816 {
817  unsigned int nSize = ReadCompactSize(is);
818  str.resize(nSize);
819  if (nSize != 0)
820  is.read(MakeWritableByteSpan(str));
821 }
822 
823 
824 
828 template <typename Stream, unsigned int N, typename T>
829 void Serialize(Stream& os, const prevector<N, T>& v)
830 {
831  if constexpr (std::is_same_v<T, unsigned char>) {
832  WriteCompactSize(os, v.size());
833  if (!v.empty())
834  os.write(MakeByteSpan(v));
835  } else {
837  }
838 }
839 
840 
841 template <typename Stream, unsigned int N, typename T>
842 void Unserialize(Stream& is, prevector<N, T>& v)
843 {
844  if constexpr (std::is_same_v<T, unsigned char>) {
845  // Limit size per read so bogus size value won't cause out of memory
846  v.clear();
847  unsigned int nSize = ReadCompactSize(is);
848  unsigned int i = 0;
849  while (i < nSize) {
850  unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
851  v.resize_uninitialized(i + blk);
852  is.read(AsWritableBytes(Span{&v[i], blk}));
853  i += blk;
854  }
855  } else {
857  }
858 }
859 
860 
864 template <typename Stream, typename T, typename A>
865 void Serialize(Stream& os, const std::vector<T, A>& v)
866 {
867  if constexpr (std::is_same_v<T, unsigned char>) {
868  WriteCompactSize(os, v.size());
869  if (!v.empty())
870  os.write(MakeByteSpan(v));
871  } else if constexpr (std::is_same_v<T, bool>) {
872  // A special case for std::vector<bool>, as dereferencing
873  // std::vector<bool>::const_iterator does not result in a const bool&
874  // due to std::vector's special casing for bool arguments.
875  WriteCompactSize(os, v.size());
876  for (bool elem : v) {
877  ::Serialize(os, elem);
878  }
879  } else {
881  }
882 }
883 
884 
885 template <typename Stream, typename T, typename A>
886 void Unserialize(Stream& is, std::vector<T, A>& v)
887 {
888  if constexpr (std::is_same_v<T, unsigned char>) {
889  // Limit size per read so bogus size value won't cause out of memory
890  v.clear();
891  unsigned int nSize = ReadCompactSize(is);
892  unsigned int i = 0;
893  while (i < nSize) {
894  unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
895  v.resize(i + blk);
896  is.read(AsWritableBytes(Span{&v[i], blk}));
897  i += blk;
898  }
899  } else {
901  }
902 }
903 
904 
908 template<typename Stream, typename K, typename T>
909 void Serialize(Stream& os, const std::pair<K, T>& item)
910 {
911  Serialize(os, item.first);
912  Serialize(os, item.second);
913 }
914 
915 template<typename Stream, typename K, typename T>
916 void Unserialize(Stream& is, std::pair<K, T>& item)
917 {
918  Unserialize(is, item.first);
919  Unserialize(is, item.second);
920 }
921 
922 
923 
927 template<typename Stream, typename K, typename T, typename Pred, typename A>
928 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
929 {
930  WriteCompactSize(os, m.size());
931  for (const auto& entry : m)
932  Serialize(os, entry);
933 }
934 
935 template<typename Stream, typename K, typename T, typename Pred, typename A>
936 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
937 {
938  m.clear();
939  unsigned int nSize = ReadCompactSize(is);
940  typename std::map<K, T, Pred, A>::iterator mi = m.begin();
941  for (unsigned int i = 0; i < nSize; i++)
942  {
943  std::pair<K, T> item;
944  Unserialize(is, item);
945  mi = m.insert(mi, item);
946  }
947 }
948 
949 
950 
954 template<typename Stream, typename K, typename Pred, typename A>
955 void Serialize(Stream& os, const std::set<K, Pred, A>& m)
956 {
957  WriteCompactSize(os, m.size());
958  for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
959  Serialize(os, (*it));
960 }
961 
962 template<typename Stream, typename K, typename Pred, typename A>
963 void Unserialize(Stream& is, std::set<K, Pred, A>& m)
964 {
965  m.clear();
966  unsigned int nSize = ReadCompactSize(is);
967  typename std::set<K, Pred, A>::iterator it = m.begin();
968  for (unsigned int i = 0; i < nSize; i++)
969  {
970  K key;
971  Unserialize(is, key);
972  it = m.insert(it, key);
973  }
974 }
975 
976 
977 
981 template<typename Stream, typename T> void
982 Serialize(Stream& os, const std::unique_ptr<const T>& p)
983 {
984  Serialize(os, *p);
985 }
986 
987 template<typename Stream, typename T>
988 void Unserialize(Stream& is, std::unique_ptr<const T>& p)
989 {
990  p.reset(new T(deserialize, is));
991 }
992 
993 
994 
998 template<typename Stream, typename T> void
999 Serialize(Stream& os, const std::shared_ptr<const T>& p)
1000 {
1001  Serialize(os, *p);
1002 }
1003 
1004 template<typename Stream, typename T>
1005 void Unserialize(Stream& is, std::shared_ptr<const T>& p)
1006 {
1007  p = std::make_shared<const T>(deserialize, is);
1008 }
1009 
1014 template <typename Stream, typename... Args>
1015 void SerializeMany(Stream& s, const Args&... args)
1016 {
1017  (::Serialize(s, args), ...);
1018 }
1019 
1020 template <typename Stream, typename... Args>
1021 inline void UnserializeMany(Stream& s, Args&&... args)
1022 {
1023  (::Unserialize(s, args), ...);
1024 }
1025 
1030  static constexpr bool ForRead() { return false; }
1031 
1032  template<typename Stream, typename... Args>
1033  static void SerReadWriteMany(Stream& s, const Args&... args)
1034  {
1035  ::SerializeMany(s, args...);
1036  }
1037 
1038  template<typename Stream, typename Type, typename Fn>
1039  static void SerRead(Stream& s, Type&&, Fn&&)
1040  {
1041  }
1042 
1043  template<typename Stream, typename Type, typename Fn>
1044  static void SerWrite(Stream& s, Type&& obj, Fn&& fn)
1045  {
1046  fn(s, std::forward<Type>(obj));
1047  }
1048 };
1050  static constexpr bool ForRead() { return true; }
1051 
1052  template<typename Stream, typename... Args>
1053  static void SerReadWriteMany(Stream& s, Args&&... args)
1054  {
1055  ::UnserializeMany(s, args...);
1056  }
1057 
1058  template<typename Stream, typename Type, typename Fn>
1059  static void SerRead(Stream& s, Type&& obj, Fn&& fn)
1060  {
1061  fn(s, std::forward<Type>(obj));
1062  }
1063 
1064  template<typename Stream, typename Type, typename Fn>
1065  static void SerWrite(Stream& s, Type&&, Fn&&)
1066  {
1067  }
1068 };
1069 
1070 /* ::GetSerializeSize implementations
1071  *
1072  * Computing the serialized size of objects is done through a special stream
1073  * object of type CSizeComputer, which only records the number of bytes written
1074  * to it.
1075  *
1076  * If your Serialize or SerializationOp method has non-trivial overhead for
1077  * serialization, it may be worthwhile to implement a specialized version for
1078  * CSizeComputer, which uses the s.seek() method to record bytes that would
1079  * be written instead.
1080  */
1082 {
1083 protected:
1084  size_t nSize{0};
1085 
1086  const int nVersion;
1087 public:
1088  explicit CSizeComputer(int nVersionIn) : nVersion(nVersionIn) {}
1089 
1091  {
1092  this->nSize += src.size();
1093  }
1094 
1096  void seek(size_t _nSize)
1097  {
1098  this->nSize += _nSize;
1099  }
1100 
1101  template<typename T>
1103  {
1104  ::Serialize(*this, obj);
1105  return (*this);
1106  }
1107 
1108  size_t size() const {
1109  return nSize;
1110  }
1111 
1112  int GetVersion() const { return nVersion; }
1113 };
1114 
1115 template<typename I>
1116 inline void WriteVarInt(CSizeComputer &s, I n)
1117 {
1118  s.seek(GetSizeOfVarInt<I>(n));
1119 }
1120 
1121 inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
1122 {
1123  s.seek(GetSizeOfCompactSize(nSize));
1124 }
1125 
1126 template <typename T>
1127 size_t GetSerializeSize(const T& t, int nVersion = 0)
1128 {
1129  return (CSizeComputer(nVersion) << t).size();
1130 }
1131 
1132 template <typename... T>
1133 size_t GetSerializeSizeMany(int nVersion, const T&... t)
1134 {
1135  CSizeComputer sc(nVersion);
1136  SerializeMany(sc, t...);
1137  return sc.size();
1138 }
1139 
1141 template <typename Params, typename SubStream>
1143 {
1145  SubStream& m_substream; // private to avoid leaking version/type into serialization code that shouldn't see it
1146 
1147 public:
1148  ParamsStream(const Params& params LIFETIMEBOUND, SubStream& substream LIFETIMEBOUND) : m_params{params}, m_substream{substream} {}
1149  template <typename U> ParamsStream& operator<<(const U& obj) { ::Serialize(*this, obj); return *this; }
1150  template <typename U> ParamsStream& operator>>(U&& obj) { ::Unserialize(*this, obj); return *this; }
1151  void write(Span<const std::byte> src) { m_substream.write(src); }
1152  void read(Span<std::byte> dst) { m_substream.read(dst); }
1153  void ignore(size_t num) { m_substream.ignore(num); }
1154  bool eof() const { return m_substream.eof(); }
1155  size_t size() const { return m_substream.size(); }
1156  const Params& GetParams() const { return m_params; }
1157  int GetVersion() = delete; // Deprecated with Params usage
1158  int GetType() = delete; // Deprecated with Params usage
1159 };
1160 
1162 template <typename Params, typename T>
1164 {
1167 
1168 public:
1169  explicit ParamsWrapper(const Params& params, T& obj) : m_params{params}, m_object{obj} {}
1170 
1171  template <typename Stream>
1172  void Serialize(Stream& s) const
1173  {
1174  ParamsStream ss{m_params, s};
1175  ::Serialize(ss, m_object);
1176  }
1177  template <typename Stream>
1178  void Unserialize(Stream& s)
1179  {
1180  ParamsStream ss{m_params, s};
1181  ::Unserialize(ss, m_object);
1182  }
1183 };
1184 
1190 template <typename Params, typename T>
1191 static auto WithParams(const Params& params, T&& t)
1192 {
1193  return ParamsWrapper<Params, T>{params, t};
1194 }
1195 
1205 #define SER_PARAMS_OPFUNC \
1206  template <typename T> \
1207  auto operator()(T&& t) const { return WithParams(*this, t); }
1208 
1209 #endif // BITCOIN_SERIALIZE_H
Wrapper that overrides the GetParams() function of a stream (and hides GetVersion/GetType).
Definition: serialize.h:1142
CSizeComputer(int nVersionIn)
Definition: serialize.h:1088
void read(Span< std::byte > dst)
Definition: serialize.h:1152
static void SerWrite(Stream &s, Type &&obj, Fn &&fn)
Definition: serialize.h:1044
static constexpr uint64_t MAX
Definition: serialize.h:554
void Serialize(Stream &s) const
Definition: serialize.h:1172
void ignore(size_t num)
Definition: serialize.h:1153
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:83
static void SerWrite(Stream &s, Type &&, Fn &&)
Definition: serialize.h:1065
Out & AsBase(In &x)
Convert any argument to a reference to X, maintaining constness.
Definition: serialize.h:157
void clear()
Definition: prevector.h:352
void ser_writedata64(Stream &s, uint64_t obj)
Definition: serialize.h:78
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
Definition: span.h:253
void WriteVarInt(CSizeComputer &os, I n)
Definition: serialize.h:1116
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:361
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition: serialize.h:1121
const Params & GetParams() const
Definition: serialize.h:1156
uint64_t htobe64(uint64_t host_64bits)
Definition: endian.h:212
void Unserialize(Stream &, char)=delete
void Unser(Stream &s, I &v)
Definition: serialize.h:590
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition: serialize.h:35
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:264
void Unser(Stream &s, I &v)
Definition: serialize.h:535
void Ser(Stream &s, Tp tp)
Definition: serialize.h:620
size_t size() const
Definition: serialize.h:1108
void ser_writedata32(Stream &s, uint32_t obj)
Definition: serialize.h:68
constexpr deserialize_type deserialize
Definition: serialize.h:49
constexpr std::size_t size() const noexcept
Definition: span.h:186
Formatter for integers in CompactSize format.
Definition: serialize.h:587
static void SerRead(Stream &s, Type &&obj, Fn &&fn)
Definition: serialize.h:1059
int GetType()=delete
uint32_t be32toh(uint32_t big_endian_32bits)
Definition: endian.h:198
void Unserialize(Stream &s)
Definition: serialize.h:1178
SubStream & m_substream
Definition: serialize.h:1145
void resize_uninitialized(size_type new_size)
Definition: prevector.h:395
static constexpr bool ForRead()
Definition: serialize.h:1050
Wrapper that serializes objects with the specified parameters.
Definition: serialize.h:1163
const int nVersion
Definition: serialize.h:1086
Simple wrapper class to serialize objects using a formatter; used by Using().
Definition: serialize.h:497
void Ser(Stream &s, const V &v)
Definition: serialize.h:683
uint32_t htole32(uint32_t host_32bits)
Definition: endian.h:191
Dummy data type to identify deserializing constructors.
Definition: serialize.h:48
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class...
Definition: serialize.h:519
Support for all macros providing or using the ser_action parameter of the SerializationOps method...
Definition: serialize.h:1029
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1127
static void SerReadWriteMany(Stream &s, Args &&... args)
Definition: serialize.h:1053
uint32_t htobe32(uint32_t host_32bits)
Definition: endian.h:184
void Serialize(Stream &s) const
Definition: serialize.h:504
void Unser(Stream &s, I &v)
Definition: serialize.h:568
CSizeComputer & operator<<(const T &obj)
Definition: serialize.h:1102
uint64_t be64toh(uint64_t big_endian_64bits)
Definition: endian.h:226
Serialization wrapper class for integers in VarInt format.
Definition: serialize.h:528
void Unser(Stream &s, V &v)
Definition: serialize.h:693
uint16_t ser_readdata16(Stream &s)
Definition: serialize.h:89
ArgsManager & args
Definition: bitcoind.cpp:269
#define LIFETIMEBOUND
Definition: attributes.h:16
uint32_t ser_readdata32(Stream &s)
Definition: serialize.h:101
constexpr CheckVarIntMode()
Definition: serialize.h:431
void ser_writedata16(Stream &s, uint16_t obj)
Definition: serialize.h:58
void write(Span< const std::byte > src)
Definition: serialize.h:1151
uint16_t htobe16(uint16_t host_16bits)
Definition: endian.h:156
void Serialize(Stream &, char)=delete
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params. ...
Definition: serialize.h:1191
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition: serialize.h:427
I ReadVarInt(Stream &is)
Definition: serialize.h:474
size_t size() const
Definition: serialize.h:1155
uint16_t le16toh(uint16_t little_endian_16bits)
Definition: endian.h:177
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:73
static void SerRead(Stream &s, Type &&, Fn &&)
Definition: serialize.h:1039
const Params & m_params
Definition: serialize.h:1165
uint64_t ser_readdata64(Stream &s)
Definition: serialize.h:113
static void SerReadWriteMany(Stream &s, const Args &... args)
Definition: serialize.h:1033
void Ser(Stream &s, I v)
Definition: serialize.h:556
Default formatter.
Definition: serialize.h:790
void write(Span< const std::byte > src)
Definition: serialize.h:1090
const Params & m_params
Definition: serialize.h:1144
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1096
uint16_t htole16(uint16_t host_16bits)
Definition: endian.h:163
void Ser(Stream &s, const std::string &v)
Definition: serialize.h:660
uint16_t ser_readdata16be(Stream &s)
Definition: serialize.h:95
uint64_t le64toh(uint64_t little_endian_64bits)
Definition: endian.h:233
uint16_t be16toh(uint16_t big_endian_16bits)
Definition: endian.h:170
constexpr C * data() const noexcept
Definition: span.h:173
const CChainParams & Params()
Return the currently selected parameters.
int GetVersion() const
Definition: serialize.h:1112
static constexpr bool ForRead()
Definition: serialize.h:1030
ParamsStream & operator<<(const U &obj)
Definition: serialize.h:1149
ParamsStream(const Params &params LIFETIMEBOUND, SubStream &substream LIFETIMEBOUND)
Definition: serialize.h:1148
bool empty() const
Definition: prevector.h:295
Serialization wrapper class for custom integers and enums.
Definition: serialize.h:551
uint64_t htole64(uint64_t host_64bits)
Definition: endian.h:219
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:259
ParamsWrapper(const Params &params, T &obj)
Definition: serialize.h:1169
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:107
unsigned int GetSizeOfVarInt(I n)
Definition: serialize.h:439
size_t GetSerializeSizeMany(int nVersion, const T &... t)
Definition: serialize.h:1133
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition: span.h:248
bool eof() const
Definition: serialize.h:1154
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
Definition: serialize.h:32
void ser_writedata16be(Stream &s, uint16_t obj)
Definition: serialize.h:63
size_type size() const
Definition: prevector.h:291
unsigned char * UCharCast(char *c)
Definition: span.h:270
void Unserialize(Stream &s)
Definition: serialize.h:505
void Unser(Stream &s, std::string &v)
Definition: serialize.h:649
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
Definition: serialize.h:1015
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:680
A Span is an object that can refer to a contiguous sequence of objects.
Definition: solver.h:20
int GetVersion()=delete
ParamsStream & operator>>(U &&obj)
Definition: serialize.h:1150
T m_object
Definition: serialize.h:499
uint32_t le32toh(uint32_t little_endian_32bits)
Definition: endian.h:205
constexpr unsigned int GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX –...
Definition: serialize.h:319
static void Unser(Stream &s, T &t)
Definition: serialize.h:796
size_t nSize
Definition: serialize.h:1084
#define T(expected, seed, data)
static void Ser(Stream &s, const T &t)
Definition: serialize.h:793
void UnserializeMany(Stream &s, Args &&... args)
Definition: serialize.h:1021
void Ser(Stream &s, I v)
Definition: serialize.h:530
void ser_writedata8(Stream &s, uint8_t obj)
Definition: serialize.h:54
void Unser(Stream &s, Tp &tp)
Definition: serialize.h:612
CompactSizeWriter(uint64_t n_in)
Definition: serialize.h:637
void Ser(Stream &s, I v)
Definition: serialize.h:600
Wrapper(T obj)
Definition: serialize.h:503
void Serialize(Stream &s) const
Definition: serialize.h:640