工作量證明機制是怎樣的?

買賣虛擬貨幣
工作證明(proof of work,簡稱pow),顧名思義,即工作量的證明。通常來說只能從結果證明,因為監測工作過程通常是繁瑣與低效的。

比特幣在block的生成過程中使用了pow機制,一個符合要求的block hash由n個前導零構成,零的個數取決於網路的難度值。要得到合理的block hash需要經過大量嘗試計算,計算時間取決於機器的雜湊運算速度。當某個節點提供出一個合理的block hash值,說明該節點確實經過了大量的嘗試計算,當然,並不能得出計算次數的絕對值,因為尋找合理hash是一個概率事件。當節點擁有佔全網n%的算力時,該節點即有n/100的概率找到block hash。

工作證明機制看似很神秘,其實在社會中的應用非常廣泛。例如,畢業證、學位證等證書,就是工作證明,擁有證書即表明你在過去投入了學習與工作。生活大部分事情都是透過結果來判斷的。


挖礦

挖礦即不斷接入新的block延續block chain的過程。


挖礦為整個系統的運轉提供原動力,是比特幣的發動機,沒有挖礦就沒有比特幣。挖礦有三個重要功能:

  1. 發行新的貨幣(總量達到之前)
  2. 維繫貨幣的支付功能
  3. 透過算力保障系統安全
金礦消耗資源將黃金注入流通經濟,比特幣透過“挖礦”完成相同的事情,只不過消耗的是cpu時間與電力。當然,比特幣的挖礦意義遠大於此。

block hash演算法

block頭部資訊的構成:
欄位名含義大小(位元組)
version版本號4
hashprevblock上一個block hash值32
hashmerkleroot上一個block產生之後至新block生成此時間內,
交易資料打包形成的hash
32
timeunix時間戳4
bits目標值,即難度4
nonce隨機數4


下面採用高度為125552的block資料為例,演示block hash的計算過程:

12345678910111213141516171819
php$header_hex="01000000".// version// previous block hash"81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000".// merkle root hash of transactions in this block"e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122b".// time"c7f5d74d".// bits (difficulty)"f2b9441a".// nonce"42a14695";$header_bin=pack("h*",$header_hex);// hex to bin$h=hash('sha256',hash('sha256',$header_bin,true),true);// double sha256echobin2hex($h),"\n";// output: 1dbd981fe6985776b644b173a4d0385ddc1aa2a829688d1e0000000000000000echobin2hex(strrev($h)),"\n";// output: 00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d
該計算過程簡單明瞭:首先將數個欄位合併成一塊資料,然後對這塊資料進行雙sha256運算。

產量調節

block的產量為大約每兩週2016個,即每10分鐘一塊。該規則在每個節點的程式碼裡都固定了。
123456
// 目標時間視窗長度:兩週staticconstint64ntargettimespan=14*24*60*60;// block頻率,每10分鐘一塊staticconstint64ntargetspacing=10*60;// 每兩週的產量2016,也是調節週期staticconstint64ninterval=ntargettimespan/ntargetspacing;
但由於實際算力總是不斷變化的(目前一直是快速上升的),所以需根據最近2016個塊的耗費時間來調整難度值,維持每10分鐘一個block的頻率.

block欄位詳解

  • version,版本號,很少變動,一般用於軟體全網升級時做標識
  • hashprevblock,前向block hash值,該欄位強制多個block之間形成連結
  • hashmerkleroot,交易hash樹的根節點hash值,起校驗作用,保障block在網路傳輸過程中的資料一致性,有新交易加入即發生變化
  • time,unix時間戳,每秒自增一,標記block的生成時間,同時為block hash探尋引入一個頻繁的變動因子
  • bits,可以推算出難度值,用於驗證block hash難度是否達標
  • nonce,隨機數,在上面數個欄位都固定的情況下,不停地更換隨機數來探尋

