Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251template <typename Stream> void Serialize(Stream& s, int16_t a) { ser_writedata16(s, uint16_t(a)); }252template <typename Stream> void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }253template <typename Stream> void Serialize(Stream& s, int32_t a) { ser_writedata32(s, uint32_t(a)); }254template <typename Stream> void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }255template <typename Stream> void Serialize(Stream& s, int64_t a) { ser_writedata64(s, uint64_t(a)); }256template <typename Stream> void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }258template <typename Stream, BasicByte B, size_t N> void Serialize(Stream& s, const B (&a)[N]) { s.write(MakeByteSpan(a)); }259template <typename Stream, BasicByte B, size_t N> void Serialize(Stream& s, const std::array<B, N>& a) { s.write(MakeByteSpan(a)); }260template <typename Stream, BasicByte B, size_t N> void Serialize(Stream& s, std::span<B, N> span) { s.write(std::as_bytes(span)); }261template <typename Stream, BasicByte B> void Serialize(Stream& s, std::span<B> span) { s.write(std::as_bytes(span)); }263template <typename Stream, CharNotInt8 V> void Unserialize(Stream&, V) = delete; // char serialization forbidden. Use uint8_t or int8_t264template <typename Stream> void Unserialize(Stream& s, std::byte& a) { a = std::byte(ser_readdata8(s)); }265template <typename Stream> void Unserialize(Stream& s, int8_t& a) { a = int8_t(ser_readdata8(s)); }266template <typename Stream> void Unserialize(Stream& s, uint8_t& a) { a = ser_readdata8(s); }267template <typename Stream> void Unserialize(Stream& s, int16_t& a) { a = int16_t(ser_readdata16(s)); }268template <typename Stream> void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }269template <typename Stream> void Unserialize(Stream& s, int32_t& a) { a = int32_t(ser_readdata32(s)); }270template <typename Stream> void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }271template <typename Stream> void Unserialize(Stream& s, int64_t& a) { a = int64_t(ser_readdata64(s)); }272template <typename Stream> void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }274template <typename Stream, BasicByte B, size_t N> void Unserialize(Stream& s, B (&a)[N]) { s.read(MakeWritableByteSpan(a)); }275template <typename Stream, BasicByte B, size_t N> void Unserialize(Stream& s, std::array<B, N>& a) { s.read(MakeWritableByteSpan(a)); }276template <typename Stream, BasicByte B, size_t N> void Unserialize(Stream& s, std::span<B, N> span) { s.read(std::as_writable_bytes(span)); }277template <typename Stream, BasicByte B> void Unserialize(Stream& s, std::span<B> span) { s.read(std::as_writable_bytes(span)); }279template <typename Stream> void Serialize(Stream& s, bool a) { uint8_t f = a; ser_writedata8(s, f); }280template <typename Stream> void Unserialize(Stream& s, bool& a) { uint8_t f = ser_readdata8(s); a = f; }281// clang-format on284/**285* Compact Size286* size < 253 -- 1 byte287* size <= USHRT_MAX -- 3 bytes (253 + 2 bytes)288* size <= UINT_MAX -- 5 bytes (254 + 4 bytes)289* size > UINT_MAX -- 9 bytes (255 + 8 bytes)290*/291constexpr inline unsigned int GetSizeOfCompactSize(uint64_t nSize)292{293if (nSize < 253) return sizeof(unsigned char);294else if (nSize <= std::numeric_limits<uint16_t>::max()) return sizeof(unsigned char) + sizeof(uint16_t);295else if (nSize <= std::numeric_limits<unsigned int>::max()) return sizeof(unsigned char) + sizeof(unsigned int);296else return sizeof(unsigned char) + sizeof(uint64_t);297}299inline void WriteCompactSize(SizeComputer& os, uint64_t nSize);301template<typename Stream>302void WriteCompactSize(Stream& os, uint64_t nSize)303{304if (nSize < 253)305{306ser_writedata8(os, nSize);307}308else if (nSize <= std::numeric_limits<uint16_t>::max())309{310ser_writedata8(os, 253);311ser_writedata16(os, nSize);312}313else if (nSize <= std::numeric_limits<unsigned int>::max())314{315ser_writedata8(os, 254);316ser_writedata32(os, nSize);317}318else319{320ser_writedata8(os, 255);321ser_writedata64(os, nSize);322}323return;324}326/**327* Decode a CompactSize-encoded variable-length integer.328*329* As these are primarily used to encode the size of vector-like serializations, by default a range330* check is performed. When used as a generic number encoding, range_check should be set to false.331*/332template<typename Stream>333uint64_t ReadCompactSize(Stream& is, bool range_check = true)334{335uint8_t chSize = ser_readdata8(is);336uint64_t nSizeRet = 0;337if (chSize < 253)338{339nSizeRet = chSize;340}341else if (chSize == 253)342{343nSizeRet = ser_readdata16(is);344if (nSizeRet < 253)345throw std::ios_base::failure("non-canonical ReadCompactSize()");346}347else if (chSize == 254)348{349nSizeRet = ser_readdata32(is);350if (nSizeRet < 0x10000u)351throw std::ios_base::failure("non-canonical ReadCompactSize()");352}353else354{355nSizeRet = ser_readdata64(is);356if (nSizeRet < 0x100000000ULL)357throw std::ios_base::failure("non-canonical ReadCompactSize()");358}359if (range_check && nSizeRet > MAX_SIZE) {360throw std::ios_base::failure("ReadCompactSize(): size too large");361}362return nSizeRet;363}365/**366* Variable-length integers: bytes are a MSB base-128 encoding of the number.367* The high bit in each byte signifies whether another digit follows. To make368* sure the encoding is one-to-one, one is subtracted from all but the last digit.369* Thus, the byte sequence a[] with length len, where all but the last byte370* has bit 128 set, encodes the number:371*372* (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1))373*374* Properties:375* * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes)376* * Every integer has exactly one encoding377* * Encoding does not depend on size of original integer type378* * No redundancy: every (infinite) byte sequence corresponds to a list379* of encoded integers.380*381* 0: [0x00] 256: [0x81 0x00]382* 1: [0x01] 16383: [0xFE 0x7F]383* 127: [0x7F] 16384: [0xFF 0x00]384* 128: [0x80 0x00] 16511: [0xFF 0x7F]385* 255: [0x80 0x7F] 65535: [0x82 0xFE 0x7F]386* 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]387*/389/**390* Mode for encoding VarInts.391*392* Currently there is no support for signed encodings. The default mode will not393* compile with signed values, and the legacy "nonnegative signed" mode will394* accept signed values, but improperly encode and decode them if they are395* negative. In the future, the DEFAULT mode could be extended to support396* negative numbers in a backwards compatible way, and additional modes could be397* added to support different varint formats (e.g. zigzag encoding).398*/399enum class VarIntMode { DEFAULT, NONNEGATIVE_SIGNED };401template <VarIntMode Mode, typename I>402struct CheckVarIntMode {403constexpr CheckVarIntMode()404{405static_assert(Mode != VarIntMode::DEFAULT || std::is_unsigned_v<I>, "Unsigned type required with mode DEFAULT.");406static_assert(Mode != VarIntMode::NONNEGATIVE_SIGNED || std::is_signed_v<I>, "Signed type required with mode NONNEGATIVE_SIGNED.");407}408};410template<VarIntMode Mode, typename I>411inline unsigned int GetSizeOfVarInt(I n)412{413CheckVarIntMode<Mode, I>();414int nRet = 0;415while(true) {416nRet++;417if (n <= 0x7F)418break;419n = (n >> 7) - 1;420}421return nRet;422}424template<typename I>425inline void WriteVarInt(SizeComputer& os, I n);427template<typename Stream, VarIntMode Mode, typename I>428void WriteVarInt(Stream& os, I n)429{430CheckVarIntMode<Mode, I>();431unsigned char tmp[CeilDiv(sizeof(n) * 8, 7u)];432int len=0;433while(true) {434tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00);435if (n <= 0x7F)436break;437n = (n >> 7) - 1;438len++;439}440do {441ser_writedata8(os, tmp[len]);442} while(len--);443}445template<typename Stream, VarIntMode Mode, typename I>446I ReadVarInt(Stream& is)447{448CheckVarIntMode<Mode, I>();449I n = 0;450while(true) {451unsigned char chData = ser_readdata8(is);452if (n > (std::numeric_limits<I>::max() >> 7)) {453throw std::ios_base::failure("ReadVarInt(): size too large");454}455n = (n << 7) | (chData & 0x7F);456if (chData & 0x80) {457if (n == std::numeric_limits<I>::max()) {458throw std::ios_base::failure("ReadVarInt(): size too large");459}460n++;461} else {462return n;463}464}465}467/** Simple wrapper class to serialize objects using a formatter; used by Using(). */468template<typename Formatter, typename T>469class Wrapper470{471static_assert(std::is_lvalue_reference_v<T>, "Wrapper needs an lvalue reference type T");472protected:473T m_object;474public:475explicit Wrapper(T obj) : m_object(obj) {}476template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }477template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }478};480/** Cause serialization/deserialization of an object to be done using a specified formatter class.481*482* To use this, you need a class Formatter that has public functions Ser(stream, const object&) for483* serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside484* READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).485*486* This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is487* const during serialization, and non-const during deserialization, which maintains const488* correctness.489*/490template<typename Formatter, typename T>491static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }493#define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)494#define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)495#define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)496#define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)497#define LIMITED_VECTOR(obj,n) Using<LimitedVectorFormatter<n>>(obj)499/** Serialization wrapper class for integers in VarInt format. */500template<VarIntMode Mode>