1 難度及相關概念
1.1 哈希運算
簡單的說,哈希運算可以看出是輸入不同輸出不同的函數(免碰撞),該函數沒有反函數,即不可以通過輸出推導出輸入(隱匿性)。哈希運算有很多種算法,不同的算法可能有位數不同的輸出,比特幣用了其中的一種,SHA256(Secure Hashing Algorithm 256),顧名思義,該算法的哈希輸出結果是256位,可以看作是256位的整數。嚴格來說免碰撞這個特性並不成立,例如比特幣使用的SHA256算法,總共會有2^256種輸出,如果我們進行2^256+1次輸入,那么必然會產生一次碰撞,甚至從概率的角度看,進行2^130次輸入就會有99%的可能發生一次碰撞。不過我們可以計算一下,假設一台計算機以每秒10000次的速度進行哈希運算,要經過10^27年才能完成2^128次哈希!甚至可以這么說,即便是人類制造的所有計算機自宇宙誕生開始一直運算到今天,發現碰撞的幾率也是極其小的。
1.2 目標值
 在比特幣中所謂的“挖礦”就是修改區塊中特定位置的值,找滿足要求的區塊,該區塊的哈希輸出要小於特定的值,該值稱作目標值,在比特幣中,規定256位整數:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
為最大目標值,區塊要被比特幣網絡接受其哈希結果必須要小於最大目標值,把該目標值對應的難度定義1,比特幣網絡會自動的調整難度值,隨着比特幣挖礦的進行,區塊的目標值會越來越小,哈希結果滿足要求的概率越來越低,即找到滿足要求的區塊會越來越難,難度和目標值有如下對應關系:
當前難度值 = 最大目標值 / 當前目標值
由於哈希的隨機性,進行一次哈希運行256位整數任意位置的值要么為0要么為1,以最高位為例,要使最高位為零(其他位不關心)理論上進行2次運算即可出現一次,進而要使最高位和次高位都為零,則理論上要進行2^2才會出現一次,依次類推,要使最高32位都為零則需要進行2^32次運行才行,即找到難度為1的哈希值理論上需要進行2^32次運行,進而要找到難度為D的哈希值,理論上要進行D*2^32次運行,數字貨幣挖礦時,礦池在對礦工進行算力統計時就是根據該理論進行的。
1.3 nBits
區塊中用一個4字節長度的字段來存儲當前區塊的目標值,4字節也就是32位,要用來存儲256位長度的難度目標值,因此這256位長度的值需要經過壓縮處理后才能放到這個字段中。壓縮規則其實很簡單,一共有4個字節來進行存儲,最高字節用來存儲目標值的有效字節數,即目標值轉換成16進制后去除前導零的字節數,另外如果最高字節值大於0x7F,則是在最高字節前添加00后字節個數,3個字節中存儲的是目標值有效位的最高3個字節,例如對於最大目標值,有效字節的個數是28,因為最高字節是0xFF所以還需在之前添加00,即有效字節數是29(十六進制0x1D),所以壓縮后的nBits的最高字節為0x1D,剩余3個字節為00FFFF,即最大目標值對應的nBits為0x1D00FFFF。對於這樣的一個壓縮后的十六進制4字節難度目標值,前2位通常稱為冪者指數,后面6位稱為系數。nBits可通過如下公式獲得目標值:
目標值=系數*2^(8*(指數-3))次方
以0x1D00FFFF為例,系數是00FFFF,指數是1D,帶入公式就是0x00FFFF*2^(8*(0x1D-3)),計算后得到的值是:
0x00000000FFFF0000000000000000000000000000000000000000000000000000
 讀者可以已經發現,相比原始的目標值,還原后的目標值,精度少了很多位,確實如此,存儲在nBits中的值是一個精度截斷后的近似值,但是該值已經很接近原始值,通過計算:
