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) 2024-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#include <kernel/bitcoinkernel.h>6#include <kernel/bitcoinkernel_wrapper.h>7#include <util/byte_units.h>8#include <util/fs.h>10// Boost.Test's SIGSTKSZ alternate stack can be smaller than Linux requires on musl.11#define BOOST_TEST_DISABLE_ALT_STACK12#define BOOST_TEST_MODULE Bitcoin Kernel Test Suite13#include <boost/test/included/unit_test.hpp>15#include <test/kernel/block_data.h>16#include <test/util/common.h>18#include <charconv>19#include <cstdint>20#include <cstdlib>21#include <iostream>22#include <memory>23#include <optional>24#include <random>25#include <ranges>26#include <span>27#include <string>28#include <string_view>29#include <vector>31using namespace btck;33std::string random_string(uint32_t length)34{35const std::string chars = "0123456789"36"abcdefghijklmnopqrstuvwxyz"37"ABCDEFGHIJKLMNOPQRSTUVWXYZ";39static std::random_device rd;40static std::default_random_engine dre{rd()};41static std::uniform_int_distribution<> distribution(0, chars.size() - 1);43std::string random;44random.reserve(length);45for (uint32_t i = 0; i < length; i++) {46random += chars[distribution(dre)];47}48return random;49}51std::vector<std::byte> hex_string_to_byte_vec(std::string_view hex)52{53std::vector<std::byte> bytes;54bytes.reserve(hex.length() / 2);56for (size_t i{0}; i < hex.length(); i += 2) {57uint8_t byte_value;58auto [ptr, ec] = std::from_chars(hex.data() + i, hex.data() + i + 2, byte_value, 16);60if (ec != std::errc{} || ptr != hex.data() + i + 2) {61throw std::invalid_argument("Invalid hex character");62}63bytes.push_back(static_cast<std::byte>(byte_value));64}65return bytes;66}68std::string byte_span_to_hex_string_reversed(std::span<const std::byte> bytes)69{70std::ostringstream oss;72// Iterate in reverse order73for (auto it = bytes.rbegin(); it != bytes.rend(); ++it) {74oss << std::hex << std::setw(2) << std::setfill('0')75<< static_cast<unsigned int>(static_cast<uint8_t>(*it));76}78return oss.str();79}81constexpr auto VERIFY_ALL_PRE_SEGWIT{ScriptVerificationFlags::P2SH | ScriptVerificationFlags::DERSIG |82ScriptVerificationFlags::NULLDUMMY | ScriptVerificationFlags::CHECKLOCKTIMEVERIFY |83ScriptVerificationFlags::CHECKSEQUENCEVERIFY};84constexpr auto VERIFY_ALL_PRE_TAPROOT{VERIFY_ALL_PRE_SEGWIT | ScriptVerificationFlags::WITNESS};86void check_equal(std::span<const std::byte> _actual, std::span<const std::byte> _expected, bool equal = true)87{88std::span<const uint8_t> actual{reinterpret_cast<const unsigned char*>(_actual.data()), _actual.size()};89std::span<const uint8_t> expected{reinterpret_cast<const unsigned char*>(_expected.data()), _expected.size()};90BOOST_CHECK_EQUAL_COLLECTIONS(91actual.begin(), actual.end(),92expected.begin(), expected.end());93}95class TestLog96{97public:98void LogMessage(std::string_view message)99{100std::cout << "kernel: " << message;101}102};104struct TestDirectory {105fs::path m_directory;106TestDirectory(std::string directory_name)107: m_directory{fs::path{fs::temp_directory_path()} / fs::u8path(directory_name + "_🌽_" + random_string(16))}108{109fs::create_directories(m_directory);110}112~TestDirectory()113{114fs::remove_all(m_directory);115}116};118class TestKernelNotifications : public KernelNotifications119{120public:121void HeaderTipHandler(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override122{123BOOST_CHECK_GT(timestamp, 0);124}126void FlushErrorHandler(std::string_view error) override127{128std::cout << error << std::endl;129}131void FatalErrorHandler(std::string_view error) override132{133std::cout << error << std::endl;134}135};137class TestValidationInterface : public ValidationInterface138{139public:140std::optional<std::vector<std::byte>> m_expected_valid_block = std::nullopt;142void BlockChecked(Block block, BlockValidationStateView state) override143{144if (m_expected_valid_block.has_value()) {145auto ser_block{block.ToBytes()};146check_equal(m_expected_valid_block.value(), ser_block);147}149auto mode{state.GetValidationMode()};150switch (mode) {151case ValidationMode::VALID: {152std::cout << "Valid block" << std::endl;153return;154}155case ValidationMode::INVALID: {156std::cout << "Invalid block: ";157auto result{state.GetBlockValidationResult()};158switch (result) {159case BlockValidationResult::UNSET:160std::cout << "initial value. Block has not yet been rejected" << std::endl;161break;162case BlockValidationResult::HEADER_LOW_WORK:163std::cout << "the block header may be on a too-little-work chain" << std::endl;164break;165case BlockValidationResult::CONSENSUS:166std::cout << "invalid by consensus rules (excluding any below reasons)" << std::endl;167break;168case BlockValidationResult::CACHED_INVALID:169std::cout << "this block was cached as being invalid and we didn't store the reason why" << std::endl;170break;171case BlockValidationResult::INVALID_HEADER:172std::cout << "invalid proof of work or time too old" << std::endl;173break;174case BlockValidationResult::MUTATED:175std::cout << "the block's data didn't match the data committed to by the PoW" << std::endl;176break;177case BlockValidationResult::MISSING_PREV:178std::cout << "We don't have the previous block the checked one is built on" << std::endl;179break;180case BlockValidationResult::INVALID_PREV:181std::cout << "A block this one builds on is invalid" << std::endl;182break;183case BlockValidationResult::TIME_FUTURE:184std::cout << "block timestamp was > 2 hours in the future (or our clock is bad)" << std::endl;185break;186}187return;188}189case ValidationMode::INTERNAL_ERROR: {190std::cout << "Internal error" << std::endl;191return;192}193}194}196void BlockConnected(Block block, BlockTreeEntry entry) override197{198std::cout << "Block connected." << std::endl;199}201void PowValidBlock(BlockTreeEntry entry, Block block) override202{203std::cout << "Block passed pow verification" << std::endl;204}206void BlockDisconnected(Block block, BlockTreeEntry entry) override207{208std::cout << "Block disconnected." << std::endl;209}210};212void run_verify_test(213const ScriptPubkey& spent_script_pubkey,214const Transaction& spending_tx,215const PrecomputedTransactionData* precomputed_txdata,216int64_t amount,217unsigned int input_index,218bool taproot)219{220auto status = ScriptVerifyStatus::OK;222if (taproot) {223BOOST_CHECK(spent_script_pubkey.Verify(224amount,225spending_tx,226precomputed_txdata,227input_index,228ScriptVerificationFlags::ALL,229status));230BOOST_CHECK(status == ScriptVerifyStatus::OK);231} else {232BOOST_CHECK(!spent_script_pubkey.Verify(233amount,234spending_tx,235precomputed_txdata,236input_index,237ScriptVerificationFlags::ALL,238status));239BOOST_CHECK(status == ScriptVerifyStatus::ERROR_SPENT_OUTPUTS_REQUIRED);240}242BOOST_CHECK(spent_script_pubkey.Verify(243amount,244spending_tx,245precomputed_txdata,246input_index,247VERIFY_ALL_PRE_TAPROOT,248status));249BOOST_CHECK(status == ScriptVerifyStatus::OK);
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.