1. 程式人生 > >以太坊挖礦和ethash

以太坊挖礦和ethash

挖礦簡介

挖礦這個詞源於對加密貨幣與黃金的類比。黃金或貴金屬很稀有,電子代幣也是,增加總量的唯一方法就是挖礦。以太坊也是這樣,發行的唯一辦法就是挖礦。但是不像其他例子,挖礦也是通過在區塊鏈中建立、驗證、發行和傳播區塊來保護網路的方法。

挖以太幣=保護網路=驗證計算

什麼是挖礦?

以太坊,和所有區塊鏈技術一樣,使用激勵驅動的安全模式。共識基於選擇具有最高總難度的區塊。礦工創造區塊,其他人檢測有效性。區塊只有在包含特定難度的工作量時才有效,還有其他合格性條件。請注意到以太坊Serenity里程碑,可能就會被取代(參考權益證明模型)。

以太坊區塊鏈在很多方面與比特幣區塊鏈類似,但也有些不同。在區塊鏈架構方面,以太坊和比特幣之間最主要的的區別是,不像比特幣,以太坊區塊不僅包含交易列表也包含最近狀態(merkle patricia特里結構的根散表編碼在狀態中更精確)除此之外,另外兩個值,區塊數和難度,也儲存在區塊中。

使用的工作量證明演算法叫Ethash(Dagger-Hashimoto演算法的改良版本),包括找到演算法的隨機數輸入以使結果低於特定的難度閾值。工作量證明演算法的意義在於,要找到這樣一個隨機數,沒有比列舉可能性更好的策略,而解決方法的驗證瑣碎又廉價。由於輸出有均勻分佈(是散表功能應用的結果),我們可以保證,平均而言,需要找到這樣一個隨機數的時間取決於難度閾值。這使得只通過操縱難度來控制找到新區塊的時間成為可能。

正如協議中所描述的,難度動態調整的方式是每15秒整個網路會產生一個區塊。我們說網路用15秒區塊時間生產一個區塊鏈。這個“心跳”基本上主要強調系統狀態同步,保證不可能維持一個分叉(允許double spend)或被惡意分子重寫歷史,除非攻擊者有半數以上的網路挖礦能力(即所謂的51%攻擊)。

任何參與到網路的節點都可能是礦工,預期的挖礦收益和他們的(相對)挖礦能力或者說成正比,比如被網路總散表率標準化的,每秒嘗試的隨機數數量。

Ethash工作量證明是記憶體難解的,這使它能抵抗ASIC。記憶體難解性由工作量證明演算法實現,需要選擇依靠隨機數和區塊標題的固定資源的子集合。這個資源(幾十億位元組大小的資料)叫做DAG。每3000個區塊的DAG完全不同,125小時的視窗叫做epoch(大約5.2天),需要一點時間來生成。由於DAG只由區塊高度決定,它可以被事先生成,如果沒有被事先生成,客戶端需要等到程序最後來生產區塊。如果客戶端沒有預生成並提前快取DAG,網路可能會在每個epoch過渡經歷大規模區塊延遲。注意不必要生成DAG以驗證工作量證明,它可以在低CPU和小記憶體的狀態下被驗證。

在特殊情況下,從零開始建立節點的時候,只有在為現存epoch建立DAG的時候才會開始挖礦。

挖礦獎勵

獲獎區塊的成功工作量證明礦工會獲得:

  • “獲勝”區塊的靜態區塊獎,包含5.0(5個)以太幣
  • 區塊內支出的gas成本 — 一定數量的以太幣,取決於當前gas價格
  • 叔伯塊的額外獎勵,形式是每個叔伯塊包含額外的1/32

在區塊中執行所有交易所消費的、由獲勝礦工提交的gas都由每個交易的傳送者支付。已發生的gas成本歸到礦工賬戶作為共識協議的一部分。隨著時間變化,這會使資料區塊獎變得矮小。

叔伯塊是穩定的區塊,比如說,和包含先前區塊(最多回6個區塊)的父區塊。有效的叔伯塊會受到獎勵以中和網路滯後給挖礦獎勵帶來的影響,因而提升安全性(這叫做GHOST協議)。叔伯塊由成功工作量證明礦工形成的區塊中所包含的叔伯塊接收7/8的資料區塊獎勵(=4.375以太幣)。每個區塊最多允許2個叔伯塊。

  • reddit上的叔伯塊ELI5
  • 解釋叔伯塊的分論壇

挖礦的成功取決於設定的區塊難度。區塊難度動態調整每個區塊,以規定網路雜湊能力來創造12秒區塊時間。找到區塊的機會因此由與難度相關的雜湊率產生。

Ethash DAG

Ethash將DAG(有向非迴圈圖)用於工作量證明演算法,這是為每個epoch生成,例如,每3000個區塊(125個小時,大約5.2天)。DAG要花很長時間生成。如果客戶端只是按需要生成它,那麼在找到新epoch第一個區塊之前,每個epoch過渡都要等待很長時間。然而,DAG只取決於區塊數量,所以可以預先計算來避免在每個epoch過渡過長的等待時間。Geth和ethminer執行自動的DAG生成,每次維持2個DAG以便epoch過渡流暢。挖礦從控制檯操控的時候,自動DAG生成會被開啟和關閉。如果geth用—mine選項啟動的時候,也會預設開啟。注意客戶端分享DAG資源,如果你執行任何客戶端的多個例項,確保自動的DAG生成只在一個例項中開啟。