0xFFFF0000000000000000000000000000000000000000000000000000*1.0/0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF=0.9999847412109375
可知該近似的精度很高了。
1.4 難度調整
比特幣網絡的難度值並不是一成不變的,差不多每兩周會調整一下難度值,因為計算的算力是變化的,為了維持差不多10分鍾出一個區塊的節奏,難度要跟隨算力變化而調整。新難度值的計算公式是這樣的新難度值=當前難度值×(最近的2016個區塊的實際出塊時間/20160分鍾)2016個區塊的意思是,假設按照理論的10分鍾出一個塊,2周也就是14天的時間,應該出2016個區塊,可以看到實際上就是計算一下實際與理論上的時間差值,彌補上這個差值即可。
2 實例分析
我們以比特幣57043(00000000152340ca42227603908689183edc47355204e7aca59383b0aaac1fd8)塊為例,通過查詢可知:

該區塊的難度是11.85,nBits是0x1c159c24,轉換成256整數后為0x159c24<<(8*(0x1c-3))=0x159c2400000000000000000000000000000000000000000000000000,用原始最大目標值計算可知:
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF*1.0/0x159c2400000000000000000000000000000000000000000000000000=11.846408911559438
用壓縮后的最大目標值計算:
0x00000000FFFF0000000000000000000000000000000000000000000000000000*1.0/0x159c2400000000000000000000000000000000000000000000000000=11.846228149704709
可知難度的近似值都是11.85。
3 工作量證明
工作量證明系統主要特征是客戶端需要做一定難度的工作得出一個結果,驗證方卻很容易通過結果來檢查出客戶端是不是做了相應的工作。這種方案的一個核心特征是不對稱性:工作對於請求方是適中的,對於驗證方則是易於驗證的。舉個例子,給定的一個基本的字符串"Hello, world!",我們給出的工作量要求是,可以在這個字符串后面添加一個叫做nonce的整數值,對變更后(添加nonce)的字符串進行SHA256哈希運算,如果得到的哈希結果(以16進制的形式表示)是以"0000"開頭的,則驗證通過。為了達到這個工作量證明的目標。我們需要不停的遞增nonce值,對得到的新字符串進行SHA256哈希運算。按照這個規則,我們需要經過4251次計算才能找到恰好前4位為0的哈希散列。
"Hello, world!0" => 1312af178c253f84028d480a6adc1e25e81caa44c749ec81976192e2ec934c64
"Hello, world!1" => e9afc424b79e4f6ab42d99c81156d3a17228d6e1eef4139be78e948a9332a7d8
"Hello, world!2" => ae37343a357a8297591625e7134cbea22f5928be8ca2a32aa475cf05fd4266b7
...
"Hello, world!4248" => 6e110d98b388e77e9c6f042ac6b497cec46660deef75a55ebc7cfdf65cc0b965
"Hello, world!4249" => c004190b822f1669cac8dc37e761cb73652e7832fb814565702245cf26ebb9e6
"Hello, world!4250" => 0000c3af42fc31103f1fdc0151fa747ff87349a4714df7cc52ea464e12dcd4e9
實際上,通過概率學址事可知,預期大概要進行2^16次嘗試,才能得到4個前導0的哈希散列。這里數學期望的計算次數,就是我們要求的“工作量”,重復多次進行的工作量證明會是一個符合統計學規律的概率事件。比特幣中所謂的“工作量”證明就是不斷變化nonce進行哈希計算,使得兩次SHA256計算結果小於目標值:
SHA256(SHA256(version + prev_hash + merkle_root + ntime + nbits + nonce )) < TARGET
由哈希函數的特性可以認為,每個礦工要找出滿足條件的nonce所需要運行哈希運算的次數從概率上來說是一樣的,只要礦工給出了滿足條件的nonce值,就可以認為它完成了特定的“工作量”。正是比特系統的工作量證明機制保證了挖礦過程沒有投機取巧的可能性,從而保證了比特幣網絡的公平及安全性。
