Skip to main content

Languages & Tools

Bitcoin Core development primarily uses C++ for the main codebase and Python for the test framework. Understanding the specific C++ idioms and tooling used in the project is essential.

C++ in Bitcoin Core

Bitcoin Core uses modern C++ (currently C++20). The project has specific coding conventions:

Style and Conventions

  • Naming: CamelCase for classes, snake_case for functions and variables
  • Prefix: C prefix for classes (CBlock, CTransaction), m_ for member variables
  • Smart pointers: std::unique_ptr and std::shared_ptr over raw pointers
  • No exceptions in consensus code — Error handling via return values
  • No RTTI — Runtime type information is disabled

Key C++ Features Used

// std::optional for nullable values
std::optional<CBlockIndex*> FindBlock(const uint256& hash);

// Span for non-owning views
bool VerifyScript(Span<const unsigned char> scriptSig, ...);

// Structured bindings
auto [iter, inserted] = mapBlockIndex.emplace(hash, new_index);

// RAII patterns for locks
LOCK(cs_main); // Acquires mutex, released at scope exit

Thread Safety

Bitcoin Core uses annotations to enforce thread safety at compile time:

// Annotated mutexes
RecursiveMutex cs_main ACQUIRED_BEFORE(cs_wallet);

// Variables guarded by specific mutexes
int nBestHeight GUARDED_BY(cs_main);

Python Test Framework

The functional test suite (test/functional/) is written in Python and is critical for protocol developers:

# Run all functional tests
test/functional/test_runner.py

# Run a specific test
test/functional/test_runner.py wallet_basic.py

# Run with verbose output
test/functional/feature_block.py --loglevel=debug

Writing a Functional Test

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal

class ExampleTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2

def run_test(self):
# Mine some blocks
self.generate(self.nodes[0], 101)

# Check balance
balance = self.nodes[0].getbalance()
assert_equal(balance, 50)

# Send funds and verify
txid = self.nodes[0].sendtoaddress(
self.nodes[1].getnewaddress(), 10
)
self.generate(self.nodes[0], 1)
assert_equal(self.nodes[1].getbalance(), 10)

Development Tools

ToolPurpose
gdb / lldbDebugger for C++
valgrindMemory error detection
clang-formatCode formatting (project has .clang-format)
clang-tidyStatic analysis
ccacheCompiler cache for faster rebuilds
bearGenerates compile_commands.json for IDE support
flamegraphPerformance profiling visualization

Debugging Bitcoin Core

# Build with debug symbols
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build

# Run under debugger
gdb --args ./build/src/bitcoind -regtest

# Useful GDB commands
(gdb) break validation.cpp:ProcessNewBlock
(gdb) run
(gdb) bt # backtrace
(gdb) p block.GetHash().ToString() # print expression