比特币源码解读之线程处理-矿工线程

(本文使用的是比特币v0.1.0版本 点击下载源码)

  • 新建矿工线程
  • 生成公钥和私钥
  • 创建创币交易
  • 创建新块并保存创币交易
  • 收集最新的验证通过的交易
  • 获取目标难度
  • 获取随机生成的难度
  • 工作量证明

  比特币源码解读之线程处理分为两篇,矿工线程处理和其他线程处理两篇,本文描述矿工线程处理,主要包含创币交易的产生、当前交易的打包处理,工作量等相关内容。流程图如下所示:

新建矿工线程

   
   
   
   
  1. if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
  2. printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");

执行矿工处理函数

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

生成公钥和私钥

利用openssl库生成

   
   
   
   
  1. CKey key;
  2. key.MakeNewKey();
  3. void MakeNewKey()
  4. {
  5. if (!EC_KEY_generate_key(pkey))
  6. throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
  7. }

创建创币交易

输入为NULL,输出为本节点地址

   
   
   
   
  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. // Add our coinbase tx as first transaction
  5. pblock->vtx.push_back(txNew);

收集最新的验证通过的交易

结束条件是:
(1)mapTransactions中所有交易处理完
(2)区块大小达到 MAX_SIZE/2才结束。

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

保存输出的字节数、创币交易以及缴费到新块中

   
   
   
   
  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值,表示该区块满足难度要求,则处理该区块ProcessBlock(区块处理在比特币源码解读之挖矿一文中介绍)

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

上一篇: 比特币源码解析之初始化
下一篇:比特币源码解读之线程处理-其他线程

版权声明:B链网原创,严禁修改。转载请注明作者和原文链接


作者:雨后的蚊子

原文链接:http://www.360bchain.com/article/59.html


你可能感兴趣的:(区块链)