Inside Bitcoin
Opening the selected file…
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.
251DataStream& operator<<(const T& obj)252{253::Serialize(*this, obj);254return (*this);255}257template <typename T>258DataStream& operator>>(T&& obj)259{260::Unserialize(*this, obj);261return (*this);262}264/** Compute total memory usage of this object (own memory + any dynamic memory). */265size_t GetMemoryUsage() const noexcept;266};268// Require empty scratch streams on entry and reset them on exit.269class ScopedDataStreamUsage270{271DataStream& m_stream;273public:274explicit ScopedDataStreamUsage(DataStream& stream) : m_stream{stream} { assert(m_stream.empty()); }276ScopedDataStreamUsage(const ScopedDataStreamUsage&) = delete;277ScopedDataStreamUsage& operator=(const ScopedDataStreamUsage&) = delete;279~ScopedDataStreamUsage() { m_stream.clear(); }280};282template <typename IStream>283class BitStreamReader284{285private:286IStream& m_istream;288/// Buffered byte read in from the input stream. A new byte is read into the289/// buffer when m_offset reaches 8.290uint8_t m_buffer{0};292/// Number of high order bits in m_buffer already returned by previous293/// Read() calls. The next bit to be returned is at this offset from the294/// most significant bit position.295int m_offset{8};297public:298explicit BitStreamReader(IStream& istream) : m_istream(istream) {}300/** Read the specified number of bits from the stream. The data is returned301* in the nbits least significant bits of a 64-bit uint.302*/303uint64_t Read(int nbits) {304if (nbits < 0 || nbits > 64) {305throw std::out_of_range("nbits must be between 0 and 64");306}308uint64_t data = 0;309while (nbits > 0) {310if (m_offset == 8) {311m_istream >> m_buffer;312m_offset = 0;313}315int bits = std::min(8 - m_offset, nbits);316data <<= bits;317data |= static_cast<uint8_t>(m_buffer << m_offset) >> (8 - bits);318m_offset += bits;319nbits -= bits;320}321return data;322}323};325template <typename OStream>326class BitStreamWriter327{328private:329OStream& m_ostream;331/// Buffered byte waiting to be written to the output stream. The byte is332/// written buffer when m_offset reaches 8 or Flush() is called.333uint8_t m_buffer{0};335/// Number of high order bits in m_buffer already written by previous336/// Write() calls and not yet flushed to the stream. The next bit to be337/// written to is at this offset from the most significant bit position.338int m_offset{0};340public:341explicit BitStreamWriter(OStream& ostream) : m_ostream(ostream) {}343~BitStreamWriter()344{345Flush();346}348/** Write the nbits least significant bits of a 64-bit int to the output349* stream. Data is buffered until it completes an octet.350*/351void Write(uint64_t data, int nbits) {352if (nbits < 0 || nbits > 64) {353throw std::out_of_range("nbits must be between 0 and 64");354}356while (nbits > 0) {357int bits = std::min(8 - m_offset, nbits);358m_buffer |= (data << (64 - nbits)) >> (64 - 8 + m_offset);359m_offset += bits;360nbits -= bits;362if (m_offset == 8) {363Flush();364}365}366}368/** Flush any unwritten bits to the output stream, padding with 0's to the369* next byte boundary.370*/371void Flush() {372if (m_offset == 0) {373return;374}376m_ostream << m_buffer;377m_buffer = 0;378m_offset = 0;379}380};382/** Non-refcounted RAII wrapper for FILE*383*384* Will automatically close the file when it goes out of scope if not null.385* If you're returning the file pointer, return file.release().386* If you need to close the file early, use autofile.fclose() instead of fclose(underlying_FILE).387*388* @note If the file has been written to, then the caller must close it389* explicitly with the `fclose()` method, check if it returns an error and treat390* such an error as if the `write()` method failed. The OS's `fclose(3)` may391* fail to flush to disk data that has been previously written, rendering the392* file corrupt.393*/394class AutoFile395{396protected:397std::FILE* m_file;398Obfuscation m_obfuscation;399std::optional<int64_t> m_position;400bool m_was_written{false};402public:403explicit AutoFile(std::FILE* file, const Obfuscation& obfuscation = {});405~AutoFile()406{407if (m_was_written) {408// Callers that wrote to the file must have closed it explicitly409// with the fclose() method and checked that the close succeeded.410// This is because here in the destructor we have no way to signal411// errors from fclose() which, after write, could mean the file is412// corrupted and must be handled properly at the call site.413// Destructors in C++ cannot signal an error to the callers because414// they do not return a value and are not allowed to throw exceptions.415Assume(IsNull());416}418if (fclose() != 0) {419LogError("Failed to close file: %s", SysErrorString(errno));420}421}423// Disallow copies424AutoFile(const AutoFile&) = delete;425AutoFile& operator=(const AutoFile&) = delete;427bool feof() const { return std::feof(m_file); }429[[nodiscard]] int fclose()430{431if (auto rel{release()}) return std::fclose(rel);432return 0;433}435/** Get wrapped FILE* with transfer of ownership.436* @note This will invalidate the AutoFile object, and makes it the responsibility of the caller437* of this function to clean up the returned FILE*.438*/439std::FILE* release()440{441std::FILE* ret{m_file};442m_file = nullptr;443return ret;444}446/** Return true if the wrapped FILE* is nullptr, false otherwise.447*/448bool IsNull() const { return m_file == nullptr; }450/** Continue with a different XOR key */451void SetObfuscation(const Obfuscation& obfuscation) { m_obfuscation = obfuscation; }453/** Implementation detail, only used internally. */454std::size_t detail_fread(std::span<std::byte> dst);456/** Wrapper around fseek(). Will throw if seeking is not possible. */457void seek(int64_t offset, int origin);459/** Find position within the file. Will throw if unknown. */460int64_t tell();462/** Return the size of the file. Will throw if unknown. */463int64_t size();465/** Wrapper around FileCommit(). */466bool Commit();468/** Wrapper around TruncateFile(). */469bool Truncate(uint64_t size);471//! Write a mutable buffer more efficiently than write(), obfuscating the buffer in-place.472void write_buffer(std::span<std::byte> src);474//475// Stream subset476//477void read(std::span<std::byte> dst);478void ignore(size_t nSize);479void write(std::span<const std::byte> src);481template <typename T>482AutoFile& operator<<(const T& obj)483{484::Serialize(*this, obj);485return *this;486}488template <typename T>489AutoFile& operator>>(T&& obj)490{491::Unserialize(*this, obj);492return *this;493}494};496using DataBuffer = std::vector<std::byte>;498/** Wrapper around an AutoFile& that implements a ring buffer to499* deserialize from. It guarantees the ability to rewind a given number of bytes.500*