(本文使用的是比特币v0.1.0版本 点击下载源码)
比特币源码解读之线程处理分为两篇,矿工线程处理和其他线程处理两篇,本文描述矿工线程处理,主要包含创币交易的产生、当前交易的打包处理,工作量等相关内容。流程图如下所示:
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
执行矿工处理函数
void ThreadBitcoinMiner(void* parg)
{
vfThreadRunning[3] = true;
CheckForShutdown(3);
try
{
bool fRet = BitcoinMiner();
printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
}
CATCH_PRINT_EXCEPTION("BitcoinMiner()")
vfThreadRunning[3] = false;
}
利用openssl库生成
CKey key;
key.MakeNewKey();
void MakeNewKey()
{
if (!EC_KEY_generate_key(pkey))
throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
}
输入为NULL,输出为本节点地址
CTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
auto_ptr<CBlock> pblock(new CBlock());
if (!pblock.get())
return false;
// Add our coinbase tx as first transaction
pblock->vtx.push_back(txNew);
结束条件是:
(1)mapTransactions中所有交易处理完
(2)区块大小达到 MAX_SIZE/2才结束。
CTxDB txdb("r");
map<uint256, CTxIndex> mapTestPool;
vector
vfAlreadyAdded(mapTransactions.size()); bool fFoundSomething = true;
unsigned int nBlockSize = 0;
while (fFoundSomething && nBlockSize < MAX_SIZE/2)
{
fFoundSomething = false;
unsigned int n = 0;
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
{
if (vfAlreadyAdded[n])
continue;
CTransaction& tx = (*mi).second;
if (tx.IsCoinBase() || !tx.IsFinal())
continue;
// Transaction fee requirements, mainly only needed for flood control
// Under 10K (about 80 inputs) is free for first 100 transactions
// Base rate is 0.01 per KB
int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);
map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
continue;
swap(mapTestPool, mapTestPoolTmp);
pblock->vtx.push_back(tx);
nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
vfAlreadyAdded[n] = true;
fFoundSomething = true;
}
}
保存输出的字节数、创币交易以及缴费到新块中
pblock->nBits = nBits;
pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
计算交易的Merkle值
tmp.block.nVersion = pblock->nVersion;
tmp.block.hashPrevBlock = pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
tmp.block.nTime = pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
tmp.block.nBits = pblock->nBits = nBits;
tmp.block.nNonce = pblock->nNonce = 1;
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));
unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
... ...
BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
BlockSHA256(&tmp.hash1, nBlocks1, &hash);
如果当前随机hash小于等于目标hash值,表示该区块满足难度要求,则处理该区块ProcessBlock(区块处理在比特币源码解读之挖矿一文中介绍)
if (hash <= hashTarget)
{
pblock->nNonce = tmp.block.nNonce;
... ...
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
CRITICAL_BLOCK(cs_main)
{
// Save key
if (!AddKey(key))
return false;
key.MakeNewKey();
// Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock.release()))
printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
Sleep(500);
break;
}
上一篇: 比特币源码解析之初始化
下一篇:比特币源码解读之线程处理-其他线程
版权声明:B链网原创,严禁修改。转载请注明作者和原文链接
作者:雨后的蚊子
原文链接:http://www.360bchain.com/article/59.html