自分でアルトコインを作ってみる②
前回の続きです。
自分のアルトコインをつくっていきます。
前回の記事でやったこと
- ライトコインのコードをダウンロードする
- 名前をHagicoin(HGC)に変更する
- コンパイルに必要なツールをインストールする
今回の記事で最後まで一気に書いていきます。
ちょっと長くなりますが、頑張りましょう!
ソースコードを編集していきます
< src/main.cpp における操作>
・"hashGenesisBlock"を検索し、ハッシュ値を変更してリセットする(2つあります)
hashGenesisBlock = uint256("0xf5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f");
↓
hashGenesisBlock = uint256("0x");
・"pchMessageStart"の変更
pchMessageStart[0] = 0xfc; pchMessageStart[1] = 0xc1;
↓
pchMessageStart[0] = 0xf2; pchMessageStart[1] = 0xc3;
・InitBlockIndex() をテキトウな値に変更(パブリックキー)
txNew.vout[0].scriptPubKey = CScript() << ParseHex("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9") << OP_CHECKSIG;
↓
txNew.vout[0].scriptPubKey = CScript() << ParseHex("123456789040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9") << OP_CHECKSIG;
・初期ブロックのメッセージを変更(なんでもいいです。)
今回はコインチェックのニュースを入れてみました。
const char* pszTimestamp = "NY Times 05/Oct/2011 Steve Jobs, Apple’s Visionary, Dies at 56";
↓
const char* pszTimestamp = "BBC NEWS 27/Jan/2018 Coincheck: World's biggest ever digital currency 'theft'";
・ナンス値を0にする(2つあります)
block.nNonce = 2084524493;
↓
block.nNonce = 0;
・ epoch timeを現在の値に変更
まずこのリンクで現在の epoch timeを取得し、コピペ。
Epoch Converter - Unix Timestamp Converter
赤枠の数字を以下のコードにペースト(2つあります)
block.nTime = 1317798646;
↓
block.nTime = 1517405314;
・hashMerkleRootのハッシュ値をリセット
assert(block.hashMerkleRoot == uint256("0x97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9"));
↓
assert(block.hashMerkleRoot == uint256("0x"));
・TimeSpanを短縮する
static const int64 nTargetTimespan = 3.5 * 24 * 60 * 60; // Hagicoin: 3.5 days static const int64 nTargetSpacing = 2.5 * 60; // Hagicoin: 2.5 minutes
↓
static const int64 nTargetTimespan = 5 * 30; // Hagicoin: 5 minitus static const int64 nTargetSpacing = 1 * 30; // Hagicoin: 30 seconds
< checkpoint.cpp における操作>
・mapCheckpointsの中身変更、余計な部分を消す(1個目)
static MapCheckpoints mapCheckpoints = boost::assign::map_list_of ( 1500, uint256(“0x841a2965955dd288cfa707a755d05a54e45f8bd476835ec9af4402a2b59a2967”)) ( 4032, uint256(“0x9ce90e427198fc0ef05e5905ce3503725b80e26afd35a987965fd7e3d9cf0846”)) : : (585010, uint256(“0xea9ea06840de20a18a66acb07c9102ee6374ad2cbafc71794e576354fea5df2d”)) (638902, uint256(“0x15238656e8ec63d28de29a8c75fcf3a5819afc953dcd9cc45cecc53baec74f38”)) ;
↓
static MapCheckpoints mapCheckpoints = boost::assign::map_list_of ( 0, uint256(“0x”)) ;
・コメントアウトする(1個目)
※削除しても問題ないと思います。
static const CCheckpointData data = { &mapCheckpoints, 1410516073, // * UNIX timestamp of last checkpoint block 4896865, // * total number of transactions between genesis and last checkpoint // (the tx=… number in the SetBestChain debug.log lines) 7000.0 // * estimated number of transactions per day after checkpoint };
↓
static const CCheckpointData data = { &mapCheckpoints, //1410516073, // * UNIX timestamp of last checkpoint block //4896865, // * total number of transactions between genesis and last checkpoint // (the tx=… number in the SetBestChain debug.log lines) //7000.0 // * estimated number of transactions per day after checkpoint };
・mapCheckpointsの中身変更(2個目)とコメントアウト(2個目)
static MapCheckpoints mapCheckpointsTestnet = boost::assign::map_list_of ( 546, uint256(“0xa0fea99a6897f531600c8ae53367b126824fd6a847b2b2b73817a95b8e27e602”)) ; static const CCheckpointData dataTestnet = { &mapCheckpointsTestnet, 1365458829, 547, 576 };
↓
static MapCheckpoints mapCheckpointsTestnet = boost::assign::map_list_of ( 0, uint256(“0x”)) ; static const CCheckpointData dataTestnet = { &mapCheckpointsTestnet, //1365458829, //547, //576 };
・以下のリンクのコードを挿入
gist.github.com
⇒一度デバッグして、最初のハッシュ値とナンス値を出力する(初期ブロック生成のため)
※一番外側のif文の閉じかっこ"}"が抜けているので足しておいてください。
//// debug print uint256 hash = block.GetHash(); printf(“%s\n”, hash.ToString().c_str()); printf(“%s\n”, hashGenesisBlock.ToString().c_str()); printf(“%s\n”, block.hashMerkleRoot.ToString().c_str()); assert(block.hashMerkleRoot == uint256(“0x”)); //----------------------------------- ここに追加コードを挿入 //------------------------------------ block.print(); assert(hash == hashGenesisBlock);
< net.cpp における操作>
・最初に接続する場所の変更、余計な部分を削除
// DNS seeds // Each pair gives a source name and a seed name. // The first name is used as information source for addrman. // The second name should resolve to a list of seed addresses. static const char *strMainNetDNSSeed[][2] = { {"hagicointools.com", "dnsseed.hagicointools.com"}, {"hagicoinpool.org", "dnsseed.hagicoinpool.org"}, {"xurious.com", "dnsseed.ltc.xurious.com"}, {"koin-project.com", "dnsseed.koin-project.com"}, {"weminemnc.com", "dnsseed.weminemnc.com"}, {NULL, NULL} };
↓
// DNS seeds // Each pair gives a source name and a seed name. // The first name is used as information source for addrman. // The second name should resolve to a list of seed addresses. static const char *strMainNetDNSSeed[][2] = { {"hagicointools.com", "(各自ローカルIPアドレスやAWSなどの番号)"}, {NULL, NULL} };
◎/hagicoin/bitcoin-qt.pro の名前を変更 → /hagicoin/hagicoin-qt.pro
< bitcoinrpc.cpp における操作>
・port 番号をテキトーな値に変更する
static inline unsigned short GetDefaultRPCPort() { return GetBoolArg("-testnet", false) ? 19332 : 9332; }
↓
static inline unsigned short GetDefaultRPCPort() { return GetBoolArg("-testnet", false) ? 5888 : 5777; }
いよいよコンパイルします!
・コンパイルする
cd .. make -f makefile.unix USE_UPNP=-
※ここで上手くいかないことが多いです。
僕も悪戦苦闘しました…
そんなときは参照にも上げましたが、このサイトの通りやればうまくいくと思います。
medium.com
・起動する
hagi-coin/src$ ./hagicoind hagicoind: main.cpp:2809: bool InitBlockIndex(): Assertion `block.hashMerkleRoot == uint256("0x")' failed. Aborted (core dumped)
初回はエラーで落ちる(core dumped)
・.tarocoinに移動してdebug.logの中身を見る
/hagi-coin/src$ cd ~/.hagicoin/ ~/.hagicoin$ vi debug.log
... 2018-01-31 14:03:45 Hagicoin version v0.8.7.4-gc1e46ab3a90b-beta () 2018-01-31 14:03:45 Using OpenSSL version OpenSSL 1.0.1f 6 Jan 2014 2018-01-31 14:03:45 Default data directory /home/vagrant/.hagicoin 2018-01-31 14:03:45 Using data directory /home/vagrant/.hagicoin 2018-01-31 14:03:45 Using at most 125 connections (1024 file descriptors available) 2018-01-31 14:03:45 init message: Verifying wallet... 2018-01-31 14:03:45 dbenv.open LogDir=/home/vagrant/.hagicoin/database ErrorFile=/home/vagrant/.hagicoin/db.log 2018-01-31 14:03:45 Bound to [::]:9333 2018-01-31 14:03:45 Bound to 0.0.0.0:9333 2018-01-31 14:03:45 init message: Loading block index... 2018-01-31 14:03:45 Opening LevelDB in /home/vagrant/.hagicoin/blocks/index 2018-01-31 14:03:45 Opened LevelDB successfully 2018-01-31 14:03:45 Opening LevelDB in /home/vagrant/.hagicoin/chainstate 2018-01-31 14:03:45 Opened LevelDB successfully 2018-01-31 14:03:45 LoadBlockIndexDB(): last block file = 0 2018-01-31 14:03:45 LoadBlockIndexDB(): transaction index disabled 2018-01-31 14:03:45 Initializing databases... 2018-01-31 14:03:45 3785e34ccb6ced56e500487ea182e0856d31257b42238682d840c50d076df71e 2018-01-31 14:03:45 0000000000000000000000000000000000000000000000000000000000000000 2018-01-31 14:03:45 902debba0bdb096123f984101c53eb9064f1349854c21cf46c1956b558c5239c
最後の行の「2018-01-31 14:03:45 902debba0bdb0..........」
の部分をコピー
=マークルルート(検証用のルート)における初回のハッシュ値(ブロックの中身が正しいかチェックするためのもの)
・main.cpp の以下の部分にペースト
//// debug print uint256 hash = block.GetHash(); printf("%s\n", hash.ToString().c_str()); printf("%s\n", hashGenesisBlock.ToString().c_str()); printf("%s\n", block.hashMerkleRoot.ToString().c_str()); assert(block.hashMerkleRoot == uint256("0x902debba0bdb096123f984101c53eb9064f1349854c21cf46c1956b558c5239c"));
・もう一度コンパイル(先ほどのmakeコマンド)する
・もう一度起動("./hagicoind")すると、しばらく動く。
※結構時間かかりました。
そして再びエラー
hagicoind: main.cpp:2845: bool InitBlockIndex(): Assertion `hash == hashGenesisBlock' failed. Aborted (core dumped)
・またもやログをチェック
/hagi-coin/src$ cd ~/.hagicoin/ ~/.hagicoin$ vi debug.log
・nonceとhashを確認する。
これ、僕の場合めっちゃ長かったです。
↑こんな感じが延々と続きます。
ナンスを総当たり法で攻めているというPOWの仕組みを改めて実感することができました。
2018-01-31 14:38:59 block.nTime = 1517402992 2018-01-31 14:38:59 block.nNonce = 537493 2018-01-31 14:38:59 block.GetHash = 2d63064b0827152138574099b3d61c35851067a0a52e26abf16839138a41dbab
ナンス値:537493
ハッシュ値:2d63064b0827152138574099b3d61c35851067a0a52e26abf16839138a41dbab
・以下の場所にペースト
◎hash「"0x"のあとにペースト」
<main.cpp>
uint256 hashGenesisBlock("0x2d63064b0827152138574099b3d61c35851067a0a52e26abf16839138a41dbab"); static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20); // Hagicoin: starting difficulty is 1 / 2^12
bool LoadBlockIndex() { if (fTestNet) { pchMessageStart[0] = 0xd2; pchMessageStart[1] = 0xc3; pchMessageStart[2] = 0xb7; pchMessageStart[3] = 0xdc; hashGenesisBlock = uint256("0x2d63064b0827152138574099b3d61c35851067a0a52e26abf16839138a41dbab"); }
<checkpoints.cpp>
static MapCheckpoints mapCheckpoints = boost::assign::map_list_of ( 0, uint256("0x2d63064b0827152138574099b3d61c35851067a0a52e26abf16839138a41dbab")) ;
◎nonce「"block.nNonce =0"の部分を変更」
<main.cpp>
block.nVersion = 1; block.nTime = 1469235421; block.nBits = 0x1e0ffff0; block.nNonce = 537493; if (fTestNet) { block.nTime = 1517402992; block.nNonce = 537493; }
・再びコンパイルしてから、起動してみる。
Error: To use hagicoind, you must set a rpcpassword in the configuration file: /home/vagrant/.hagicoin/hagicoin.conf It is recommended you use the following random password: rpcuser=hagicoinrpc rpcpassword=rPjbWWErf3oxmRfnxwWv5KuFmBuyUYNkAGVtsLjKziB (you do not need to remember this password) The username and password MUST NOT be the same. If the file does not exist, create it with owner-readable-only file permissions. It is also recommended to set alertnotify so you are notified of problems; for example: alertnotify=echo %s | mail -s "Hagicoin Alert" admin@foo.com
・どうやら/.hagicoin配下にconfファイルが無いと怒られているらしいので新しくファイルを作成する。
/hagi-coin/src$ cd ~/.hagicoin ~/.hagicoin$ ls blocks chainstate db.log debug.log peers.dat wallet.dat ~/.hagicoin$ touch hagicoin.conf ~/.hagicoin$ ls blocks chainstate db.log debug.log hagicoin.conf peers.dat wallet.dat ~/.hagicoin$ vim hagicoin.conf
・作成したhagicoin.confの中にオススメされたユーザーネームとパスワードを書き込む。(これは何でもいいので自分で考えたものでもいいです)
rpcuser=hagicoinrpc rpcpassword=rPjbWWErf3oxmRfnxwWv5KuFmBuyUYNkAGVtsLjKziB
・もう一度起動するとうまくいく。
/hagi-coin/src$ ./hagicoind
この状態で動かなくなる。
・別の端末を開く
・getinfoで情報を取得する
/hagi-coin/src$ ./hagicoind getinfo { "version" : 80704, "protocolversion" : 70002, "walletversion" : 60000, "balance" : 0.00000000, "blocks" : 0, "timeoffset" : 1, "connections" : 4, "proxy" : "", "difficulty" : 0.00024414, "testnet" : false, "keypoololdest" : 1517411108, "keypoolsize" : 101, "paytxfee" : 0.00000000, "mininput" : 0.00001000, "errors" : "URGENT: Alert key compromised, upgrade required" }
何やらエラーメッセージがあるのですが、バージョンが古いことが原因でアップグレードすればよい(ウォレット関係?)だけみたいなので、今回は疲れたから無視!
無事Hagicoin完成!!
長かった…
以上お疲れさまでした!