Overview
This guide covers the essential development practices, tips, and conventions used in Bitcoin Core. While various coding styles have been used historically, the project is now converging to a single consistent style.When writing patches, favor the new style over attempting to mimic surrounding code, except for move-only commits. Do not submit patches solely to modify the style of existing code.
Development Environment
Compiling for Debugging
When using the default build configuration withcmake -B build, the -DCMAKE_BUILD_TYPE is set to RelWithDebInfo. This adds debug symbols but performs compiler optimizations that may make debugging trickier.
For exclusive debugging builds:
Debug Logging
Thedebug.log file in the data directory contains error and debugging messages. Debug logging can be controlled:
- At startup: Use
-debugand-loglevelconfiguration options - While running: Use the
loggingRPC command
-debugor-debug=1- Turn on all log categories-loglevel=trace- Turn on all log severity levels-debug=qt- See Qt-specific logging (routesqDebug()output)
Test Networks
Bitcoin Core provides several test network options:- Signet/Testnet: Use
-signetor-testnet4for multi-machine testing across the internet with “play bitcoins” - Regtest: Use
-regtestfor single-machine testing where blocks can be created on demand
Debugging Tools
DEBUG_LOCKORDER
Bitcoin Core is multi-threaded, and deadlocks can be difficult to track. The-DCMAKE_BUILD_TYPE=Debug build option adds -DDEBUG_LOCKORDER, which:
- Inserts run-time checks to track which locks are held
- Adds warnings to
debug.logif inconsistencies are detected
DEBUG_LOCKCONTENTION
DefiningDEBUG_LOCKCONTENTION adds a “lock” logging category that logs the location and duration of each lock contention.
Enable it by:
-debug=lock at startup or bitcoin-cli logging '["lock"]' at runtime.
Assertions and Checks
Thesrc/util/check.h file offers helpers to protect against coding bugs. They must never validate user, network, or external input.
assert/Assert: For assumptions where violations mean execution cannot safely continue (e.g., validation code bugs)CHECK_NONFATAL: For recoverable internal logic bugs; throws an exception on failureAssume: Documents assumptions where execution can safely continue even if violated; acts likeassertin debug builds but is optimized away in production
Valgrind
Valgrind is useful for memory debugging and leak detection. The repo contains a suppressions file attest/sanitizer_suppressions/valgrind.supp:
Sanitizers
Bitcoin Core can be compiled with various sanitizers for detecting memory safety issues, thread race conditions, or undefined behavior:Sanitizers have runtime overhead, so they’re most useful when testing changes or producing debugging builds. Not all sanitizers can be enabled simultaneously (e.g., address and thread are mutually incompatible).
Performance Profiling with perf
On Linux, useperf for performance profiling:
Code Coverage
Using LCOV
Generate test coverage reports with LCOV:Using LLVM/Clang
For source-based coverage with Clang:Locking and Threading
Thread Overview
Bitcoin Core uses multiple threads:- Main thread (
bitcoind): Startup and shutdown - Init load (
b-initload): Block import, reindex, chain activation - CCheckQueue::Loop (
b-scriptch.x): Parallel script validation - ThreadHTTP (
b-http): RPC and REST connections - HTTP workers (
b-httpworker.x): Service RPC/REST requests - Indexer threads (
b-txindex): One per indexer - SchedulerThread (
b-scheduler): Asynchronous background tasks - Net threads: Message handling, DNS seeds, socket I/O, connections
Mutex Usage
The code uses mutexes withLOCK and TRY_LOCK macros:
- Compile with
-DDEBUG_LOCKORDERto detect lock order inconsistencies - Deadlocks occur when threads lock mutexes in different orders
- Goal: Better-defined interfaces between components with self-contained locking
Development Guidelines
General Practices
- New features: Expose on RPC first, then make available in GUI
- Rationale: RPC allows better automatic testing; GUI test suite is limited
Logging Levels
Use these logging macros appropriately:LogDebug(BCLog::CATEGORY, ...): Most common; for debugging messages that can reasonably run in production with-debug=categoryLogInfo(...): Rare; for startup messages or important infrequent events (new block tip, new outbound connection). Unconditional logging.LogError(...): Severe problems requiring node/subsystem shutdown (e.g., insufficient storage)LogWarning(...): Severe problems requiring admin attention but not shutdown (e.g., wrong system time)LogTrace(BCLog::CATEGORY, ...): Messages too noisy/resource-intensive for production; requires-debug=category -loglevel=category:trace
Format strings and parameters of
LogDebug and LogTrace are only evaluated if the category is enabled, so avoid side-effects in those expressions.IWYU (Include What You Use)
Theinclude-what-you-use tool helps enforce source code organization:
- Run the IWYU CI job locally for consistency
- Accept suggestions for headers that enable implicit conversions
- Use
IWYU pragma: exportvery sparingly
Generating Documentation
Bitcoin Core uses Doxygen for official documentation. Install dependencies:- Linux:
sudo apt install doxygen graphviz - macOS:
brew install doxygen graphviz
build/doc/doxygen/html/index.html
Subtrees
Several parts of the repository are subtrees of external software:- Active Bitcoin Core developers maintain: Changes go upstream first, merged back in next subtree merge
- External projects: Send changes upstream; critical bugfixes may be PRed against Bitcoin Core subtree
src/leveldb- Upstream at https://github.com/google/leveldbsrc/crc32c- Upstream at https://github.com/google/crc32c
Release Notes
Write release notes for any PR that:- Introduces a notable new feature
- Fixes a significant bug
- Changes an API or configuration model
- Makes any other visible end-user change
/doc/release-notes-<PR number>.md
All release notes files are merged into release-notes-<version>.md before release.