• <option id="cacee"><noscript id="cacee"></noscript></option>
  • <table id="cacee"><noscript id="cacee"></noscript></table>
  • <td id="cacee"></td>
  • <option id="cacee"></option>
  • <table id="cacee"></table>
  • <option id="cacee"><option id="cacee"></option></option>
  • <table id="cacee"><source id="cacee"></source></table><td id="cacee"><rt id="cacee"></rt></td>
    <option id="cacee"><option id="cacee"></option></option>
     找回密碼
     立即注冊

    掃一掃,登錄網站

    首頁 自媒體 查看內容
    • 3602
    • 0
    • 分享到

    區塊鏈100講:知乎千贊回答講清挖礦過程

    2018-5-11 12:44

    來源: HiBlock-Net



    前幾天整理了挖礦和算力的介紹,盆友看完之后跟我說要嘗試去挖礦了,我默默地給他點了贊,然后覺得應該做點什么幫幫他,于是又找了一些關于比特幣挖礦過程的介紹,這篇就厲害了,想挖礦的同學要認真看了~


    另外,《區塊鏈100講》的目的是希望能形成體系化的區塊鏈知識圖譜,供大家查閱和了解區塊鏈技術,每天一個點的介紹,由淺入深,歡迎在文末留言你希望了解什么、或者為文章糾錯哦,如果能投稿那就更好了


    1

    挖礦的流程


    比特幣挖礦的算法,可以簡單地總結為對區塊頭做兩次sha256哈希運算,得到的結果如果小于區塊頭中規定的難度目標,即挖礦成功。


    區塊頭的結構如下



    那么挖礦的算法可以表達為


    block_header = version + previous_block_hash + merkle_root + time + target_bits + nonce

    for i in range(02**32):

         if sha256(sha256(block_header)) < target_bits:       

            break    

        else:        

           continue


    簡單回顧下挖礦的流程。



    挖礦節點首先對交易做驗證,剔除有問題的,然后通過一套自定義的標準來選擇哪些交易希望打包進區塊,比如通過交易費與交易占用的字節大小的比值超過某個門檻來判斷,這樣的交易才被認為有利可圖。當然,節點也可以特意選擇要加入某條交易,或者故意忽略某些交易,每個挖礦節點有很大的自由裁度權力。


    如果是通過礦池挖礦的話,礦池的服務器會去篩選交易,然后分配給每個參與的礦機一個獨立的任務。這個任務的難度小于總的挖礦難度,完成了小難度的計算,即確認了自己參與的工作量。每臺不同的礦機計算的問題不會重復,當其中一臺礦機成功挖礦時,其他礦機依據工作量分配獲得的總收益。


    一旦篩選好交易數據,按照時間排序,兩兩哈希,層層約減,通過這些交易就可以計算出一棵Merkle樹,可以確定一個唯一的摘要,這就是Merkl樹的根。



    merkle樹中,任何節點的變化,都會導致merkle root發生變化,通過這個值,可以用來驗證區塊中的交易數據是否被改動過。


    然后我們再依次獲取挖礦需要的每一項區塊頭的信息。 區塊頭只有80個字節,挖礦只需要對區塊頭進行運算即可。交易數據都通過merkle樹固定了下來,不需要再包含進來。而所謂的區塊鏈,其實也是通過區塊頭而鏈接在一起的。下面的示意圖比較簡單明確地解釋了區塊鏈和區塊的構成。



    比特幣區塊鏈示意圖


    區塊頭中的信息,在挖礦前大部分已經是固定下來的,或者是可計算的。


    版本號


    跟隨比特幣客戶端而定,一段時間內不會改變。即使要改變,也會有比特幣的核心開發人員來協調升級策略,這個可以理解為一個靜態常數。


    前一區塊的哈希摘要


    一次哈希即可。前一區塊已經是打包好的。


    默克爾樹的根


    剛才已經得到了結果,根據本次交易包含的交易列表得到


    時間


    取打包時的時間。也不需要很精確,前后幾秒,幾十秒也都可以。


    難度目標


    參考上兩周產生的區塊的平均生成時間而定。兩周內如果平均10分鐘產生一個區塊的話,兩周會產生2016個區塊,軟件會計算最新的2016個區塊生成的時間,然后做對比,隨之調整難度,使得接下來產生的區塊的預期時間保持在10分鐘左右。因為最近的2016個區塊已經確定,所以這個數字也是確定的。


    隨機數nonce


    這個就是挖礦的目標了。這是一個32位的數字。


    隨機數可以變化,而且要從0試到最大值2^32。直到最后出現的hash結果,其數字低于難度目標值。不過以現在的計算機算力,一臺礦機用不了一秒就把全部的變化可能計算完了,所以還需要改變區塊內部的創幣交易中的附帶消息,這樣就讓merkle root也發生了變化,從而有更多的可能去找到符合要求的nonce。


    合格的區塊條件如下:


    SHA256D(Blockherder) < F(nBits)


    其中,SHA256D(Blockherder)就是挖礦結果,F(nBits)是難度對應的目標值,兩者都是256位,都當成大整數處理,直接對比大小以判斷是否符合難度要求。


    為了節約區塊鏈存儲空間,將256位的目標值通過一定變換無損壓縮保存在32位的nBits字段里。具體變換方法為拆分利用nBits的4個字節,第1個字節代表右移的位數,用V1表示,后3個字節記錄值,用V3表示,則有:


    F(nBits)=V_3 * 2^(8*(V_1-3) )


    此外難度有最低限制,也就是說 F(nBits) 有個最大值,比特幣最低難度取值nBits=0x1d00ffff,對應的最大目標值為:


    0x00000000FFFF0000000000000000000000000000000000000000000000000000


    因此挖礦可以形象的類比拋硬幣,好比有256枚硬幣,給定編號1,2,3……256,每進行一次Hash運算,就像拋一次硬幣,256枚硬幣同時拋出,落地后要求編號前n的所有硬幣全部正面向上。


    挖礦中,第一筆交易是創幣交易。創幣交易可以附帶一段文字消息,這段信息可以用來提供更多的nonce. 比如中本聰在挖出創世區塊時植入的信息。


    The Times 03/Jan/2009 Chancellor on brink of second bailout for banks


    2

    算法驗證


    講完了基本的原理,我們開始使用實際數據來驗證這個算法。我們以區塊277316為例,其信息來自網站http://blockchain.info


    選擇這個區塊的原因是為了與《Mastering Bitcoin》一書中的介紹做參考。此書中文社區譯本和英文原版在介紹這部分內容時有出入,而且作者Antonopoulos并沒有做完整的演算;沒有提到一個關鍵點,就是字節順序的問題,相信很多人可能會踩這個坑。這里還原的細節可以幫助讀者對書中介紹工作量證明的算法部分徹底理解。



    比特幣區塊277316的信息

    比特幣區塊277316的hash值


    3

    算法演示


    接下來演示具體的驗算算法。


    第一步,準備數據,轉換時間


    (版本號的十進制)0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569 (前一區塊hash值的16進制)c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e  (merkle root16進制)

    2013-12-27 23:11:54 utc時間)

    419668748  (難度目標的十進制)

    924591752  (隨機數的十進制)


    轉換時間,記住,一定要轉為utc的時間戳,此處遇到過坑,小心。算法本身不難,困難的是你需要把其中所有的數據都準備正確。


    >>> import datetime

    >>> from datetime import timezone

    >>> datetime.datetime.strptime('2013-12-27 23:11:54', '%Y-%m-%d %H:%M:%S').replace(tzinfo=timezone.utc).timestamp()

    1388185914.0



    第二步,全部轉換為16進制


    00000002

    0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e

    52be093a

    1903a30c

    371c2688


    第三步,從big-endian轉化為little-endian


    這一步的發現異常艱辛,耗費了大量的查詢和嘗試,大坑,大坑,謹記!發明人中本聰可能為了讓機器計算更快,而變為了更接近機器的編碼方式little-endian.


    02000000

    69054f28012b4474caa9e821102655cc74037c415ad2bba70200000000000000

    2ecfc74ceb512c5055bcff7e57735f7323c32f8bbb48f5e96307e5268c001cc9

    3a09be52

    0ca30319

    88261c37


    再說一遍,算法不難,最難的地方就在于親自驗算的過程中,你要把所有的隱藏知識都挖掘出來。中文資料中,極少有人做過通篇驗算,而一旦真正理解了驗算的過程,你會發現比特幣的算法真的不難。


    第四步,拼接字符串,開始驗證


    import binascii

    from hashlib import sha256 as sk = '0200000069054f28012b4474caa9e821102655cc74037c415ad2bba702000000000000002ecfc74ceb512c5055bcff7e57735f7323c32f8bbb48f5e96307e5268c001cc93a09be520ca3031988261c37

    'hk = binascii.unhexlify(k)

    res = binascii.hexlify(s(s(hk).digest()).digest()[::-1])


    代碼中為何要再轉換一次順序?又是因為字節順序的問題,我們在平常使用和網站展示時,都使用大端順序,所以需要轉換過來。


    最終得到的結果就是


    0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4


    16進制下前面15個0,然后是1。 為了得到這個數字,需要花費我近一個星期的時間,先從橢圓曲線加密算法開始學起,再到各種原始資料的閱讀,還下載了難懂的源代碼,論壇也翻了個遍。看到前面有一堆0,感覺勝利的曙光快來了。


    不急,我們仍然要驗證最后一步,是否滿足難度目標。當然是滿足的,因為我們是在驗證結果嘛,不過如果是在正向計算的挖礦過程中的話,就一定要驗證。


    難度目標對應的數字是


    0x03a30c*0x0100**(0x19-0x03) =

    0000000000000003a30c00000000000000000000000000000000000000000000


    16進制下前面15個0,然后是3。


    計算結果小于難度目標,符合要求。那這個結果就一定是網站上公布的數字了。



    正確的hash值


    在挖礦時,nonce隨機數是未知的,要從0試到2^32,但是這個數字其實不大,只有4294967296。以現在的一臺礦機動輒14T每秒的算力,全部算完到上限也不需要一秒。上文提到在這種情況下,需要使用創幣交易中的附帶信息,額外的字符串成為extra nonce。


    對這個結果我們解釋下意味著什么,在2013年年底時,這個區塊產生,這需要算力達到8T/s的設備,即每秒8*10^15次暴力驗證,連續工作10分鐘。這對于2018年的現在來說的確不算什么,一臺礦機,不比兩三塊磚頭大多少,就擁有14T/s的算力,只需要6,7分鐘單獨就可以挖到。但在當時,8T也是全網千分之一的算力了,需要當時最好的礦機上百臺一起工作。而如果這個計算使用一臺普通的桌面電腦,需要26年。如果使用2018年最好的手機iphoneX的話,每秒可以做70次計算,那么將需要四百萬年。


    通過上面的算法我們完整地回顧了比特幣區塊鏈的工作量證明算法,如果各位完全理清了其中的思路,也就可以手動實現自己的挖礦程序,或者另外嘗試設計一些新的區塊鏈產品了。最艱深的技術,我們希望能夠在底層去了解,然而撥開云霧,其實底層的邏輯并不難。


    不過比特幣里面的技術遠不止挖礦算法,加密算法,Script智能合約,各種協議,各種網絡,交易的驗證,每一個都充滿了魔性,進出之間,不由得讓人驚嘆發明人知識的深度與廣度。無論比特幣是什么,將會怎樣,但是以比特幣為第一個大規模應用的區塊鏈技術,已經擴散了開來,整個系統的嚴密與邏輯的復雜,的確讓人著迷。


    4

    One more thing...


    創世區塊也可以通過上面的方法來驗證,有好奇的朋友可以嘗試下。雖然創世區塊后來硬編碼在客戶端,但仍然是挖出來的。


    提示:


    • 對于創世區塊,版本號是1。

    • 前一區塊的hash摘要,猜想會是什么呢?對于創世區塊,是沒有前一區塊的。

    • 難度目標是1,這是定義為一個sha256結果的前32位是0,也就是對應的16進制字符串要有8個0,那么難度bits此時是0x1d00ffff。這個數字的得出需要概率論的知識,同時也是中本聰的一個規定。

    • 然后再用上面的解法去求解隨機數就可以了。


    挖礦的流程講完了,你看明白了嗎?感覺可以試著挖挖看了呢~

    版權申明:本內容來自于互聯網,屬第三方匯集推薦平臺。本文的版權歸原作者所有,文章言論不代表鏈門戶的觀點,鏈門戶不承擔任何法律責任。如有侵權請聯系QQ:3341927519進行反饋。
    相關新聞
    發表評論

    請先 注冊/登錄 后參與評論

      回頂部
    • <option id="cacee"><noscript id="cacee"></noscript></option>
    • <table id="cacee"><noscript id="cacee"></noscript></table>
    • <td id="cacee"></td>
    • <option id="cacee"></option>
    • <table id="cacee"></table>
    • <option id="cacee"><option id="cacee"></option></option>
    • <table id="cacee"><source id="cacee"></source></table><td id="cacee"><rt id="cacee"></rt></td>
      <option id="cacee"><option id="cacee"></option></option>
      妖精视频