最為關鍵的欄位是hashprevblock,該欄位使得block之間連結起來,形成一個巨大的“鏈條”。block本是稀鬆平常的資料結構,但以鏈式結構組織起來後卻使得它們具有非常深遠的意義:

  1. 形成分支博弈,使得算力總是在主分支上角逐
  2. 算力攻擊的概率難度呈指數上升(泊松分佈)

每個block都必須指向前一個block,否則無法驗證透過。追溯至源頭,便是高度為零的創世紀塊(genesis block),這裡是block chain的起點,其前向block hash為零,或者說為空。

新block誕生過程

下面是一個簡單的步驟描述,實際礦池運作會有區別,複雜一些:

  1. 節點監聽全網交易,透過驗證的交易進入節點的記憶體池(tx mem pool),並更新交易資料的merkle hash值
  2. 更新時間戳
  3. 嘗試不同的隨機數(nonce),進行hash計算
  4. 重複該過程至找到合理的hash
  5. 打包block:先裝入block meta資訊,然後是交易資料
  6. 對外部廣播出新block
  7. 其他節點驗證透過後,連結至block chain,主鏈高度加一,然後切換至新block後面挖礦

由於hashprevblock欄位的存在,使得大家總是在最新的block後面開挖,稍後會分析原因。

主鏈分叉

從block hash演算法我們知道,合理的block並不是唯一的,同一高度存在多個block的可能性。那麼,當同一個高度出現多個時,主鏈即出現分叉(fork)。遇到分叉時,網路會根據下列原則選舉出best chain:

  1. 不同高度的分支,總是接受最高(即最長)的那條分支
  2. 相同高度的,接受難度最大的
  3. 高度相同且難度一致的,接受時間最早的
  4. 若所有均相同,則按照從網路接受的順序
  5. 等待block chain高度增一,則重新選擇best chain

按照這個規則運作的節點,稱為誠實節點(honest nodes)。節點可以誠實也可以不誠實。

分支博弈

我們假設所有的節點:

  1. 都是理性的,追求收益最大化
  2. 都是不誠實的,且不惜任何手段獲取利益

所有節點均獨自挖礦不理會其他節點,並將所得收益放入自己口袋,現象就是一個節點挖一個分支。由於機器的配置總是有差別的,那麼算力最強的節點挖得的分支必然是最長的,如果一個節點的分支不是最長的,意味其收益存在不被認可的風險(即零收益)。為了降低、逃避此風險,一些節點肯定會聯合起來一起挖某個分支,試圖成為最長的分支或保持最長分支優勢。

一旦出現有少量的節點聯合,那麼其他節點必然會效仿,否則他們收益為零的風險會更大。於是,分支迅速合併彙集,所有節點都會選擇算力更強的分支,只有這樣才能保持收益風險最小。最終,只會存在一個這樣的分支,就是主幹分支(best/main chain)。

對於不誠實節點來說,結局是無奈的:能且只能加入主幹挖礦。不加入即意味被拋棄,零收益;加入就是老實幹活,按佔比分成。

hash dance

block hash的計算是隨機概率事件,當有節點廣播出難度更高的block後,大家便跑到那個分支。在比特幣系統執行過程中,算力經常在分支間跳來跳去,此現象稱為hash dance。一般情況下,分支的高度為1~2,沒有大的故障很難出現高於2的分支。

hash dance起名源於google dance.

算力攻擊的概率

算力攻擊是一個概率問題,這裡作簡單敘述:

  • p = 誠實節點挖出block概率
  • q = 攻擊者挖出block概率,q = 1 – p
  • qz = 攻擊者從z個block追上的概率

我們假設p>q,否則攻擊者掌握了一半以上的算力,那麼概率上永遠是贏的。該事件(攻擊者勝出)的概率是固定,且n次事件之間是相互獨立的,那麼這一系列隨機過程符合泊松分佈(poisson distribution)z個塊時,攻擊者勝出的期望為lambda

攻擊者在攻擊時已經偷偷的計算了k個塊,那麼這

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;