Bitcoin ABC 0.32.4
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
10#include <compat/endian.h>
11#include <prevector.h>
12#include <rcu.h>
13#include <span.h>
14
15#include <algorithm>
16#include <array>
17#include <concepts>
18#include <cstdint>
19#include <cstring>
20#include <ios>
21#include <limits>
22#include <map>
23#include <memory>
24#include <set>
25#include <string>
26#include <utility>
27#include <vector>
28
33static constexpr uint64_t MAX_SIZE = 0x02000000;
34
39static const unsigned int MAX_VECTOR_ALLOCATE = 5000000;
40
53
57template <typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) {
58 s.write(AsBytes(Span{&obj, 1}));
59}
60template <typename Stream>
61inline void ser_writedata16(Stream &s, uint16_t obj) {
62 obj = htole16(obj);
63 s.write(AsBytes(Span{&obj, 1}));
64}
65template <typename Stream>
66inline void ser_writedata16be(Stream &s, uint16_t obj) {
67 obj = htobe16(obj);
68 s.write(AsBytes(Span{&obj, 1}));
69}
70template <typename Stream>
71inline void ser_writedata32(Stream &s, uint32_t obj) {
72 obj = htole32(obj);
73 s.write(AsBytes(Span{&obj, 1}));
74}
75template <typename Stream>
76inline void ser_writedata32be(Stream &s, uint32_t obj) {
77 obj = htobe32(obj);
78 s.write(AsBytes(Span{&obj, 1}));
79}
80template <typename Stream>
81inline void ser_writedata64(Stream &s, uint64_t obj) {
82 obj = htole64(obj);
83 s.write(AsBytes(Span{&obj, 1}));
84}
85template <typename Stream> inline uint8_t ser_readdata8(Stream &s) {
86 uint8_t obj;
87 s.read(AsWritableBytes(Span{&obj, 1}));
88 return obj;
89}
90template <typename Stream> inline uint16_t ser_readdata16(Stream &s) {
91 uint16_t obj;
92 s.read(AsWritableBytes(Span{&obj, 1}));
93 return le16toh(obj);
94}
95template <typename Stream> inline uint16_t ser_readdata16be(Stream &s) {
96 uint16_t obj;
97 s.read(AsWritableBytes(Span{&obj, 1}));
98 return be16toh(obj);
99}
100template <typename Stream> inline uint32_t ser_readdata32(Stream &s) {
101 uint32_t obj;
102 s.read(AsWritableBytes(Span{&obj, 1}));
103 return le32toh(obj);
104}
105template <typename Stream> inline uint32_t ser_readdata32be(Stream &s) {
106 uint32_t obj;
107 s.read(AsWritableBytes(Span{&obj, 1}));
108 return be32toh(obj);
109}
110template <typename Stream> inline uint64_t ser_readdata64(Stream &s) {
111 uint64_t obj;
112 s.read(AsWritableBytes(Span{&obj, 1}));
113 return le64toh(obj);
114}
115inline uint64_t ser_double_to_uint64(double x) {
116 uint64_t tmp;
117 std::memcpy(&tmp, &x, sizeof(x));
118 static_assert(sizeof(tmp) == sizeof(x),
119 "double and uint64_t assumed to have the same size");
120 return tmp;
121}
122inline uint32_t ser_float_to_uint32(float x) {
123 uint32_t tmp;
124 std::memcpy(&tmp, &x, sizeof(x));
125 static_assert(sizeof(tmp) == sizeof(x),
126 "float and uint32_t assumed to have the same size");
127 return tmp;
128}
129inline double ser_uint64_to_double(uint64_t y) {
130 double tmp;
131 std::memcpy(&tmp, &y, sizeof(y));
132 static_assert(sizeof(tmp) == sizeof(y),
133 "double and uint64_t assumed to have the same size");
134 return tmp;
135}
136inline float ser_uint32_to_float(uint32_t y) {
137 float tmp;
138 std::memcpy(&tmp, &y, sizeof(y));
139 static_assert(sizeof(tmp) == sizeof(y),
140 "float and uint32_t assumed to have the same size");
141 return tmp;
142}
143
145//
146// Templates for serializing to anything that looks like a stream,
147// i.e. anything that supports .read(Span<std::byte>) and .write(Span<const
148// std::byte>)
149//
150class CSizeComputer;
151
152enum {
153 // primary actions
154 SER_NETWORK = (1 << 0),
155 SER_DISK = (1 << 1),
156 SER_GETHASH = (1 << 2),
157};
158
161template <typename X> X &ReadWriteAsHelper(X &x) {
162 return x;
163}
164template <typename X> const X &ReadWriteAsHelper(const X &x) {
165 return x;
166}
167
168#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
169#define READWRITEAS(type, obj) \
170 (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
171#define SER_READ(obj, code) \
172 ::SerRead( \
173 s, ser_action, obj, \
174 [&](Stream &s, typename std::remove_const<Type>::type &obj) { code; })
175#define SER_WRITE(obj, code) \
176 ::SerWrite(s, ser_action, obj, [&](Stream &s, const Type &obj) { code; })
177
196#define FORMATTER_METHODS(cls, obj) \
197 template <typename Stream> static void Ser(Stream &s, const cls &obj) { \
198 SerializationOps(obj, s, CSerActionSerialize()); \
199 } \
200 template <typename Stream> static void Unser(Stream &s, cls &obj) { \
201 SerializationOps(obj, s, CSerActionUnserialize()); \
202 } \
203 template <typename Stream, typename Type, typename Operation> \
204 static inline void SerializationOps(Type &obj, Stream &s, \
205 Operation ser_action)
206
215#define SERIALIZE_METHODS(cls, obj) \
216 template <typename Stream> void Serialize(Stream &s) const { \
217 static_assert(std::is_same<const cls &, decltype(*this)>::value, \
218 "Serialize type mismatch"); \
219 Ser(s, *this); \
220 } \
221 template <typename Stream> void Unserialize(Stream &s) { \
222 static_assert(std::is_same<cls &, decltype(*this)>::value, \
223 "Unserialize type mismatch"); \
224 Unser(s, *this); \
225 } \
226 FORMATTER_METHODS(cls, obj)
227
228// Typically int8_t and char are distinct types, but some systems may define
229// int8_t in terms of char. Forbid serialization of char in the typical case,
230// but allow it if it's the only way to describe an int8_t.
231template <class T>
232concept CharNotInt8 = std::same_as<T, char> && !std::same_as<T, int8_t>;
233
234// char serialization forbidden. Use uint8_t or int8_t
235template <typename Stream, CharNotInt8 V> void Serialize(Stream &, V) = delete;
236template <typename Stream> void Serialize(Stream &s, std::byte a) {
237 ser_writedata8(s, uint8_t(a));
238}
239template <typename Stream> inline void Serialize(Stream &s, int8_t a) {
240 ser_writedata8(s, a);
241}
242template <typename Stream> inline void Serialize(Stream &s, uint8_t a) {
243 ser_writedata8(s, a);
244}
245template <typename Stream> inline void Serialize(Stream &s, int16_t a) {
246 ser_writedata16(s, a);
247}
248template <typename Stream> inline void Serialize(Stream &s, uint16_t a) {
249 ser_writedata16(s, a);
250}
251template <typename Stream> inline void Serialize(Stream &s, int32_t a) {
252 ser_writedata32(s, a);
253}
254template <typename Stream> inline void Serialize(Stream &s, uint32_t a) {
255 ser_writedata32(s, a);
256}
257template <typename Stream> inline void Serialize(Stream &s, int64_t a) {
258 ser_writedata64(s, a);
259}
260template <typename Stream> inline void Serialize(Stream &s, uint64_t a) {
261 ser_writedata64(s, a);
262}
263template <typename Stream> inline void Serialize(Stream &s, float a) {
265}
266template <typename Stream> inline void Serialize(Stream &s, double a) {
268}
269template <typename Stream, size_t N>
270inline void Serialize(Stream &s, const int8_t (&a)[N]) {
271 s.write(a, N);
272}
273template <typename Stream, BasicByte B, size_t N>
274void Serialize(Stream &s, const B (&a)[N]) {
275 s.write(MakeByteSpan(a));
276}
277template <typename Stream, size_t N>
278inline void Serialize(Stream &s, const std::array<int8_t, N> &a) {
279 s.write(a.data(), N);
280}
281template <typename Stream, size_t N>
282inline void Serialize(Stream &s, const std::array<uint8_t, N> &a) {
283 s.write(MakeByteSpan(a));
284}
285template <typename Stream, BasicByte B, std::size_t N>
286void Serialize(Stream &s, const std::array<B, N> &a) {
287 s.write(MakeByteSpan(a));
288}
289template <typename Stream, BasicByte B>
290void Serialize(Stream &s, Span<B> span) {
291 s.write(AsBytes(span));
292}
293
294// char serialization forbidden. Use uint8_t or int8_t
295template <typename Stream, CharNotInt8 V>
296void Unserialize(Stream &, V) = delete;
297template <typename Stream> void Unserialize(Stream &s, std::byte &a) {
298 a = std::byte{ser_readdata8(s)};
299}
300template <typename Stream> inline void Unserialize(Stream &s, int8_t &a) {
301 a = ser_readdata8(s);
302}
303template <typename Stream> inline void Unserialize(Stream &s, uint8_t &a) {
304 a = ser_readdata8(s);
305}
306template <typename Stream> inline void Unserialize(Stream &s, int16_t &a) {
307 a = ser_readdata16(s);
308}
309template <typename Stream> inline void Unserialize(Stream &s, uint16_t &a) {
310 a = ser_readdata16(s);
311}
312template <typename Stream> inline void Unserialize(Stream &s, int32_t &a) {
313 a = ser_readdata32(s);
314}
315template <typename Stream> inline void Unserialize(Stream &s, uint32_t &a) {
316 a = ser_readdata32(s);
317}
318template <typename Stream> inline void Unserialize(Stream &s, int64_t &a) {
319 a = ser_readdata64(s);
320}
321template <typename Stream> inline void Unserialize(Stream &s, uint64_t &a) {
322 a = ser_readdata64(s);
323}
324template <typename Stream> inline void Unserialize(Stream &s, float &a) {
326}
327template <typename Stream> inline void Unserialize(Stream &s, double &a) {
329}
330template <typename Stream, size_t N>
331inline void Unserialize(Stream &s, int8_t (&a)[N]) {
332 s.read(MakeWritableByteSpan(a));
333}
334template <typename Stream, BasicByte B, size_t N>
335void Unserialize(Stream &s, B (&a)[N]) {
336 s.read(MakeWritableByteSpan(a));
337}
338
339template <typename Stream> inline void Serialize(Stream &s, bool a) {
340 char f = a;
341 ser_writedata8(s, f);
342}
343template <typename Stream> inline void Unserialize(Stream &s, bool &a) {
344 char f = ser_readdata8(s);
345 a = f;
346}
347template <typename Stream, BasicByte B, std::size_t N>
348void Unserialize(Stream &s, std::array<B, N> &a) {
349 s.read(MakeWritableByteSpan(a));
350}
351template <typename Stream, BasicByte B>
352void Unserialize(Stream &s, Span<B> span) {
353 s.read(AsWritableBytes(span));
354}
355
363inline uint32_t GetSizeOfCompactSize(uint64_t nSize) {
364 if (nSize < 253) {
365 return sizeof(uint8_t);
366 }
367 if (nSize <= std::numeric_limits<uint16_t>::max()) {
368 return sizeof(uint8_t) + sizeof(uint16_t);
369 }
370 if (nSize <= std::numeric_limits<uint32_t>::max()) {
371 return sizeof(uint8_t) + sizeof(uint32_t);
372 }
373
374 return sizeof(uint8_t) + sizeof(uint64_t);
375}
376
377inline void WriteCompactSize(CSizeComputer &os, uint64_t nSize);
378
379template <typename Stream> void WriteCompactSize(Stream &os, uint64_t nSize) {
380 if (nSize < 253) {
382 } else if (nSize <= std::numeric_limits<uint16_t>::max()) {
383 ser_writedata8(os, 253);
385 } else if (nSize <= std::numeric_limits<uint32_t>::max()) {
386 ser_writedata8(os, 254);
388 } else {
389 ser_writedata8(os, 255);
391 }
392 return;
393}
394
402template <typename Stream>
403uint64_t ReadCompactSize(Stream &is, bool range_check = true) {
404 uint8_t chSize = ser_readdata8(is);
405 uint64_t nSizeRet = 0;
406 if (chSize < 253) {
407 nSizeRet = chSize;
408 } else if (chSize == 253) {
409 nSizeRet = ser_readdata16(is);
410 if (nSizeRet < 253) {
411 throw std::ios_base::failure("non-canonical ReadCompactSize()");
412 }
413 } else if (chSize == 254) {
414 nSizeRet = ser_readdata32(is);
415 if (nSizeRet < 0x10000u) {
416 throw std::ios_base::failure("non-canonical ReadCompactSize()");
417 }
418 } else {
419 nSizeRet = ser_readdata64(is);
420 if (nSizeRet < 0x100000000ULL) {
421 throw std::ios_base::failure("non-canonical ReadCompactSize()");
422 }
423 }
424 if (range_check && nSizeRet > MAX_SIZE) {
425 throw std::ios_base::failure("ReadCompactSize(): size too large");
426 }
427 return nSizeRet;
428}
429
465
466template <VarIntMode Mode, typename I> struct CheckVarIntMode {
467 constexpr CheckVarIntMode() {
468 static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned<I>::value,
469 "Unsigned type required with mode DEFAULT.");
470 static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED ||
471 std::is_signed<I>::value,
472 "Signed type required with mode NONNEGATIVE_SIGNED.");
473 }
474};
475
476template <VarIntMode Mode, typename I>
477inline unsigned int GetSizeOfVarInt(I n) {
479 int nRet = 0;
480 while (true) {
481 nRet++;
482 if (n <= 0x7F) {
483 return nRet;
484 }
485 n = (n >> 7) - 1;
486 }
487}
488
489template <typename I> inline void WriteVarInt(CSizeComputer &os, I n);
490
491template <typename Stream, VarIntMode Mode, typename I>
492void WriteVarInt(Stream &os, I n) {
494 uint8_t tmp[(sizeof(n) * 8 + 6) / 7];
495 int len = 0;
496 while (true) {
497 tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);
498 if (n <= 0x7F) {
499 break;
500 }
501 n = (n >> 7) - 1;
502 len++;
503 }
504 do {
505 ser_writedata8(os, tmp[len]);
506 } while (len--);
507}
508
509template <typename Stream, VarIntMode Mode, typename I>
510I ReadVarInt(Stream &is) {
512 I n = 0;
513 while (true) {
514 uint8_t chData = ser_readdata8(is);
515 if (n > (std::numeric_limits<I>::max() >> 7)) {
516 throw std::ios_base::failure("ReadVarInt(): size too large");
517 }
518 n = (n << 7) | (chData & 0x7F);
519 if ((chData & 0x80) == 0) {
520 return n;
521 }
522 if (n == std::numeric_limits<I>::max()) {
523 throw std::ios_base::failure("ReadVarInt(): size too large");
524 }
525 n++;
526 }
527}
528
533template <typename Formatter, typename T> class Wrapper {
534 static_assert(std::is_lvalue_reference<T>::value,
535 "Wrapper needs an lvalue reference type T");
536
537protected:
539
540public:
541 explicit Wrapper(T obj) : m_object(obj) {}
542 template <typename Stream> void Serialize(Stream &s) const {
543 Formatter().Ser(s, m_object);
544 }
545 template <typename Stream> void Unserialize(Stream &s) {
546 Formatter().Unser(s, m_object);
547 }
548};
549
563template <typename Formatter, typename T>
564static inline Wrapper<Formatter, T &> Using(T &&t) {
565 return Wrapper<Formatter, T &>(t);
566}
567
568#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
569#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
570#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
571#define LIMITED_STRING(obj, n) Using<LimitedStringFormatter<n>>(obj)
572
576template <VarIntMode Mode> struct VarIntFormatter {
577 template <typename Stream, typename I> void Ser(Stream &s, I v) {
578 WriteVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s, v);
579 }
580
581 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
582 v = ReadVarInt<Stream, Mode, typename std::remove_cv<I>::type>(s);
583 }
584};
585
596template <int Bytes, bool BigEndian = false> struct CustomUintFormatter {
597 static_assert(Bytes > 0 && Bytes <= 8,
598 "CustomUintFormatter Bytes out of range");
599 static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
600
601 template <typename Stream, typename I> void Ser(Stream &s, I v) {
602 if (v < 0 || v > MAX) {
603 throw std::ios_base::failure(
604 "CustomUintFormatter value out of range");
605 }
606 if (BigEndian) {
607 uint64_t raw = htobe64(v);
608 s.write({BytePtr(&raw) + 8 - Bytes, Bytes});
609 } else {
610 uint64_t raw = htole64(v);
611 s.write({BytePtr(&raw), Bytes});
612 }
613 }
614
615 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
616 using U = typename std::conditional<std::is_enum<I>::value,
617 std::underlying_type<I>,
618 std::common_type<I>>::type::type;
619 static_assert(std::numeric_limits<U>::max() >= MAX &&
620 std::numeric_limits<U>::min() <= 0,
621 "Assigned type too small");
622 uint64_t raw = 0;
623 if (BigEndian) {
624 s.read({BytePtr(&raw) + 8 - Bytes, Bytes});
625 v = static_cast<I>(be64toh(raw));
626 } else {
627 s.read({BytePtr(&raw), Bytes});
628 v = static_cast<I>(le64toh(raw));
629 }
630 }
631};
632
633template <int Bytes>
635
637template <bool RangeCheck> struct CompactSizeFormatter {
638 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
639 uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
640 if (n < std::numeric_limits<I>::min() ||
641 n > std::numeric_limits<I>::max()) {
642 throw std::ios_base::failure("CompactSize exceeds limit of type");
643 }
644 v = n;
645 }
646
647 template <typename Stream, typename I> void Ser(Stream &s, I v) {
648 static_assert(std::is_unsigned<I>::value,
649 "CompactSize only supported for unsigned integers");
650 static_assert(std::numeric_limits<I>::max() <=
651 std::numeric_limits<uint64_t>::max(),
652 "CompactSize only supports 64-bit integers and below");
653
654 WriteCompactSize<Stream>(s, v);
655 }
656};
657
658template <typename U, bool LOSSY = false> struct ChronoFormatter {
659 template <typename Stream, typename Tp> void Unser(Stream &s, Tp &tp) {
660 U u;
661 s >> u;
662 // Lossy deserialization does not make sense, so force Wnarrowing
663 tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
664 }
665 template <typename Stream, typename Tp> void Ser(Stream &s, Tp tp) {
666 if constexpr (LOSSY) {
667 s << U(tp.time_since_epoch().count());
668 } else {
669 s << U{tp.time_since_epoch().count()};
670 }
671 }
672};
673template <typename U> using LossyChronoFormatter = ChronoFormatter<U, true>;
674
675template <size_t Limit> struct LimitedStringFormatter {
676 template <typename Stream> void Unser(Stream &s, std::string &v) {
677 size_t size = ReadCompactSize(s);
678 if (size > Limit) {
679 throw std::ios_base::failure("String length limit exceeded");
680 }
681 v.resize(size);
682 if (size != 0) {
683 s.read(MakeWritableByteSpan(v));
684 }
685 }
686
687 template <typename Stream> void Ser(Stream &s, const std::string &v) {
688 s << v;
689 }
690};
691
708template <class Formatter> struct VectorFormatter {
709 template <typename Stream, typename V> void Ser(Stream &s, const V &v) {
710 Formatter formatter;
711 WriteCompactSize(s, v.size());
712 for (const typename V::value_type &elem : v) {
713 formatter.Ser(s, elem);
714 }
715 }
716
717 template <typename Stream, typename V> void Unser(Stream &s, V &v) {
718 Formatter formatter;
719 v.clear();
720 size_t size = ReadCompactSize(s);
721 size_t allocated = 0;
722 while (allocated < size) {
723 // For DoS prevention, do not blindly allocate as much as the stream
724 // claims to contain. Instead, allocate in 5MiB batches, so that an
725 // attacker actually needs to provide X MiB of data to make us
726 // allocate X+5 Mib.
727 static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE,
728 "Vector element size too large");
729 allocated =
730 std::min(size, allocated + MAX_VECTOR_ALLOCATE /
731 sizeof(typename V::value_type));
732 v.reserve(allocated);
733 while (v.size() < allocated) {
734 v.emplace_back();
735 formatter.Unser(s, v.back());
736 }
737 }
738 };
739};
740
752 uint64_t m_shift = 0;
753
754public:
755 template <typename Stream, typename I> void Ser(Stream &s, I v) {
756 if (v < m_shift || v >= std::numeric_limits<uint64_t>::max()) {
757 throw std::ios_base::failure("differential value overflow");
758 }
760 m_shift = uint64_t(v) + 1;
761 }
762 template <typename Stream, typename I> void Unser(Stream &s, I &v) {
763 uint64_t n = ReadCompactSize(s);
764 m_shift += n;
765 if (m_shift < n || m_shift >= std::numeric_limits<uint64_t>::max() ||
766 m_shift < std::numeric_limits<I>::min() ||
767 m_shift > std::numeric_limits<I>::max()) {
768 throw std::ios_base::failure("differential value overflow");
769 }
770 v = I(m_shift++);
771 }
772};
773
785 template <typename Stream, typename T> void Ser(Stream &s, T v) {
786 DifferenceFormatter::Ser(s, v.index);
787 v.SerData(s);
788 }
789
790 template <typename Stream, typename T> void Unser(Stream &s, T &v) {
791 DifferenceFormatter::Unser(s, v.index);
792 v.UnserData(s);
793 }
794};
795
803template <typename Stream, typename C>
804void Serialize(Stream &os, const std::basic_string<C> &str);
805template <typename Stream, typename C>
806void Unserialize(Stream &is, std::basic_string<C> &str);
807
811template <typename Stream, unsigned int N, typename T>
812inline void Serialize(Stream &os, const prevector<N, T> &v);
813template <typename Stream, unsigned int N, typename T>
814inline void Unserialize(Stream &is, prevector<N, T> &v);
815
819template <typename Stream, typename T, typename A>
820inline void Serialize(Stream &os, const std::vector<T, A> &v);
821template <typename Stream, typename T, typename A>
822inline void Unserialize(Stream &is, std::vector<T, A> &v);
823
827template <typename Stream, typename K, typename T>
828void Serialize(Stream &os, const std::pair<K, T> &item);
829template <typename Stream, typename K, typename T>
830void Unserialize(Stream &is, std::pair<K, T> &item);
831
835template <typename Stream, typename K, typename T, typename Pred, typename A>
836void Serialize(Stream &os, const std::map<K, T, Pred, A> &m);
837template <typename Stream, typename K, typename T, typename Pred, typename A>
838void Unserialize(Stream &is, std::map<K, T, Pred, A> &m);
839
843template <typename Stream, typename K, typename Pred, typename A>
844void Serialize(Stream &os, const std::set<K, Pred, A> &m);
845template <typename Stream, typename K, typename Pred, typename A>
846void Unserialize(Stream &is, std::set<K, Pred, A> &m);
847
851template <typename Stream, typename T>
852void Serialize(Stream &os, const std::shared_ptr<const T> &p);
853template <typename Stream, typename T>
854void Unserialize(Stream &os, std::shared_ptr<const T> &p);
855
859template <typename Stream, typename T>
860void Serialize(Stream &os, const std::unique_ptr<const T> &p);
861template <typename Stream, typename T>
862void Unserialize(Stream &os, std::unique_ptr<const T> &p);
863
867template <typename Stream, typename T>
868void Serialize(Stream &os, const RCUPtr<const T> &p);
869template <typename Stream, typename T>
870void Unserialize(Stream &os, RCUPtr<const T> &p);
871
876template <class T, class Stream>
877concept Serializable = requires(T a, Stream s) { a.Serialize(s); };
878template <typename Stream, typename T>
880void Serialize(Stream &os, const T &a) {
881 a.Serialize(os);
882}
883
884template <class T, class Stream>
885concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };
886template <typename Stream, typename T>
888void Unserialize(Stream &is, T &&a) {
889 a.Unserialize(is);
890}
891
899 template <typename Stream, typename T>
900 static void Ser(Stream &s, const T &t) {
901 Serialize(s, t);
902 }
903
904 template <typename Stream, typename T> static void Unser(Stream &s, T &t) {
905 Unserialize(s, t);
906 }
907};
908
912template <typename Stream, typename C>
913void Serialize(Stream &os, const std::basic_string<C> &str) {
914 WriteCompactSize(os, str.size());
915 if (!str.empty()) {
916 os.write(MakeByteSpan(str));
917 }
918}
919
920template <typename Stream, typename C>
921void Unserialize(Stream &is, std::basic_string<C> &str) {
922 size_t nSize = ReadCompactSize(is);
923 str.resize(nSize);
924 if (nSize != 0) {
925 is.read(MakeWritableByteSpan(str));
926 }
927}
928
932template <typename Stream, unsigned int N, typename T>
933void Serialize(Stream &os, const prevector<N, T> &v) {
934 if constexpr (BasicByte<T>) {
935 // Use optimized version for unformatted basic bytes
936 WriteCompactSize(os, v.size());
937 if (!v.empty()) os.write(MakeByteSpan(v));
938 } else {
940 }
941}
942
943template <typename Stream, unsigned int N, typename T>
944void Unserialize(Stream &is, prevector<N, T> &v) {
945 if constexpr (BasicByte<T>) {
946 // Use optimized version for unformatted basic bytes
947 // Limit size per read so bogus size value won't cause out of memory
948 v.clear();
949 size_t nSize = ReadCompactSize(is);
950 size_t i = 0;
951 while (i < nSize) {
952 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
953 v.resize_uninitialized(i + blk);
954 is.read(AsWritableBytes(Span{&v[i], blk}));
955 i += blk;
956 }
957 } else {
959 }
960}
961
965template <typename Stream, typename T, typename A>
966void Serialize(Stream &os, const std::vector<T, A> &v) {
967 if constexpr (BasicByte<T>) {
968 // Use optimized version for unformatted basic bytes
969 WriteCompactSize(os, v.size());
970 if (!v.empty()) {
971 os.write(MakeByteSpan(v));
972 }
973 } else if constexpr (std::is_same_v<T, bool>) {
974 // A special case for std::vector<bool>, as dereferencing
975 // std::vector<bool>::const_iterator does not result in a const bool&
976 // due to std::vector's special casing for bool arguments.
977 WriteCompactSize(os, v.size());
978 for (bool elem : v) {
979 ::Serialize(os, elem);
980 }
981 } else {
983 }
984}
985
986template <typename Stream, typename T, typename A>
987void Unserialize(Stream &is, std::vector<T, A> &v) {
988 if constexpr (BasicByte<T>) {
989 // Use optimized version for unformatted basic bytes
990 // Limit size per read so bogus size value won't cause out of memory
991 v.clear();
992 size_t nSize = ReadCompactSize(is);
993 size_t i = 0;
994 while (i < nSize) {
995 size_t blk = std::min(nSize - i, size_t(1 + 4999999 / sizeof(T)));
996 v.resize(i + blk);
997 is.read(AsWritableBytes(Span{&v[i], blk}));
998 i += blk;
999 }
1000 } else {
1002 }
1003}
1004
1008template <typename Stream, typename K, typename T>
1009void Serialize(Stream &os, const std::pair<K, T> &item) {
1010 Serialize(os, item.first);
1011 Serialize(os, item.second);
1012}
1013
1014template <typename Stream, typename K, typename T>
1015void Unserialize(Stream &is, std::pair<K, T> &item) {
1016 Unserialize(is, item.first);
1017 Unserialize(is, item.second);
1018}
1019
1023template <typename Stream, typename K, typename T, typename Pred, typename A>
1024void Serialize(Stream &os, const std::map<K, T, Pred, A> &m) {
1025 WriteCompactSize(os, m.size());
1026 for (const auto &entry : m) {
1027 Serialize(os, entry);
1028 }
1029}
1030
1031template <typename Stream, typename K, typename T, typename Pred, typename A>
1032void Unserialize(Stream &is, std::map<K, T, Pred, A> &m) {
1033 m.clear();
1034 size_t nSize = ReadCompactSize(is);
1035 typename std::map<K, T, Pred, A>::iterator mi = m.begin();
1036 for (size_t i = 0; i < nSize; i++) {
1037 std::pair<K, T> item;
1038 Unserialize(is, item);
1039 mi = m.insert(mi, item);
1040 }
1041}
1042
1046template <typename Stream, typename K, typename Pred, typename A>
1047void Serialize(Stream &os, const std::set<K, Pred, A> &m) {
1048 WriteCompactSize(os, m.size());
1049 for (const K &i : m) {
1050 Serialize(os, i);
1051 }
1052}
1053
1054template <typename Stream, typename K, typename Pred, typename A>
1055void Unserialize(Stream &is, std::set<K, Pred, A> &m) {
1056 m.clear();
1057 size_t nSize = ReadCompactSize(is);
1058 typename std::set<K, Pred, A>::iterator it = m.begin();
1059 for (size_t i = 0; i < nSize; i++) {
1060 K key;
1061 Unserialize(is, key);
1062 it = m.insert(it, key);
1063 }
1064}
1065
1069template <typename Stream, typename T>
1070void Serialize(Stream &os, const std::unique_ptr<const T> &p) {
1071 Serialize(os, *p);
1072}
1073
1074template <typename Stream, typename T>
1075void Unserialize(Stream &is, std::unique_ptr<const T> &p) {
1076 p.reset(new T(deserialize, is));
1077}
1078
1082template <typename Stream, typename T>
1083void Serialize(Stream &os, const std::shared_ptr<const T> &p) {
1084 Serialize(os, *p);
1085}
1086
1087template <typename Stream, typename T>
1088void Unserialize(Stream &is, std::shared_ptr<const T> &p) {
1089 p = std::make_shared<const T>(deserialize, is);
1090}
1091
1095template <typename Stream, typename T>
1096void Serialize(Stream &os, const RCUPtr<const T> &p) {
1097 Serialize(os, *p);
1098}
1099
1100template <typename Stream, typename T>
1101void Unserialize(Stream &is, RCUPtr<const T> &p) {
1103}
1104
1109 constexpr bool ForRead() const { return false; }
1110};
1112 constexpr bool ForRead() const { return true; }
1113};
1114
1128protected:
1129 size_t nSize;
1130
1131 const int nVersion;
1132
1133public:
1134 explicit CSizeComputer(int nVersionIn) : nSize(0), nVersion(nVersionIn) {}
1135
1136 void write(Span<const std::byte> src) { this->nSize += src.size(); }
1137
1139 void seek(size_t _nSize) { this->nSize += _nSize; }
1140
1141 template <typename T> CSizeComputer &operator<<(const T &obj) {
1142 ::Serialize(*this, obj);
1143 return (*this);
1144 }
1145
1146 size_t size() const { return nSize; }
1147
1148 int GetVersion() const { return nVersion; }
1149};
1150
1151template <typename Stream> void SerializeMany(Stream &s) {}
1152
1153template <typename Stream, typename Arg, typename... Args>
1154void SerializeMany(Stream &s, const Arg &arg, const Args &...args) {
1155 ::Serialize(s, arg);
1156 ::SerializeMany(s, args...);
1157}
1158
1159template <typename Stream> inline void UnserializeMany(Stream &s) {}
1160
1161template <typename Stream, typename Arg, typename... Args>
1162inline void UnserializeMany(Stream &s, Arg &&arg, Args &&...args) {
1163 ::Unserialize(s, arg);
1164 ::UnserializeMany(s, args...);
1165}
1166
1167template <typename Stream, typename... Args>
1168inline void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action,
1169 const Args &...args) {
1170 ::SerializeMany(s, args...);
1171}
1172
1173template <typename Stream, typename... Args>
1174inline void SerReadWriteMany(Stream &s, CSerActionUnserialize ser_action,
1175 Args &&...args) {
1176 ::UnserializeMany(s, args...);
1177}
1178
1179template <typename Stream, typename Type, typename Fn>
1180inline void SerRead(Stream &s, CSerActionSerialize ser_action, Type &&, Fn &&) {
1181}
1182
1183template <typename Stream, typename Type, typename Fn>
1184inline void SerRead(Stream &s, CSerActionUnserialize ser_action, Type &&obj,
1185 Fn &&fn) {
1186 fn(s, std::forward<Type>(obj));
1187}
1188
1189template <typename Stream, typename Type, typename Fn>
1190inline void SerWrite(Stream &s, CSerActionSerialize ser_action, Type &&obj,
1191 Fn &&fn) {
1192 fn(s, std::forward<Type>(obj));
1193}
1194
1195template <typename Stream, typename Type, typename Fn>
1196inline void SerWrite(Stream &s, CSerActionUnserialize ser_action, Type &&,
1197 Fn &&) {}
1198
1199template <typename I> inline void WriteVarInt(CSizeComputer &s, I n) {
1200 s.seek(GetSizeOfVarInt<I>(n));
1201}
1202
1203inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) {
1204 s.seek(GetSizeOfCompactSize(nSize));
1205}
1206
1207template <typename T> size_t GetSerializeSize(const T &t, int nVersion = 0) {
1208 return (CSizeComputer(nVersion) << t).size();
1209}
1210
1211template <typename... T>
1212size_t GetSerializeSizeMany(int nVersion, const T &...t) {
1213 CSizeComputer sc(nVersion);
1214 SerializeMany(sc, t...);
1215 return sc.size();
1216}
1217
1218#endif // BITCOIN_SERIALIZE_H
GetSerializeSize implementations
Definition: serialize.h:1127
CSizeComputer & operator<<(const T &obj)
Definition: serialize.h:1141
void write(Span< const std::byte > src)
Definition: serialize.h:1136
CSizeComputer(int nVersionIn)
Definition: serialize.h:1134
size_t nSize
Definition: serialize.h:1129
size_t size() const
Definition: serialize.h:1146
const int nVersion
Definition: serialize.h:1131
void seek(size_t _nSize)
Pretend _nSize bytes are written, without specifying them.
Definition: serialize.h:1139
int GetVersion() const
Definition: serialize.h:1148
Helper for differentially encoded Compact Size integers in lists.
Definition: serialize.h:751
void Unser(Stream &s, I &v)
Definition: serialize.h:762
void Ser(Stream &s, I v)
Definition: serialize.h:755
Definition: rcu.h:85
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
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:533
Wrapper(T obj)
Definition: serialize.h:541
T m_object
Definition: serialize.h:538
void Serialize(Stream &s) const
Definition: serialize.h:542
void Unserialize(Stream &s)
Definition: serialize.h:545
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:398
void clear()
Definition: prevector.h:451
size_type size() const
Definition: prevector.h:396
void resize_uninitialized(size_type new_size)
Definition: prevector.h:492
If none of the specialized versions above matched, default to calling member function.
Definition: serialize.h:877
uint16_t be16toh(uint16_t big_endian_16bits)
Definition: endian.h:156
uint16_t htobe16(uint16_t host_16bits)
Definition: endian.h:144
uint32_t le32toh(uint32_t little_endian_32bits)
Definition: endian.h:186
uint32_t htobe32(uint32_t host_32bits)
Definition: endian.h:168
uint16_t le16toh(uint16_t little_endian_16bits)
Definition: endian.h:162
uint64_t htobe64(uint64_t host_64bits)
Definition: endian.h:192
uint64_t be64toh(uint64_t big_endian_64bits)
Definition: endian.h:204
uint32_t be32toh(uint32_t big_endian_32bits)
Definition: endian.h:180
uint64_t htole64(uint64_t host_64bits)
Definition: endian.h:198
uint32_t htole32(uint32_t host_32bits)
Definition: endian.h:174
uint16_t htole16(uint16_t host_16bits)
Definition: endian.h:150
uint64_t le64toh(uint64_t little_endian_64bits)
Definition: endian.h:210
void Serialize(Stream &, V)=delete
void SerializeMany(Stream &s)
Definition: serialize.h:1151
static const unsigned int MAX_VECTOR_ALLOCATE
Maximum amount of memory (in bytes) to allocate at once when deserializing vectors.
Definition: serialize.h:39
uint8_t ser_readdata8(Stream &s)
Definition: serialize.h:85
float ser_uint32_to_float(uint32_t y)
Definition: serialize.h:136
I ReadVarInt(Stream &is)
Definition: serialize.h:510
void ser_writedata32be(Stream &s, uint32_t obj)
Definition: serialize.h:76
void WriteVarInt(CSizeComputer &os, I n)
Definition: serialize.h:1199
VarIntMode
Variable-length integers: bytes are a MSB base-128 encoding of the number.
Definition: serialize.h:464
@ NONNEGATIVE_SIGNED
void ser_writedata32(Stream &s, uint32_t obj)
Definition: serialize.h:71
size_t GetSerializeSizeMany(int nVersion, const T &...t)
Definition: serialize.h:1212
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:363
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:33
constexpr deserialize_type deserialize
Definition: serialize.h:52
void ser_writedata16(Stream &s, uint16_t obj)
Definition: serialize.h:61
uint32_t ser_float_to_uint32(float x)
Definition: serialize.h:122
@ SER_DISK
Definition: serialize.h:155
@ SER_NETWORK
Definition: serialize.h:154
@ SER_GETHASH
Definition: serialize.h:156
void Unserialize(Stream &, V)=delete
X & ReadWriteAsHelper(X &x)
Convert the reference base type to X, without changing constness or reference type.
Definition: serialize.h:161
void SerReadWriteMany(Stream &s, CSerActionSerialize ser_action, const Args &...args)
Definition: serialize.h:1168
void SerWrite(Stream &s, CSerActionSerialize ser_action, Type &&obj, Fn &&fn)
Definition: serialize.h:1190
void ser_writedata16be(Stream &s, uint16_t obj)
Definition: serialize.h:66
uint16_t ser_readdata16(Stream &s)
Definition: serialize.h:90
uint64_t ser_readdata64(Stream &s)
Definition: serialize.h:110
double ser_uint64_to_double(uint64_t y)
Definition: serialize.h:129
void ser_writedata8(Stream &s, uint8_t obj)
Lowest-level serialization and conversion.
Definition: serialize.h:57
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:403
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
Definition: serialize.h:564
unsigned int GetSizeOfVarInt(I n)
Definition: serialize.h:477
uint32_t ser_readdata32(Stream &s)
Definition: serialize.h:100
uint16_t ser_readdata16be(Stream &s)
Definition: serialize.h:95
void SerRead(Stream &s, CSerActionSerialize ser_action, Type &&, Fn &&)
Definition: serialize.h:1180
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition: serialize.h:1207
void UnserializeMany(Stream &s)
Definition: serialize.h:1159
uint64_t ser_double_to_uint64(double x)
Definition: serialize.h:115
void ser_writedata64(Stream &s, uint64_t obj)
Definition: serialize.h:81
uint32_t ser_readdata32be(Stream &s)
Definition: serialize.h:105
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition: serialize.h:1203
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 SERIALIZE_METHODS and READWRITE macro.
Definition: serialize.h:1108
constexpr bool ForRead() const
Definition: serialize.h:1109
constexpr bool ForRead() const
Definition: serialize.h:1112
constexpr CheckVarIntMode()
Definition: serialize.h:467
void Unser(Stream &s, Tp &tp)
Definition: serialize.h:659
void Ser(Stream &s, Tp tp)
Definition: serialize.h:665
Formatter for integers in CompactSize format.
Definition: serialize.h:637
void Unser(Stream &s, I &v)
Definition: serialize.h:638
void Ser(Stream &s, I v)
Definition: serialize.h:647
Serialization wrapper class for custom integers and enums.
Definition: serialize.h:596
static constexpr uint64_t MAX
Definition: serialize.h:599
void Ser(Stream &s, I v)
Definition: serialize.h:601
void Unser(Stream &s, I &v)
Definition: serialize.h:615
Default formatter.
Definition: serialize.h:898
static void Ser(Stream &s, const T &t)
Definition: serialize.h:900
static void Unser(Stream &s, T &t)
Definition: serialize.h:904
Helper for a list of items containing a differentially encoded index as their first member.
Definition: serialize.h:784
void Unser(Stream &s, T &v)
Definition: serialize.h:790
void Ser(Stream &s, T v)
Definition: serialize.h:785
void Unser(Stream &s, std::string &v)
Definition: serialize.h:676
void Ser(Stream &s, const std::string &v)
Definition: serialize.h:687
Serialization wrapper class for integers in VarInt format.
Definition: serialize.h:576
void Ser(Stream &s, I v)
Definition: serialize.h:577
void Unser(Stream &s, I &v)
Definition: serialize.h:581
Formatter to serialize/deserialize vector elements using another formatter.
Definition: serialize.h:708
void Unser(Stream &s, V &v)
Definition: serialize.h:717
void Ser(Stream &s, const V &v)
Definition: serialize.h:709
Dummy data type to identify deserializing constructors.
Definition: serialize.h:51