比特币源码解读之创世块的产生
(本文使用的是比特币v0.1.0版本 点击下载源码)
本文主要描述创世块是如何产生的,接着之前的文章《比特币源码解读之初始化》中初始化加载模块进行描述,本文主要描述创世块时间戳、创币奖励、区块信息的初始化,以及区块的存储以及区块索引的生成。
流程图如下所示:
加载区块索引
if (!LoadBlockIndex())
strErrors += "Error loading blkindex.dat\n";
bool LoadBlockIndex(bool fAllowNew)
{
//
// Load block index
//
CTxDB txdb("cr");
if (!txdb.LoadBlockIndex())
return false;
txdb.Close();
....
}
判断区块索引是否为空
// Init with genesis block
//
if (mapBlockIndex.empty())
{
if (!fAllowNew)
return false;
...
}
初始化时间戳和交易
(1)时间戳为”The Times 03/Jan/2009 Chancellor on brink of second bailout for banks” ,这句话正是泰晤士报当天的头版文章标题“2009年1月3日,财政大臣正站在第二轮救助银行业的边缘”。时间戳是作为存在性证明(Proof of existence)的关键参数。
(2)创世币的奖励为50BTC,输入为空,输出公钥为
// Genesis block
char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
初始化区块
CBlock block;
block.vtx.push_back(txNew);
block.hashPrevBlock = 0; 前一区块为0
block.hashMerkleRoot = block.BuildMerkleTree(); 计算交易的Merkle值
block.nVersion = 1; 版本号为1
block.nTime = 1231006505; 北京时间为2009/1/4 2:15:5
block.nBits = 0x1d00ffff; 记录本区块难度
block.nNonce = 2083236893; 随机数
其中nNonce 的值设定使得该块的hash是以一串0开头的。对于块数据的一点点改变(比如nonce)都会引起block hash的巨大变化。由于逆向预测hash值相对应的一组bit值(hash原文)是不可行的,在尝试足够多的nonce值且计算每个nonce值相对应的block hash之后可以找到一个满足有指定数量 0 bits (0比特位) 的hash值。
HASH校验
校验交易的Merkle值和区块Hash
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
assert(block.GetHash() == hashGenesisBlock);
区块写入磁盘中
文件名为blk0001.dat,后续区块名字递增,如blk0002.dat …
unsigned int nFile;
unsigned int nBlockPos;
if (!block.WriteToDisk(!fClient, nFile, nBlockPos))
return error("LoadBlockIndex() : writing genesis block to disk failed");
bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)
{
// Open history file to append
CAutoFile fileout = AppendBlockFile(nFileRet);
if (!fileout)
return error("CBlock::WriteToDisk() : AppendBlockFile failed");
if (!fWriteTransactions)
fileout.nType |= SER_BLOCKHEADERONLY;
// Write index header
unsigned int nSize = fileout.GetSerializeSize(*this);
fileout << FLATDATA(pchMessageStart) << nSize;
// Write block
nBlockPosRet = ftell(fileout);
if (nBlockPosRet == -1)
return error("CBlock::WriteToDisk() : ftell failed");
fileout << *this;
return true;
}
增加区块索引
if (!block.AddToBlockIndex(nFile, nBlockPos))
return error("LoadBlockIndex() : genesis block not accepted");
其功能包含重复性区块检查、最好分支处理、新最好分支处理等等,在后续比特币源码解读之挖矿一文中介绍
上一篇: 比特币源码解读之私钥、公钥和地址
版权声明:B链网原创,严禁修改。转载请注明作者和原文链接
http://www.360bchain.com/article/76.html