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_TEST_UTIL_POOLRESOURCETESTER_H6#define BITCOIN_TEST_UTIL_POOLRESOURCETESTER_H8#include <support/allocators/pool.h>9#include <util/check.h>11#include <algorithm>12#include <cassert>13#include <cstddef>14#include <cstdint>15#include <vector>17/**18* Helper to get access to private parts of PoolResource. Used in unit tests and in the fuzzer19*/20class PoolResourceTester21{22struct PtrAndBytes {23uintptr_t ptr;24std::size_t size;26PtrAndBytes(const void* p, std::size_t s)27: ptr(reinterpret_cast<uintptr_t>(p)), size(s)28{29}31/**32* defines a sort ordering by the pointer value33*/34friend bool operator<(PtrAndBytes const& a, PtrAndBytes const& b)35{36return a.ptr < b.ptr;37}38};40public:41/**42* Extracts the number of elements per freelist43*/44template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>45static std::vector<std::size_t> FreeListSizes(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource)46{47auto sizes = std::vector<std::size_t>();48for (const auto* ptr : resource.m_free_lists) {49size_t size = 0;50while (ptr != nullptr) {51++size;52const auto* ptr_ = ptr;53ASAN_UNPOISON_MEMORY_REGION(ptr_, sizeof(typename PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>::ListNode));54ptr = ptr->m_next;55ASAN_POISON_MEMORY_REGION(ptr_, sizeof(typename PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>::ListNode));56}57sizes.push_back(size);58}59return sizes;60}62/**63* How many bytes are still available from the last allocated chunk64*/65template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>66static std::size_t AvailableMemoryFromChunk(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource)67{68return resource.m_available_memory_end - resource.m_available_memory_it;69}71/**72* Once all blocks are given back to the resource, tests that the freelists are consistent:73*74* * All data in the freelists must come from the chunks75* * Memory doesn't overlap76* * Each byte in the chunks can be accounted for in either the freelist or as available bytes.77*/78template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>79static void CheckAllDataAccountedFor(const PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>& resource)80{81// collect all free blocks by iterating all freelists82std::vector<PtrAndBytes> free_blocks;83for (std::size_t freelist_idx = 0; freelist_idx < resource.m_free_lists.size(); ++freelist_idx) {84std::size_t bytes = freelist_idx * resource.ELEM_ALIGN_BYTES;85auto* ptr = resource.m_free_lists[freelist_idx];86while (ptr != nullptr) {87free_blocks.emplace_back(ptr, bytes);88const auto* ptr_ = ptr;89ASAN_UNPOISON_MEMORY_REGION(ptr_, sizeof(typename PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>::ListNode));90ptr = ptr->m_next;91ASAN_POISON_MEMORY_REGION(ptr_, sizeof(typename PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES>::ListNode));92}93}94// also add whatever has not yet been used for blocks95auto num_available_bytes = resource.m_available_memory_end - resource.m_available_memory_it;96if (num_available_bytes > 0) {97free_blocks.emplace_back(resource.m_available_memory_it, num_available_bytes);98}100// collect all chunks101std::vector<PtrAndBytes> chunks;102for (const std::byte* ptr : resource.m_allocated_chunks) {103chunks.emplace_back(ptr, resource.ChunkSizeBytes());104}106// now we have all the data from all freelists on the one hand side, and all chunks on the other hand side.107// To check if all of them match, sort by address and iterate.108std::sort(free_blocks.begin(), free_blocks.end());109std::sort(chunks.begin(), chunks.end());111auto chunk_it = chunks.begin();112auto chunk_ptr_remaining = chunk_it->ptr;113auto chunk_size_remaining = chunk_it->size;114for (const auto& free_block : free_blocks) {115if (chunk_size_remaining == 0) {116assert(chunk_it != chunks.end());117++chunk_it;118assert(chunk_it != chunks.end());119chunk_ptr_remaining = chunk_it->ptr;120chunk_size_remaining = chunk_it->size;121}122assert(free_block.ptr == chunk_ptr_remaining); // ensure addresses match123assert(free_block.size <= chunk_size_remaining); // ensure no overflow124assert((free_block.ptr & (resource.ELEM_ALIGN_BYTES - 1)) == 0); // ensure correct alignment125chunk_ptr_remaining += free_block.size;126chunk_size_remaining -= free_block.size;127}128// ensure we are at the end of the chunks129assert(chunk_ptr_remaining == chunk_it->ptr + chunk_it->size);130++chunk_it;131assert(chunk_it == chunks.end());132assert(chunk_size_remaining == 0);133}134};136#endif // BITCOIN_TEST_UTIL_POOLRESOURCETESTER_H
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.