Module 1: Bitcoin Core Development

Estimated time: 90 minutes

Welcome to the Final Stage

You've come a long way—from understanding Bitcoin's protocol to building applications on top of it. Now you're ready for the most important step: contributing to Bitcoin itself.

Bitcoin is not owned by any company or government. It belongs to everyone who runs it, uses it, and improves it. Every line of code in Bitcoin Core is the result of countless hours of review, testing, and consensus-building by developers around the world. You can be one of them.

"Bitcoin is an idea whose time has come, and code is the language of that idea."

Before We Begin: Think Like a Core Developer

Before diving into Bitcoin Core's codebase, consider the unique challenges of developing the world's most important financial software:

How do you change code that secures hundreds of billions of dollars?

A bug in Bitcoin Core could cause network splits, loss of funds, or worse. What processes ensure that changes are safe?

How do thousands of independent developers coordinate without a CEO?

No one is "in charge" of Bitcoin. How do developers reach consensus on what code to merge?

🧪
How do you test software that must never fail?

Traditional software can have bugs and release patches. Bitcoin Core protects people's life savings. What testing standards are required?

Why does Bitcoin Core development move slowly compared to other projects?

Some pull requests take months or years to merge. Is this a bug or a feature?

Bitcoin Core's answer: Rigorous testing, extensive review, and consensus-driven development

Bitcoin Core Architecture Tour

Bitcoin Core is approximately 400,000 lines of C++ code, organized into functional components. Understanding this architecture is essential for contributing effectively.

Repository Structure

bitcoin/
├── src/                    # Main source code
│   ├── consensus/          # Consensus-critical code (BE CAREFUL!)
│   │   ├── consensus.cpp
│   │   ├── params.h
│   │   └── validation.cpp
│   ├── net/                # P2P networking layer
│   │   ├── net.cpp
│   │   └── net_processing.cpp
│   ├── wallet/             # Wallet functionality
│   │   ├── wallet.cpp
│   │   └── spend.cpp
│   ├── rpc/                # RPC server and commands
│   │   ├── blockchain.cpp
│   │   └── mining.cpp
│   ├── script/             # Script interpreter
│   │   ├── interpreter.cpp
│   │   └── script.cpp
│   ├── validation/         # Transaction/block validation
│   ├── util/               # Utility functions
│   └── primitives/         # Core data structures
├── test/                   # Test suite
│   ├── functional/         # Python functional tests
│   └── fuzz/               # Fuzz testing
├── doc/                    # Documentation
│   ├── developer-notes.md
│   └── release-notes/
└── contrib/                # Build scripts and tools

Core Components

1. Consensus Layer - The heart of Bitcoin

  • Most critical code in the project - Changes here require extreme caution
  • Defines block validation rules, transaction validity, script execution
  • Must be bug-free: consensus bugs can split the network
  • Changes require multiple ACKs from experienced reviewers

2. P2P Networking - Communication between nodes

  • Block and transaction relay
  • Peer discovery and connection management
  • DoS protection and peer banning
  • Network message handling

3. Wallet - Key and transaction management

  • HD wallet key derivation
  • UTXO selection and coin selection algorithms
  • Transaction creation and signing
  • Address book and label management

4. RPC Interface - External communication

  • JSON-RPC server for programmatic access
  • Command handling for wallet, blockchain, network operations
  • Authentication and security

5. Validation - Transaction and block checking

  • Mempool management
  • Block validation and storage
  • UTXO set management
  • Reorganization handling

⚠️ Consensus-Critical vs Non-Consensus Code

Understanding the difference is crucial:

  • Consensus-critical: Code that affects block/transaction validity. A bug here can cause network splits. Requires highest scrutiny.
  • Non-consensus: Code for wallet, RPC, GUI, networking. Bugs are bad but won't split the network. More room for iteration.

New contributors should start with non-consensus code while learning the codebase.

Bitcoin Core Development Workflow

Contributing to Bitcoin Core follows a rigorous process designed to maintain the highest code quality and security standards.

