比特币代码分析5 挖矿代码分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比特币代码分析5 挖矿代码分析相关的知识,希望对你有一定的参考价值。

本文描述矿工处理线程,通过本文学习,可以了解矿工挖矿的大致流程。
主要包含挖矿费用交易的产生、当前交易池的打包处理,工作量证明等相关内容。流程图(参考网络)如下所示:。
技术分享图片

矿工处理函数
1.void ThreadBitcoinMiner(void* parg)
2.{

  1. vfThreadRunning[3] = true;
  2. CheckForShutdown(3);
  3. try
  4. {
  5. bool fRet = BitcoinMiner();
  6. printf("BitcoinMiner returned %s ", fRet ? "true" : "false");
  7. }
  8. CATCH_PRINT_EXCEPTION("BitcoinMiner()")
  9. vfThreadRunning[3] = false;
    12.}

生成公钥和私钥
利用openssl库生成
1.CKey key;
2.key.MakeNewKey();
3.
4.void MakeNewKey()
5.{

  1. if (!EC_KEY_generate_key(pkey))
  2. 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.{

  1. fFoundSomething = false;
  2. unsigned int n = 0;
  3. for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi, ++n)
  4. {
  5. if (vfAlreadyAdded[n])
  6. continue;
  7. CTransaction& tx = (*mi).second;
  8. if (tx.IsCoinBase() || !tx.IsFinal())
  9. continue;
  10. // Transaction fee requirements, mainly only needed for flood control
  11. // Under 10K (about 80 inputs) is free for first 100 transactions
  12. // Base rate is 0.01 per KB
  13. int64 nMinFee = tx.GetMinFee(pblock->vtx.size() < 100);
  14. map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
  15. if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), 0, nFees, false, true, nMinFee))
  16. continue;
  17. swap(mapTestPool, mapTestPoolTmp);
  18. pblock->vtx.push_back(tx);
  19. nBlockSize += ::GetSerializeSize(tx, SER_NETWORK);
  20. vfAlreadyAdded[n] = true;
  21. fFoundSomething = true;
  22. }
    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.{

  1. pblock->nNonce = tmp.block.nNonce;
  2. ... ...
  3. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  4. CRITICAL_BLOCK(cs_main)
  5. {
  6. // Save key
  7. if (!AddKey(key))
  8. return false;
  9. key.MakeNewKey();
  10. // Process this block the same as if we had received it from another node
  11. if (!ProcessBlock(NULL, pblock.release()))
  12. printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted ");
  13. }
  14. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
  15. Sleep(500);
  16. break;
    21.}

以上是关于比特币代码分析5 挖矿代码分析的主要内容,如果未能解决你的问题,请参考以下文章

比特币2021.5.16行情分析

比特币代码分析2 比特币全节点流程

FIL挖矿比特币以太坊行情分析(数字货币量化交易app)2021.4.24

比特币代码分析11 比特币存储机制

比特币代码分析3 命令调用框架

比特币代码分析1 整体架构