Forking an altcoin
from Bitcoin

Toptal academy Blockchain lectures #4

2018-03-05

ivan.voras@toptal.com

Today's agenda

  • Descriptions of minimal necessary changes to fork a cryptocurrency from Bitcoin
  • Live demo

What is a cryptocurrency blockchain?

  • Genesis block
  • Consensus rules
  • Network protocol
  • Peers / clients (miners + users)

How to fork a cryptocurrency

  1. Fork the code itself (e.g. Github)
  2. Change the genesis block (& hash)
  3. Change network ports
  4. Change seed servers
  5. Change checkpoints
  6. Adjust difficulties
  7. ???
  8. Profit

 

In Bitcoin and cryptocurrencies forked from Bitcoin, most of this is in chainparams.c / chainparams.h

Mining the Genesis block

Needs to be done "manually" by adding code, because mining was removed from the official Bitcoin Core software.

 

Difficulty statement:

if block_hash < difficulity_target: return True

 

nBits: compact representation of the difficulty target

 

0x1d00ffff

 

number of 0 bytes+3

prefix

means: starts with 00ffff, and 0x1d-3=26 zero bytes

Mining the Genesis block

So if nBits is 0x1d00ffff, the difficulty statement is:

 

if block_hash < 0x00000000ffff0000000000000000000000000000000000000000000000000000: true

 

Because of the nBits format, the "easiest" difficulty still has 3 bytes fixed.

In chainparams.cpp, around line 150:

srand(time(NULL));
genesis = CreateGenesisBlock(1520173282, rand(), 0x1f00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
while (!CheckProofOfWork(genesis.GetHash(), genesis.nBits, consensus.powLimit)) {
    genesis.nNonce++;
    if (genesis.nNonce % (1024*1024) == 0) {
      printf("Genesis mining trying %u\r", genesis.nNonce);
    }
}
printf("@@@ mainnet new genesis block hash: %s\n@@ merkle root: %s\n@@ nonce: %x\n", consensus.hashGenesisBlock.GetHex().c_str(), genesis.hashMerkleRoot.GetHex().c_str(), genesis.nNonce);
assert(consensus.hashGenesisBlock == uint256S("0x1cae3ba472a97ef60cb3e9b72cc0588142574db4b8a0f0680091ddadb998a1ea"));
assert(genesis.hashMerkleRoot == uint256S("0xebe85c5648c26076e6db053964c402882b0ed89393d23ab978f1795e35d0b10d"));

 

mining :)

lower difficulty (less leading 0s),

also needs lowering the powLimit

In chainparams.cpp, at beginning:

bool CheckProofOfWork(uint256 hash, unsigned int nBits, uint256 powLimit)
{
  bool fNegative;
  bool fOverflow;
  arith_uint256 bnTarget;
  bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
  // Check range
  if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(powLimit))
      return false;
  // Check proof of work matches claimed amount
  if (UintToArith256(hash) > bnTarget)
      return false;
  return true;
}

Adapted from pow.cpp

Helpful links

 

 

Next: live demo

Notes

  • Addresses begin with 5 in this version/fork, e.g. 5L1k8Pn6mRXv96C9AH6v7sQ1r2WWcwiZyU 
  • Start bitcoind with:
    ./bitcoind -datadir=/home/ivoras/btcdata/ -server -rpcuser=user -rpcpassword=password -rpcallowip=10.0.0.0/24 -debug=1 -prematurewitness
  • Use the same rpcuser / rpcpassword parameters (or a config file) to issue bitcoin-cli commands (like getnewaddress)
  • Start minerd with:
    minerd -a sha256d -O user:password -o http://127.0.0.1:8332 --coinbase-addr=5L1k8Pn6mRXv96C9AH6v7sQ1r2WWcwiZyU
  • Diff for chainparams.cpp:
    https://gist.github.com/ivoras/6e18ed32151d579b428e9dd00ad2f285

Note on addresses

Build screenshot

debug.log (in datadir)

Make one yourself...

Homework

 

  • Fork a cryptocurrency from Bitcoin (or any other template, if you're feeling adventurous)
  • Mine some blocks, e.g. by using the cpuminer ("minerd")
  • Inspect the blocks and the transactions
  • Explore, play with it.

 

Blockchain lectures #4: Forking an altcoin from Bitcoin

By Ivan Voras

Blockchain lectures #4: Forking an altcoin from Bitcoin

The minimal set of changes which need to be made to the C++ code of the Bitcoin Core daemon to make a new cryptocurrency.

  • 754