Bitcoin ABC 0.32.6
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()) os.write(MakeByteSpan(v));
1004 } else {
1006 }
1007}
1008
1009template <typename Stream, unsigned int N, typename T>
1010void Unserialize(Stream &is, prevector<N, T> &v) {
1011 if constexpr (BasicByte<T>) {
1012 // Use optimized version for unformatted basic bytes
1013 // Limit size per read so bogus size value won't cause out of memory
1014 v.clear();
1015 size_t nSize = ReadCompactSize(is);
1016 size_t i = 0;
1017 while (i < nSize) {
1018 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1019 v.resize_uninitialized(i + blk);
1020 is.read(AsWritableBytes(Span{&v[i], blk}));
1021 i += blk;
1022 }
1023 } else {
1025 }
1026}
1027
1031template <typename Stream, typename T, typename A>
1032void Serialize(Stream &os, const std::vector<T, A> &v) {
1033 if constexpr (BasicByte<T>) {
1034 // Use optimized version for unformatted basic bytes
1035 WriteCompactSize(os, v.size());
1036 if (!v.empty()) {
1037 os.write(MakeByteSpan(v));
1038 }
1039 } else if constexpr (std::is_same_v<T, bool>) {
1040 // A special case for std::vector<bool>, as dereferencing
1041 // std::vector<bool>::const_iterator does not result in a const bool&
1042 // due to std::vector's special casing for bool arguments.
1043 WriteCompactSize(os, v.size());
1044 for (bool elem : v) {
1045 ::Serialize(os, elem);
1046 }
1047 } else {
1049 }
1050}
1051
1052template <typename Stream, typename T, typename A>
1053void Unserialize(Stream &is, std::vector<T, A> &v) {
1054 if constexpr (BasicByte<T>) {
1055 // Use optimized version for unformatted basic bytes
1056 // Limit size per read so bogus size value won't cause out of memory
1057 v.clear();
1058 size_t nSize = ReadCompactSize(is);
1059 size_t i = 0;
1060 while (i < nSize) {
1061 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
1062 v.resize(i + blk);
1063 is.read(AsWritableBytes(Span{&v[i], blk}));
1064 i += blk;
1065 }
1066 } else {
1068 }
1069}
1070
1074template <typename Stream, typename K, typename T>
1075void Serialize(Stream &os, const std::pair<K, T> &item) {
1076 Serialize(os, item.first);
1077 Serialize(os, item.second);
1078}
1079
1080template <typename Stream, typename K, typename T>
1081void Unserialize(Stream &is, std::pair<K, T> &item) {
1082 Unserialize(is, item.first);
1083 Unserialize(is, item.second);
1084}
1085
1089template <typename Stream, typename K, typename T, typename Pred, typename A>
1090void Serialize(Stream &os, const std::map<K, T, Pred, A> &m) {
1091 WriteCompactSize(os, m.size());
1092 for (const auto &entry : m) {
1093 Serialize(os, entry);
1094 }
1095}
1096
1097template <typename Stream, typename K, typename T, typename Pred, typename A>
1098void Unserialize(Stream &is, std::map<K, T, Pred, A> &m) {
1099 m.clear();
1100 size_t nSize = ReadCompactSize(is);
1101 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1102 for (size_t i = 0; i < nSize; i++) {
1103 std::pair<K, T> item;
1104 Unserialize(is, item);
1105 mi = m.insert(mi, item);
1106 }
1107}
1108
1112template <typename Stream, typename K, typename Pred, typename A>
1113void Serialize(Stream &os, const std::set<K, Pred, A> &m) {
1114 WriteCompactSize(os, m.size());
1115 for (const K &i : m) {
1116 Serialize(os, i);
1117 }
1118}
1119
1120template <typename Stream, typename K, typename Pred, typename A>
1121void Unserialize(Stream &is, std::set<K, Pred, A> &m) {
1122 m.clear();
1123 size_t nSize = ReadCompactSize(is);
1124 typename std::set<K, Pred, A>::iterator it = m.begin();
1125 for (size_t i = 0; i < nSize; i++) {
1126 K key;
1127 Unserialize(is, key);
1128 it = m.insert(it, key);
1129 }
1130}
1131
1135template <typename Stream, typename T>
1136void Serialize(Stream &os, const std::unique_ptr<const T> &p) {
1137 Serialize(os, *p);
1138}
1139
1140template <typename Stream, typename T>
1141void Unserialize(Stream &is, std::unique_ptr<const T> &p) {
1142 p.reset(new T(deserialize, is));
1143}
1144
1148template <typename Stream, typename T>
1149void Serialize(Stream &os, const std::shared_ptr<const T> &p) {
1150 Serialize(os, *p);
1151}
1152
1153template <typename Stream, typename T>
1154void Unserialize(Stream &is, std::shared_ptr<const T> &p) {
1155 p = std::make_shared<const T>(deserialize, is);
1156}
1157
1161template <typename Stream, typename T>
1162void Serialize(Stream &os, const RCUPtr<const T> &p) {
1163 Serialize(os, *p);
1164}
1165
1166template <typename Stream, typename T>
1167void Unserialize(Stream &is, RCUPtr<const T> &p) {
1169}
1170
1176 constexpr bool ForRead() const { return false; }
1177};
1179 constexpr bool ForRead() const { return true; }
1180};
1181
1195protected:
1196 size_t nSize{0};
1197
1198public:
1200
1201 void write(Span<const std::byte> src) { this->nSize += src.size(); }
1202
1204 void seek(size_t _nSize) { this->nSize += _nSize; }
1205
1206 template <typename T> SizeComputer &operator<<(const T &obj) {
1207 ::Serialize(*this, obj);
1208 return (*this);
1209 }
1210
1211 size_t size() const { return nSize; }
1212};
1213
1214template <typename Stream, typename... Args>
1215void SerializeMany(Stream &s, const Args &...args) {
1216 (::Serialize(s, args), ...);
1217}
1218
1219template <typename Stream, typename... Args>
1220inline void UnserializeMany(Stream &s, Args &&...args) {
1221 (::Unserialize(s, args), ...);
1222}
1223
1224template <typename Stream, typename... Args>
1225inline void SerReadWriteMany(Stream &s, ActionSerialize ser_action,
1226 const Args &...args) {
1227 ::SerializeMany(s, args...);
1228}
1229
1230template <typename Stream, typename... Args>
1231inline void SerReadWriteMany(Stream &s, ActionUnserialize ser_action,
1232 Args &&...args) {
1233 ::UnserializeMany(s, args...);
1234}
1235
1236template <typename Stream, typename Type, typename Fn>
1237inline void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&) {}
1238
1239template <typename Stream, typename Type, typename Fn>
1240inline void SerRead(Stream &s, ActionUnserialize ser_action, Type &&obj,
1241 Fn &&fn) {
1242 fn(s, std::forward<Type>(obj));
1243}
1244
1245template <typename Stream, typename Type, typename Fn>
1246inline void SerWrite(Stream &s, ActionSerialize ser_action, Type &&obj,
1247 Fn &&fn) {
1248 fn(s, std::forward<Type>(obj));
1249}
1250
1251template <typename Stream, typename Type, typename Fn>
1252inline void SerWrite(Stream &s, ActionUnserialize ser_action, Type &&, Fn &&) {}
1253
1254template <typename I> inline void WriteVarInt(SizeComputer &s, I n) {
1255 s.seek(GetSizeOfVarInt<I>(n));
1256}
1257
1258inline void WriteCompactSize(SizeComputer &s, uint64_t nSize) {
1259 s.seek(GetSizeOfCompactSize(nSize));
1260}
1261
1262template <typename T> size_t GetSerializeSize(const T &t) {
1263 return (SizeComputer{} << t).size();
1264}
1265
1270template <typename Params, typename SubStream> class ParamsStream {
1272 // private to avoid leaking version/type into serialization code that
1273 // shouldn't see it
1274 SubStream &m_substream;
1275
1276public:
1278 SubStream &substream LIFETIMEBOUND)
1279 : m_params{params}, m_substream{substream} {}
1280 template <typename U> ParamsStream &operator<<(const U &obj) {
1281 ::Serialize(*this, obj);
1282 return *this;
1283 }
1284 template <typename U> ParamsStream &operator>>(U &&obj) {
1285 ::Unserialize(*this, obj);
1286 return *this;
1287 }
1288 void write(Span<const std::byte> src) { m_substream.write(src); }
1289 void read(Span<std::byte> dst) { m_substream.read(dst); }
1290 void ignore(size_t num) { m_substream.ignore(num); }
1291 bool eof() const { return m_substream.eof(); }
1292 size_t size() const { return m_substream.size(); }
1293 const Params &GetParams() const { return m_params; }
1294 // Deprecated with Params usage
1295 int GetVersion() = delete;
1296 // Deprecated with Params usage
1297 int GetType() = delete;
1298};
1299
1301template <typename Params, typename T> class ParamsWrapper {
1302 static_assert(std::is_lvalue_reference<T>::value,
1303 "ParamsWrapper needs an lvalue reference type T");
1306
1307public:
1308 explicit ParamsWrapper(const Params &params, T obj)
1309 : m_params{params}, m_object{obj} {}
1310
1311 template <typename Stream> void Serialize(Stream &s) const {
1312 ParamsStream ss{m_params, s};
1313 ::Serialize(ss, m_object);
1314 }
1315 template <typename Stream> void Unserialize(Stream &s) {
1316 ParamsStream ss{m_params, s};
1318 }
1319};
1320
1328template <typename Params, typename T>
1329static auto WithParams(const Params &params, T &&t) {
1330 return ParamsWrapper<Params, T &>{params, t};
1331}
1332
1333#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:1270
const Params & m_params
Definition: serialize.h:1271
void ignore(size_t num)
Definition: serialize.h:1290
ParamsStream(const Params &params LIFETIMEBOUND, SubStream &substream LIFETIMEBOUND)
Definition: serialize.h:1277
void write(Span< const std::byte > src)
Definition: serialize.h:1288
int GetVersion()=delete
ParamsStream & operator<<(const U &obj)
Definition: serialize.h:1280
void read(Span< std::byte > dst)
Definition: serialize.h:1289
bool eof() const
Definition: serialize.h:1291
const Params & GetParams() const
Definition: serialize.h:1293
ParamsStream & operator>>(U &&obj)
Definition: serialize.h:1284
size_t size() const
Definition: serialize.h:1292
SubStream & m_substream
Definition: serialize.h:1274
int GetType()=delete
Wrapper that serializes objects with the specified parameters.
Definition: serialize.h:1301
const Params & m_params
Definition: serialize.h:1304
void Unserialize(Stream &s)
Definition: serialize.h:1315
void Serialize(Stream &s) const
Definition: serialize.h:1311
ParamsWrapper(const Params &params, T obj)
Definition: serialize.h:1308
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:1194
void write(Span< const std::byte > src)
Definition: serialize.h:1201
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1204
size_t nSize
Definition: serialize.h:1196
size_t size() const
Definition: serialize.h:1211
SizeComputer & operator<<(const T &obj)
Definition: serialize.h:1206
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:1262
void Serialize(Stream &, V)=delete
void SerRead(Stream &s, ActionSerialize ser_action, Type &&, Fn &&)
Definition: serialize.h:1237
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:1220
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:1254
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1258
void SerializeMany(Stream &s, const Args &...args)
Definition: serialize.h:1215
static auto WithParams(const Params &params, T &&t)
Return a wrapper around t that (de)serializes it with specified parameter params.
Definition: serialize.h:1329
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:1225
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:1246
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:1175
constexpr bool ForRead() const
Definition: serialize.h:1176
constexpr bool ForRead() const
Definition: serialize.h:1179
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