Skip to main content

Creating Your Own Bitcoin Core Fork

You don't have to accept every decision made by Bitcoin Core developers. Bitcoin is open source software — you can modify it to match your preferences. This guide shows how to create a minimal fork with a single policy change: restoring the original OP_RETURN data carrier size limit.

Why Implementation Diversity Matters

Bitcoin's security model assumes no single entity controls the network. But what about the software that runs the network?

The Current State

Bitcoin Core: ~77%
Bitcoin Knots: ~23%
All others: ~1%

As of July 2026 (Coin Dance: 22.7%; bitdis.org: 22.97%) · Live data: coin.dance/nodes

This is a monoculture problem. When ~99% of nodes run code from two closely-related implementations:

  • A single bug could affect almost the entire network
  • Governance becomes centralized in a small group of maintainers
  • Alternative views on policy get marginalized
  • Users have limited real choice

The Case for More Implementations

Every additional implementation strengthens Bitcoin:

More ImplementationsBenefit
More codebasesBugs in one don't affect all
More maintainersNo single point of capture
More policy optionsUsers get real choices
More reviewDifferent eyes catch different issues

Your fork could become the third slice on that pie chart.

Even if only 1% of nodes run your implementation, that's:

  • ~200+ nodes worldwide
  • Independent verification of consensus rules
  • A credible alternative if Core/Knots go astray

Two Paths: Personal or Public

This guide works for both goals:

Path A: Personal Fork

  • Run your own policies
  • Understand exactly what your node does
  • Learn how Bitcoin works at the code level
  • No need to maintain for others

Path B: Public Implementation

  • Distribute your fork for others to run
  • Build a community around your vision
  • Become a slice on the pie chart
  • Commit to ongoing maintenance and security updates
Start Personal, Go Public Later

Most successful implementations started as personal projects. Build something you want to run yourself first.


Why Fork?

The Scenario

Bitcoin Core v30 raised the default standardness limit on OP_RETURN outputs from 80 bytes of data to 100,000 bytes, and marked the -datacarrier/-datacarriersize options as deprecated. The policy limit still technically exists, but at 100 kB it no longer meaningfully constrains data storage.

You might:

  • Disagree with this change
  • Want the old behavior back
  • Not want to switch to a full alternative like Bitcoin Knots
  • Prefer to understand exactly what's different in your node

The Philosophy of Minimal Changes

The safest approach to forking Bitcoin is minimal divergence:

  1. Change only what you need — Every modification is potential risk
  2. Policy, not consensus — Never touch consensus rules unless you want a new coin
  3. Track upstream — Stay close to Core for security updates
  4. Document everything — Future you needs to understand past you
Policy vs Consensus

Policy rules affect what your node relays and mines, but don't affect block validity. You can change these freely.

Consensus rules determine what blocks are valid. Changing these creates a new cryptocurrency (intentionally or accidentally).

OP_RETURN limits are policy only — safe to modify.

The Change We're Making

We're going to restore the pre-v30 behavior:

SettingCore v29Core v30+Our Fork
Default datacarriersize83100,000 bytes83
-datacarrier/-datacarriersize optionsSupportedDeprecatedSupported
OP_RETURN relayLimitedEffectively unconstrainedLimited

This is a one-line change that affects default behavior while still allowing users to override it via configuration.

Prerequisites

You'll need:

  • Git — Version control
  • Build tools — CMake (3.22+) and a C++ compiler
  • Dependencies — Libraries Bitcoin Core needs
  • ~50GB disk space — For source, build artifacts, and regtest testing (a synced mainnet node additionally needs ~700 GB for the full blockchain, or ~25 GB pruned)
  • 2-4 hours — For first build (faster on subsequent builds)

Install Build Dependencies

