什么是調整挖礦難度?
挖礦就是不斷嘗試nonce,使整個block header中的哈希值小於等於給定的目標閾值 target。H(block header) <= target。
target越小,挖礦難度越大。調整挖礦難度,就是調整目標空間在整個輸出空間中所占的比例。比特幣中的hash算法是SHA-256,整個輸出空間是2^256個可能取值。通俗的說,調整目標空間占整個輸出空間的比例,就是哈希值前面要多少個0,但不是完全准確。
挖礦難度 difficulty與目標閾值 target成反比。difficulty = difficulty_1_target(挖礦難度位1時所對應的閾值) / target(當前的目標閾值)。difficulty最小就是1,此時的target是非常大的數。
為什么調整挖礦難度?
系統總算力越來越強,如果難度不變,出塊時間將會越來越短。一個區塊傳播給大多數節點所需要的時間大約是幾十秒,如果出塊時間縮短,如幾秒鍾一個,那么會很容易出現分叉。分叉過多,系統不易達成共識,威脅系統安全性。
假設大部分算力掌握在誠實的人手里。系統中總算力越強,安全性越好,因為要發動51%攻擊所需要的算力也就越大。但是如果出現過多分叉,系統中的總算力就會被分散,惡意節點集中算力擴展自己的分叉,很快就可以成為最長鏈,此時可能不再需要51%算力才能發動攻擊,攻擊成本大大降低。
如何調整挖礦難度?
每2016個區塊調一下閾值 target。(2016*10min)/(60min*24h)= 14天。也就是每14天調整一下閾值 target。
target = target *(actual time / expected time)
difficulty = difficulty *(expected time / actual time)
其中actual time就是指的系統中產生的最近的2016個區塊實際花費的時間 time spent mining the last 2016 blocks。expected time就是指的2016*10min,也就是14天。
如果最近2016個區塊產生的時間超過14天,說明平均每一個區塊的出塊時間超過10min,這時候挖礦難度應該降低。如果實際時間小於14天,說明出塊太快,這時候應該提高挖礦難度。實際代碼中,上調或下調都有4倍的限制。比如實際時間非常長,超過8周,那么算的時候也按照8周來算,最多增大4倍。相反如果實際時間很短,不到半周,那么算的時候按照半周來算,最小也是1/4。
如何讓所有礦工同時調整目標閾值?
計算target的方法是寫在比特幣系統的代碼中,每挖到2016個區塊,會自動進行調整,代碼開源。如果有的惡意節點故意不調,那么發布的區塊,誠實礦工不會認同。block header中不直接存儲target,因為它是256位的,nBits域在header中只有4位,可以認為是target的壓縮編碼。如果有惡意礦工不調難度,那么在檢查區塊合法性(nBits域)就不會通過。
系統實際情況舉例:(截止到18年,圖片來源於視頻)
這張圖顯示的是09-18年比特幣系統中總算力的情況。沒有流行之前很長一段時間沒有明顯增長,后面幾年增長較快,呈現指數級的增長。但是即使在這段期間,算力也不是單調遞增,中間有波動,但是總體是增長很快的。
這個是09-18年挖礦難度的變化情況。與算力增長幾乎同步,通過調整挖礦難度,使得出塊時間保持穩定。
這個圖顯示的是10-18年每天的出塊時間。總的來說出塊時間穩定在10分鍾上下震動,說明難度調整達到了預期目的。