Bitcoin Core  29.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/assumptions.h> // IWYU pragma: keep
11 #include <compat/endian.h>
12 #include <prevector.h>
13 #include <span.h>
14 
15 #include <algorithm>
16 #include <concepts>
17 #include <cstdint>
18 #include <cstring>
19 #include <ios>
20 #include <limits>
21 #include <map>
22 #include <memory>
23 #include <set>
24 #include <string>
25 #include <utility>
26 #include <vector>
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_internal(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_internal(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_internal(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_internal(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_internal(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_internal(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_internal(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_internal(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_internal(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_internal(obj);
118 }
119 
120 
121 class SizeComputer;
122 
143 template <class Out, class In>
145 {
146  static_assert(std::is_base_of_v<Out, In>);
147  return x;
148 }
149 template <class Out, class In>
150 const Out& AsBase(const In& x)
151 {
152  static_assert(std::is_base_of_v<Out, In>);
153  return x;
154 }
155 
156 #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__))
157 #define SER_READ(obj, code) ser_action.SerRead(s, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
158 #define SER_WRITE(obj, code) ser_action.SerWrite(s, obj, [&](Stream& s, const Type& obj) { code; })
159 
176 #define FORMATTER_METHODS(cls, obj) \
177  template<typename Stream> \
178  static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, ActionSerialize{}); } \
179  template<typename Stream> \
180  static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, ActionUnserialize{}); } \
181  template<typename Stream, typename Type, typename Operation> \
182  static void SerializationOps(Type& obj, Stream& s, Operation ser_action)
183 
217 #define SER_PARAMS(type) (s.template GetParams<type>())
218 
219 #define BASE_SERIALIZE_METHODS(cls) \
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 
240 #define SERIALIZE_METHODS(cls, obj) \
241  BASE_SERIALIZE_METHODS(cls) \
242  FORMATTER_METHODS(cls, obj)
243 
244 // Templates for serializing to anything that looks like a stream,
245 // i.e. anything that supports .read(Span<std::byte>) and .write(Span<const std::byte>)
246 //
247 // clang-format off
248 
249 // Typically int8_t and char are distinct types, but some systems may define int8_t
250 // in terms of char. Forbid serialization of char in the typical case, but allow it if
251 // it's the only way to describe an int8_t.
252 template<class T>
253 concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
254 
255 template <typename Stream, CharNotInt8 V> void Serialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
256 template <typename Stream> void Serialize(Stream& s, std::byte a) { ser_writedata8(s, uint8_t(a)); }
257 template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
258 template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
259 template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
260 template<typename Stream> inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
261 template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
262 template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
263 template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
264 template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
265 template <typename Stream, BasicByte B, int N> void Serialize(Stream& s, const B (&a)[N]) { s.write(MakeByteSpan(a)); }
266 template <typename Stream, BasicByte B, std::size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { s.write(MakeByteSpan(a)); }
267 template <typename Stream, BasicByte B, std::size_t N> void Serialize(Stream& s, std::span<B, N> span) { s.write(std::as_bytes(span)); }
268 template <typename Stream, BasicByte B> void Serialize(Stream& s, Span<B> span) { s.write(AsBytes(span)); }
269 
270 template <typename Stream, CharNotInt8 V> void Unserialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t
271 template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte{ser_readdata8(s)}; }
272 template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
273 template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
274 template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
275 template<typename Stream> inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
276 template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
277 template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
278 template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
279 template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
280 template <typename Stream, BasicByte B, int N> void Unserialize(Stream& s, B (&a)[N]) { s.read(MakeWritableByteSpan(a)); }
281 template <typename Stream, BasicByte B, std::size_t N> void Unserialize(Stream& s, std::array<B, N>& a) { s.read(MakeWritableByteSpan(a)); }
282 template <typename Stream, BasicByte B, std::size_t N> void Unserialize(Stream& s, std::span<B, N> span) { s.read(std::as_writable_bytes(span)); }
283 template <typename Stream, BasicByte B> void Unserialize(Stream& s, Span<B> span) { s.read(AsWritableBytes(span)); }
284 
285 template <typename Stream> inline void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); }
286 template <typename Stream> inline void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; }
287 // clang-format on
288 
289 
297 constexpr inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
298 {
299  if (nSize < 253) return sizeof(unsigned char);
300  else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);
301  else if (nSize <= std::numeric_limits<unsigned int>::max()) return sizeof(unsigned char) + sizeof(unsigned int);
302  else return sizeof(unsigned char) + sizeof(uint64_t);
303 }
304 
305 inline void WriteCompactSize(SizeComputer& os, uint64_t nSize);
306 
307 template<typename Stream>
308 void WriteCompactSize(Stream& os, uint64_t nSize)
309 {
310  if (nSize < 253)
311  {
312  ser_writedata8(os, nSize);
313  }
314  else if (nSize <= std::numeric_limits<uint16_t>::max())
315  {
316  ser_writedata8(os, 253);
317  ser_writedata16(os, nSize);
318  }
319  else if (nSize <= std::numeric_limits<unsigned int>::max())
320  {
321  ser_writedata8(os, 254);
322  ser_writedata32(os, nSize);
323  }
324  else
325  {
326  ser_writedata8(os, 255);
327  ser_writedata64(os, nSize);
328  }
329  return;
330 }
331 
338 template<typename Stream>
339 uint64_t ReadCompactSize(Stream& is, bool range_check = true)
340 {
341  uint8_t chSize = ser_readdata8(is);
342  uint64_t nSizeRet = 0;
343  if (chSize < 253)
344  {
345  nSizeRet = chSize;
346  }
347  else if (chSize == 253)
348  {
349  nSizeRet = ser_readdata16(is);
350  if (nSizeRet < 253)
351  throw std::ios_base::failure("non-canonical ReadCompactSize()");
352  }
353  else if (chSize == 254)
354  {
355  nSizeRet = ser_readdata32(is);
356  if (nSizeRet < 0x10000u)
357  throw std::ios_base::failure("non-canonical ReadCompactSize()");
358  }
359  else
360  {
361  nSizeRet = ser_readdata64(is);
362  if (nSizeRet < 0x100000000ULL)
363  throw std::ios_base::failure("non-canonical ReadCompactSize()");
364  }
365  if (range_check && nSizeRet > MAX_SIZE) {
366  throw std::ios_base::failure("ReadCompactSize(): size too large");
367  }
368  return nSizeRet;
369 }
370 
406 
407 template <VarIntMode Mode, typename I>
409  constexpr CheckVarIntMode()
410  {
411  static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value, "Unsigned type required with mode DEFAULT.");
412  static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed<I>::value, "Signed type required with mode NONNEGATIVE_SIGNED.");
413  }
414 };
415 
416 template<VarIntMode Mode, typename I>
417 inline unsigned int GetSizeOfVarInt(I n)
418 {
420  int nRet = 0;
421  while(true) {
422  nRet++;
423  if (n <= 0x7F)
424  break;
425  n = (n >> 7) - 1;
426  }
427  return nRet;
428 }
429 
430 template<typename I>
431 inline void WriteVarInt(SizeComputer& os, I n);
432 
433 template<typename Stream, VarIntMode Mode, typename I>
434 void WriteVarInt(Stream& os, I n)
435 {
437  unsigned char tmp[(sizeof(n)*8+6)/7];
438  int len=0;
439  while(true) {
440  tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
441  if (n <= 0x7F)
442  break;
443  n = (n >> 7) - 1;
444  len++;
445  }
446  do {
447  ser_writedata8(os, tmp[len]);
448  } while(len--);
449 }
450 
451 template<typename Stream, VarIntMode Mode, typename I>
452 I ReadVarInt(Stream& is)
453 {
455  I n = 0;
456  while(true) {
457  unsigned char chData = ser_readdata8(is);
458  if (n > (std::numeric_limits<I>::max() >> 7)) {
459  throw std::ios_base::failure("ReadVarInt(): size too large");
460  }
461  n = (n << 7) | (chData & 0x7F);
462  if (chData & 0x80) {
463  if (n == std::numeric_limits<I>::max()) {
464  throw std::ios_base::failure("ReadVarInt(): size too large");
465  }
466  n++;
467  } else {
468  return n;
469  }
470  }
471 }
472 
474 template<typename Formatter, typename T>
475 class Wrapper
476 {
477  static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
478 protected:
479  T m_object;
480 public:
481  explicit Wrapper(T obj) : m_object(obj) {}
482  template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
483  template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
484 };
485 
496 template<typename Formatter, typename T>
497 static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
498 
499 #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
500 #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
501 #define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
502 #define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
503 
505 template<VarIntMode Mode>
507 {
508  template<typename Stream, typename I> void Ser(Stream &s, I v)
509  {
510  WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
511  }
512 
513  template<typename Stream, typename I> void Unser(Stream& s, I& v)
514  {
515  v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
516  }
517 };
518 
528 template<int Bytes, bool BigEndian = false>
530 {
531  static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
532  static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
533 
534  template <typename Stream, typename I> void Ser(Stream& s, I v)
535  {
536  if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
537  if (BigEndian) {
538  uint64_t raw = htobe64_internal(v);
539  s.write(AsBytes(Span{&raw, 1}).last(Bytes));
540  } else {
541  uint64_t raw = htole64_internal(v);
542  s.write(AsBytes(Span{&raw, 1}).first(Bytes));
543  }
544  }
545 
546  template <typename Stream, typename I> void Unser(Stream& s, I& v)
547  {
548  using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
549  static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
550  uint64_t raw = 0;
551  if (BigEndian) {
552  s.read(AsWritableBytes(Span{&raw, 1}).last(Bytes));
553  v = static_cast<I>(be64toh_internal(raw));
554  } else {
555  s.read(AsWritableBytes(Span{&raw, 1}).first(Bytes));
556  v = static_cast<I>(le64toh_internal(raw));
557  }
558  }
559 };
560 
562 
564 template<bool RangeCheck>
566 {
567  template<typename Stream, typename I>
568  void Unser(Stream& s, I& v)
569  {
570  uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
571  if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
572  throw std::ios_base::failure("CompactSize exceeds limit of type");
573  }
574  v = n;
575  }
576 
577  template<typename Stream, typename I>
578  void Ser(Stream& s, I v)
579  {
580  static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
581  static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
582 
583  WriteCompactSize<Stream>(s, v);
584  }
585 };
586 
587 template <typename U, bool LOSSY = false>
589  template <typename Stream, typename Tp>
590  void Unser(Stream& s, Tp& tp)
591  {
592  U u;
593  s >> u;
594  // Lossy deserialization does not make sense, so force Wnarrowing
595  tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
596  }
597  template <typename Stream, typename Tp>
598  void Ser(Stream& s, Tp tp)
599  {
600  if constexpr (LOSSY) {
601  s << U(tp.time_since_epoch().count());
602  } else {
603  s << U{tp.time_since_epoch().count()};
604  }
605  }
606 };
607 template <typename U>
609 
611 {
612 protected:
613  uint64_t n;
614 public:
615  explicit CompactSizeWriter(uint64_t n_in) : n(n_in) { }
616 
617  template<typename Stream>
618  void Serialize(Stream &s) const {
619  WriteCompactSize<Stream>(s, n);
620  }
621 };
622 
623 template<size_t Limit>
625 {
626  template<typename Stream>
627  void Unser(Stream& s, std::string& v)
628  {
629  size_t size = ReadCompactSize(s);
630  if (size > Limit) {
631  throw std::ios_base::failure("String length limit exceeded");
632  }
633  v.resize(size);
634  if (size != 0) s.read(MakeWritableByteSpan(v));
635  }
636 
637  template<typename Stream>
638  void Ser(Stream& s, const std::string& v)
639  {
640  s << v;
641  }
642 };
643 
657 template<class Formatter>
659 {
660  template<typename Stream, typename V>
661  void Ser(Stream& s, const V& v)
662  {
663  Formatter formatter;
664  WriteCompactSize(s, v.size());
665  for (const typename V::value_type& elem : v) {
666  formatter.Ser(s, elem);
667  }
668  }
669 
670  template<typename Stream, typename V>
671  void Unser(Stream& s, V& v)
672  {
673  Formatter formatter;
674  v.clear();
675  size_t size = ReadCompactSize(s);
676  size_t allocated = 0;
677  while (allocated < size) {
678  // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
679  // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
680  // X MiB of data to make us allocate X+5 Mib.
681  static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
682  allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
683  v.reserve(allocated);
684  while (v.size() < allocated) {
685  v.emplace_back();
686  formatter.Unser(s, v.back());
687  }
688  }
689  };
690 };
691 
699 template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
700 template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
701 
705 template<typename Stream, unsigned int N, typename T> inline void Serialize(Stream& os, const prevector<N, T>& v);
706 template<typename Stream, unsigned int N, typename T> inline void Unserialize(Stream& is, prevector<N, T>& v);
707 
711 template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
712 template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
713 
717 template<typename Stream, typename K, typename T> void Serialize(Stream& os, const std::pair<K, T>& item);
718 template<typename Stream, typename K, typename T> void Unserialize(Stream& is, std::pair<K, T>& item);
719 
723 template<typename Stream, typename K, typename T, typename Pred, typename A> void Serialize(Stream& os, const std::map<K, T, Pred, A>& m);
724 template<typename Stream, typename K, typename T, typename Pred, typename A> void Unserialize(Stream& is, std::map<K, T, Pred, A>& m);
725 
729 template<typename Stream, typename K, typename Pred, typename A> void Serialize(Stream& os, const std::set<K, Pred, A>& m);
730 template<typename Stream, typename K, typename Pred, typename A> void Unserialize(Stream& is, std::set<K, Pred, A>& m);
731 
735 template<typename Stream, typename T> void Serialize(Stream& os, const std::shared_ptr<const T>& p);
736 template<typename Stream, typename T> void Unserialize(Stream& os, std::shared_ptr<const T>& p);
737 
741 template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);
742 template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);
743 
744 
748 template <class T, class Stream>
749 concept Serializable = requires(T a, Stream s) { a.Serialize(s); };
750 template <typename Stream, typename T>
751  requires Serializable<T, Stream>
752 void Serialize(Stream& os, const T& a)
753 {
754  a.Serialize(os);
755 }
756 
757 template <class T, class Stream>
758 concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };
759 template <typename Stream, typename T>
760  requires Unserializable<T, Stream>
761 void Unserialize(Stream& is, T&& a)
762 {
763  a.Unserialize(is);
764 }
765 
772 {
773  template<typename Stream, typename T>
774  static void Ser(Stream& s, const T& t) { Serialize(s, t); }
775 
776  template<typename Stream, typename T>
777  static void Unser(Stream& s, T& t) { Unserialize(s, t); }
778 };
779 
780 
781 
782 
783 
787 template<typename Stream, typename C>
788 void Serialize(Stream& os, const std::basic_string<C>& str)
789 {
790  WriteCompactSize(os, str.size());
791  if (!str.empty())
792  os.write(MakeByteSpan(str));
793 }
794 
795 template<typename Stream, typename C>
796 void Unserialize(Stream& is, std::basic_string<C>& str)
797 {
798  unsigned int nSize = ReadCompactSize(is);
799  str.resize(nSize);
800  if (nSize != 0)
801  is.read(MakeWritableByteSpan(str));
802 }
803 
804 
805 
809 template <typename Stream, unsigned int N, typename T>
810 void Serialize(Stream& os, const prevector<N, T>& v)
811 {
812  if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes
813  WriteCompactSize(os, v.size());
814  if (!v.empty()) os.write(MakeByteSpan(v));
815  } else {
817  }
818 }
819 
820 
821 template <typename Stream, unsigned int N, typename T>
822 void Unserialize(Stream& is, prevector<N, T>& v)
823 {
824  if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes
825  // Limit size per read so bogus size value won't cause out of memory
826  v.clear();
827  unsigned int nSize = ReadCompactSize(is);
828  unsigned int i = 0;
829  while (i < nSize) {
830  unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
831  v.resize_uninitialized(i + blk);
832  is.read(AsWritableBytes(Span{&v[i], blk}));
833  i += blk;
834  }
835  } else {
837  }
838 }
839 
840 
844 template <typename Stream, typename T, typename A>
845 void Serialize(Stream& os, const std::vector<T, A>& v)
846 {
847  if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes
848  WriteCompactSize(os, v.size());
849  if (!v.empty()) os.write(MakeByteSpan(v));
850  } else if constexpr (std::is_same_v<T, bool>) {
851  // A special case for std::vector<bool>, as dereferencing
852  // std::vector<bool>::const_iterator does not result in a const bool&
853  // due to std::vector's special casing for bool arguments.
854  WriteCompactSize(os, v.size());
855  for (bool elem : v) {
856  ::Serialize(os, elem);
857  }
858  } else {
860  }
861 }
862 
863 
864 template <typename Stream, typename T, typename A>
865 void Unserialize(Stream& is, std::vector<T, A>& v)
866 {
867  if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes
868  // Limit size per read so bogus size value won't cause out of memory
869  v.clear();
870  unsigned int nSize = ReadCompactSize(is);
871  unsigned int i = 0;
872  while (i < nSize) {
873  unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
874  v.resize(i + blk);
875  is.read(AsWritableBytes(Span{&v[i], blk}));
876  i += blk;
877  }
878  } else {
880  }
881 }
882 
883 
887 template<typename Stream, typename K, typename T>
888 void Serialize(Stream& os, const std::pair<K, T>& item)
889 {
890  Serialize(os, item.first);
891  Serialize(os, item.second);
892 }
893 
894 template<typename Stream, typename K, typename T>
895 void Unserialize(Stream& is, std::pair<K, T>& item)
896 {
897  Unserialize(is, item.first);
898  Unserialize(is, item.second);
899 }
900 
901 
902 
906 template<typename Stream, typename K, typename T, typename Pred, typename A>
907 void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)
908 {
909  WriteCompactSize(os, m.size());
910  for (const auto& entry : m)
911  Serialize(os, entry);
912 }
913 
914 template<typename Stream, typename K, typename T, typename Pred, typename A>
915 void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)
916 {
917  m.clear();
918  unsigned int nSize = ReadCompactSize(is);
919  typename std::map<K, T, Pred, A>::iterator mi = m.begin();
920  for (unsigned int i = 0; i < nSize; i++)
921  {
922  std::pair<K, T> item;
923  Unserialize(is, item);
924  mi = m.insert(mi, item);
925  }
926 }
927 
928 
929 
933 template<typename Stream, typename K, typename Pred, typename A>
934 void Serialize(Stream& os, const std::set<K, Pred, A>& m)
935 {
936  WriteCompactSize(os, m.size());
937  for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)
938  Serialize(os, (*it));
939 }
940 
941 template<typename Stream, typename K, typename Pred, typename A>
942 void Unserialize(Stream& is, std::set<K, Pred, A>& m)
943 {
944  m.clear();
945  unsigned int nSize = ReadCompactSize(is);
946  typename std::set<K, Pred, A>::iterator it = m.begin();
947  for (unsigned int i = 0; i < nSize; i++)
948  {
949  K key;
950  Unserialize(is, key);
951  it = m.insert(it, key);
952  }
953 }
954 
955 
956 
960 template<typename Stream, typename T> void
961 Serialize(Stream& os, const std::unique_ptr<const T>& p)
962 {
963  Serialize(os, *p);
964 }
965 
966 template<typename Stream, typename T>
967 void Unserialize(Stream& is, std::unique_ptr<const T>& p)
968 {
969  p.reset(new T(deserialize, is));
970 }
971 
972 
973 
977 template<typename Stream, typename T> void
978 Serialize(Stream& os, const std::shared_ptr<const T>& p)
979 {
980  Serialize(os, *p);
981 }
982 
983 template<typename Stream, typename T>
984 void Unserialize(Stream& is, std::shared_ptr<const T>& p)
985 {
986  p = std::make_shared<const T>(deserialize, is);
987 }
988 
993 template <typename Stream, typename... Args>
994 void SerializeMany(Stream& s, const Args&... args)
995 {
996  (::Serialize(s, args), ...);
997 }
998 
999 template <typename Stream, typename... Args>
1000 inline void UnserializeMany(Stream& s, Args&&... args)
1001 {
1002  (::Unserialize(s, args), ...);
1003 }
1004 
1009  static constexpr bool ForRead() { return false; }
1010 
1011  template<typename Stream, typename... Args>
1012  static void SerReadWriteMany(Stream& s, const Args&... args)
1013  {
1014  ::SerializeMany(s, args...);
1015  }
1016 
1017  template<typename Stream, typename Type, typename Fn>
1018  static void SerRead(Stream& s, Type&&, Fn&&)
1019  {
1020  }
1021 
1022  template<typename Stream, typename Type, typename Fn>
1023  static void SerWrite(Stream& s, Type&& obj, Fn&& fn)
1024  {
1025  fn(s, std::forward<Type>(obj));
1026  }
1027 };
1029  static constexpr bool ForRead() { return true; }
1030 
1031  template<typename Stream, typename... Args>
1032  static void SerReadWriteMany(Stream& s, Args&&... args)
1033  {
1034  ::UnserializeMany(s, args...);
1035  }
1036 
1037  template<typename Stream, typename Type, typename Fn>
1038  static void SerRead(Stream& s, Type&& obj, Fn&& fn)
1039  {
1040  fn(s, std::forward<Type>(obj));
1041  }
1042 
1043  template<typename Stream, typename Type, typename Fn>
1044  static void SerWrite(Stream& s, Type&&, Fn&&)
1045  {
1046  }
1047 };
1048 
1049 /* ::GetSerializeSize implementations
1050  *
1051  * Computing the serialized size of objects is done through a special stream
1052  * object of type SizeComputer, which only records the number of bytes written
1053  * to it.
1054  *
1055  * If your Serialize or SerializationOp method has non-trivial overhead for
1056  * serialization, it may be worthwhile to implement a specialized version for
1057  * SizeComputer, which uses the s.seek() method to record bytes that would
1058  * be written instead.
1059  */
1061 {
1062 protected:
1063  size_t nSize{0};
1064 
1065 public:
1066  SizeComputer() = default;
1067 
1069  {
1070  this->nSize += src.size();
1071  }
1072 
1074  void seek(size_t _nSize)
1075  {
1076  this->nSize += _nSize;
1077  }
1078 
1079  template<typename T>
1081  {
1082  ::Serialize(*this, obj);
1083  return (*this);
1084  }
1085 
1086  size_t size() const {
1087  return nSize;
1088  }
1089 };
1090 
1091 template<typename I>
1092 inline void WriteVarInt(SizeComputer &s, I n)
1093 {
1094  s.seek(GetSizeOfVarInt<I>(n));
1095 }
1096 
1097 inline void WriteCompactSize(SizeComputer &s, uint64_t nSize)
1098 {
1099  s.seek(GetSizeOfCompactSize(nSize));
1100 }
1101 
1102 template <typename T>
1103 size_t GetSerializeSize(const T& t)
1104 {
1105  return (SizeComputer() << t).size();
1106 }
1107 
1109 template<typename T>
1110 concept ContainsStream = requires(T t) { t.GetStream(); };
1111 
1113 template <typename SubStream, typename Params>
1115 {
1117  // If ParamsStream constructor is passed an lvalue argument, Substream will
1118  // be a reference type, and m_substream will reference that argument.
1119  // Otherwise m_substream will be a substream instance and move from the
1120  // argument. Letting ParamsStream contain a substream instance instead of
1121  // just a reference is useful to make the ParamsStream object self contained
1122  // and let it do cleanup when destroyed, for example by closing files if
1123  // SubStream is a file stream.
1124  SubStream m_substream;
1125 
1126 public:
1127  ParamsStream(SubStream&& substream, const Params& params LIFETIMEBOUND) : m_params{params}, m_substream{std::forward<SubStream>(substream)} {}
1128 
1129  template <typename NestedSubstream, typename Params1, typename Params2, typename... NestedParams>
1130  ParamsStream(NestedSubstream&& s, const Params1& params1 LIFETIMEBOUND, const Params2& params2 LIFETIMEBOUND, const NestedParams&... params LIFETIMEBOUND)
1131  : ParamsStream{::ParamsStream{std::forward<NestedSubstream>(s), params2, params...}, params1} {}
1132 
1133  template <typename U> ParamsStream& operator<<(const U& obj) { ::Serialize(*this, obj); return *this; }
1134  template <typename U> ParamsStream& operator>>(U&& obj) { ::Unserialize(*this, obj); return *this; }
1135  void write(Span<const std::byte> src) { GetStream().write(src); }
1136  void read(Span<std::byte> dst) { GetStream().read(dst); }
1137  void ignore(size_t num) { GetStream().ignore(num); }
1138  bool eof() const { return GetStream().eof(); }
1139  size_t size() const { return GetStream().size(); }
1140 
1142  template <typename P>
1143  const auto& GetParams() const
1144  {
1145  if constexpr (std::is_convertible_v<Params, P>) {
1146  return m_params;
1147  } else {
1148  return m_substream.template GetParams<P>();
1149  }
1150  }
1151 
1153  auto& GetStream()
1154  {
1155  if constexpr (ContainsStream<SubStream>) {
1156  return m_substream.GetStream();
1157  } else {
1158  return m_substream;
1159  }
1160  }
1161  const auto& GetStream() const
1162  {
1163  if constexpr (ContainsStream<SubStream>) {
1164  return m_substream.GetStream();
1165  } else {
1166  return m_substream;
1167  }
1168  }
1169 };
1170 
1176 template <typename Substream, typename Params>
1177 ParamsStream(Substream&&, const Params&) -> ParamsStream<Substream, Params>;
1178 
1183 template <typename Substream, typename Params1, typename Params2, typename... Params>
1184 ParamsStream(Substream&& s, const Params1& params1, const Params2& params2, const Params&... params) ->
1185  ParamsStream<decltype(ParamsStream{std::forward<Substream>(s), params2, params...}), Params1>;
1186 
1188 template <typename Params, typename T>
1190 {
1193 
1194 public:
1195  explicit ParamsWrapper(const Params& params, T& obj) : m_params{params}, m_object{obj} {}
1196 
1197  template <typename Stream>
1198  void Serialize(Stream& s) const
1199  {
1200  ParamsStream ss{s, m_params};
1201  ::Serialize(ss, m_object);
1202  }
1203  template <typename Stream>
1204  void Unserialize(Stream& s)
1205  {
1206  ParamsStream ss{s, m_params};
1207  ::Unserialize(ss, m_object);
1208  }
1209 };
1210 
1220 #define SER_PARAMS_OPFUNC \
1221  \
1226  template <typename T> \
1227  auto operator()(T&& t) const \
1228  { \
1229  return ParamsWrapper{*this, t}; \
1230  }
1231 
1232 #endif // BITCOIN_SERIALIZE_H
Wrapper that overrides the GetParams() function of a stream.
Definition: serialize.h:1114
BSWAP_CONSTEXPR uint32_t htole32_internal(uint32_t host_32bits)
Definition: endian.h:38
static void SerWrite(Stream &s, Type &&obj, Fn &&fn)
Definition: serialize.h:1023
static constexpr uint64_t MAX
Definition: serialize.h:532
void Serialize(Stream &s) const
Definition: serialize.h:1198
BSWAP_CONSTEXPR uint64_t htole64_internal(uint64_t host_64bits)
Definition: endian.h:58
concept CharNotInt8
Definition: serialize.h:253
SizeComputer & operator<<(const T &obj)
Definition: serialize.h:1080
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:83
static void SerWrite(Stream &s, Type &&, Fn &&)
Definition: serialize.h:1044
Out & AsBase(In &x)
Convert any argument to a reference to X, maintaining constness.
Definition: serialize.h:144
void clear()
Definition: prevector.h:355
const auto & GetStream() const
Definition: serialize.h:1161
void ser_writedata64(Stream &s, uint64_t obj)
Definition: serialize.h:78
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
Definition: span.h:263
BSWAP_CONSTEXPR uint16_t be16toh_internal(uint16_t big_endian_16bits)
Definition: endian.h:23
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:339
void write(Span< const std::byte > src)
Definition: serialize.h:1135
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1074
void Unser(Stream &s, I &v)
Definition: serialize.h:568
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1103
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition: serialize.h:35
const Params & m_params
Definition: serialize.h:1116
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:274
void Unser(Stream &s, I &v)
Definition: serialize.h:513
void Ser(Stream &s, Tp tp)
Definition: serialize.h:598
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:187
Formatter for integers in CompactSize format.
Definition: serialize.h:565
static void SerRead(Stream &s, Type &&obj, Fn &&fn)
Definition: serialize.h:1038
void Unserialize(Stream &s)
Definition: serialize.h:1204
BSWAP_CONSTEXPR uint64_t htobe64_internal(uint64_t host_64bits)
Definition: endian.h:53
void resize_uninitialized(size_type new_size)
Definition: prevector.h:401
static constexpr bool ForRead()
Definition: serialize.h:1029
Wrapper that serializes objects with the specified parameters.
Definition: serialize.h:1189
Simple wrapper class to serialize objects using a formatter; used by Using().
Definition: serialize.h:475
void Ser(Stream &s, const V &v)
Definition: serialize.h:661
SizeComputer()=default
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:497
size_t nSize
Definition: serialize.h:1063
Support for all macros providing or using the ser_action parameter of the SerializationOps method...
Definition: serialize.h:1008
static void SerReadWriteMany(Stream &s, Args &&... args)
Definition: serialize.h:1032
void Serialize(Stream &s) const
Definition: serialize.h:482
void Unser(Stream &s, I &v)
Definition: serialize.h:546
Serialization wrapper class for integers in VarInt format.
Definition: serialize.h:506
void Unser(Stream &s, V &v)
Definition: serialize.h:671
concept Serializable
If none of the specialized versions above matched, default to calling member function.
Definition: serialize.h:749
uint16_t ser_readdata16(Stream &s)
Definition: serialize.h:89
void Unserialize(Stream &, V)=delete
ParamsStream(NestedSubstream &&s, const Params1 &params1 LIFETIMEBOUND, const Params2 &params2 LIFETIMEBOUND, const NestedParams &... params LIFETIMEBOUND)
Definition: serialize.h:1130
ArgsManager & args
Definition: bitcoind.cpp:277
#define LIFETIMEBOUND
Definition: attributes.h:16
BSWAP_CONSTEXPR uint16_t htole16_internal(uint16_t host_16bits)
Definition: endian.h:18
uint32_t ser_readdata32(Stream &s)
Definition: serialize.h:101
#define B
Definition: util_tests.cpp:545
constexpr CheckVarIntMode()
Definition: serialize.h:409
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1097
void write(Span< const std::byte > src)
Definition: serialize.h:1068
void ser_writedata16(Stream &s, uint16_t obj)
Definition: serialize.h:58
ParamsStream & operator>>(U &&obj)
Definition: serialize.h:1134
Params1
Definition: serialize.h:1185
BSWAP_CONSTEXPR uint32_t htobe32_internal(uint32_t host_32bits)
Definition: endian.h:33
auto & GetStream()
Get reference to underlying stream.
Definition: serialize.h:1153
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition: serialize.h:405
I ReadVarInt(Stream &is)
Definition: serialize.h:452
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:73
static void SerRead(Stream &s, Type &&, Fn &&)
Definition: serialize.h:1018
const Params & m_params
Definition: serialize.h:1191
uint64_t ser_readdata64(Stream &s)
Definition: serialize.h:113
static void SerReadWriteMany(Stream &s, const Args &... args)
Definition: serialize.h:1012
void Ser(Stream &s, I v)
Definition: serialize.h:534
Default formatter.
Definition: serialize.h:771
size_t size() const
Definition: serialize.h:1139
BSWAP_CONSTEXPR uint32_t le32toh_internal(uint32_t little_endian_32bits)
Definition: endian.h:48
concept ContainsStream
Check if type contains a stream by seeing if has a GetStream() method.
Definition: serialize.h:1110
SubStream m_substream
Definition: serialize.h:1124
void Ser(Stream &s, const std::string &v)
Definition: serialize.h:638
void read(Span< std::byte > dst)
Definition: serialize.h:1136
uint16_t ser_readdata16be(Stream &s)
Definition: serialize.h:95
ParamsStream & operator<<(const U &obj)
Definition: serialize.h:1133
const CChainParams & Params()
Return the currently selected parameters.
bool eof() const
Definition: serialize.h:1138
static constexpr bool ForRead()
Definition: serialize.h:1009
bool empty() const
Definition: prevector.h:298
void Serialize(Stream &, V)=delete
Serialization wrapper class for custom integers and enums.
Definition: serialize.h:529
ParamsStream(SubStream &&substream, const Params &params LIFETIMEBOUND)
Definition: serialize.h:1127
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:269
concept Unserializable
Definition: serialize.h:758
ParamsWrapper(const Params &params, T &obj)
Definition: serialize.h:1195
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:107
unsigned int GetSizeOfVarInt(I n)
Definition: serialize.h:417
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition: span.h:258
const auto & GetParams() const
Get reference to stream parameters.
Definition: serialize.h:1143
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
ParamsStream(Substream &&, const Params &) -> ParamsStream< Substream, Params >
Explicit template deduction guide is required for single-parameter constructor so Substream&& is trea...
void ser_writedata16be(Stream &s, uint16_t obj)
Definition: serialize.h:63
BSWAP_CONSTEXPR uint64_t le64toh_internal(uint64_t little_endian_64bits)
Definition: endian.h:68
BSWAP_CONSTEXPR uint16_t htobe16_internal(uint16_t host_16bits)
Definition: endian.h:13
size_type size() const
Definition: prevector.h:294
void Unserialize(Stream &s)
Definition: serialize.h:483
void Unser(Stream &s, std::string &v)
Definition: serialize.h:627
void SerializeMany(Stream &s, const Args &... args)
Support for (un)serializing many things at once.
Definition: serialize.h:994
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:658
void WriteVarInt(SizeComputer &os, I n)
Definition: serialize.h:1092
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:97
BSWAP_CONSTEXPR uint64_t be64toh_internal(uint64_t big_endian_64bits)
Definition: endian.h:63
T m_object
Definition: serialize.h:477
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:297
void ignore(size_t num)
Definition: serialize.h:1137
static void Unser(Stream &s, T &t)
Definition: serialize.h:777
BSWAP_CONSTEXPR uint32_t be32toh_internal(uint32_t big_endian_32bits)
Definition: endian.h:43
#define T(expected, seed, data)
static void Ser(Stream &s, const T &t)
Definition: serialize.h:774
void UnserializeMany(Stream &s, Args &&... args)
Definition: serialize.h:1000
void Ser(Stream &s, I v)
Definition: serialize.h:508
void ser_writedata8(Stream &s, uint8_t obj)
Definition: serialize.h:54
void Unser(Stream &s, Tp &tp)
Definition: serialize.h:590
BSWAP_CONSTEXPR uint16_t le16toh_internal(uint16_t little_endian_16bits)
Definition: endian.h:28
CompactSizeWriter(uint64_t n_in)
Definition: serialize.h:615
void Ser(Stream &s, I v)
Definition: serialize.h:578
Wrapper(T obj)
Definition: serialize.h:481
void Serialize(Stream &s) const
Definition: serialize.h:618
size_t size() const
Definition: serialize.h:1086