Since v29, Bitcoin Core builds with CMake (autotools is gone), and from v30 the GUI requires Qt 6.

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y build-essential cmake pkgconf python3
sudo apt-get install -y libevent-dev libboost-dev libsqlite3-dev
# Optional: ZMQ notifications
sudo apt-get install -y libzmq3-dev
# For GUI (optional, Qt 6)
sudo apt-get install -y qt6-base-dev qt6-tools-dev qt6-l10n-tools qt6-tools-dev-tools

macOS:

brew install cmake boost pkgconf libevent sqlite qt@6 zeromq

For other systems, see Core's build documentation.

Step 1: Clone Bitcoin Core

# Create a workspace
mkdir -p ~/bitcoin-dev
cd ~/bitcoin-dev

# Clone the official repository
git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin

# See available release tags
git tag -l 'v3*' | tail -10

Step 2: Create Your Fork Branch

Choose a recent stable release as your base:

# Check out the latest stable release (example: v31.0)
git checkout v31.0

# Create your fork branch
git checkout -b my-policy-fork

# Verify you're on your new branch
git branch

As of mid-2026, v31.0 is the latest stable release; the 30.x series is maintained at v30.2 if you prefer an older base.

Naming convention suggestion: v31.0-mypolicy or v31.0-opreturn-limit

Step 3: Find the Code to Change

Let's locate where the OP_RETURN limit is defined:

# Search for datacarriersize
grep -rn "datacarriersize" src/

# Search for the default value
grep -rn "MAX_OP_RETURN" src/
grep -rn "nMaxDatacarrierBytes" src/

In Bitcoin Core v30 and later, the key files are:

  • src/policy/policy.h — Default constants
  • src/policy/policy.cpp — Policy implementation
  • src/init.cpp — Command-line argument handling

Let's examine the relevant code:

# View the policy header
cat src/policy/policy.h | head -80

Step 4: Make the Change

Understanding the Current Code

In Core v30 and later, you'll find something like:

