ethash實現了pow,pow的精妙在於通過乙個隨機數確定,礦工確實做了大量的工作,並且是沒有辦法作弊的。接下來將介紹:
ethash的挖礦本質。
ethash是如何挖礦的。
如何驗證ethash的隨機數。
挖礦的本質是找到乙個隨機數,證明自己做了很多任務作(計算)。在ethash中,該隨機數稱為nonce
,它需要滿足乙個公式:
rand(hash, nonce) ≤ maxvalue / difficulty
其中,以上引數中,在得到區塊頭的hash之後,只有nonce是未知的。
**公式的含義是,使用hash和nonce生成的雜湊值必須落在合法的區間。**利用下圖介紹一下,rand()函式結果取值範圍是[0, maxvalue],但只有計算出的雜湊值在[0, maxvalue / difficulty]內,才是符合條件的雜湊值,進而該nonce才是符合條件的,否則只能再去尋找下乙個nonce。
以太坊可以通過調整difficulty來調節當前挖礦的難度,difficulty越大,挖礦的難度越大。當difficulty越大時,maxvalue / difficulty
越小,合法的雜湊值範圍越小,造成挖礦難度增加。
雜湊值滿足條件的概率是p = (maxvalue / difficulty) / maxvalue = 1 / difficulty
,礦工需要進行1 / p = difficulty
次的判斷,才有可能找到乙個符合條件的nonce,當前以太坊難度為3241847139727150。
ethash挖礦的主要思想是,開啟多個執行緒去尋找符合條件的nonce,給每個執行緒分配乙個隨機數,作為本執行緒的nonce的初始值,然後每個執行緒判斷當前的nonce是否符合上面的公式,如果不符合,則把nonce加1,再次進行判斷,這樣不定的迭代下去,直到找到乙個符合條件的nonce,或者挖礦被叫停。
接下來介紹挖礦的幾個主要函式的實現,它們是:
挖礦的入口seal函式。
挖礦函式mine函式。
挖礦需要的資料cache和dataset。
rand()函式的實現hashimotofull和hashimoto。
seal
是引擎的挖礦入口函式,它是管理崗位,負責管理挖礦的執行緒。它發起多個執行緒執行ethash.mine
進行並行挖礦,當要更新或者停止的時候,重新啟動或停止這些執行緒。
mine
函式負責挖礦。seal
在啟動每乙個mine
的時候,給它分配了乙個seed
,mine
會把它作為nonce
的初始值,然後生成本高度使用的dataset
,然後把dataset, hash, nonce
傳遞給hashimotofull
函式,這個函式可以認為是原理介紹中的rand
隨機函式,他會生成雜湊值result
,當result <= target
的時候,說明雜湊值落在符合條件的區間了,mine找到了符合條件的nonce,使用digest和nonce組成新的區塊後,傳送給seal
,否則驗證下乙個nonce是否是符合條件的。
dataset
用來生成result
,而cache
用來生成dataset
。至於如何使用dataset
生成result
在hashimoto()
中講述,本節介紹如何生成dataset。
dataset和cache中存放的都是偽隨機數,每個epoch的區塊使用相同的cache和dataset,並且dataset需要暫用大量的記憶體。剛開始時cache是16mb,dataset是1gb,但每個epoch它們就會增大一次,它們的大小分別定義在datasetsizes
和cachesizes
,dataset每次增長8mb,最大能達到16gb,所以挖礦的節點必須有足夠大的記憶體。
使用cache生成dataset。使用cache的部分資料,進行雜湊和異或運算,就能生成一組dataset的item,比如下圖中的cache中黃色塊,能生成dataset中的黃色塊,最後把這些item拼起來就生成了完整的dataset,完成該功能的函式是generatedataset
。
dataset.generate()
是dataset的生成函式,該函式只執行一次,先使用generatecache()
生成cache,再將cache作為generatedataset()
的入參生成dataset,其中需要重點關注的是generatedatasetitem()
,該函式是根據部分cache,生成一組dataset item,驗證pow的nonce的時候,也需要使用該函式。
hashimotofull
功能是使用dataset、hash和nonce生成digest和result。它建立乙個獲取dataset部分資料的lookup函式,該函式能夠返回連續的64位元組dataset中的資料,然後把lookup函式、hash和nonce傳遞給hashimoto
。
hashimoto
的功能是根據hash和nonce,以及lookup函式生成digest
和result
,lookup函式能夠返回64位元組的資料就行。它把hash和nonce合成種子,然後根據種子生成混合的資料mix,然後進入乙個迴圈,使用mix和seed獲得dataset的行號,使用lookup獲取指定行的資料,然後把資料混合到mix中,混合的方式是使用雜湊和異或運算,迴圈結束後再使用雜湊和異或函式把mix壓縮為64位元組,把mix轉為小端模式就得到了digest,把seed和mix進行hash運算得到result。
pow的驗證是證明出塊人確實進行了大量的雜湊計算。ethash驗證區塊頭中的nonce
和mixdigest
是否合法,如果驗證通過,則認為出塊人確實進行了大量的雜湊運算。驗證方式是確定區塊頭中的nonce
是否符合公式,並且區塊頭中的mixdigest
是否與使用此nonce
計算出的是否相同。
驗證與挖礦相比,簡直是毫不費力,因為:
時間節省。驗證只進行1次hashimoto
運算,而挖礦進行大約difficulty次。
空間節省。驗證只需要cache,不需要dataset,也就不需要計算龐大的dataset,因此不挖礦的驗證節點,不需要很高的配置。
接下來介紹驗證函式verifyseal()
,以及根據cache生成digest
和result
的hashimotolight()
。
ethash.verifyseal
實現pow驗證功能。首先先判斷區塊中的difficulty是否匹配,然後生成(獲取)當前區塊高度的cache,把cache和nonce傳遞給hashimotolight
,該函式能根據cache, hash, nonce
生成digest和result,然後校驗digest是否匹配以及result是否符合條件。
hashimotolight
使用cache, hash, nonce
生成digest
和result
。生成digest和result只需要部分的dataset資料,而這些部分dataset資料時可以通過cache生成,因此也就不需要完整的dataset。它把generatedatasetitem
函式封裝成了獲取部分dataset資料的lookup函式,然後傳遞給hashimoto
計算出digest和result。
如果這篇文章對你有幫助,不妨關注下我的github,有文章會收到通知。
以太坊原始碼分析 Ethash共識演算法
ethereum當前和bitcoin一樣,採用基於工作量證明 proof of work,pow 的共識演算法來產生新的區塊。與bitcoin不同的是,ethereum採用的共識演算法可以抵禦asic礦機對挖礦工作的壟斷地位,這個演算法叫做ethash。為什麼要反asic pow的的核心是hash運...
以太坊原始碼分析 共識(1)礦工
礦工在pow中負責了產生區塊的工作,把一大堆交易交給它,它生成乙個證明自己做了很多任務作的區塊,然後將這個區塊加入到本地區塊鏈並且廣播給其他節點。接下來我們將從以下角度介紹礦工 角色。礦工不是乙個人,而是一類人,可以把這一類人分成若干角色。通過了解乙個區塊產生的主要流程,掌握礦工的工作流。通過了解礦...
以太坊原始碼分析 Whisper
whisper具有以下基本特性和概念 通訊加密 每一條whisper訊息在網路上都是加密傳輸的,可以選擇非對稱加密 橢圓曲線 和對稱加密 aes gsm 兩種加密演算法之一。envelope 信封 envelope是網路中傳輸的whisper訊息的基本單位,它包含已加密的原始訊息以及訊息相關的控制資...