Image for post
Image for post

Note: This guide has been updated as of Bitcoin-core release version 0.16.2 .


Bitcoin is an experimental peer to peer cryptocurrency utilizing new methods of cryptography combined with proof of work to prevent double spending of a scarce digital asset and achieve Byzantine Fault Tolerance. The bitcoin repository is on Github at: The bitcoin development is well managed by a global team that really knows what they are doing.

Join people in 22 countries around the world in my course on Become a Bitcoin + Blockchain Programmer.


The first thing to do is to fork the repo by clicking:

Image for post
Image for post

This will let you have your own copy of the repository in your account.

Test Build

A good first step is to make sure it builds on your system. Using Ubuntu 16.04, I found I needed to install some dependencies first:

$ sudo apt-get install software-properties-common -y
$ sudo add-apt-repository ppa:bitcoin/bitcoin
$ sudo apt-get update
$ sudo apt-get upgrade -y
$ sudo apt-get install libdb4.8-dev libdb4.8++-dev
$ ./
$ ./configure
$ make


There are several steps to make to ensure that your application does not conflict with Bitcoin. Also, there are several ways you can customize the consensus rules to fit your project’s needs. All customization is done in the src/ folder.

  1. Change default ports for all nets (mainnet, testnet, regtest):
nRPCPort = <port_number>; // in chainparamsbase.cppnDefaultPort = <port_number>; // in chainparams.cpp

2. Change the “magic message” or the message prefix for all nets (mainnet, testnet, regtest):

To generate random values that are not common ascii characters, here’s a hint:

$ python
>>> import random
>>> hex(random.randint(127,255))
// In chainparams.cpp
pchMessageStart[0] = 0x<random_byte_value>;
pchMessageStart[1] = 0x<random_byte_value>;
pchMessageStart[2] = 0x<random_byte_value>;
pchMessageStart[3] = 0x<random_byte_value>;

3. Change the address prefixes (optional) for all nets (mainnet, testnet, regtest) and for all address types (P2PKH, P2SH, and secret keys).

This determines the first character of an address (so it’s easily recognizable). Refer to List of Address Prefixes for which byte value to use for the character you want.

// In chainparams.cpp (see other nets below)
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,128);

4. Change the block reward (optional)

This is how many coins a miner gets for solving a block.

// in validation.cpp
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)

5. Change the coinbase maturity (optional)

This determines how many block confirmations are required to be able spend a mining reward (coinbase transaction).

// in consensus/consensus.h
static const int COINBASE_MATURITY = 100;

6. Change the halving interval (optional)

This determines how often the block reward is halved. In bitcoin it is halved every 2016 blocks or every 4 years (with a 10 min block time). Note this is one of the methods that indirectly affects the total coin supply.

CChainParams::nSubsidyHalvingInternal in chainparams.cpp.

7. Update max money check value (required if this should be different)

This is only for checking and doesn’t change the total coin supply. To do that you have to do the math between the halving interval, the block reward, and the block time. For that you can use my python script:

static const CAmount MAX_MONEY = 21000000 * COIN; in amount.h.

8. Reset minimum chain work

// In chainparams.cpp:
consensus.nMinimumChainWork = uint256S("0000000000000000000000000000000000000000000000000000000100010001");

9. Remove DNS seeds

These are nodes you can use to seed connections at the beginning.

  • In chainparams.cpp, remove lines start with vSeeds.emplace_back

10. Remove checkpoints

These are checkpoints in the blockchain, but you will start with nothing.

  • In chainparams.cpp, set checkpointData = {};


Allow blocks to be 10 years (4000 days) apart (to allow the original genesis block mined in 2009). Note you could also mine your own genesis block, but that is more involved.

// In validation.cpp:
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE * 4000;

12. Change block time (optional) for all nets (mainnet, testnet, regtest)

// In chainparams.cpp
consensus.nPowTargetSpacing = 10 * 60; // 60 seconds*10 = 10 minutes

13. Change the difficulty adjustment interval (optional) for all nets (mainnet, testnet, regtest)

This determines how often the block difficulty is adjusted so that the blocktime can average the consensus.nPowTargetSpacing parameter.

// in chainparams.cpp
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks

Managing Updates

Bitcoin has a slightly backwards approach to managing development on git than I have seen. The development is done on the master branch and releases have their own release candidate branch e.g. 0.16. Interestingly, bitcoin has still not had a major release (it’s still experimental). Patches are done on the release candidate branch.

To make updates from bitcoin easier, I’ve found it convenient to add the upstream fork using git remote add upstream and fetch the latest using git fetch upstream . This allows you to merge bitcoin’s work into your own branches.

I like to sync my master branch with the latest release candidate branch (after a release is posted). Then I will do development on the master branch, and merge that with my own release branch. Then I create a matching release (with my changes).

See the full course and join people in 22 countries around the world in my course on Become a Bitcoin + Blockchain Programmer.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store