The Contribution Lifecycle

1Fork and Clone

# Fork bitcoin/bitcoin on GitHub, then:
git clone https://github.com/YOUR_USERNAME/bitcoin.git
cd bitcoin
git remote add upstream https://github.com/bitcoin/bitcoin.git

2Build Bitcoin Core

# Install dependencies (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install build-essential libtool autotools-dev automake \
  pkg-config bsdmainutils python3 libssl-dev libevent-dev libboost-dev \
  libsqlite3-dev libdb++-dev

# Build
./autogen.sh
./configure
make -j$(nproc)

# Run tests
make check

3Create a Branch

# Always branch from latest master
git checkout master
git pull upstream master
git checkout -b my-improvement-description

4Make Changes

Follow the developer-notes.md coding standards:

  • Use consistent formatting (run make lint)
  • Write clear, descriptive commit messages
  • Keep commits atomic and logical
  • Add tests for new functionality
  • Update documentation

5Test Thoroughly

# Run all tests
make check                           # Unit tests
test/functional/test_runner.py      # Functional tests
test/lint/lint-all.sh                # Linting

# Test specific functionality
test/functional/wallet_basic.py
src/test/test_bitcoin --run_test=validation_tests

6Push and Create PR

# Push to your fork
git push origin my-improvement-description

# Create PR on GitHub with:
# - Clear title describing the change
# - Detailed description of what and why
# - Test plan
# - Any breaking changes

7Address Review Feedback

Reviewers will comment on your PR. Respond to feedback by:

  • Making requested changes
  • Explaining your reasoning if you disagree
  • Keeping discussions professional and technical
  • Being patient—review takes time

Commit Message Standards

Bitcoin Core uses a specific commit message format:

component: Short description (50 chars max)

Longer description explaining what changed and why.
Can span multiple paragraphs.

- Include relevant background
- Explain design decisions
- Reference related issues/PRs

Fixes #12345

Examples of good commit messages:

validation: Add helper function for checking sequence locks

rpc: Return fee rate in getmempoolinfo

test: Add coverage for wallet backup restoration

doc: Clarify RBF behavior in transaction creation

Bitcoin Core Testing Framework

Bitcoin Core has one of the most comprehensive testing frameworks in open source. Understanding it is essential for contributing quality code.

1. Unit Tests (C++)

Test individual functions and components in isolation. Located in src/test/.

// Example: test/validation_tests.cpp
BOOST_AUTO_TEST_CASE(test_simple_block_validity)
{
    CBlock block;
    block.nVersion = 1;
    block.nTime = GetTime();

    // Test block is valid
    CValidationState state;
    BOOST_CHECK(CheckBlock(block, state));
}

Running unit tests:

# Run all unit tests
make check

# Run specific test suite
src/test/test_bitcoin --run_test=validation_tests

# Run with verbose output
src/test/test_bitcoin --run_test=* --log_level=all

2. Functional Tests (Python)

Test end-to-end functionality by running actual Bitcoin Core nodes. Located in test/functional/.

# Example functional test structure
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal

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

    def run_test(self):
        # Test wallet functionality
        addr = self.nodes[0].getnewaddress()
        txid = self.nodes[0].sendtoaddress(addr, 1)

        # Generate block and verify
        self.generate(self.nodes[0], 1)
        tx = self.nodes[0].gettransaction(txid)
        assert_equal(tx['confirmations'], 1)

Running functional tests:

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

# Run specific test
test/functional/wallet_basic.py

# Run with debug output
test/functional/wallet_basic.py --tracerpc

# Run extended tests (slow, comprehensive)
test/functional/test_runner.py --extended

3. Fuzz Testing

Automatically generates random inputs to find edge cases and crashes. Critical for security-sensitive code.

# Build with fuzzing enabled
./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
make

# Run fuzzer
src/test/fuzz/process_message /path/to/seed/corpus

Writing Tests for Your Changes

Golden Rule: Every change needs tests

