1. Ethash 算法c++
1.1 Ethashgit
Ethash是以太坊1.0中使用的PoW(工做量證實)算法,它是Hashimoto算法結合Dagger以後產生的一個變種。它的特色是計算的效率基本與CPU無關,卻和內存大小和內存帶寬正相關。所以經過共享內存的方式大規模部署的礦機芯片並不能在挖礦效率上有線性或者超線性的增加。github
該算法的通常流程以下:算法
1.2 內存難解spa
因爲比特幣將hash算法做爲pow工做量證實的重要手段,後續的各類採用pow的數字貨幣也延續了這個設計,以SHA25六、MD5(MD5後來被證實不具有強碰撞性數字貨幣通常不用)爲表明算法。在設計之初都是算力敏感型,意味着計算資源是瓶頸,主頻越高的 CPU 進行 Hash 的速度也越快。這個設計直接致使後來的礦機出現,採用ASIC芯片的礦機更是將這種運算能力成倍提高,更多礦場的出現使得當時的比特幣面臨算力中心化的威脅。爲了限制計算能力的依賴,人們開始尋求新的算法,既然要限制CPU的能力,目光天然投向存儲依賴,也就是內存依賴。設計
Hashimoto算法採用IO飽和的策略來對抗ASIC,使內存讀取成爲採礦過程當中的限制因素。3d
Dagger算法使用DAG(directed acyclic graphs 有向無環圖)來同時實現內存難解和內存易驗證兩個特色。 主要原理是,計算每一個nonce須要DAG中的一小部分,採礦過程須要存儲完整的DAG,禁止每次計算DAG的相應子集,而驗證過程是容許的。blog
1.3 參數定義內存
WORD_BYTES | 4 | Word的字節數 | |
---|---|---|---|
DATASET_BYTES_INIT | 2**30 1GB | Dataset的初始大小 | | |
DATASET_BYTES_GROWTH | 2**23 8MB | 每一個紀元dataset的增加量 | | |
CACHE_BYTES_INIT | 2**24 16MB | Cache的初始大小 | | |
CHCHE_BYTES_GROWTH | 2**17 128KB | 每一個紀元cache的增加量 | | |
CACHE_MULTIPLIER | 1024 | Size of the DAG relative to the cache | | |
EPOCH_LENGTH | 30000 | 每一個epoch的塊數 | | |
MIX_BYTES | 128 | Mix的寬度 | | |
HASH_BYTES | 64 | Hash的長度 | | |
DATASET_PARENTS | 256 | 每一個數據集元素的parents數量 | | |
CACHE_ROUNDS | 3 | 計算cache時的輪數 | | |
ACCESSES | 64 | Hashimoto循環的次數 | |
2 DAG資源
DAG是ethash算法中須要頻繁訪問的數據集,這個爲每一個epoch生成的。DAG要花很長時間生成,若是客戶端至少按照須要生成它,那麼在找到新epoch第一個區塊以前,每一個epoch過渡都要等待很長時間。然而,DAG的生成只取決於區塊數量,因此能夠預先計算出DAG來避免在每一個epoch過渡過長的等待時間。
DAG的生成流程以下:
2.1 Dag_size 和Cache_size
每一個epoch的dagsize和cachesize都不一樣,上面已經定義了創世時的初始值,以太坊還提供了一個表來存儲接下來2048個紀元(大約20年)的各個值。詳見官網或源碼cpp-ethereum/libethash/data_sizes.h.
獲取datasize 和cachesize的方法以下:
2.2 Seedhash
算法中須要一個seedhash,由下面程序生成,從程序可見每一個epoch的seed是不變的。
2.3 Cache
使用seedhash計算cache。
2.4 DAG
最後使用cache計算DAG,light參數中保存的是cache數據.
2.5 DAG文件
DAG每次生成都須要很長時間,所以生成時候須要存在文件中,再使用mmap映射到內存中。DAG文件路徑通常以下
Mac/Linux : $HOME/.ethash/full-R–
Windows: $HOME/Appdata/Local/Ethash/full-R–
是ethash算法的版本號,在libethash/ethash.h 中REVISION定義。
是上面計算出來的seedhash
路徑下可能會有多個DAG文件,這取決於用戶或者客戶端是否刪除過期的DAG文件。
格式:
DAG文件以8字節的幻數開頭,值爲0xfee1deadbaddcafe, 以小端格式寫入。接下來是小端格式寫入的dataset數據。
3 Ethash實現
3.1 Ethash
圖1 算法流程圖
參數說明:
Header_hash: 是當前塊頭部數據的hash值,在礦機調用get_ethwork時從任務參數中獲取。
Nonce: 是每次計算ethash使用不一樣的數,不能重複。能夠取時間戳或隨機數做爲起始值,而後遞增。
對於礦工來講,若是result的值小於或等於target,那麼就完成了挖礦過程,將當前的nonce和mix_hash做爲工做量證實提交工做;若是result的值大於target,那麼就須要改變nonce的值,再次調用ethash算法.
Ethash算法程序以下:
從圖中看,每次ethash從DAG隨機取64128=8192Bytes, 以GTX1070顯卡爲例,帶寬爲256GB/s, 那麼每秒能承受256102410241024/8192=33554432次ethash運算,即33MH/s的算力。可見,該算法對內存帶寬的要求很高。
3.2 快速驗證
當驗證一個工做提交是否有效時,速度很快。
下面是快速驗證程序:
原文連接:http://wangxiaoming.com/blog/2018/06/26/HPB-47-ETH-Pow/