Okay, this time I’m going to talk about how to claim the coinbase transaction from the genesis block, add premined coins, and change the number of coins issued.
Get the private key for the coinbase
Earlier, we used openssl to get a key pair to use for the genesis coinbase. We pasted the public key, in hex form, into the coinbase transaction of the genesis block. Under normal circumstances this coinbase is not spendable. Because there is no wallet at the time the coinbase transaction is created, the private key does not get saved into a wallet. But if we can import the private key into our wallet after the wallet is created, then the genesis coinbase can be spent.
So, go back to the key pair whose public key you used for the genesis coinbase. The corresponding private key is the one you need to spend it. But first you have to figure out what the heck it looks like in the base58 format that you can import into your wallet.
So you need to take the private key and do things to it, to get it into wallet-importable format.
Here is the sequence of steps you need to do:
First, take your private key: For this example, let’s say it’s
0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
(which it certainly won’t be, but I digress.)
Add the prefix byte for newcoin’s secret keys.
Then, whatever byte you picked as the value for base58prefixes[SECRET_KEY] when you were setting the network parameters, paste that byte in (in hex form!) as a prefix to the key. We’ll say our byte for base58prefixes was 0xAA.
So now you’ve got
AA0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
Find SHA256D of the result
Now you take double SHA256 of that, which you can do from the command line again.
echo AA0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF | xxd -r -p > temp
puts the key in binary form into the file temp.
openssl dgst -sha256 temp
outputs the SHA256 hash of that key. It will look like this:
SHA256(temp)= 855d46b953763179ae26937d7d5d9a7fbdf063f6e23fa5abc08e02b1ee202b0e
Now you copy the hex string and paste it into the following command:
echo 855d46b953763179ae26937d7d5d9a7fbdf063f6e23fa5abc08e02b1ee202b0e | xxd -r -p > temp2
The effect of that is to put the hash of the key, in binary form into the file temp2. So now you can get SHA256 of the hash like so:
openssl dgst -sha256 temp2
and openssl will spit out the hash of the hash.
The effect is to do 2 iterations of SHA256 on the private key: Without piping through xxd both times, we’d be doing SHA256 on a string of bytes which happens to be the ASCII representation of the hexadecimal string instead. Anyway, the output from that is the SHA256D hash of the prefix byte plus private key. For our example, it happens to be
SHA256(temp2)=02709d7a22eebf159eb9e67669afb4c565a6fa90d9ac2f6069beccce226b04ab
Extract the checksum bytes from the SHA256D hash
The first four bytes of that – which are 02, 70, 9d, 7a, are the checksum for the private key – this is a four-byte code that is appended to keys to make it extremely unlikely (about one chance in four billion) that a mistyped key will actually be a valid key. This is intended to make it unlikely that people spend coins to wrong addresses. Of course they do that anyway, but thanks to this checksum it’s not because they mistype the addresses.
Append the Checksum bytes to the prefix-extended key
Anyway, you take the key, with the prefix byte, and put the checksum bits at the end of it, so you get
AA0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF02709D7A.
Now, this is a number in hexadecimal, which you have to convert into base58check form. https://en.bitcoin.it/wiki/Base58Check_encoding on the bitcoin wiki explains how base58check is encoded, but doesn’t point at any handy utility to actually do it that doesn’t depend on bitcoin’s secret-key prefix. So I’m going to code one.
A simple little lisp dialect called Scheme, believe it or not, is my favorite scripting language. I have mit-scheme on my machine, and Scheme has standard bignums and understands numeric notation in hexadecimal. If you’re happier doing this sort of thing in Haskell or Eiffel or Python or whatever, use that instead. But I’ll actually write the six-line program for you if you want to use Scheme. If you don’t have it on your system, you can type
sudo apt-get install mit-scheme
to get it. Then at the command line type
mit-scheme
to start it, and paste this function definition into it:
(define (base58check input) (define (base58digit k) (string-ref "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" k)) (define (extractdigits n digits) (if (> 58 n) (list->string (cons (base58digit n) digits)) (extractdigits (quotient n 58) (cons (base58digit (modulo n 58)) digits)))) (extractdigits input '()))
Now you just have to give your key to that function as a hexadecimal number:
(base58check #xAA0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF02709D7A)
and mit-scheme will politely cough out the base58check form of it; In our example, this is the string
"6hU445Fi7j2WSwc2uLsbcQMJ1r2xbENWxGdfxTApKaRRaQ2Ppk1"
And that is the form of the key that you need to import into your wallet, to enable you to spend the coinbase transaction from the genesis block.
Cool, huh? Now type
(exit)
and then ‘y’ at the yes/no prompt, to quit scheme.
Adding a Premine
Now we’re going to come to one of the most abused features of cryptocurrency; I’m going to explain how to add a premine.
The next thing, if you want to treat the genesis coinbase as your premine, is the question, how to change the amount? There are three things you have to change. The obvious thing is in chainparams.cpp, in the line above the one where you pasted in the coinbase tx public key. It’s at the line where the code says
txNew.vout[0].nValue = 50 * COIN;
So, we’ll say you want 5000 coins instead of 50 for your premine. That’s an easy enough change here; you just change the number here so it says
txNew.vout[0].nValue = 5000 * COIN;
instead.
Change GetBlockValue to Allow your Premine
But this is only the obvious thing. There are two other things you have to change for this to work. The next one is the function GetBlockValue in main.cpp. If you don’t change this, your block chain will not be valid when your client tries to check it. This function says what the coinbases are supposed to be worth, and if the client checking the block chain finds a coinbase transaction that doesn’t match what this function says it ought to be, then it will reject the genesis block. The function looks like
CAmount GetBlockValue(int nHeight, const CAmount& nFees) { CAmount nSubsidy = 50 * COIN; int halvings = nHeight / Params().SubsidyHalvingInterval(); // Force block reward to zero when right shift is undefined. if (halvings >= 64) return nFees; // Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years. nSubsidy >>= halvings; return nSubsidy + nFees; }
and you want to make the subsidy for the block at height zero (ie, the genesis block) worth 5000 coins instead of 50. And while we’re here we might as well correct the comment’s assumption of ten-minute blocks. So your revised function can look like this:
CAmount GetBlockValue(int nHeight, const CAmount& nFees) { CAmount nSubsidy = (nHeight == 0 ? 5000 : 50) * COIN; int halvings = nHeight / Params().SubsidyHalvingInterval(); // Force block reward to zero when right shift is undefined. if (halvings >= 64) return nFees; // Subsidy is cut in half every 350,000 blocks which will occur approximately every 4 years. nSubsidy >>= halvings; return nSubsidy + nFees; }
Then go back to chainparams.cpp and set the subsidy halving interval to 350000 instead of 210000 to maintain the 4-year halving interval (assuming you want a 4-year halving interval). Another effect of this change is that it will also change your ultimate number of coins to be issued to be ~35M instead of ~21M.
Regenerate the Nonces
Okay, that was the second of three things. Now for the third. You should already know what this is. When we changed the genesis coinbase, We changed the hash of the transaction. And when we changed the hash of the transaction, we changed the merkle root in the genesis block. And that invalidated our nonce. So you need to mine your genesis blocks again.
I covered this already when I explained how to mine genesis blocks. You go back to chainparams.cpp, change the ‘false’s to ‘true’s, erase the ~/.newcoin directory, compile, and start it up. It’ll take a while. Then you look at the debug.log in the (re-created) ~/.newcoin directory to get the new values. Paste them in for the main params, Rinse, repeat, paste in the testnet params. Rinse, repeat, paste in the regtest params. Then change the ‘true’s to ‘false’s, and compile again.
So now newcoin has a genesis block coinbase with a premine of 5000 coins, and you have a key you can import into your wallet later which will allow you to actually spend the 5000 coins.
Changing the number of coins that can be issued
With your premine and different halving interval you’ve changed the number of coins that can be issued. But you need to change other parts of the code for this to be fully supported. The first and most obvious is in amount.h, where it says
/** No amount larger than this (in satoshi) is valid */ static const CAmount MAX_MONEY = 21000000 * COIN;
And, obviously, you change the 21000000 to 35004950. (remember, you added 4950 coins to the total when you changed the output of the genesis coinbase).
The second is in rpcserver.cpp, in the function AmountFromValue. It looks like this:
CAmount AmountFromValue(const Value& value) { double dAmount = value.get_real(); if (dAmount <= 0.0 || dAmount > 21000000.0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); CAmount nAmount = roundint64(dAmount * COIN); if (!MoneyRange(nAmount)) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); return nAmount; }
And once again, you need to change that 21000000 to 35004950. And now you have code for a client that is correct for your new block spacing and coin distribution.
Yes, I will cheerfully admit that this set of instructions is incomplete. It gets you 95% of the way there but this is the most abused thing in the world and idiots are always launching cryptocurrencies while absolutely clueless about how they work, so I left one roadbump that you still have to figure out.
You will have to do testing and understand at least part of what the code does to find it.
If you launched without fixing it and discover you can’t spend your premine, you (don’t) deserve what you (don’t) get for (not) understanding the code.