When to add which tests:

  • New feature: Functional test + unit tests for edge cases
  • Bug fix: Test that fails before fix, passes after
  • Refactor: Ensure existing tests still pass
  • Performance improvement: Add benchmark if measurable

Test coverage best practices:

  • Test normal cases and edge cases
  • Test error conditions
  • Test boundary conditions
  • Make tests deterministic (no random failures)
  • Keep tests fast when possible

Bitcoin Core Code Review Culture

Code review is the most important part of Bitcoin development. More valuable than writing code is carefully reviewing others' code.

The Review Process

Types of review feedback:

  • Concept ACK: Agree with the general idea, haven't reviewed code
  • Approach ACK: Agree with the approach, haven't reviewed thoroughly
  • tACK (tested ACK): Reviewed code, tested functionality, approve
  • ACK: Reviewed code thoroughly and approve
  • NACK: Disagree with approach/implementation (must explain why)
  • nit: Minor suggestion, not blocking merge

How to Review Code

1Checkout the PR branch

# Fetch PR branch
git fetch upstream pull/12345/head:pr-12345
git checkout pr-12345

2Build and test

# Rebuild with changes
make clean
make -j$(nproc)

# Run tests
make check
test/functional/test_runner.py

3Review the code

Ask yourself:

  • Does this solve the stated problem?
  • Are there edge cases not covered?
  • Is the approach sound?
  • Are there security implications?
  • Is the code well-documented?
  • Are tests adequate?
  • Does it follow coding standards?

4Leave constructive feedback

# Good review comments:
"Consider using std::optional here to handle the null case"
"nit: Variable naming could be more descriptive"
"Could this cause a deadlock if the lock is held in function X?"
"Approach ACK - minor suggestions below"

# Bad review comments:
"This is wrong" (not constructive)
"Why didn't you do X?" (condescending)
"NACK" (without explanation)

Review Best Practices

Guidelines for Effective Review

  • Be respectful and constructive - remember there's a human on the other side
  • Ask questions instead of making demands
  • Explain your reasoning
  • Focus on the code, not the person
  • Acknowledge good work
  • Be specific in your feedback
  • Separate "must fix" from "nice to have"
  • Review promptly - don't leave PRs hanging

Be Patient

PRs often take weeks or months to merge. This is normal and healthy. Bitcoin Core prioritizes correctness over speed. Don't be discouraged if:

  • Your PR sits for weeks without review (reviewers are volunteers)
  • You need to make many revisions (thorough review is good!)
  • Your PR is eventually closed (maybe approach was wrong, try again)

The most important thing is learning and contributing quality code.

Hands-On Exercise: Navigate the Codebase

Goal: Get comfortable with Bitcoin Core's structure

Tasks:

  1. Clone Bitcoin Core and build it
  2. Find the code that validates transaction signatures (hint: src/script/interpreter.cpp)
  3. Find the RPC handler for getblockchaininfo (hint: src/rpc/blockchain.cpp)
  4. Run the unit tests and find one that tests UTXO selection
  5. Run a functional test of your choice and read its source code
  6. Find and read a recent merged PR on GitHub
  7. Leave a review comment on an open PR (even just "Concept ACK")

Bonus Challenge:

  • Fix a typo in documentation and open your first PR
  • Add a new functional test that tests basic wallet functionality
  • Review a "good first issue" PR thoroughly

Key Takeaways

  • Bitcoin Core is ~400k lines of C++ organized into consensus, networking, wallet, and RPC layers
  • Consensus-critical code requires extreme caution and extensive review
  • Development follows a fork → branch → commit → PR → review → merge workflow
  • Every change needs tests: unit tests, functional tests, and often fuzz tests
  • Code review is as important as writing code - maybe more important
  • Review feedback types: Concept ACK, Approach ACK, tACK, ACK, NACK
  • PRs take time to merge - patience and quality are valued over speed
  • Start with non-consensus changes while learning the codebase
  • The community values respectful, constructive collaboration

Essential Resources