为了账号安全,请及时绑定邮箱和手机立即绑定

修改创世块生成新币(二)(一个跨世纪本质的修改)

标签:
区块链

参考:

http://shusunny.github.io/2016/04/13/altcoin_build_1/

http://blog.csdn.net/hacode/article/details/40422535

1.获取源码

https://github.com/bitcoin/bitcoin/

使用版本 0.10 0.12 0.12版本后,客户端不能直接挖矿,所以最新的测试到0.12.我选择0.102.

全文复制于http://shusunny.github.io/2016/04/13/altcoin_build_1/

修正原文一个书写错误,添加一个遗漏,添加一处说明

书写错误:

 openssl ecparam -genkey -name secp256k1 -out genesiscoinbase.pem

 openssl ec -in genesiscoinbase.pem -text > genesiscoinbase.hex

  此处genesiscoinbase.pem原文为testnetalert.pem。 

 遗漏:获得创世区块后,回填的时候nBit也应当回填,

另外,原博主挖矿代码设定的难度值过小,需修改block.nBits = 0x1f00ffff;更大,或者修改最小难度设定

 bnProofOfWorkLimit = ~uint256(0) >> 32



修改区块链参数

首先我们需要进入chainparams.cpp

cd src

sudo gedit chainparams.cpp

然后我们在代码中搜索mapCheckpoints,在第55行,它大概是这个样子的:

static Checkpoints::MapCheckpoints mapCheckpoints =

boost::assign::map_list_of

( 11111, uint256("0x00223155*****"));

这里会显示一大串数据,分别是不同区块的hash值,是比特币客户端用来验证之前区块值是否正确。

而我们需要把11111那一行的数值改为

( 0, uint256("0x001"));

这里,0代表的是第几个区块。0后面的uint256表示的就是初始块的hash值。

可是我们的新币还没有正式运行呢?怎么得到它的hash值呢?我们下面会讲如果挖创始块。这里我们姑且做一个大胆并且绝对错误的推断,让其等于001。

同样的,我们还需要搜索并更改mapCheckpointsTestnet 和mapCheckpointsRegtest 同一位置的数据。可能他们只有一行,并非大串数据。他们表示的是测试网络的区块值。

没关系,大胆的把他们全部变成( 0, uint256("0x001"));。

现在我们返回mapCheckpoints,在刚才的数据地图的下面,我们可以看到

1397080064, // * UNIX timestamp of last checkpoint block

36544669, // * total number of transactions between genesis and last checkpoint

// (the tx=... number in the SetBestChain debug.log lines)

60000.0 // * estimated number of transactions per day after checkpoint

这里通过英文注释我们可以看到,第一行代表上个检查点的时间,第二行是创始块直到上次检查时的交易数量。第三行表示平均每天的交易量。我们运行

date +%s

将上面命令行得到的值替换到上述bitcoin代码的第一行,第二行交易数量随便填,估且填为10吧。第三行看情况来,先填成10000吧。

将同样的时间和交易数量数据像上面那样填进test和regtest的信息里。平均交易量填一半就好。

在mapCheckpointsRegtest下是CMainParams函数。在函数中有四行指针代码表示pchMessageStart。一般作为用来对比特币的交易进行验证的协议(protocol)。其中每个数组的值都是0-255中的数值,以16进制的形式表示。他们一旦改变,任何人都无法将我们的客户端连进比特币的了。

我们可以在http://numbermonk.com/?all=1 的表中从0-255找到我们喜欢的数字填进去。如果可以的话,再找8个填进CTestNetParams和CRegTestParams。

下面的代码是vAlertPubKey。所以我们需要更改alert和genesis coinbase的key值。我们用命令行生成一些

openssl ecparam -genkey -name secp256k1 -out alertkey.pem

openssl ec -in alertkey.pem -text > alertkey.hex

openssl ecparam -genkey -name secp256k1 -out testnetalert.pem

openssl ec -in testnetalert.pem -text > testnetalert.hex

openssl ecparam -genkey -name secp256k1 -out genesiscoinbase.pem

openssl ec -in genesiscoinbase.pem -text > genesiscoinbase.hex

这样我们就得到了一系列alertkey和genesiscoinbase key。我们首先打开alertkeycat alertkey.hex。我们把‘pub’和‘ASN1 OID: secp256k1′中间的5行数值去掉冒号和空格填到vAlertPubKey = ParseHex(“…”);里去。然后我们再用cat testnetalert.hex把其中的数据填入到CTestNetParams函数中去。

下面我们更改时间标签pszTimestamp。在这一行

const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";

填入任意内容,最好小于90字节。带上时间戳

接下来我们将创始块的pubkey填进去。打开cat genesiscoinbase.hex,在

txNew.vout[0].scriptPubKey = CScript() << ParseHex("...") << OP_CHECKSIG;