為任意epoch生成DAG:

geth makedag <block number> <outputdir>

例項geth makedag 360000 ~/.ethash.。請注意ethash為DAG使用~/.ethash (Mac/Linux) 或~/AppData/Ethash (Windows),這樣它可以在不同的客戶端實現以及多個執行例項中分享。

演算法

我們的演算法,Ethash(之前被稱為Dagger-Hashimoto),是基於一個大的、瞬時的、任意生成的、形成DAG(Dagger-part)的資料組規定,嘗試解決它一個特定的約束,部分通過區塊標題雜湊來決定。

它被設計用於在一個只有慢CPU的環境中來雜湊快速驗證時間,但在被提供大量高頻寬記憶體時,為挖礦提供大量的加速。大量記憶體需求意味著大規模礦工獲得相對少的超線性利益。高頻寬需求意味著從堆在很多超速處理單元、分享同樣記憶體的加速在每個單獨的單元給出很少的利益(譯者注:通過阻止專用晶片共享記憶體的方式,降低礦機的作用)。

沒有節點驗證的利益因而阻礙中心化,這在挖礦中很重要。

外部挖礦應用和以太坊工作規定和報送的後臺程式之間的交流通過JSON-RPC API發生。提供兩個RPC功能;eth_getWork和eth_submitWork。

這些被正式記錄在JSON-RPC API維基百科文章的礦工條目下。

為了挖礦你需要一個完全同步的、能夠挖礦的以太坊客戶端和至少一個以太坊賬戶。這個賬戶用於傳送挖礦獎勵,通常被稱為貨幣基或以太基。檢視這個說明的“建立帳戶”章節,學習如何建立帳戶。

警告:開始挖礦前,確保區塊鏈和主鏈完全同步,否則就不能在主鏈上挖礦。

設計目標

  • 抵抗礦機(ASIC Resistance)。使用專門優化的晶片產生的挖礦優勢應該儘可能的小,小到即使使用普通CPU挖礦也能產生收益。
  • 輕客戶端可驗證。輕客戶端應該有能力驗證每一個塊的真實性。目標是在普通桌面電腦上執行用C實現的驗證演算法,驗證時間小於0.01秒,用Python或者Javascript小於0.1秒,使用記憶體不超過1MB。

挖礦演算法

以太幣(ether)的挖礦演算法叫做Ethash, 又名Dashimoto (Dagger-Hashimoto),是Hashimoto演算法結合Dagger之後產成的一個變種。它的特點是挖礦的效率基本與CPU無關,卻和記憶體大小和記憶體頻寬正相關。對記憶體大小和頻寬的要求意味著那些通過共享記憶體的方式大規模部署的礦機晶片並不能在挖礦效率上有線性或者超線性(super-linear)的增長。

接下來讓我們看看Dashimoto的基本流程:

  1. 對於每一個塊(block),先計算出一個種子(seed)。種子的計算只依賴於當前塊的資訊,例如block number以及block headers。
  2. 使用種子產生32MB的偽隨機資料集,稱為cache。輕客戶端需要儲存cache。
  3. 基於cache再生成一個1GB大小的資料集,稱為the DAG。這個資料集中的每一個元素都只依賴cache中的某幾個元素,換句話說,只要有cache就可以快速計算出DAG中指定位置的元素。完整的可挖礦的客戶端需要儲存DAG。
  4. 挖礦可以概括為從DAG中隨機選擇元素然後對其進行hash的過程。驗證的過程也是一樣,只不過不是從DAG裡面選擇元素,而是基於cache計算得到指定位置的元素,然後驗證這個元素集合的hash結果小於某個值。由於cache很小, 而且指定位置的DAG元素很容易計算,因此驗證過程只需要普通CPU和普通記憶體即可完成。
  5. cache和DAG每一個週期更新一次,一個週期的長度是1000個塊。也就是說這1000個塊產生的cache和DAG是完全一樣的,因此挖礦的主要工作在於從DAG中讀取資料,而不是更新cache和DAG。DAG的大小隨時間的推移線性增長,從1GB開始,每年增加大約7GB – 因此到2015年12月大約是8GB, 到2016年12月大約15GB。

注:以上步驟中的數字已經隨著開發的推進有了調整,準確值請參考原始碼。

挖礦軟體

我們預計在上線之時將有至少兩種挖礦方式:

  1. 使用Mist客戶端(官方客戶端實現,基於Go語言)進行CPU挖礦。
  2. 通過以太坊守護程序(eth daemon)和sgminer的組合進行GPU挖礦。守護程序和sgminer之前的資料通訊可以通過JSON-RPC API完成。目前有兩個API和挖礦有關:eth_getWork以及eth_submitWork。