Bitcoin 中的挖矿算法(3) 挖矿算法代码说明
1. 步驟說明:
step1. createNewBlock生成一個新塊
step2. 輪循nounce,計算hash以符合難度值
step2.1 先循環增加CoinBase交易的Script 的nounce
step2.2 再循環CBlockHeader中的nounce來計算hash
2. 代碼:
step2 大循環
while (true) { //step1 std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(empty_mempool, Params()).CreateNewBlock(::ChainstateActive(), coinbase_script));CBlock* pblock = &pblocktemplate->block;IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);int64_t nStart = GetTime();arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);uint256 hash;uint32_t nNonce = 0;while (true) {// Check if something foundif (ScanHash(pblock, nNonce, &hash)) {if (UintToArith256(hash) <= hashTarget) {// Found a solutionpblock->nNonce = nNonce;assert(hash == pblock->GetHash()); break;}}// Check for stop or if block needs to be rebuiltboost::this_thread::interruption_point();// Regtest mode doesn't require peers//if (vNodes.empty() && chainparams.MiningRequiresPeers())//break;if (nNonce >= 0xffff0000)break;if (empty_mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)break;if (pindexPrev != ::ChainstateActive().m_chain.Tip())break;// Update nTime every few secondsif (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0)break; // Recreate the block if the clock has run backwards,// so that we can use the correct time.if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) {// Changing pblock->nTime can change work required on testnet:hashTarget.SetCompact(pblock->nBits);}} ...step 2.1 先循環增加CoinBase交易的Script 的nounce
自2012年以來,比特幣挖礦發展出一個解決區塊頭結構的根本性限制的方案。在比特幣的早期,礦工可以通過遍歷隨機數(Nonce)直到生成的哈希值小于target從而挖出一個區塊。隨著難度的增加,礦工經常在嘗試了40億個nonce值后仍然沒有出塊。然而,這很容易通過更新區塊的時間戳并計算經過的時間來解決。因為時間戳是區塊頭的一部分,它的變化可以讓礦工再次遍歷nonce的值。然而,當挖礦硬件的速度超過了4GH/秒,這種方法變得越來越困難,因為隨機數的取值在一秒內就被用盡了。隨著ASIC礦機的出現并且超過了TH/秒的hash速率后,挖礦軟件為了找到有效的塊,需要更多的空間來儲存nonce值。時間戳可以延伸一點,但如果把它移動得太過遙遠(too far into the future),會導致區塊變為無效。
區塊頭里面需要一個新的“改變”的源頭。解決方案是使用coinbase交易作為額外隨機值的來源,因為coinbase腳本可以儲存2-100字節的數據,礦工們開始使用這個空間作為額外隨機值的空間,允許他們去探索一個大得多的區塊頭值的范圍來找到有效的區塊。這個coinbase交易包含在merkle樹中,這意味著任何coinbase腳本的變化將導致Merkle根的變化。8個字節的額外隨機數,加上4個字節的“標準”隨機數,允許礦工每秒嘗試2^96(8后面跟28個零)種可能性而無需修改時間戳。如果未來礦工嘗試完了以上所有的可能性,他們還可以通過修改時間戳來解決。同樣,coinbase腳本中也有更多的空間可以為將來隨機數的額外空間擴展做準備。
step2.2. 再循環CBlockHeader中的nounce來計算hash
bool static ScanHash(const CBlockHeader* pblock, uint32_t& nNonce, uint256* phash) {// Write the first 76 bytes of the block header to a double-SHA256 state.CHash256 hasher;CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);ss << *pblock;assert(ss.size() == 80);hasher.Write((unsigned char*)&ss[0], 76);while (true) {nNonce++;// Write the last 4 bytes of the block header //(the nonce) to a copy of// the double-SHA256 state, and compute the result.CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);// Return the nonce if the hash has at least some //zero bits, caller will check if it has enough // to reach the targetif (((uint16_t*)phash)[15] == 0)return true;// If nothing found after trying for a while, return -1if ((nNonce & 0xfff) == 0)return false;}. 將CBlockHeader中除nNonce的值都寫入buf,. 既是寫入到 CDataStream
class CBlockHeader { public:// headerint32_t nVersion;uint256 hashPrevBlock;uint256 hashMerkleRoot;uint32_t nTime;uint32_t nBits;uint32_t nNonce; class CBlockHeader {SERIALIZE_METHODS(CBlockHeader, obj){ READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce);}.實際上算hash時先寫入76bytes到CHash256 中,然后循環nNonce.
76bytes = 4bytes(nVersion)+ 32bytes(hashPrevBlock) + +32bytes(hashMerkleRoot)+4bytes(nTime)+4bytes(nBits) = 76bytes.CHash256 計算hash值:
hash.h /** A hasher class for Bitcoin's 256-bit hash (double SHA-256). */ class CHash256 { private:CSHA256 sha;void Finalize(unsigned char hash[OUTPUT_SIZE]) {unsigned char buf[CSHA256::OUTPUT_SIZE];// 第一次SHA-256哈希計算sha.Finalize(buf);// 對上一步的計算結果再一次進行SHA-256哈希計算sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(hash);}CHash256& Write(const unsigned char *data, size_t len) {sha.Write(data, len);return *this;}總結
以上是生活随笔為你收集整理的Bitcoin 中的挖矿算法(3) 挖矿算法代码说明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Bitcoin 中的挖矿算法(2) 难度
- 下一篇: Bitcoin 中的挖矿算法(4) 产生