Bitcoin ABC 0.33.12
P2P Digital Currency
serialize.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 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>
11#include <compat/endian.h>
12#include <prevector.h>
13#include <rcu.h>
14#include <span.h>
15
16#include <algorithm>
17#include <array>
18#include <concepts>
19#include <cstdint>
20#include <cstring>
21#include <ios>
22#include <limits>
23#include <map>
24#include <memory>
25#include <set>
26#include <string>
27#include <utility>
28#include <vector>
29
34static constexpr uint64_t MAX_SIZE = 0x02000000;
35
40static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
41
54
58template <typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) {
59 s.write(AsBytes(Span{&obj, 1}));
60}
61template <typename Stream>
62inline void ser_writedata16(Stream &s, uint16_t obj) {
63 obj = htole16_internal(obj);
64 s.write(AsBytes(Span{&obj, 1}));
65}
66template <typename Stream>
67inline void ser_writedata16be(Stream &s, uint16_t obj) {
68 obj = htobe16_internal(obj);
69 s.write(AsBytes(Span{&obj, 1}));
70}
71template <typename Stream>
72inline void ser_writedata32(Stream &s, uint32_t obj) {
73 obj = htole32_internal(obj);
74 s.write(AsBytes(Span{&obj, 1}));
75}
76template <typename Stream>
77inline void ser_writedata32be(Stream &s, uint32_t obj) {
78 obj = htobe32_internal(obj);
79 s.write(AsBytes(Span{&obj, 1}));
80}
81template <typename Stream>
82inline void ser_writedata64(Stream &s, uint64_t obj) {
83 obj = htole64_internal(obj);
84 s.write(AsBytes(Span{&obj, 1}));
85}
86template <typename Stream> inline uint8_t ser_readdata8(Stream &s) {
87 uint8_t obj;
88 s.read(AsWritableBytes(Span{&obj, 1}));
89 return obj;
90}
91template <typename Stream> inline uint16_t ser_readdata16(Stream &s) {
92 uint16_t obj;
93 s.read(AsWritableBytes(Span{&obj, 1}));
94 return le16toh_internal(obj);
95}
96template <typename Stream> inline uint16_t ser_readdata16be(Stream &s) {
97 uint16_t obj;
98 s.read(AsWritableBytes(Span{&obj, 1}));
99 return be16toh_internal(obj);
100}
101template <typename Stream> inline uint32_t ser_readdata32(Stream &s) {
102 uint32_t obj;
103 s.read(AsWritableBytes(Span{&obj, 1}));
104 return le32toh_internal(obj);
105}
106template <typename Stream> inline uint32_t ser_readdata32be(Stream &s) {
107 uint32_t obj;
108 s.read(AsWritableBytes(Span{&obj, 1}));
109 return be32toh_internal(obj);
110}
111template <typename Stream> inline uint64_t ser_readdata64(Stream &s) {
112 uint64_t obj;
113 s.read(AsWritableBytes(Span{&obj, 1}));
114 return le64toh_internal(obj);
115}
116inline uint64_t ser_double_to_uint64(double x) {
117 uint64_t tmp;
118 std::memcpy(&tmp, &x, sizeof(x));
119 static_assert(sizeof(tmp) == sizeof(x),
120 "double and uint64_t assumed to have the same size");
121 return tmp;
122}
123inline uint32_t ser_float_to_uint32(float x) {
124 uint32_t tmp;
125 std::memcpy(&tmp, &x, sizeof(x));
126 static_assert(sizeof(tmp) == sizeof(x),
127 "float and uint32_t assumed to have the same size");
128 return tmp;
129}
130inline double ser_uint64_to_double(uint64_t y) {
131 double tmp;
132 std::memcpy(&tmp, &y, sizeof(y));
133 static_assert(sizeof(tmp) == sizeof(y),
134 "double and uint64_t assumed to have the same size");
135 return tmp;
136}
137inline float ser_uint32_to_float(uint32_t y) {
138 float tmp;
139 std::memcpy(&tmp, &y, sizeof(y));
140 static_assert(sizeof(tmp) == sizeof(y),
141 "float and uint32_t assumed to have the same size");
142 return tmp;
143}
144
145class SizeComputer;
146
167template <class Out, class In> Out &AsBase(In &x) {
168 static_assert(std::is_base_of_v<Out, In>);
169 return x;
170}
171template <class Out, class In> const Out &AsBase(const In &x) {
172 static_assert(std::is_base_of_v<Out, In>);
173 return x;
174}
175
176#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
177#define SER_READ(obj, code) \
178 ::SerRead( \
179 s, ser_action, obj, \
180 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
181#define SER_WRITE(obj, code) \
182 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
183
202#define FORMATTER_METHODS(cls, obj) \
203 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
204 SerializationOps(obj, s, ActionSerialize()); \
205 } \
206 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
207 SerializationOps(obj, s, ActionUnserialize()); \
208 } \
209 template <typename Stream, typename Type, typename Operation> \
210 static void SerializationOps(Type &obj, Stream &s, Operation ser_action)
211
245#define FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
246 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
247 SerializationOps(obj, s, ActionSerialize{}, s.GetParams()); \
248 } \
249 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
250 SerializationOps(obj, s, ActionUnserialize{}, s.GetParams()); \
251 } \
252 template <typename Stream, typename Type, typename Operation> \
253 static void SerializationOps(Type &obj, Stream &s, Operation ser_action, \
254 const paramcls &paramobj)
255
256#define BASE_SERIALIZE_METHODS(cls) \
257 template <typename Stream> void Serialize(Stream &s) const { \
258 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
259 "Serialize type mismatch"); \
260 Ser(s, *this); \
261 } \
262 template <typename Stream> void Unserialize(Stream &s) { \
263 static_assert(std::is_same<cls &, decltype(*this)>::value, \
264 "Unserialize type mismatch"); \
265 Unser(s, *this); \
266 }
267
276#define SERIALIZE_METHODS(cls, obj) \
277 BASE_SERIALIZE_METHODS(cls) \
278 FORMATTER_METHODS(cls, obj)
279
285#define SERIALIZE_METHODS_PARAMS(cls, obj, paramcls, paramobj) \
286 BASE_SERIALIZE_METHODS(cls) \
287 FORMATTER_METHODS_PARAMS(cls, obj, paramcls, paramobj)
288
289// Typically int8_t and char are distinct types, but some systems may define
290// int8_t in terms of char. Forbid serialization of char in the typical case,
291// but allow it if it's the only way to describe an int8_t.
292template <class T>
293concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
294
295// Templates for serializing to anything that looks like a stream,
296// i.e. anything that supports .read(Span<std::byte>) and
297// .write(Span<const std::byte>)
298//
299
300// char serialization forbidden. Use uint8_t or int8_t
301template <typename Stream, CharNotInt8 V> void Serialize(Stream &, V) = delete;
302template <typename Stream> void Serialize(Stream &s, std::byte a) {
303 ser_writedata8(s, uint8_t(a));
304}
305template <typename Stream> inline void Serialize(Stream &s, int8_t a) {
306 ser_writedata8(s, a);
307}
308template <typename Stream> inline void Serialize(Stream &s, uint8_t a) {
309 ser_writedata8(s, a);
310}
311template <typename Stream> inline void Serialize(Stream &s, int16_t a) {
312 ser_writedata16(s, a);
313}
314template <typename Stream> inline void Serialize(Stream &s, uint16_t a) {
315 ser_writedata16(s, a);
316}
317template <typename Stream> inline void Serialize(Stream &s, int32_t a) {
318 ser_writedata32(s, a);
319}
320template <typename Stream> inline void Serialize(Stream &s, uint32_t a) {
321 ser_writedata32(s, a);
322}
323template <typename Stream> inline void Serialize(Stream &s, int64_t a) {
324 ser_writedata64(s, a);
325}
326template <typename Stream> inline void Serialize(Stream &s, uint64_t a) {
327 ser_writedata64(s, a);
328}
329template <typename Stream> inline void Serialize(Stream &s, float a) {
331}
332template <typename Stream> inline void Serialize(Stream &s, double a) {
334}
335template <typename Stream, size_t N>
336inline void Serialize(Stream &s, const int8_t (&a)[N]) {
337 s.write(a, N);
338}
339template <typename Stream, BasicByte B, size_t N>
340void Serialize(Stream &s, const B (&a)[N]) {
341 s.write(MakeByteSpan(a));
342}
343template <typename Stream, size_t N>
344inline void Serialize(Stream &s, const std::array<int8_t, N> &a) {
345 s.write(a.data(), N);
346}
347template <typename Stream, size_t N>
348inline void Serialize(Stream &s, const std::array<uint8_t, N> &a) {
349 s.write(MakeByteSpan(a));
350}
351template <typename Stream, BasicByte B, std::size_t N>
352void Serialize(Stream &s, const std::array<B, N> &a) {
353 s.write(MakeByteSpan(a));
354}
355template <typename Stream, BasicByte B>
356void Serialize(Stream &s, Span<B> span) {
357 s.write(AsBytes(span));
358}
359
360// char serialization forbidden. Use uint8_t or int8_t
361template <typename Stream, CharNotInt8 V>
362void Unserialize(Stream &, V) = delete;
363template <typename Stream> void Unserialize(Stream &s, std::byte &a) {
364 a = std::byte{ser_readdata8(s)};
365}
366template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) {
367 a = ser_readdata8(s);
368}
369template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) {
370 a = ser_readdata8(s);
371}
372template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) {
373 a = ser_readdata16(s);
374}
375template <typename Stream> inline void Unserialize(Stream &s, uint16_t &a) {
376 a = ser_readdata16(s);
377}
378template <typename Stream> inline void Unserialize(Stream &s, int32_t &a) {
379 a = ser_readdata32(s);
380}
381template <typename Stream> inline void Unserialize(Stream &s, uint32_t &a) {
382 a = ser_readdata32(s);
383}
384template <typename Stream> inline void Unserialize(Stream &s, int64_t &a) {
385 a = ser_readdata64(s);
386}
387template <typename Stream> inline void Unserialize(Stream &s, uint64_t &a) {
388 a = ser_readdata64(s);
389}
390template <typename Stream> inline void Unserialize(Stream &s, float &a) {
392}
393template <typename Stream> inline void Unserialize(Stream &s, double &a) {
395}
396template <typename Stream, size_t N>
397inline void Unserialize(Stream &s, int8_t (&a)[N]) {
398 s.read(MakeWritableByteSpan(a));
399}
400template <typename Stream, BasicByte B, size_t N>
401void Unserialize(Stream &s, B (&a)[N]) {
402 s.read(MakeWritableByteSpan(a));
403}
404
405template <typename Stream> inline void Serialize(Stream &s, bool a) {
406 char f = a;
407 ser_writedata8(s, f);
408}
409template <typename Stream> inline void Unserialize(Stream &s, bool &a) {
410 char f = ser_readdata8(s);
411 a = f;
412}
413template <typename Stream, BasicByte B, std::size_t N>
414void Unserialize(Stream &s, std::array<B, N> &a) {
415 s.read(MakeWritableByteSpan(a));
416}
417template <typename Stream, BasicByte B>
418void Unserialize(Stream &s, Span<B> span) {
419 s.read(AsWritableBytes(span));
420}
421
429inline uint32_t GetSizeOfCompactSize(uint64_t nSize) {
430 if (nSize < 253) {
431 return sizeof(uint8_t);
432 }
433 if (nSize <= std::numeric_limits<uint16_t>::max()) {
434 return sizeof(uint8_t) + sizeof(uint16_t);
435 }
436 if (nSize <= std::numeric_limits<uint32_t>::max()) {
437 return sizeof(uint8_t) + sizeof(uint32_t);
438 }
439
440 return sizeof(uint8_t) + sizeof(uint64_t);
441}
442
443inline void WriteCompactSize(SizeComputer &os, uint64_t nSize);
444
445template <typename Stream> void WriteCompactSize(Stream &os, uint64_t nSize) {
446 if (nSize < 253) {
448 } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
449 ser_writedata8(os, 253);
451 } else if (nSize <= std::numeric_limits<uint32_t>::max()) {
452 ser_writedata8(os, 254);
454 } else {
455 ser_writedata8(os, 255);
457 }
458 return;
459}
460
468template <typename Stream>
469uint64_t ReadCompactSize(Stream &is, bool range_check = true) {
470 uint8_t chSize = ser_readdata8(is);
471 uint64_t nSizeRet = 0;
472 if (chSize < 253) {
473 nSizeRet = chSize;
474 } else if (chSize == 253) {
475 nSizeRet = ser_readdata16(is);
476 if (nSizeRet < 253) {
477 throw std::ios_base::failure("non-canonical ReadCompactSize()");
478 }
479 } else if (chSize == 254) {
480 nSizeRet = ser_readdata32(is);
481 if (nSizeRet < 0x10000u) {
482 throw std::ios_base::failure("non-canonical ReadCompactSize()");
483 }
484 } else {
485 nSizeRet = ser_readdata64(is);
486 if (nSizeRet < 0x100000000ULL) {
487 throw std::ios_base::failure("non-canonical ReadCompactSize()");
488 }
489 }
490 if (range_check && nSizeRet > MAX_SIZE) {
491 throw std::ios_base::failure("ReadCompactSize(): size too large");
492 }
493 return nSizeRet;
494}
495
531
532template <VarIntMode Mode, typename I> struct CheckVarIntMode {
533 constexpr CheckVarIntMode() {
534 static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value,
535 "Unsigned type required with mode DEFAULT.");
536 static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED ||
537 std::is_signed<I>::value,
538 "Signed type required with mode NONNEGATIVE_SIGNED.");
539 }
540};
541
542template <VarIntMode Mode, typename I>
543inline unsigned int GetSizeOfVarInt(I n) {
545 int nRet = 0;
546 while (true) {
547 nRet++;
548 if (n <= 0x7F) {
549 return nRet;
550 }
551 n = (n >> 7) - 1;
552 }
553}
554
555template <typename I> inline void WriteVarInt(SizeComputer &os, I n);
556
557template <typename Stream, VarIntMode Mode, typename I>
558void WriteVarInt(Stream &os, I n) {
560 uint8_t tmp[(sizeof(n) * 8 + 6) / 7];
561 int len = 0;
562 while (true) {
563 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
564 if (n <= 0x7F) {
565 break;
566 }
567 n = (n >> 7) - 1;
568 len++;
569 }
570 do {
571 ser_writedata8(os, tmp[len]);
572 } while (len--);
573}
574
575template <typename Stream, VarIntMode Mode, typename I>
576I ReadVarInt(Stream &is) {
578 I n = 0;
579 while (true) {
580 uint8_t chData = ser_readdata8(is);
581 if (n > (std::numeric_limits<I>::max() >> 7)) {
582 throw std::ios_base::failure("ReadVarInt(): size too large");
583 }
584 n = (n << 7) | (chData & 0x7F);
585 if ((chData & 0x80) == 0) {
586 return n;
587 }
588 if (n == std::numeric_limits<I>::max()) {
589 throw std::ios_base::failure("ReadVarInt(): size too large");
590 }
591 n++;
592 }
593}
594
599template <typename Formatter, typename T> class Wrapper {
600 static_assert(std::is_lvalue_reference<T>::value,
601 "Wrapper needs an lvalue reference type T");
602
603protected:
605
606public:
607 explicit Wrapper(T obj) : m_object(obj) {}
608 template <typename Stream> void Serialize(Stream &s) const {
609 Formatter().Ser(s, m_object);
610 }
611 template <typename Stream> void Unserialize(Stream &s) {
612 Formatter().Unser(s, m_object);
613 }
614};
615
629template <typename Formatter, typename T>
630static inline Wrapper<Formatter, T &> Using(T &&t) {
631 return Wrapper<Formatter, T &>(t);
632}
633
634#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
635#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
636#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
637#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
638
642template <VarIntMode Mode> struct VarIntFormatter {
643 template <typename Stream, typename I> void Ser(Stream &s, I v) {
644 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
645 }
646
647 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
648 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
649 }
650};
651
662template <int Bytes, bool BigEndian = false> struct CustomUintFormatter {
663 static_assert(Bytes > 0 && Bytes <= 8,
664 "CustomUintFormatter Bytes out of range");
665 static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
666
667 template <typename Stream, typename I> void Ser(Stream &s, I v) {
668 if (v < 0 || v > MAX) {
669 throw std::ios_base::failure(
670 "CustomUintFormatter value out of range");
671 }
672 if (BigEndian) {
673 uint64_t raw = htobe64_internal(v);
674 s.write({BytePtr(&raw) + 8 - Bytes, Bytes});
675 } else {
676 uint64_t raw = htole64_internal(v);
677 s.write({BytePtr(&raw), Bytes});
678 }
679 }
680
681 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
682 using U = typename std::conditional<std::is_enum<I>::value,
683 std::underlying_type<I>,
684 std::common_type<I>>::type::type;
685 static_assert(std::numeric_limits<U>::max() >= MAX &&
686 std::numeric_limits<U>::min() <= 0,
687 "Assigned type too small");
688 uint64_t raw = 0;
689 if (BigEndian) {
690 s.read({BytePtr(&raw) + 8 - Bytes, Bytes});
691 v = static_cast<I>(be64toh_internal(raw));
692 } else {
693 s.read({BytePtr(&raw), Bytes});
694 v = static_cast<I>(le64toh_internal(raw));
695 }
696 }
697};
698
699template <int Bytes>
701
703template <bool RangeCheck> struct CompactSizeFormatter {
704 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
705 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
706 if (n < std::numeric_limits<I>::min() ||
707 n > std::numeric_limits<I>::max()) {
708 throw std::ios_base::failure("CompactSize exceeds limit of type");
709 }
710 v = n;
711 }
712
713 template <typename Stream, typename I> void Ser(Stream &s, I v) {
714 static_assert(std::is_unsigned<I>::value,
715 "CompactSize only supported for unsigned integers");
716 static_assert(std::numeric_limits<I>::max() <=
717 std::numeric_limits<uint64_t>::max(),
718 "CompactSize only supports 64-bit integers and below");
719
720 WriteCompactSize<Stream>(s, v);
721 }
722};
723
724template <typename U, bool LOSSY = false> struct ChronoFormatter {
725 template <typename Stream, typename Tp> void Unser(Stream &s, Tp &tp) {
726 U u;
727 s >> u;
728 // Lossy deserialization does not make sense, so force Wnarrowing
729 tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
730 }
731 template <typename Stream, typename Tp> void Ser(Stream &s, Tp tp) {
732 if constexpr (LOSSY) {
733 s << U(tp.time_since_epoch().count());
734 } else {
735 s << U{tp.time_since_epoch().count()};
736 }
737 }
738};
739template <typename U> using LossyChronoFormatter = ChronoFormatter<U, true>;
740
741template <size_t Limit> struct LimitedStringFormatter {
742 template <typename Stream> void Unser(Stream &s, std::string &v) {
743 size_t size = ReadCompactSize(s);
744 if (size > Limit) {
745 throw std::ios_base::failure("String length limit exceeded");
746 }
747 v.resize(size);
748 if (size != 0) {
749 s.read(MakeWritableByteSpan(v));
750 }
751 }
752
753 template <typename Stream> void Ser(Stream &s, const std::string &v) {
754 s << v;
755 }
756};
757
774template <class Formatter> struct VectorFormatter {
775 template <typename Stream, typename V> void Ser(Stream &s, const V &v) {
776 Formatter formatter;
777 WriteCompactSize(s, v.size());
778 for (const typename V::value_type &elem : v) {
779 formatter.Ser(s, elem);
780 }
781 }
782
783 template <typename Stream, typename V> void Unser(Stream &s, V &v) {
784 Formatter formatter;
785 v.clear();
786 size_t size = ReadCompactSize(s);
787 size_t allocated = 0;
788 while (allocated < size) {
789 // For DoS prevention, do not blindly allocate as much as the stream
790 // claims to contain. Instead, allocate in 5MiB batches, so that an
791 // attacker actually needs to provide X MiB of data to make us
792 // allocate X+5 Mib.
793 static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE,
794 "Vector element size too large");
795 allocated =
796 std::min(size, allocated + MAX_VECTOR_ALLOCATE /
797 sizeof(typename V::value_type));
798 v.reserve(allocated);
799 while (v.size() < allocated) {
800 v.emplace_back();
801 formatter.Unser(s, v.back());
802 }
803 }
804 };
805};
806
818 uint64_t m_shift = 0;
819
820public:
821 template <typename Stream, typename I> void Ser(Stream &s, I v) {
822 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
823 throw std::ios_base::failure("differential value overflow");
824 }
826 m_shift = uint64_t(v) + 1;
827 }
828 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
829 uint64_t n = ReadCompactSize(s);
830 m_shift += n;
831 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
832 m_shift < std::numeric_limits<I>::min() ||
833 m_shift > std::numeric_limits<I>::max()) {
834 throw std::ios_base::failure("differential value overflow");
835 }
836 v = I(m_shift++);
837 }
838};
839
851 template <typename Stream, typename T> void Ser(Stream &s, T v) {
852 DifferenceFormatter::Ser(s, v.index);
853 v.SerData(s);
854 }
855
856 template <typename Stream, typename T> void Unser(Stream &s, T &v) {
857 DifferenceFormatter::Unser(s, v.index);
858 v.UnserData(s);
859 }
860};
861
869template <typename Stream, typename C>
870void Serialize(Stream &os, const std::basic_string<C> &str);
871template <typename Stream, typename C>
872void Unserialize(Stream &is, std::basic_string<C> &str);
873
877template <typename Stream, unsigned int N, typename T>
878inline void Serialize(Stream &os, const prevector<N, T> &v);
879template <typename Stream, unsigned int N, typename T>
880inline void Unserialize(Stream &is, prevector<N, T> &v);
881
885template <typename Stream, typename T, typename A>
886inline void Serialize(Stream &os, const std::vector<T, A> &v);
887template <typename Stream, typename T, typename A>
888inline void Unserialize(Stream &is, std::vector<T, A> &v);
889
893template <typename Stream, typename K, typename T>
894void Serialize(Stream &os, const std::pair<K, T> &item);
895template <typename Stream, typename K, typename T>
896void Unserialize(Stream &is, std::pair<K, T> &item);
897
901template <typename Stream, typename K, typename T, typename Pred, typename A>
902void Serialize(Stream &os, const std::map<K, T, Pred, A> &m);
903template <typename Stream, typename K, typename T, typename Pred, typename A>
904void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
905
909template <typename Stream, typename K, typename Pred, typename A>
910void Serialize(Stream &os, const std::set<K, Pred, A> &m);
911template <typename Stream, typename K, typename Pred, typename A>
912void Unserialize(Stream &is, std::set<K, Pred, A> &m);
913
917template <typename Stream, typename T>
918void Serialize(Stream &os, const std::shared_ptr<const T> &p);
919template <typename Stream, typename T>
920void Unserialize(Stream &os, std::shared_ptr<const T> &p);
921
925template <typename Stream, typename T>
926void Serialize(Stream &os, const std::unique_ptr<const T> &p);
927template <typename Stream, typename T>
928void Unserialize(Stream &os, std::unique_ptr<const T> &p);
929
933template <typename Stream, typename T>
934void Serialize(Stream &os, const RCUPtr<const T> &p);
935template <typename Stream, typename T>
936void Unserialize(Stream &os, RCUPtr<const T> &p);
937
942template <class T, class Stream>
943concept Serializable = requires(T a, Stream s) { a.Serialize(s); };
944template <typename Stream, typename T>
946void Serialize(Stream &os, const T &a) {
947 a.Serialize(os);
948}
949
950template <class T, class Stream>
951concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };
952template <typename Stream, typename T>
954void Unserialize(Stream &is, T &&a) {
955 a.Unserialize(is);
956}
957
965 template <typename Stream, typename T>
966 static void Ser(Stream &s, const T &t) {
967 Serialize(s, t);
968 }
969
970 template <typename Stream, typename T> static void Unser(Stream &s, T &t) {
971 Unserialize(s, t);
972 }
973};
974
978template <typename Stream, typename C>
979void Serialize(Stream &os, const std::basic_string<C> &str) {
980 WriteCompactSize(os, str.size());
981 if (!str.empty()) {
982 os.write(MakeByteSpan(str));
983 }
984}
985
986template <typename Stream, typename C>
987void Unserialize(Stream &is, std::basic_string<C> &str) {
988 size_t nSize = ReadCompactSize(is);
989 str.resize(nSize);
990 if (nSize != 0) {
991 is.read(MakeWritableByteSpan(str));
992 }
993}
994
998template <typename Stream, unsigned int N, typename T>
999void Serialize(Stream &os, const prevector<N, T> &v) {
1000 if constexpr (BasicByte<T>) {
1001 // Use optimized version for unformatted basic bytes
1002 WriteCompactSize(os, v.size());
1003 if (!v.empty()) {
1004 os.write(MakeByteSpan(v));
1005 }
1006 } else {
1008 }
1009}
1010
1011template <typename Stream, unsigned int N, typename T>
1012void Unserialize(Stream &is, prevector<N, T> &v) {
1013 if constexpr (BasicByte<T>) {
1014 // Use optimized version for unformatted basic bytes
1015 // Limit size per read so bogus size value won't cause out of memory
1016 v.clear();
1017 size_t nSize = ReadCompactSize(is);
1018 size_t i = 0;
1019 while (i < nSize) {
1020 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1021 v.resize_uninitialized(i + blk);
1022 is.read(AsWritableBytes(Span{&v[i], blk}));
1023 i += blk;
1024 }
1025 } else {
1027 }
1028}
1029
1033template <typename Stream, typename T, typename A>
1034void Serialize(Stream &os, const std::vector<T, A> &v) {
1035 if constexpr (BasicByte<T>) {
1036 // Use optimized version for unformatted basic bytes
1037 WriteCompactSize(os, v.size());
1038 if (!v.empty()) {
1039 os.write(MakeByteSpan(v));
1040 }
1041 } else if constexpr (std::is_same_v<T, bool>) {
1042 // A special case for std::vector<bool>, as dereferencing
1043 // std::vector<bool>::const_iterator does not result in a const bool&
1044 // due to std::vector's special casing for bool arguments.
1045 WriteCompactSize(os, v.size());
1046 for (bool elem : v) {
1047 ::Serialize(os, elem);
1048 }
1049 } else {
1051 }
1052}
1053
1054template <typename Stream, typename T, typename A>
1055void Unserialize(Stream &is, std::vector<T, A> &v) {
1056 if constexpr (BasicByte<T>) {
1057 // Use optimized version for unformatted basic bytes
1058 // Limit size per read so bogus size value won't cause out of memory
1059 v.clear();
1060 size_t nSize = ReadCompactSize(is);
1061 size_t i = 0;
1062 while (i < nSize) {
1063 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1064 v.resize(i + blk);
1065 is.read(AsWritableBytes(Span{&v[i], blk}));
1066 i += blk;
1067 }
1068 } else {
1070 }
1071}
1072
1076template <typename Stream, typename K, typename T>
1077void Serialize(Stream &os, const std::pair<K, T> &item) {
1078 Serialize(os, item.first);
1079 Serialize(os, item.second);
1080}
1081
1082template <typename Stream, typename K, typename T>
1083void Unserialize(Stream &is, std::pair<K, T> &item) {
1084 Unserialize(is, item.first);
1085 Unserialize(is, item.second);
1086}
1087
1091template <typename Stream, typename K, typename T, typename Pred, typename A>
1092void Serialize(Stream &os, const std::map<K, T, Pred, A> &m) {
1093 WriteCompactSize(os, m.size());
1094 for (const auto &entry : m) {
1095 Serialize(os, entry);
1096 }
1097}
1098
1099template <typename Stream, typename K, typename T, typename Pred, typename A>
1100void Unserialize(Stream &is, std::map<K, T, Pred, A> &m) {
1101 m.clear();
1102 size_t nSize = ReadCompactSize(is);
1103 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1104 for (size_t i = 0; i < nSize; i++) {
1105 std::pair<K, T> item;
1106 Unserialize(is, item);
1107 mi = m.insert(mi, item);
1108 }
1109}
1110
1114template <typename Stream, typename K, typename Pred, typename A>
1115void Serialize(Stream &os, const std::set<K, Pred, A> &m) {
1116 WriteCompactSize(os, m.size());
1117 for (const K &i : m) {
1118 Serialize(os, i);
1119 }
1120}
1121
1122template <typename Stream, typename K, typename Pred, typename A>
1123void Unserialize(Stream &is, std::set<K, Pred, A> &m) {
1124 m.clear();
1125 size_t nSize = ReadCompactSize(is);
1126 typename std::set<K, Pred, A>::iterator it = m.begin();
1127 for (size_t i = 0; i < nSize; i++) {
1128 K key;
1129 Unserialize(is, key);
1130 it = m.insert(it, key);
1131 }
1132}
1133
1137template <typename Stream, typename T>
1138void Serialize(Stream &os, const std::unique_ptr<const T> &p) {
1139 Serialize(os, *p);
1140}
1141
1142template <typename Stream, typename T>
1143void Unserialize(Stream &is, std::unique_ptr<const T> &p) {
1144 p.reset(new T(deserialize, is));
1145}
1146
1150template <typename Stream, typename T>
1151void Serialize(Stream &os, const std::shared_ptr<const T> &p) {
1152 Serialize(os, *p);
1153}
1154
1155template <typename Stream, typename T>
1156void Unserialize(Stream &is, std::shared_ptr<const T> &p) {
1157 p = std::make_shared<const T>(deserialize, is);
1158}
1159
1163template <typename Stream, typename T>
1164void Serialize(Stream &os, const RCUPtr<const T> &p) {
1165 Serialize(os, *p);
1166}
1167
1168template <typename Stream, typename T>
1169void Unserialize(Stream &is, RCUPtr<const T> &p) {
1171}
1172
1178 constexpr bool ForRead() const { return false; }
1179};
1181 constexpr bool ForRead() const { return true; }
1182};
1183
1197protected:
1198 size_t nSize{0};
1199
1200public:
1201 SizeComputer() = default;
1202
1203 void write(Span<const std::byte> src) { this->nSize += src.size(); }
1204
1206 void seek(size_t _nSize) { this->nSize += _nSize; }
1207
1208 template <typename T> SizeComputer &operator<<(const T &obj) {
1209 ::Serialize(*this, obj);
1210 return (*this);
1211 }
1212
1213 size_t size() const { return nSize; }
1214};
1215
1216template <typename Stream, typename... Args>
1217void SerializeMany(Stream &s, const Args &...args) {
1218 (::Serialize(s, args), ...);
1219}
1220
1221template <typename Stream, typename... Args>
1222inline void UnserializeMany(Stream &s, Args &&...args) {
1223 (::Unserialize(s, args), ...);
1224}
1225
1226template <typename Stream, typename... Args>
1227inline void SerReadWriteMany(Stream &s, ActionSerialize ser_action,
1228 const Args &...args) {
1229 ::SerializeMany(s, args...);
1230}
1231
1232template <typename Stream, typename... Args>
1233inline void SerReadWriteMany(Stream &s, ActionUnserialize ser_action,
1234 Args &&...args) {
1235 ::UnserializeMany(s, args...);
1236}
1237
1238template <typename Stream, typename Type, typename Fn>
1239inline void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&) {}
1240
1241template <typename Stream, typename Type, typename Fn>
1242inline void SerRead(Stream &s, ActionUnserialize ser_action, Type &&obj,
1243 Fn &&fn) {
1244 fn(s, std::forward<Type>(obj));
1245}
1246
1247template <typename Stream, typename Type, typename Fn>
1248inline void SerWrite(Stream &s, ActionSerialize ser_action, Type &&obj,
1249 Fn &&fn) {
1250 fn(s, std::forward<Type>(obj));
1251}
1252
1253template <typename Stream, typename Type, typename Fn>
1254inline void SerWrite(Stream &s, ActionUnserialize ser_action, Type &&, Fn &&) {}
1255
1256template <typename I> inline void WriteVarInt(SizeComputer &s, I n) {
1257 s.seek(GetSizeOfVarInt<I>(n));
1258}
1259
1260inline void WriteCompactSize(SizeComputer &s, uint64_t nSize) {
1261 s.seek(GetSizeOfCompactSize(nSize));
1262}
1263
1264template <typename T> size_t GetSerializeSize(const T &t) {
1265 return (SizeComputer{} << t).size();
1266}
1267
1272template <typename Params, typename SubStream> class ParamsStream {
1274 // private to avoid leaking version/type into serialization code that
1275 // shouldn't see it
1276 SubStream &m_substream;
1277
1278public:
1280 SubStream &substream LIFETIMEBOUND)
1281 : m_params{params}, m_substream{substream} {}
1282 template <typename U> ParamsStream &operator<<(const U &obj) {
1283 ::Serialize(*this, obj);
1284 return *this;
1285 }
1286 template <typename U> ParamsStream &operator>>(U &&obj) {
1287 ::Unserialize(*this, obj);
1288 return *this;
1289 }
1290 void write(Span<const std::byte> src) { m_substream.write(src); }
1291 void read(Span<std::byte> dst) { m_substream.read(dst); }
1292 void ignore(size_t num) { m_substream.ignore(num); }
1293 bool eof() const { return m_substream.eof(); }
1294 size_t size() const { return m_substream.size(); }
1295 const Params &GetParams() const { return m_params; }
1296 // Deprecated with Params usage
1297 int GetVersion() = delete;
1298 // Deprecated with Params usage
1299 int GetType() = delete;
1300};
1301
1303template <typename Params, typename T> class ParamsWrapper {
1304 static_assert(std::is_lvalue_reference<T>::value,
1305 "ParamsWrapper needs an lvalue reference type T");
1308
1309public:
1310 explicit ParamsWrapper(const Params &params, T obj)
1311 : m_params{params}, m_object{obj} {}
1312
1313 template <typename Stream> void Serialize(Stream &s) const {
1314 ParamsStream ss{m_params, s};
1315 ::Serialize(ss, m_object);
1316 }
1317 template <typename Stream> void Unserialize(Stream &s) {
1318 ParamsStream ss{m_params, s};
1320 }
1321};
1322
1330template <typename Params, typename T>
1331static auto WithParams(const Params &params, T &&t) {
1332 return ParamsWrapper<Params, T &>{params, t};
1333}
1334
1335#endif // BITCOIN_SERIALIZE_H
#define LIFETIMEBOUND
Definition: attributes.h:16
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:21
Helper for differentially encoded Compact Size integers in lists.
Definition: serialize.h:817
void Unser(Stream &s, I &v)
Definition: serialize.h:828
void Ser(Stream &s, I v)
Definition: serialize.h:821
Wrapper that overrides the GetParams() function of a stream (and hides GetVersion/GetType).
Definition: serialize.h:1272
const Params & m_params
Definition: serialize.h:1273
void ignore(size_t num)
Definition: serialize.h:1292
ParamsStream(const Params &params LIFETIMEBOUND, SubStream &substream LIFETIMEBOUND)
Definition: serialize.h:1279
void write(Span< const std::byte > src)
Definition: serialize.h:1290
int GetVersion()=delete
ParamsStream & operator<<(const U &obj)
Definition: serialize.h:1282
void read(Span< std::byte > dst)
Definition: serialize.h:1291
bool eof() const
Definition: serialize.h:1293
const Params & GetParams() const
Definition: serialize.h:1295
ParamsStream & operator>>(U &&obj)
Definition: serialize.h:1286
size_t size() const
Definition: serialize.h:1294
SubStream & m_substream
Definition: serialize.h:1276
int GetType()=delete
Wrapper that serializes objects with the specified parameters.
Definition: serialize.h:1303
const Params & m_params
Definition: serialize.h:1306
void Unserialize(Stream &s)
Definition: serialize.h:1317
void Serialize(Stream &s) const
Definition: serialize.h:1313
ParamsWrapper(const Params &params, T obj)
Definition: serialize.h:1310
Definition: rcu.h:85
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
GetSerializeSize implementations
Definition: serialize.h:1196
void write(Span< const std::byte > src)
Definition: serialize.h:1203
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1206
size_t nSize
Definition: serialize.h:1198
size_t size() const
Definition: serialize.h:1213
SizeComputer()=default
SizeComputer & operator<<(const T &obj)
Definition: serialize.h:1208
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:94
constexpr std::size_t size() const noexcept
Definition: span.h:210
Simple wrapper class to serialize objects using a formatter; used by Using().
Definition: serialize.h:599
Wrapper(T obj)
Definition: serialize.h:607
T m_object
Definition: serialize.h:604
void Serialize(Stream &s) const
Definition: serialize.h:608
void Unserialize(Stream &s)
Definition: serialize.h:611
Implements a drop-in replacement for std::vector<T> which stores up to N elements directly (without h...
Definition: prevector.h:38
bool empty() const
Definition: prevector.h:400
void clear()
Definition: prevector.h:453
size_type size() const
Definition: prevector.h:398
void resize_uninitialized(size_type new_size)
Definition: prevector.h:494
If none of the specialized versions above matched, default to calling member function.
Definition: serialize.h:943
BSWAP_CONSTEXPR uint32_t be32toh_internal(uint32_t big_endian_32bits)
Definition: endian.h:56
BSWAP_CONSTEXPR uint16_t be16toh_internal(uint16_t big_endian_16bits)
Definition: endian.h:27
BSWAP_CONSTEXPR uint64_t htobe64_internal(uint64_t host_64bits)
Definition: endian.h:71
BSWAP_CONSTEXPR uint16_t htobe16_internal(uint16_t host_16bits)
Definition: endian.h:13
BSWAP_CONSTEXPR uint32_t htole32_internal(uint32_t host_32bits)
Definition: endian.h:49
BSWAP_CONSTEXPR uint16_t htole16_internal(uint16_t host_16bits)
Definition: endian.h:20
BSWAP_CONSTEXPR uint64_t be64toh_internal(uint64_t big_endian_64bits)
Definition: endian.h:85
BSWAP_CONSTEXPR uint16_t le16toh_internal(uint16_t little_endian_16bits)
Definition: endian.h:35
BSWAP_CONSTEXPR uint64_t htole64_internal(uint64_t host_64bits)
Definition: endian.h:78
BSWAP_CONSTEXPR uint64_t le64toh_internal(uint64_t little_endian_64bits)
Definition: endian.h:93
BSWAP_CONSTEXPR uint32_t le32toh_internal(uint32_t little_endian_32bits)
Definition: endian.h:64
BSWAP_CONSTEXPR uint32_t htobe32_internal(uint32_t host_32bits)
Definition: endian.h:42
size_t GetSerializeSize(const T &t)
Definition: serialize.h:1264
void Serialize(Stream &, V)=delete
void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&)
Definition: serialize.h:1239
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition: serialize.h:40
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:86
float ser_uint32_to_float(uint32_t y)
Definition: serialize.h:137
I ReadVarInt(Stream &is)
Definition: serialize.h:576
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:77
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition: serialize.h:530
@ NONNEGATIVE_SIGNED
void ser_writedata32(Stream &s, uint32_t obj)
Definition: serialize.h:72
uint32_t GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 byt...
Definition: serialize.h:429
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:34
void UnserializeMany(Stream &s, Args &&...args)
Definition: serialize.h:1222
constexpr deserialize_type deserialize
Definition: serialize.h:53
void ser_writedata16(Stream &s, uint16_t obj)
Definition: serialize.h:62
uint32_t ser_float_to_uint32(float x)
Definition: serialize.h:123
void Unserialize(Stream &, V)=delete
Out & AsBase(In &x)
Convert any argument to a reference to X, maintaining constness.
Definition: serialize.h:167
void WriteVarInt(SizeComputer &os, I n)
Definition: serialize.h:1256
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1260
void SerializeMany(Stream &s, const Args &...args)
Definition: serialize.h:1217
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
Definition: serialize.h:1331
void ser_writedata16be(Stream &s, uint16_t obj)
Definition: serialize.h:67
void SerReadWriteMany(Stream &s, ActionSerialize ser_action, const Args &...args)
Definition: serialize.h:1227
uint16_t ser_readdata16(Stream &s)
Definition: serialize.h:91
uint64_t ser_readdata64(Stream &s)
Definition: serialize.h:111
double ser_uint64_to_double(uint64_t y)
Definition: serialize.h:130
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
Definition: serialize.h:58
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:469
void SerWrite(Stream &s, ActionSerialize ser_action, Type &&obj, Fn &&fn)
Definition: serialize.h:1248
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
Definition: serialize.h:630
unsigned int GetSizeOfVarInt(I n)
Definition: serialize.h:543
uint32_t ser_readdata32(Stream &s)
Definition: serialize.h:101
uint16_t ser_readdata16be(Stream &s)
Definition: serialize.h:96
uint64_t ser_double_to_uint64(double x)
Definition: serialize.h:116
void ser_writedata64(Stream &s, uint64_t obj)
Definition: serialize.h:82
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:106
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
Definition: span.h:298
const std::byte * BytePtr(const void *data)
Convert a data pointer to a std::byte data pointer.
Definition: span.h:287
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:302
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition: span.h:295
Span< std::byte > MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:305
Support for all macros providing or using the ser_action parameter of the SerializationOps method.
Definition: serialize.h:1177
constexpr bool ForRead() const
Definition: serialize.h:1178
constexpr bool ForRead() const
Definition: serialize.h:1181
constexpr CheckVarIntMode()
Definition: serialize.h:533
void Unser(Stream &s, Tp &tp)
Definition: serialize.h:725
void Ser(Stream &s, Tp tp)
Definition: serialize.h:731
Formatter for integers in CompactSize format.
Definition: serialize.h:703
void Unser(Stream &s, I &v)
Definition: serialize.h:704
void Ser(Stream &s, I v)
Definition: serialize.h:713
Serialization wrapper class for custom integers and enums.
Definition: serialize.h:662
static constexpr uint64_t MAX
Definition: serialize.h:665
void Ser(Stream &s, I v)
Definition: serialize.h:667
void Unser(Stream &s, I &v)
Definition: serialize.h:681
Default formatter.
Definition: serialize.h:964
static void Ser(Stream &s, const T &t)
Definition: serialize.h:966
static void Unser(Stream &s, T &t)
Definition: serialize.h:970
Helper for a list of items containing a differentially encoded index as their first member.
Definition: serialize.h:850
void Unser(Stream &s, T &v)
Definition: serialize.h:856
void Ser(Stream &s, T v)
Definition: serialize.h:851
void Unser(Stream &s, std::string &v)
Definition: serialize.h:742
void Ser(Stream &s, const std::string &v)
Definition: serialize.h:753
Serialization wrapper class for integers in VarInt format.
Definition: serialize.h:642
void Ser(Stream &s, I v)
Definition: serialize.h:643
void Unser(Stream &s, I &v)
Definition: serialize.h:647
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:774
void Unser(Stream &s, V &v)
Definition: serialize.h:783
void Ser(Stream &s, const V &v)
Definition: serialize.h:775
Dummy data type to identify deserializing constructors.
Definition: serialize.h:52