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.
251assert(real[idx].capacity() > old_cap);252assert(real[idx].capacity() <= 2 * (old_cap + 1));253}254break;255}256if (existing_buffer_non_full && command-- == 0) {257/* emplace_front() */258uint64_t seed{rng.rand64()};259size_t old_size = real[idx].size();260size_t old_cap = real[idx].capacity();261sim[idx].emplace_front(seed);262real[idx].emplace_front(seed);263assert(real[idx].size() == old_size + 1);264if (old_cap > old_size) {265assert(real[idx].capacity() == old_cap);266} else {267assert(real[idx].capacity() > old_cap);268assert(real[idx].capacity() <= 2 * (old_cap + 1));269}270break;271}272if (existing_buffer_non_empty && command-- == 0) {273/* front() [modifying] */274tmp = T(rng.rand64());275size_t old_size = real[idx].size();276assert(sim[idx].front() == real[idx].front());277sim[idx].front() = *tmp;278real[idx].front() = std::move(*tmp);279assert(real[idx].size() == old_size);280break;281}282if (existing_buffer_non_empty && command-- == 0) {283/* back() [modifying] */284tmp = T(rng.rand64());285size_t old_size = real[idx].size();286assert(sim[idx].back() == real[idx].back());287sim[idx].back() = *tmp;288real[idx].back() = *tmp;289assert(real[idx].size() == old_size);290break;291}292if (existing_buffer_non_empty && command-- == 0) {293/* operator[] [modifying] */294tmp = T(rng.rand64());295size_t pos = provider.ConsumeIntegralInRange<size_t>(0, sim[idx].size() - 1);296size_t old_size = real[idx].size();297assert(sim[idx][pos] == real[idx][pos]);298sim[idx][pos] = *tmp;299real[idx][pos] = std::move(*tmp);300assert(real[idx].size() == old_size);301break;302}303if (existing_buffer_non_empty && command-- == 0) {304/* pop_front() */305assert(sim[idx].front() == real[idx].front());306size_t old_size = real[idx].size();307sim[idx].pop_front();308real[idx].pop_front();309assert(real[idx].size() == old_size - 1);310break;311}312if (existing_buffer_non_empty && command-- == 0) {313/* pop_back() */314assert(sim[idx].back() == real[idx].back());315size_t old_size = real[idx].size();316sim[idx].pop_back();317real[idx].pop_back();318assert(real[idx].size() == old_size - 1);319break;320}321}322}324/* Fully compare the final state. */325for (unsigned i = 0; i < sim.size(); ++i) {326// Make sure const getters work.327const VecDeque<T>& realbuf = real[i];328const std::deque<T>& simbuf = sim[i];329compare_fn(realbuf, simbuf);330for (unsigned j = 0; j < sim.size(); ++j) {331assert((realbuf == real[j]) == (simbuf == sim[j]));332assert(((realbuf <=> real[j]) >= 0) == (simbuf >= sim[j]));333assert(((realbuf <=> real[j]) <= 0) == (simbuf <= sim[j]));334}335// Clear out the buffers so we can check below that no objects exist anymore.336sim[i].clear();337real[i].clear();338}340if constexpr (CheckNoneLeft) {341tmp = std::nullopt;342T::CheckNoneExist();343}344}346/** Data structure with built-in tracking of all existing objects. */347template<size_t Size>348class TrackedObj349{350static_assert(Size > 0);352/* Data type for map that actually stores the object data.353*354* The key is a pointer to the TrackedObj, the value is the uint64_t it was initialized with.355* Default-constructed and moved-from objects hold an std::nullopt.356*/357using track_map_type = std::map<const TrackedObj<Size>*, std::optional<uint64_t>>;359private:361/** Actual map. */362static inline track_map_type g_tracker;364/** Iterators into the tracker map for this object.365*366* This is an array of size Size, all holding the same value, to give the object configurable367* size. The value is g_tracker.end() if this object is not fully initialized. */368typename track_map_type::iterator m_track_entry[Size];370void Check() const371{372auto it = g_tracker.find(this);373for (size_t i = 0; i < Size; ++i) {374assert(m_track_entry[i] == it);375}376}378/** Create entry for this object in g_tracker and populate m_track_entry. */379void Register()380{381auto [it, inserted] = g_tracker.emplace(this, std::nullopt);382assert(inserted);383for (size_t i = 0; i < Size; ++i) {384m_track_entry[i] = it;385}386}388void Deregister()389{390Check();391assert(m_track_entry[0] != g_tracker.end());392g_tracker.erase(m_track_entry[0]);393for (size_t i = 0; i < Size; ++i) {394m_track_entry[i] = g_tracker.end();395}396}398/** Get value corresponding to this object in g_tracker. */399std::optional<uint64_t>& Deref()400{401Check();402assert(m_track_entry[0] != g_tracker.end());403return m_track_entry[0]->second;404}406/** Get value corresponding to this object in g_tracker. */407const std::optional<uint64_t>& Deref() const408{409Check();410assert(m_track_entry[0] != g_tracker.end());411return m_track_entry[0]->second;412}414public:415~TrackedObj() { Deregister(); }416TrackedObj() { Register(); }418TrackedObj(uint64_t value)419{420Register();421Deref() = value;422}424TrackedObj(const TrackedObj& other)425{426Register();427Deref() = other.Deref();428}430TrackedObj(TrackedObj&& other)431{432Register();433Deref() = other.Deref();434other.Deref() = std::nullopt;435}437TrackedObj& operator=(const TrackedObj& other)438{439if (this == &other) return *this;440Deref() = other.Deref();441return *this;442}444TrackedObj& operator=(TrackedObj&& other)445{446if (this == &other) return *this;447Deref() = other.Deref();448other.Deref() = std::nullopt;449return *this;450}452friend bool operator==(const TrackedObj& a, const TrackedObj& b)453{454return a.Deref() == b.Deref();455}457friend std::strong_ordering operator<=>(const TrackedObj& a, const TrackedObj& b)458{459// Libc++ 15 & 16 do not support std::optional<T>::operator<=> yet. See460// https://reviews.llvm.org/D146392.461if (!a.Deref().has_value() || !b.Deref().has_value()) {462return a.Deref().has_value() <=> b.Deref().has_value();463}464return *a.Deref() <=> *b.Deref();465}467static void CheckNoneExist()468{469assert(g_tracker.empty());470}471};473} // namespace475FUZZ_TARGET(vecdeque)476{477// Run the test with simple uints (which satisfy all the trivial properties).478static_assert(std::is_trivially_copyable_v<uint32_t>);479static_assert(std::is_trivially_destructible_v<uint64_t>);480TestType<uint8_t, false>(buffer, 1);481TestType<uint16_t, false>(buffer, 2);482TestType<uint32_t, false>(buffer, 3);483TestType<uint64_t, false>(buffer, 4);485// Run the test with TrackedObjs (which do not).486static_assert(!std::is_trivially_copyable_v<TrackedObj<3>>);487static_assert(!std::is_trivially_destructible_v<TrackedObj<17>>);488TestType<TrackedObj<1>, true>(buffer, 5);489TestType<TrackedObj<3>, true>(buffer, 6);490TestType<TrackedObj<17>, true>(buffer, 7);491}
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.