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.
752/**753* unique_ptr754*/755template<typename Stream, typename T> void Serialize(Stream& os, const std::unique_ptr<const T>& p);756template<typename Stream, typename T> void Unserialize(Stream& os, std::unique_ptr<const T>& p);759/**760* If none of the specialized versions above matched, default to calling member function.761*/762template <class T, class Stream>763concept Serializable = requires(T a, Stream s) { a.Serialize(s); };764template <typename Stream, typename T>765requires Serializable<T, Stream>766void Serialize(Stream& os, const T& a)767{768a.Serialize(os);769}771template <class T, class Stream>772concept Unserializable = requires(T a, Stream s) { a.Unserialize(s); };773template <typename Stream, typename T>774requires Unserializable<T, Stream>775void Unserialize(Stream& is, T&& a)776{777a.Unserialize(is);778}780/** Default formatter. Serializes objects as themselves.781*782* The vector/prevector serialization code passes this to VectorFormatter783* to enable reusing that logic. It shouldn't be needed elsewhere.784*/785struct DefaultFormatter786{787template<typename Stream, typename T>788static void Ser(Stream& s, const T& t) { Serialize(s, t); }790template<typename Stream, typename T>791static void Unser(Stream& s, T& t) { Unserialize(s, t); }792};794/**795* Limited vector formatter. Throws an error if a vector is oversized.796*/798template<size_t Limit, class Formatter = DefaultFormatter>799struct LimitedVectorFormatter800{801template<typename Stream, typename V>802void Unser(Stream& s, V& v)803{804Formatter formatter;805v.clear();806size_t size = ReadCompactSize(s);807if (size > Limit) {808throw std::ios_base::failure("Vector length limit exceeded");809}810v.reserve(size);811for (size_t i = 0; i < size; ++i) {812v.emplace_back();813formatter.Unser(s, v.back());814}815}817template<typename Stream, typename V>818void Ser(Stream& s, const V& v)819{820VectorFormatter<Formatter>{}.Ser(s, v);821}822};827/**828* string829*/830template<typename Stream, typename C>831void Serialize(Stream& os, const std::basic_string<C>& str)832{833WriteCompactSize(os, str.size());834if (!str.empty())835os.write(MakeByteSpan(str));836}838template<typename Stream, typename C>839void Unserialize(Stream& is, std::basic_string<C>& str)840{841unsigned int nSize = ReadCompactSize(is);842str.resize(nSize);843if (nSize != 0)844is.read(MakeWritableByteSpan(str));845}847/**848* string_view849*/850template<typename Stream, typename C>851void Serialize(Stream& os, const std::basic_string_view<C>& str)852{853WriteCompactSize(os, str.size());854if (!str.empty()) {855os.write(MakeByteSpan(str));856}857}859/**860* prevector861*/862template <typename Stream, unsigned int N, typename T>863void Serialize(Stream& os, const prevector<N, T>& v)864{865if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes866WriteCompactSize(os, v.size());867if (!v.empty()) os.write(MakeByteSpan(v));868} else {869Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));870}871}874template <typename Stream, unsigned int N, typename T>875void Unserialize(Stream& is, prevector<N, T>& v)876{877if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes878// Limit size per read so bogus size value won't cause out of memory879v.clear();880unsigned int nSize = ReadCompactSize(is);881unsigned int i = 0;882while (i < nSize) {883unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));884v.resize_uninitialized(i + blk);885is.read(std::as_writable_bytes(std::span{&v[i], blk}));886i += blk;887}888} else {889Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));890}891}894/**895* vector896*/897template <typename Stream, typename T, typename A>898void Serialize(Stream& os, const std::vector<T, A>& v)899{900if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes901WriteCompactSize(os, v.size());902if (!v.empty()) os.write(MakeByteSpan(v));903} else if constexpr (std::is_same_v<T, bool>) {904// A special case for std::vector<bool>, as dereferencing905// std::vector<bool>::const_iterator does not result in a const bool&906// due to std::vector's special casing for bool arguments.907WriteCompactSize(os, v.size());908for (bool elem : v) {909::Serialize(os, elem);910}911} else {912Serialize(os, Using<VectorFormatter<DefaultFormatter>>(v));913}914}917template <typename Stream, typename T, typename A>918void Unserialize(Stream& is, std::vector<T, A>& v)919{920if constexpr (BasicByte<T>) { // Use optimized version for unformatted basic bytes921// Limit size per read so bogus size value won't cause out of memory922v.clear();923unsigned int nSize = ReadCompactSize(is);924unsigned int i = 0;925while (i < nSize) {926unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));927v.resize(i + blk);928is.read(std::as_writable_bytes(std::span{&v[i], blk}));929i += blk;930}931} else {932Unserialize(is, Using<VectorFormatter<DefaultFormatter>>(v));933}934}937/**938* pair939*/940template<typename Stream, typename K, typename T>941void Serialize(Stream& os, const std::pair<K, T>& item)942{943Serialize(os, item.first);944Serialize(os, item.second);945}947template<typename Stream, typename K, typename T>948void Unserialize(Stream& is, std::pair<K, T>& item)949{950Unserialize(is, item.first);951Unserialize(is, item.second);952}956/**957* map958*/959template<typename Stream, typename K, typename T, typename Pred, typename A>960void Serialize(Stream& os, const std::map<K, T, Pred, A>& m)961{962WriteCompactSize(os, m.size());963for (const auto& entry : m)964Serialize(os, entry);965}967template<typename Stream, typename K, typename T, typename Pred, typename A>968void Unserialize(Stream& is, std::map<K, T, Pred, A>& m)969{970m.clear();971unsigned int nSize = ReadCompactSize(is);972typename std::map<K, T, Pred, A>::iterator mi = m.begin();973for (unsigned int i = 0; i < nSize; i++)974{975std::pair<K, T> item;976Unserialize(is, item);977mi = m.insert(mi, item);978}979}983/**984* set985*/986template<typename Stream, typename K, typename Pred, typename A>987void Serialize(Stream& os, const std::set<K, Pred, A>& m)988{989WriteCompactSize(os, m.size());990for (typename std::set<K, Pred, A>::const_iterator it = m.begin(); it != m.end(); ++it)991Serialize(os, (*it));992}994template<typename Stream, typename K, typename Pred, typename A>995void Unserialize(Stream& is, std::set<K, Pred, A>& m)996{997m.clear();998unsigned int nSize = ReadCompactSize(is);999typename std::set<K, Pred, A>::iterator it = m.begin();1000for (unsigned int i = 0; i < nSize; i++)