本文描述矿工处理线程,通过本文学习,可以了解矿工挖矿的大致流程。
主要包含挖矿费用交易的产生、当前交易池的打包处理,工作量证明等相关内容。流程图(参考网络)如下所示:。
矿工处理函数
1.void ThreadBitcoinMiner(void* parg)
2.{
- 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;
12.}
生成公钥和私钥
利用openssl库生成
1.CKey key;
2.key.MakeNewKey();
3.
4.void MakeNewKey()
5.{
- if (!EC_KEY_generate_key(pkey))
- throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
8.}
创建挖矿费用,用于挖矿后的奖励
1.CTransaction txNew;
2.txNew.vin.resize(1);
3.txNew.vin[0].prevout.SetNull();
4.txNew.vin[0].scriptSig << nBits << ++bnExtraNonce;
5.txNew.vout.resize(1);
6.txNew.vout[0].scriptPubKey << key.GetPubKey() << OP_CHECKSIG;
创建新块并保存挖矿费用交易
1.auto_ptr<CBlock> pblock(new CBlock());
2.if (!pblock.get())
3.return false;
4.
5.// Add our coinbase tx as first transaction
pblock->vtx.push_back(txNew);
收集最新的验证通过的交易,主要是交易池里的交易
结束条件是:
(1)mapTransactions中所有交易处理完
(2)区块大小达到 MAX_SIZE/2才结束。
1.CTxDB txdb("r");
2.map<uint256, CTxIndex> mapTestPool;
3.vector<char> vfAlreadyAdded(mapTransactions.size());
4.bool fFoundSomething = true;
5.unsigned int nBlockSize = 0;
6.while (fFoundSomething && nBlockSize < MAX_SIZE/2)
7.{
- 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;
- }
33.}
保存输出的字节数、挖矿交易以及缴费到新块中
1.pblock->nBits = nBits;
2.pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nFees);
计算交易的Merkle值
1.tmp.block.nVersion = pblock->nVersion;
2.tmp.block.hashPrevBlock = pblock->hashPrevBlock = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
3.tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
4.tmp.block.nTime = pblock->nTime = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
5.tmp.block.nBits = pblock->nBits = nBits;
6.tmp.block.nNonce = pblock->nNonce = 1;
获取目标难度
1.uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
获取随机生成的难度
1.unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));
2.unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
3.... ...
4.BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
5.BlockSHA256(&tmp.hash1, nBlocks1, &hash);
工作量证明
如果当前随机hash小于等于目标hash值,表示该区块满足难度要求,则处理该区块
1.if (hash <= hashTarget)
2.{
- 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;
21.}
原文地址:http://blog.51cto.com/13878196/2326489