Forking BitcoinJ for a New Coin

Under construction.

Step 2:  Forking GitHub Repositories

There are two parts to the android wallet of a coin.  The first part is the base library that handles the coin blockchain, peers and transactions.  This part will be forked from bitcoinj (the Java implimentation of the Bitcoin protocol).  The second part is the user interface, which is forked from Andreas Schildbach’s bitcoin-wallet.  These two repo’s are stored here:

https://github.com/bitcoinj/bitcoinj

Hash Engineering has forked this repo and modified it to make it easier to adapt their code for another coin.

https://github.com/HashEngineering/digitalcoinj

The main difference between the Hash Engineering fork and the original repo is that we added a class in the com.google.bitcoin.core package called CoinDefinition which stores all the key coin parameters.  It does not have the difficulty adjustment code.  To clone the HashEngineering repos do the following in the command prompt (after installing git) in the directory of your choice.

git clone https://github.com/HashEngineering/digitalcoinj my_coin_j

or to clone the bitcoin repos:

git clone https://github.com/bitcoinj/bitcoinj my_coin_j

Alternatively, you can fork either of these repos in your GitHub account using the “Fork this repo” button. Your account only allows 1 fork using this method per repo.  If you want to fork the same repo several times to handle many coin wallets, you will need to do the above method.  Once the two repos are forked, they can be renamed on the GitHub site.  Then you will need to clone it locally.

git clone https://github.com/<my_account>/my_coinj

Next, you should make sure that the origin remote on the local repo are set to your github account and that the upstream remote is set to the repo that it was cloned from.  This allows pulling changes from our repos or the bitcoin repos that may include bug fixes or new features.  The following command will allow you to check your remotes:

git remote -v

To set the upstream remote, use this command in your my_coinj repo:

git remote add upstream https://github.com/HashEngineering/digitalcoinj

Step 3 Modifying pom.xml

These files need to be changed to rename the Java packages.  It is not necessary to rename every occurrence of bitcoin to my_coin in the source code.

Step 4 Coin Parameters

The coin parameters include the hash function used for proof of work, network parameters (which include port, protocol version, packet magic numbers, etc) and difficulty adjustment.  Some coins also have other unique attributes such as the hashes for message, transaction signatures or perhaps even transaction comments.

Hash Functions and Proof of Work

The bitcoinj library is set up to use SHA256D (double SHA256) hashes for messages, address checksums, blocks, transactions, transaction signatures, merkle roots and the proof of work (which relates to difficulty).   Scrypt coins based on litecoin use the same SHA256 hashes except for the proof of work.  Quark uses a 9 rounds of various SHA-3 candidate hashes for its proof of work and block hashes, while other hashes still use SHA256D.  Understanding this is very important as using the wrong hash functions will definitely prevent the library from working.

In the CoinDefinition class (in digitalcoinj) there is a property called coinHash.  It only supports SHA256 and scrypt.  The value will indicate which hash is used for proof of work in the Block.checkProofOfWork method.  If bitcoinj is being forked for a scrypt coin, then some other code and libraries must be added to allow the checkProofOfWork method to use the correct POW hash.  Some coins use multiple proof of work functions.  In some cases they were changed after a certain block number (hard fork).  In other cases it depends on the hash function used to solve the block (for coins that have multiple algorithms such as myriadcoin and digitalcoin).

Genesis Block

Every parameter must be set correctly so that the hash generated from the genesis block after it is created matches the hash that is in the C++ source and the block explorers.  If a HashEngineering fork is being used then these parameters are available in the CoinDefinition class.  If using a bitcoinj fork, then the NetworkParameters class is used along with MainNetParams.

The following code is from CoinDefinition, but besides the genesis block time, difficulty, nonce, transaction in bytes and transaction out bytes, value that must be set, the hash value calculations are important.  That includes the hash value of the genesis block, merkelroot and transaction.  Bitcoin uses SHA256D for all of these, but GroestlCoin proved especially difficulty because it used Groestl512D, SHA256D and SHA256 for these three different hashes.

//main.cpp: LoadBlockIndex
static public long genesisBlockDifficultyTarget = (0x1e0ffff0L);
//main.cpp: LoadBlockIndex
static public long genesisBlockTime = 1368144664L;
//main.cpp: LoadBlockIndex                       
static public long genesisBlockNonce = (731837);
//main.cpp: hashGenesisBlock 
static public String genesisHash = "19225ae90d538561217b5949e98ca4964ac91af39090d1a4407c892293e4f44f"; 
//main.cpp: LoadBlockIndex 
static public int genesisBlockValue = 0;                                                              

//taken from the raw data of the block explorer
static public String genesisXInBytes = "04ffff001d01042f352f392f3230313320416964656e2077696c6c20626520612079656172206f6c6420696e2074776f206d6f6e746873";   //"5/9/2013 Aiden will be a year old in two months"
//from main.cpp:  LoadBlockIndex
static public String genessiXOutBytes = "040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9";

Network Parameters

These parameters include the communication protocols (pchMessageStart / packetMagic), port numbers,  protocol version and the public and private address parameters.  All of these parameters are specified in CoinDefinition (for HashEngineering forks) or in NetworkParameters and MainNetParams in bitcoinj forks.

Bloom Filters

Max. Money, Transaction Fees, Precision

Step 5 Difficulty Adjustments and Block Rewards

Block rewards are specified in the Block class for bitcoinj forks and the CoinDefinition class for HashEngineering forks.

 

The checkDifficultyAdjustments method of the AbstractBlockChain class does the Difficulty Adjustment calculation of GetNextWorkRequired (C++)checkDifficultyAdjustments throws an exception of the calculated difficulty doesn’t match the next block, where as GetNextWorkRequired returns the calculated difficulty for the next block.  Many coins have changed their difficulty adjustment algorithms with Hard Forks.  These complicate the code, but are necessary to include.

Examples of Difficulty Adjustment Algorithms

Linear – Bitcoin & Litecoin

KGW – Kimoto Gravity Well

DGW – Dark Gravity Wave

DGW2 – Dark Gravity Wave 2

DGW3 – Dark Gravity Wave 3

FGW – Franko Gravity Well

Freicoin

Peercoin (from Infinitecoin)

Multialgorithm – Digitalcoin & Myriadcoin

 

 

Step 6 Unit Tests

The unit tests in digitalcoinj or bitcoinj are not easily adapted to work on other coins.  Therefore they cannot be used to test the my_coinj library that you are creating unless you go through every test file and change the hard coded strings that apply only to Bitcoin.  Making these unit tests work for my_coin would a great benefit to ensure the reliability of all the coin parameters.

Step 7 BuildCheckpoints as a Test

Since the Unit tests are not reliable (without a lot of work), the next best way to test the my_coinj library is to run the BuiltCheckpoints.java file under the tools.  When this is run it will connect to the coin network (which will be through a locally running client) and begin to download the entire blockchain (headers only).  If there are any problems with any parameter or the difficulty retarget methods, then the BuildCheckpoints program will throw an exception or give other information in the logs that will indicate which parameter is not set correctly.  Later the resulting checkpoints file can be used to prevent new users from downloading the entire blockchain to sync their apps.  This will save battery life and time for new users or any user that needs to reset the blockchain.