src/policy/policy.h (Core v30+ - simplified)
/** Default for -datacarriersize */
static constexpr unsigned int MAX_OP_RETURN_RELAY{100'000};

In earlier versions (v29 and before):

src/policy/policy.h (Core v29)
/** Default for -datacarriersize */
static const unsigned int MAX_OP_RETURN_RELAY = 83;

Making the Edit

Open the file in your editor:

# Use your preferred editor
nano src/policy/policy.h
# or
vim src/policy/policy.h
# or
code src/policy/policy.h

Find the MAX_OP_RETURN_RELAY constant and change it back to 83:

src/policy/policy.h (your change)
/**
* Default for -datacarriersize. 83 bytes allows up to 80 bytes of data
* after accounting for the OP_RETURN opcode and pushdata opcodes.
*
* MODIFIED: Restored pre-v30 default limit.
*/
static constexpr unsigned int MAX_OP_RETURN_RELAY = 83;
Why 83?
  • 1 byte for OP_RETURN opcode
  • 1-2 bytes for pushdata opcode
  • 80 bytes of actual data
  • Total: ~83 bytes

Check if there are other places that need updating:

grep -rn "MAX_OP_RETURN_RELAY\|datacarriersize\|nMaxDatacarrier" src/

You may need to update src/init.cpp if the argument handling changed:

src/init.cpp (if needed)
// Ensure the default matches your constant
argsman.AddArg("-datacarriersize",
strprintf("Maximum size of data in OP_RETURN outputs we relay and mine (default: %u)",
MAX_OP_RETURN_RELAY),
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);

Step 5: Document Your Change

Create a file documenting what you changed:

cat > doc/my-policy-changes.md << 'EOF'
# My Policy Fork Changes

## Overview

This fork restores the pre-v30 OP_RETURN data carrier size limit.

## Changes from Bitcoin Core v31.0

### 1. OP_RETURN Size Limit (src/policy/policy.h)

- **Before (Core v30+):** 100,000 bytes by default
- **After (this fork):** 83 bytes (80 bytes of data)

This is a **policy-only** change. It affects:
- What transactions this node relays
- What transactions this node includes in block templates

It does NOT affect:
- Block validation (consensus)
- What blocks this node accepts
- Network compatibility

### Rationale

[Your reasoning here - e.g., "Reduce bandwidth for non-financial data"]

### Configuration

Users can still override this default:
```ini
# To allow larger OP_RETURN (not recommended)
datacarriersize=1000000

# To disable OP_RETURN relay entirely
datacarriersize=0
```

## Compatibility

This fork maintains full consensus compatibility with Bitcoin Core.
Nodes running this fork will:
- Accept all valid blocks
- Be indistinguishable on the network (except for relay behavior)
- Work with all Bitcoin wallets and services

## Updating

To update this fork when Core releases a new version:
1. Fetch upstream: `git fetch origin`
2. Rebase: `git rebase v31.1` (or merge)
3. Resolve conflicts in policy.h
4. Rebuild and test

EOF

Step 6: Commit Your Changes

# Stage your changes
git add src/policy/policy.h
git add doc/my-policy-changes.md

# Commit with a clear message
git commit -m "policy: Restore 83-byte OP_RETURN default limit

Reverts the default datacarriersize to 83 bytes (80 bytes of data),
matching pre-v30 behavior.

This is a policy-only change that does not affect consensus.
Users can still override via -datacarriersize configuration.

Rationale: [Your reason]"

Step 7: Build Your Fork

Bitcoin Core uses CMake (since v29) — there is no autogen.sh or ./configure anymore.

Configure

# Basic build (no GUI, no tests)
cmake -B build -DBUILD_TESTS=OFF

# With GUI (Qt 6)
cmake -B build -DBUILD_GUI=ON

# See all options
cmake -B build -LH

Recommended for first build:

cmake -B build -DBUILD_TESTS=OFF

Compile

# Use all CPU cores
cmake --build build -j$(nproc)

# Or specify core count
cmake --build build -j4

This takes 30-90 minutes depending on your hardware. Binaries land in build/bin/.

Verify Build

# Check the binaries exist
ls -la build/bin/bitcoind build/bin/bitcoin-cli

# Check version
./build/bin/bitcoind --version

# Verify your change is present
./build/bin/bitcoind -help | grep datacarriersize

Step 8: Test Your Fork

Basic Functionality Test

# Create a test data directory
mkdir -p /tmp/bitcoin-test

# Start in regtest mode (private test network)
./build/bin/bitcoind -regtest -datadir=/tmp/bitcoin-test -daemon

# Wait a moment, then test RPC
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test getblockchaininfo

# Check your policy setting
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test getnetworkinfo

# Stop the node
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test stop

Test the OP_RETURN Limit

# Start regtest node
./build/bin/bitcoind -regtest -datadir=/tmp/bitcoin-test -daemon
sleep 2

# Create a wallet and generate some coins
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test createwallet "test"
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test -generate 101

# Create an OP_RETURN transaction with 80 bytes of data (should work)
# This requires more complex scripting - see Bitcoin Core's functional tests
# for examples of creating OP_RETURN transactions

# Cleanup
./build/bin/bitcoin-cli -regtest -datadir=/tmp/bitcoin-test stop
rm -rf /tmp/bitcoin-test
# Rebuild with tests enabled (the default)
cmake -B build -DBUILD_TESTS=ON
cmake --build build -j$(nproc)

# Run unit tests
ctest --test-dir build

# Run the functional test suite
./build/test/functional/test_runner.py

# Run specific policy tests
./build/test/functional/mempool_datacarrier.py

Step 9: Install Your Fork

Option A: Install System-Wide

sudo cmake --install build

This installs to /usr/local/bin/. Your system's bitcoind is now your fork.

Option B: Run from Build Directory

# Add to your PATH
export PATH="$HOME/bitcoin-dev/bitcoin/build/bin:$PATH"

# Or create aliases
alias bitcoind-custom="$HOME/bitcoin-dev/bitcoin/build/bin/bitcoind"
alias bitcoin-cli-custom="$HOME/bitcoin-dev/bitcoin/build/bin/bitcoin-cli"

Option C: Parallel Installation

# Configure with a different install prefix
cmake -B build -DCMAKE_INSTALL_PREFIX=$HOME/bitcoin-custom
cmake --build build -j$(nproc)
cmake --install build

# Run with explicit path
~/bitcoin-custom/bin/bitcoind

Step 10: Maintaining Your Fork

Staying Updated

When Bitcoin Core releases security updates, you need to update your fork:

cd ~/bitcoin-dev/bitcoin

# Fetch upstream changes
git fetch origin

# See new tags
git tag -l 'v3*' | tail -5

# Option A: Rebase onto new version (cleaner history)
git checkout my-policy-fork
git rebase v31.1

# Option B: Merge new version (preserves history)
git checkout my-policy-fork
git merge v31.1

# Resolve any conflicts in policy.h
# The conflict will likely be straightforward - just keep your value

# Rebuild from scratch
rm -rf build
cmake -B build [your options]
cmake --build build -j$(nproc)

(Substitute whatever the newest tag actually is — e.g. a future v31.x point release, or v30.2 if you track the 30.x series.)

Tracking Changes

Keep a simple changelog:

cat >> doc/my-policy-changes.md << 'EOF'

## Changelog

### v31.1-mypolicy (2026-XX-XX)
- Rebased onto Bitcoin Core v31.1
- No additional changes

### v31.0-mypolicy (2026-XX-XX)
- Initial fork from Bitcoin Core v31.0
- Restored 83-byte OP_RETURN default

EOF

Advanced: Multiple Policy Changes

If you want to make additional changes, follow the same pattern:

Example: Also Restore Dust Limit

src/policy/policy.h
// Restore stricter dust limit
static constexpr CAmount DUST_RELAY_TX_FEE = 3000; // sat/kvB

Example: Disable OP_RETURN by Default

src/policy/policy.h
// Disable OP_RETURN relay by default
static constexpr unsigned int MAX_OP_RETURN_RELAY = 0;

Keep Changes Isolated

Make separate commits for each policy change:

git commit -m "policy: Restore OP_RETURN limit"
git commit -m "policy: Increase dust threshold"
git commit -m "policy: Disable bare multisig"

This makes it easier to:

  • Understand what changed
  • Cherry-pick specific changes
  • Resolve conflicts during updates

Publishing Your Fork (Optional)

If you want others to use your fork:

Create a GitHub Repository

# Create repo on GitHub first, then:
git remote add myfork https://github.com/yourusername/bitcoin-mypolicy.git
git push -u myfork my-policy-fork

Document for Users

Create a clear README:

# Bitcoin Core + Policy Tweaks

This is a minimal fork of Bitcoin Core with the following changes:
- Restored 83-byte OP_RETURN limit (pre-v30 default)

## Compatibility
100% consensus compatible with Bitcoin Core. Same blocks, same chain.

## Building
Same as Bitcoin Core. See doc/build-*.md

## Differences from Core
See doc/my-policy-changes.md

Why Knots Instead?

After going through this process, you might appreciate why Bitcoin Knots exists:

DIY ForkBitcoin Knots
You maintain itCommunity maintained (led by Luke Dashjr, longest-active Core contributor)
You handle security updatesTracks Core security fixes
Single policy changeMany useful options
Your testing onlyCommunity tested
No GUI improvementsDark mode, mempool stats, etc.

Knots already includes the OP_RETURN limit (and makes it configurable). Knots traditionally defaulted datacarriersize to 42; current releases temporarily default to 83:

bitcoin.conf (Knots)
# Knots: Set OP_RETURN limit explicitly (or the stricter traditional 42)
datacarriersize=83

# Or use Core-compatible permissive policy
corepolicy=1

See Also