日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Bitcoin 中的挖矿算法(3) 挖矿算法代码说明

發布時間:2025/3/21 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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腳本中也有更多的空間可以為將來隨機數的額外空間擴展做準備。

void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) {// Update nExtraNoncestatic uint256 hashPrevBlock;if (hashPrevBlock != pblock->hashPrevBlock) {nExtraNonce = 0;hashPrevBlock = pblock->hashPrevBlock;}++nExtraNonce;unsigned int nHeight = pindexPrev->nHeight + 1; // Height first in coinbase required for block.version=2CMutableTransaction txCoinbase(*pblock->vtx[0]);txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce));assert(txCoinbase.vin[0].scriptSig.size() <= 100);pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); }

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) 挖矿算法代码说明的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。