中插入我们的key值。同样的去掉冒号和空格。

接下来,我们需要将

assert(hashGenesisBlock == uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));

assert(genesis.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

这两行用//注释掉,以免在我们找初始块的时候报错影响程序运行。所有的文件改完别忘了保存一下。

下面的vSeeds表示的种子文件的位置,我们还没有种子文件的域名,先不要进行改动。

挖取创始块

现在我们开挖,打开main.cpp

sudo gedit main.cpp

我们在这一行后面

CBlock &block = const_cast<CBlock&>(Params().GenesisBlock());

以及

// Start new block file

unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);

这一行前面,加入我们挖创始块的代码

uint256 bnTarget;

bool fNegative;

bool fOverflow;

uint256 hashGenesisBlock;

block.nBits = 0x1f00ffff;

bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);

LogPrintf("ProofOfWorkLimit %s\n", Params().ProofOfWorkLimit().ToString());

if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) {

error("InitBlockIndex CheckProofOfWork() : nBits below minimum work");

}else {

block.nTime = GetTime();//1231006505;

LogPrintf("block.nTime %d\n", block.nTime);

LogPrintf("bnTarget %s\n", bnTarget.ToString());

block.nNonce = 0;

while (true) {

if (block.nNonce%1000000000 == 0)

LogPrintf("block.nNonce--- %d\n", block.nNonce);

hashGenesisBlock = block.GetHash();

if (hashGenesisBlock <= bnTarget)

break;

block.nNonce++;

}

LogPrintf("block.nNonce******** %d\n", block.nNonce);

LogPrintf("hashGenesisBlock******** %s\n", hashGenesisBlock.ToString());

LogPrintf("hashMerkleRoot******** %s\n", block.hashMerkleRoot.ToString());

}

这段代码是会在我们程序运行的时候不断计算,并在debug.log中导出我们所需要的GenesisBlock的Hash值。保存并返回newcoin文件夹。重新编译

cd ..

make

如果我们上一篇中环境安装完全的话,应该会秒通过。然后我们运行我们的程序

然后程序会通知我们将文件目录放在哪里,用默认的设置就好。这时程序可能会跑一段时间崩溃掉。没关系,我们用

tail ~/.bitcoin/debug.log

进入到debug文件中去。看看我们是否导出了以下数值

2016-04-11 21:16:20 ProofOfWorkLimit 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

2016-04-11 21:16:20 block.nTime 1460410772

2016-04-11 21:16:20 bnTarget 0000ffff00000000000000000000000000000000000000000000000000000000

2016-04-11 21:16:20 block.nNonce--- 0

2016-04-11 21:16:20 block.nNonce******** 43973

2016-04-11 21:16:20 hashGenesisBlock******** 0000f51a735d0f7da96f10797ad76e00e53614422987f2b6056aaf61857e165e

2016-04-11 21:16:20 hashMerkleRoot******** d5c218da6f5c257709c0d59177ae4527ea5049f15baf26260a071c2e212154ac

2016-04-11 21:16:20 Pre-allocating up to position 0x1000000 in blk00000.dat

2016-04-11 21:16:20 Pre-allocating up to position 0x100000 in rev00000.dat

如果有,那么恭喜你,你已经挖到了创始块,那么让我们返回到chainparams.cpp中,将hashGenesisBlock,hashMerkleRoot填入到刚才的区块地图中,即uint256(“0x001”),将001改为我们前面得到的hashGenesisBlock值,并将其填入已经被我们注释掉的assert中,并把注释去掉。

同样的,将上面log中block.nTime和block.nNonce的值填回到CMainParams的genesis.nTime和genesis.nNonce中去。他们在下面这行代码的上边。

hashGenesisBlock = genesis.GetHash();

最终回填结果为

genesis.nTime=1460410772;

genesis.nBits=0x1f00ffff;

genesis.nNonce=43973;

hashGenesisBlock=genesis.GetHash();

assert(hashGenesisBlock==uint256("0000f51a735d0f7da96f10797ad76e00e53614422987f2b6056aaf61857e165e"));

assert(genesis.hashMerkleRoot==uint256("d5c218da6f5c257709c0d59177ae4527ea5049f15baf26260a071c2e212154ac"));

保存。现在我们已经得到了我们的初始块,别忘了将main.cpp中我们刚才填加的代码删掉,这样我们就完全构建出了一套属于我们的电子币系统。并且不会出现像比特币那样挖不着的情况。(毕竟是我们自己的,想挖多少就挖多少。哈哈哈)

你也可以将上面的程序额外运行两次,并把得到的hash值和各参数填入到Testnet和Regtest中去。

下面我们返回newcoin文件夹中,重新编译,并删除原来的文件目录(非常重要)

cd ..

sudo make

rm -rf ~/.newcoin

原文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消