This post is based on
https://bitcointalk.org/index.php?topic=225690.0 and is an update to it.
Disclaimer:I was trying to setup my own private bitcoin network and understand how it works. Thanks to fisheater’s famous post(150k read!)(
https://bitcointalk.org/index.php?topic=225690.0) I could get a start. However, it was created in 2013 and I found some of the changes no longer applies today. So I made this post as an update.
I used the same title, but this is not a post to guide how to make new coins or ICOs, just help to study how bitcoin and blockchain works only.
This post does not include making changes to the qt GUI program, only command line programs.
This post is based on bitcoin core code base, not litecoin.
Preparation:Download the bitcoin core full source code, if you cloned the source tree, make a new branch to work on. Setup the compiling environment and make a successful build.
Design the coin’s parameters:Refer to fisheater’s post.
Code change:1. Name substitution
You could run a search in the whole tree and replace all occurrences of “bitcoin” or “BTC” to your coin name. But this is not important.
2. Network ports
2.1 Change RPC port:
CBaseChainParams::nRPCPort in chainparamsbase.cpp
2.2 Change deamon port:
CChainParams::nDefaultPort in chainparams.cpp
3. Message signature
Choose a different message start signature:
CChainParams::pchMessageStart in chainparams.cpp
pchMessageStart[0] = 0xf0;
pchMessageStart[1] = 0xb0;
pchMessageStart[2] = 0xb0;
pchMessageStart[3] = 0xd0;
This is important, without this change, if you accidentally connect your node to the bitcoin network, it will decide that bitcoin’s chain is longer and starting to download the real bitcoin blocks hence override your coin’s blocks.
4. Address prefixes:
Choose your preferred address prefix letter. Refer to the table in
https://en.bitcoin.it/wiki/List_of_address_prefixes, for example, if you want address start with ‘X’, use 75 or 76.
CChainParams::base58Prefixes in chainparams.cpp.
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,75);
You can also choose prefixes of segwit address, private keys, and extended keys.
5. Block reward
This decide how many coins are generated for each mined blocks.
in validation.cpp:
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
// Force block reward to zero when right shift is undefined.
if (halvings >= 64)
return 0;
CAmount nSubsidy = (1 << 10) * COIN; // Initial block reward 1024 coins
// Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
nSubsidy >>= halvings;
return nSubsidy;
}
6. Coinbase maturity
This decide how many blocks after could the generated coins be spent.
in consensus/consensus.h:
static const int COINBASE_MATURITY = 100;
7. Halving interval
How many blocks will block reward be halved.
CChainParams::nSubsidyHalvingInternal in chainparams.cpp.
8. Max money
static const CAmount MAX_MONEY = 21000000 * COIN; in amount.h.
Note this isn’t the total supply of the coins, and modify this value won’t limit the total number of coins can be generated. The total coin is controlled by block reward in GetBlockSubsidy, this is just a value to help run sanity checks.
9. Minimum chain work
This is the minimum chain work required to consider the blockchain is updated. Set this to the minimum value otherwise your coin will not mine. When you have mined some blocks, this can be updated to a larger value.
In chainparams.cpp:
consensus.nMinimumChainWork = uint256S("0000000000000000000000000000000000000000000000000000000100010001");
10. Remove dns seeds
In chainparams.cpp, remove lines start with “vSeeds.emplace_back”
11. Remove checkpoints
In chainparams.cpp, set checkpointData = { };
12. Generate genesis block
Bitcoin’s block have to satisfy certain difficulty, so you cannot just modify genesis parameters and use that arbitrary block hash, you have to mine the genesis block.
12.1 Generate a private key and get its public key, e.g.
048E794284AD7E4D776919BDA05CDD38447D89B436BDAF5F65EBE9D7AD3A0B084908B88162BB60B1AA5ED6542063A30FC9584A335F656A54CD9F66D6C742B67F55
12.2 Choose a genesis message, like a New York Times headline
NY Times 07/Apr/2018 More Jobs, Faster Growth and Now, the Threat of a Trade War
12.3 Get and compile the genesis block generator from
https://github.com/liveblockchain/genesisgenThe program is based on Remember remember the 5th of November’s post
https://bitcointalk.org/index.php?topic=181981.0, with an improvements:
The timestamp string cannot be longer than 91 bytes, since the coinbase transaction’s scriptSig is limited to 100 bytes. Also, when the string is longer than 76 bytes, add OP_PUSHDATA1(0x4c) prefix into the script.
gcc genesis.c -o genesis -lcrypto
12.4 Feed the data into the program and let it mine the genesis block
$ ./genesis 048E794284AD7E4D776919BDA05CDD38447D89B436BDAF5F65EBE9D7AD3A0B084908B88162BB60B1AA5ED6542063A30FC9584A335F656A54CD9F66D6C742B67F55 "NY Times 07/Apr/2018 More Jobs, Faster Growth and Now, the Threat of a Trade War" 486604799
nBits: 0x1d00ffff
startNonce: 0
unixtime: 0
Coinbase: 04ffff001d01044c504e592054696d65732030372f4170722f32303138204d6f7265204a6f62732c204661737465722047726f77746820616e64204e6f772c2074686520546872656174206f66206120547261646520576172
PubkeyScript: 41048e794284ad7e4d776919bda05cdd38447d89b436bdaf5f65ebe9d7ad3a0b084908b88162bb60b1aa5ed6542063a30fc9584a335f656a54cd9f66d6c742b67f55ac
Merkle Hash: 63f73f6e72c8355d21b5c198406fde2480acf0263fec63dcbe7f6165d410c2c8
Byteswapped: c8c210d465617fbedc63ec3f26f0ac8024de6f4098c1b5215d35c8726e3ff763
Generating block...
939453 Hashes/s, Nonce 23980758224
Block found!
Hash: 00000000ad913538b8764573d00c3eb4a87723e11d8bd008f9125246c58e0252
Nonce: 2398108787
Unix time: 1524021159
12.5 When it’s done, set the block data in chainparams.cpp
In CMainParams constructor, set the nonce and unittime, block hash and merkle root assertions:
genesis = CreateGenesisBlock(1524021159, 2398108787, 0x1d00ffff, 1, 50 * COIN);
assert(consensus.hashGenesisBlock == uint256S("0x00000000ad913538b8764573d00c3eb4a87723e11d8bd008f9125246c58e0252"));
assert(genesis.hashMerkleRoot == uint256S("0xc8c210d465617fbedc63ec3f26f0ac8024de6f4098c1b5215d35c8726e3ff763"));
in function static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward), set the timestap string:
const char* pszTimestamp = "NY Times 07/Apr/2018 More Jobs, Faster Growth and Now, the Threat of a Trade War";
const CScript genesisOutputScript = CScript() << ParseHex("048e794284ad7e4d776919bda05cdd38447d89b436bdaf5f65ebe9d7ad3a0b084908b88162bb60b1aa5ed6542063a30fc9584a335f656a54cd9f66d6c742b67f55") << OP_CHECKSIG;
13. If you do not want to generate your own genesis block, you can just use the original bitcoin genesis block, but update the DEFAULT_MAX_TIP_AGE value to a larger value.
In validation.cpp:
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE * 4000;
DEFAULT_MAX_TIP_AGE is one day, if the gap between the tip block and current time, the node won’t mine new blocks, so set this at least to the time elapsed since the creation of bitcoin in Jan 2009.
Mining1. Get cpuminer from
https://github.com/pooler/cpuminer and build it
2. Start mining
./minerd --user rpcuser --pass 111111 --url http://127.0.0.1:6332/ --threads 4 --coinbase-addr XQg3PmNxX9oEbxsymqtQHir6dkPpVPTJ6P --coinbase-sig "my test coins" -a sha256d -D
When a block is mined, you will notice bitcoind will log something like this:
2018-04-18 02:31:52 UpdateTip: new best=00000000fbf2808044cbcf00ddb54988c600f65c0960dcf5143bc0a1ed84da39 height=1 version=0x20000000 log2_work=33.000022 tx=2 date='2018-04-18 02:31:36' progress=0.000000 cache=0.0MiB(1txo)
2018-04-18 02:31:52 CreateNewBlock(): block weight: 764 txs: 0 fees: 0 sigops 400
2018-04-18 02:31:52 AddToWallet 8663f334ca80d55ed41ebaaf313935163d57ba3eead98399a3e0b4a2cf679b81 new
You have now made your own coins. Enjoy!