主页 > imtoken怎么退出账号 > 如何以比特币为模型创建自己的山寨币(二)

如何以比特币为模型创建自己的山寨币(二)

imtoken怎么退出账号 2023-01-17 03:13:36

如何以比特币为模型创建自己的山寨币(二)

上次我们将比特币中的所有文件名和内容更改为我们的新币 newcoin。但这还不够。为什么?因为所有内核参数都还在比特币中,即使客户端在运行,也会同步之前的比特币数据。现在是深入代码、探索比特币奥秘并做出一些真正属于我们的改变的时候了。

修改区块链参数

首先我们需要输入chainparams.cpp

cd src
sudo gedit chainparams.cpp

然后我们在代码中搜索mapCheckpoints比特币nbits,在第55行,看起来是这样的:

static Checkpoints::MapCheckpoints mapCheckpoints =
      boost::assign::map_list_of
      ( 11111, uint256("0x00223155*****"));

这里会展示一大串数据,是不同区块的哈希值,比特币客户端用来验证之前的区块值是否正确。我们需要将 11111 行的值更改为

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

这里,0 表示块的数量。0后面的uint256代表初始块的hash值。但是我们的新币还没有正式运行?如何得到它的哈希值?我们将在下面讨论如何挖掘创世块。这里我们做一个大胆且绝对错误的推论,让它等于001。

同样,我们也需要在mapCheckpointsTestnet和mapCheckpointsRegtest的同一位置搜索和更改数据。也许他们只有一行,而不是一大串数据。它们代表测试网络的块值。没关系,大胆的把它们都变成(0, uint256("0x001"));。

比特币nbits

现在我们回到mapCheckpoints,在之前的数据map下,我们可以看到

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

把上面命令行得到的值替换成上面比特币代码的第一行,第二行填写交易号,估计是10。第三行看情况,先填10000。

使用与上述相同的时间和交易计数数据填写测试和注册测试信息。只需填写平均交易量的一半。

在 mapCheckpointsRegtest 下是 CMainParams 函数。函数中有四行指针代码代表 pchMessageStart。通常用作验证比特币交易的协议。每个数组的值是一个从 0 到 255 的数值,以十六进制形式表示。一旦它们发生变化,就没有人能够将我们的客户连接到比特币。

我们可以在表格中从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 testnetalert.pem -text > genesiscoinbase.hex

比特币nbits

这样我们就得到了一系列的 alertkey 和 genesiscoinbase 密钥。我们先打开alertkey

cat 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字以内)比特币nbits,然后填写。

接下来我们填写创世块的公钥。打开 cat genesiscoinbase.hex,在

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

将我们的键值插入 . 同时删除冒号和空格。

接下来,我们需要

比特币nbits

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

这两行用//注释掉,以免我们找到初始块时报错,影响程序运行。更改后不要忘记保存所有文件。

下图vSeeds指示的torrent文件的位置,我们还没有torrent文件的域名,所以先不要更改。

挖掘创世区块

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

sudo gedit main.cpp

我们在这条线之后

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

// Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);

比特币nbits

在此行之前,添加我们用于挖掘创世块的代码

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

如果我们上一篇文章中的环境已经完全安装好了,应该是几秒钟就可以通过了。然后我们运行我们的程序

cd src/qt
sudo ./newcoin-qt

然后程序会告诉我们把文件目录放在哪里,使用默认设置即可。这时候程序可能运行一段时间就崩溃了。没关系,我们用

tail ~/.newcoin/debug.log

转到调试文件。看看我们是否导出以下值

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

比特币nbits

如果是,那么恭喜你挖到了创世块,那我们回到chainparams.cpp,将hashGenesisBlock、hashMerkleRoot填充到刚才的block map中,即uint256("0x001"),把001改成我们之前得到的hashGenesisBlock值,将其填入我们已注释掉的断言中,然后删除该注释。同样,将上述日志中block.nTime和block.nNonce的值填回CMainParams的genesis.nTime和genesis.nNonce。它们位于下面的代码行之上。

hashGenesisBlock = genesis.GetHash();

节省。既然我们已经拿到了我们的初始区块,别忘了删除我们刚刚在main.cpp中添加的代码,这样我们就已经完全构建了一套属于我们的电子货币系统。并且不会出现像比特币一样不能开采的情况。(毕竟是我们自己的,想挖多少挖多少就挖多少。哈哈哈)

也可以将上述程序运行两次,将得到的哈希值和参数填入Testnet和Regtest。

接下来我们回到newcoin文件夹,重新编译,删除原文件目录(很重要)

cd ..
sudo make
rm -rf ~/.newcoin

然后运行它。如果一切顺利,程序就会运行起来,然后我们就可以得到如下程序

不要羡慕上面的数值,既然所有的参数都是我们自己改的,当然我们可以修改main.cpp中的区块数据,从而在短时间内挖到最多的币。

写于 2016 年 4 月 14 日 bysun

随意分享!