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.
1// Copyright (c) 2022-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_UTIL_BITDEQUE_H6#define BITCOIN_UTIL_BITDEQUE_H8#include <bitset>9#include <cstddef>10#include <deque>11#include <limits>12#include <stdexcept>13#include <tuple>14#include <util/overflow.h>16/** Class that mimics std::deque<bool>, but with std::vector<bool>'s bit packing.17*18* BITS_PER_WORD selects the (minimum) number of bits that are allocated at once.19* Larger values reduce the asymptotic memory usage overhead, at the cost of20* needing larger up-front allocations. The default is 4096 bytes.21*/22template<int BITS_PER_WORD = 4096 * 8>23class bitdeque24{25// Internal definitions26using word_type = std::bitset<BITS_PER_WORD>;27using deque_type = std::deque<word_type>;28static_assert(BITS_PER_WORD > 0);30// Forward and friend declarations of iterator types.31template<bool Const> class Iterator;32template<bool Const> friend class Iterator;34/** Iterator to a bitdeque element, const or not. */35template<bool Const>36class Iterator37{38using deque_iterator = std::conditional_t<Const, typename deque_type::const_iterator, typename deque_type::iterator>;40deque_iterator m_it;41int m_bitpos{0};42Iterator(const deque_iterator& it, int bitpos) : m_it(it), m_bitpos(bitpos) {}43friend class bitdeque;45public:46using iterator_category = std::random_access_iterator_tag;47using value_type = bool;48using pointer = void;49using const_pointer = void;50using reference = std::conditional_t<Const, bool, typename word_type::reference>;51using const_reference = bool;52using difference_type = std::ptrdiff_t;54/** Default constructor. */55Iterator() = default;57/** Default copy constructor. */58Iterator(const Iterator&) = default;60/** Conversion from non-const to const iterator. */61template<bool ConstArg = Const, typename = std::enable_if_t<Const && ConstArg>>62Iterator(const Iterator<false>& x) : m_it(x.m_it), m_bitpos(x.m_bitpos) {}64Iterator& operator+=(difference_type dist)65{66if (dist > 0) {67if (dist + m_bitpos >= BITS_PER_WORD) {68++m_it;69dist -= BITS_PER_WORD - m_bitpos;70m_bitpos = 0;71}72auto jump = dist / BITS_PER_WORD;73m_it += jump;74m_bitpos += dist - jump * BITS_PER_WORD;75} else if (dist < 0) {76dist = -dist;77if (dist > m_bitpos) {78--m_it;79dist -= m_bitpos + 1;80m_bitpos = BITS_PER_WORD - 1;81}82auto jump = dist / BITS_PER_WORD;83m_it -= jump;84m_bitpos -= dist - jump * BITS_PER_WORD;85}86return *this;87}89friend difference_type operator-(const Iterator& x, const Iterator& y)90{91return BITS_PER_WORD * (x.m_it - y.m_it) + x.m_bitpos - y.m_bitpos;92}94Iterator& operator=(const Iterator&) = default;95Iterator& operator-=(difference_type dist) { return operator+=(-dist); }96Iterator& operator++() { ++m_bitpos; if (m_bitpos == BITS_PER_WORD) { m_bitpos = 0; ++m_it; }; return *this; }97Iterator operator++(int) { auto ret{*this}; operator++(); return ret; }98Iterator& operator--() { if (m_bitpos == 0) { m_bitpos = BITS_PER_WORD; --m_it; }; --m_bitpos; return *this; }99Iterator operator--(int) { auto ret{*this}; operator--(); return ret; }100friend Iterator operator+(Iterator x, difference_type dist) { x += dist; return x; }101friend Iterator operator+(difference_type dist, Iterator x) { x += dist; return x; }102friend Iterator operator-(Iterator x, difference_type dist) { x -= dist; return x; }103friend auto operator<=>(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) <=> std::tie(y.m_it, y.m_bitpos); }104friend bool operator==(const Iterator& x, const Iterator& y) { return x.m_it == y.m_it && x.m_bitpos == y.m_bitpos; }105reference operator*() const { return (*m_it)[m_bitpos]; }106reference operator[](difference_type pos) const { return *(*this + pos); }107};109public:110using value_type = bool;111using size_type = std::size_t;112using difference_type = typename deque_type::difference_type;113using reference = typename word_type::reference;114using const_reference = bool;115using iterator = Iterator<false>;116using const_iterator = Iterator<true>;117using pointer = void;118using const_pointer = void;119using reverse_iterator = std::reverse_iterator<iterator>;120using const_reverse_iterator = std::reverse_iterator<const_iterator>;122private:123/** Deque of bitsets storing the actual bit data. */124deque_type m_deque;126/** Number of unused bits at the front of m_deque.front(). */127int m_pad_begin;129/** Number of unused bits at the back of m_deque.back(). */130int m_pad_end;132/** Shrink the container by n bits, removing from the end. */133void erase_back(size_type n)134{135if (n >= static_cast<size_type>(BITS_PER_WORD - m_pad_end)) {136n -= BITS_PER_WORD - m_pad_end;137m_pad_end = 0;138m_deque.erase(m_deque.end() - 1 - (n / BITS_PER_WORD), m_deque.end());139n %= BITS_PER_WORD;140}141if (n) {142auto& last = m_deque.back();143while (n) {144last.reset(BITS_PER_WORD - 1 - m_pad_end);145++m_pad_end;146--n;147}148}149}151/** Extend the container by n bits, adding at the end. */152void extend_back(size_type n)153{154if (n > static_cast<size_type>(m_pad_end)) {155n -= m_pad_end + 1;156m_pad_end = BITS_PER_WORD - 1;157m_deque.insert(m_deque.end(), 1 + (n / BITS_PER_WORD), {});158n %= BITS_PER_WORD;159}160m_pad_end -= n;161}163/** Shrink the container by n bits, removing from the beginning. */164void erase_front(size_type n)165{166if (n >= static_cast<size_type>(BITS_PER_WORD - m_pad_begin)) {167n -= BITS_PER_WORD - m_pad_begin;168m_pad_begin = 0;169m_deque.erase(m_deque.begin(), m_deque.begin() + 1 + (n / BITS_PER_WORD));170n %= BITS_PER_WORD;171}172if (n) {173auto& first = m_deque.front();174while (n) {175first.reset(m_pad_begin);176++m_pad_begin;177--n;178}179}180}182/** Extend the container by n bits, adding at the beginning. */183void extend_front(size_type n)184{185if (n > static_cast<size_type>(m_pad_begin)) {186n -= m_pad_begin + 1;187m_pad_begin = BITS_PER_WORD - 1;188m_deque.insert(m_deque.begin(), 1 + (n / BITS_PER_WORD), {});189n %= BITS_PER_WORD;190}191m_pad_begin -= n;192}194/** Insert a sequence of falses anywhere in the container. */195void insert_zeroes(size_type before, size_type count)196{197size_type after = size() - before;198if (before < after) {199extend_front(count);200std::move(begin() + count, begin() + count + before, begin());201} else {202extend_back(count);203std::move_backward(begin() + before, begin() + before + after, end());204}205}207public:208/** Construct an empty container. */209explicit bitdeque() : m_pad_begin{0}, m_pad_end{0} {}211/** Set the container equal to count times the value of val. */212void assign(size_type count, bool val)213{214m_deque.clear();215m_deque.resize(CeilDiv(count, size_type{BITS_PER_WORD}));216m_pad_begin = 0;217m_pad_end = 0;218if (val) {219for (auto& elem : m_deque) elem.flip();220}221if (count % BITS_PER_WORD) {222erase_back(BITS_PER_WORD - (count % BITS_PER_WORD));223}224}226/** Construct a container containing count times the value of val. */227bitdeque(size_type count, bool val) { assign(count, val); }229/** Construct a container containing count false values. */230explicit bitdeque(size_t count) { assign(count, false); }232/** Copy constructor. */233bitdeque(const bitdeque&) = default;235/** Move constructor. */236bitdeque(bitdeque&&) noexcept = default;238/** Copy assignment operator. */239bitdeque& operator=(const bitdeque& other) = default;241/** Move assignment operator. */242bitdeque& operator=(bitdeque&& other) noexcept = default;244// Iterator functions.245iterator begin() noexcept { return {m_deque.begin(), m_pad_begin}; }246iterator end() noexcept { return iterator{m_deque.end(), 0} - m_pad_end; }247const_iterator begin() const noexcept { return const_iterator{m_deque.cbegin(), m_pad_begin}; }248const_iterator cbegin() const noexcept { return const_iterator{m_deque.cbegin(), m_pad_begin}; }249const_iterator end() const noexcept { return const_iterator{m_deque.cend(), 0} - m_pad_end; }250const_iterator cend() const noexcept { return const_iterator{m_deque.cend(), 0} - m_pad_end; }
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.