比特幣挖礦
比特幣的網路是依賴礦工而運行的,因為比特幣是一個去中心化的網路,每一個礦工就相當於網路上的一個節點。他們查證交易記錄,製造和存儲所有的區塊,並對被寫入區塊鏈的區塊達成共識。
要成為比特幣礦工,首先必須要加入比特幣網路並與其他節點建立連接。建立連接以後,主要需要完成6個任務:
- 維護區塊鏈網路。必須先維護區塊鏈網路,為了做到這一點,一開始你可以要求其他節點把區塊鏈上的歷史記錄同步過來。
- 監聽交易廣播。每個礦工都需要監聽網路上的交易廣播,然後驗證該交易是否有效。包括檢驗交易腳本,是否有雙重交易等。
- 監聽新的區塊。礦工都需要監聽那些網路上廣播的新的區塊,並驗證是否有效,包括每筆交易是否有效,
- 組裝一個備選區塊。一旦擁有最新的全部區塊鏈數據備份,你就可以製造自己的區塊了。需要把監聽到的所有交易組合併放進一個新的備選的區塊,同時保證裡面的每個交易都是有效的。
- 找到一個讓你的區塊有效的隨機數。這是礦工工作中最難的一個環節,也就是常說的pow工作量證明最關鍵的地方
- 將你的區塊廣播出去。如果你成功挖出一個區塊,那就要廣播出去,並希望其他礦工接受你的區塊,然後從該區塊繼續接龍下去。當然,這一步你也可能會遇到競爭對手。
- 獲得獎勵。如果所有其他礦工接受了你的區塊,也就是你的區塊成為了區塊鏈上的一個新的節點,那麼你就會獲得相應的獎勵。
所以,一個全節點的礦工任務主要有兩類:第一類是驗證交易和區塊,這是比特幣網路賴以生存和運轉的基礎。第二類任務是和其他礦工競爭,爭取獎勵,這是為了鼓勵礦工完成第一類任務而設立的,礦工只有獲得了獎勵,才會心甘情願地去完成重要的任務,同時競爭時付出了一定的代價,也增加了惡意行為的成本,使得礦工自覺地變得「誠實」起來。
挖礦流程
在挖礦之前要構件好區塊,每一個區塊主要是由區塊頭部和交易組成。區塊內的所有交易以Merkle樹的結果存在,並且將樹根存儲在區塊頭部中,區塊頭部結構如下:
當區塊構建好後,就要開始挖礦。挖礦簡單說就是做一道數學題:題目就是把當前準備的區塊頭部中的父區塊哈希值,Merkle樹根,nonce值進行一個哈希運算,如果哈希結果小於目標值,那麼就表示把這道題解出來了,也表示挖礦成功了。挖礦成功後,就打包這個區塊,向全網廣播,等待加入到區塊鏈中。如果哈希結果大於目標值,那麼就表示此次未能解出答案,那麼就會將Nonce值加1,重複整個過程。流程如下:
Nonce,隨機數
Nonce值加1,雖然只是改變了1個比特,但是對於整個哈希結果來說,可能就是千差萬別的。如果Nonce從一串0開始,每次加1,那麼就會有2的32次方種可能,在這些可能中找出一個滿足解題規則的值。那麼問題來了,如果隨機數試過了32位所有的可能性之後,仍然不能產生一個有效的哈希值怎麼辦?
如下圖,除了Nonce這個隨機數,在coinbase的交易中(每個區塊的第一筆交易),還有一個可以調整的隨機數,當遍歷了Nonce所有的可能性不能得到有效值後,可以改變coinbase交易里的隨機數,整個Merkle樹上交易的哈希值都會改變,那麼頭部的Merkle根植也會改變,接著,可以重新按照上面流程,改變Nonce的值。
可以看出,改變交易中coinbase隨機數比改變頭部Nonce隨機數代價大得多,所以,只有在遍歷了Nonce所有的可能性還沒找到一個有效區塊時,才去改動coinbase的隨機數。
一般情況下,你所嘗試的絕大多數隨機數都不會成功,但是若能夠堅持足夠長的時間,總能找到一對正確的臨時隨機數組合---頭部Nonce隨機數和coinbase隨機數,用來產生一個符合哈希值要求的新區開。找到後可以立即宣布,就有希望得到相應的區塊獎勵。
每個人都在運算同一個謎題嗎?
你可能會想,每個礦工都在臨時隨機數值上加1,豈不是都按照同一個模式解同樣的題,那麼速度快的礦工豈不是一直都快,一直都能贏呢?從現實結果來看,肯定不是的。就算每個礦工準備的區塊中,頭部的父區塊哈希和Nonce隨機數一摸一樣,那Merkle樹根值也不可能一樣。原因有幾個:1. 每個礦工準備的區塊中包含的交易或多或少有區別,2. 每個礦工準備的區塊中的交易次序可能會有差異,3. coinbase交易中,礦工會寫自己的地址接收新幣,不同的礦工地址是不同的。以上三種情況,只要稍微有些不同,那麼這些區別會沿著Merkle樹往上傳遞直達樹根,導致整棵樹的哈希值差別非常大。
挖礦難度
我們在一些比特幣相關的網站上,經常可以看到如上所示的比特幣難度說明。它顯示了當前比特幣網路的全網算力,當前挖礦的難度和下一次難度調整的時間和幅度。
比特幣網路每挖出2016個區塊,挖礦難度會改變一次。因為每個區塊大概10分鐘,通過一個簡單的數學計算,可以得出,每2個星期會調整一下挖礦難度。根據實際時長和期望時長的比值,如果區塊產生的速率比10分鐘快,則增加難度,比10分鐘慢則降低難度。下一個挖礦難度公式為:
新難度值 = 當前難度值 * ( 產生上2016個區塊所花費的時間 / 2016 × 10分 )
所以,這個公式的意義就在於,將全網難度維持平均每10分鐘一個區塊的速度。為什麼要選擇挖礦難度兩周一調整,其實也沒有什麼特別的意義,就是一個權衡結果。如果太短,難度會隨著每一個周期找到的區塊數目不同而波動(概率問題),如果太長,整個網路的哈希算力就會與難度大大的失衡(難度的調整滯後於計算能力的變化)
我感覺比特幣系統的巧妙就在這裡,很多設計看起來平平無奇,其實很有深意。比如又為什麼要10分鐘出一個區塊,為什麼生成地址時使用base58,為什麼要對公鑰做雙哈希運算等等。
比特幣的挖礦難度受什麼影響呢?最主要受全網算力的影響,而全網算力受到有多少新的礦工加入的影響,新礦工加入本身又是由比特幣的當前價格來決定的。總的來說,當越來越多的礦工加入並且挖礦的設備效率越來越高時,找到有效區塊的時間就越來越短,按照上面的公式,分母就會變小,導致難度增加,直到重新回到每10分鐘一個區塊。
每個比特幣礦工獨立地計算難度,只接受達到這個難度的區塊。兩個在不同分叉上的礦工可能會有不同的計算難度,但在同一個區塊鏈上工作的礦工一定會對計算難度達成共識。
目標值
目標值是根據難度來的,兩者的關係是難度越大,目標值就越小,反之難度越小,目標值就越大。計算公式是:
目標值 = 最大目標值 / 難度值
其中最大目標值是一個恆定值,即00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF(64位16進位),得出的目標值是也是一個64位16進位(即256位二進位)的數字,使用16進位來表示形式如:
000c975dea7bb4c4998040ab8fe6dab0471abebbf0173fc29921f68ffcaba44c
前面的0越多,就表示目標值越小,那麼為什麼目標值越小,挖礦就越難呢?下面我用一段代碼來說明一下:
上面的代碼中hashnum的參數表示sha256運算後得到的哈希值前面有幾個0,關係大概是:
6個0以下大概需要0到3秒鐘,7至8個0大概需要1分鐘左右,9個0需要4分鐘,10個0以上我的電腦跑到內存溢出也沒算出來。
現在的目標值,前面的0已經在20個以上了,每增加一個0,挖礦的難度增加都是指數級的增長。
挖礦的硬體
CPU挖礦
第一代挖礦是在普通電腦上完成的,也就是用通用中央處理器CPU來運算。CPU的演算法一般是礦工按照如下代碼,簡單地按照線性方式嘗試所有臨時變數值,在軟體中進行SHA-256運算,並檢查結果是否找到一個有效區塊。需要注意的是,這段代碼實際進行了兩次HASH-256運算
TARGET = (65535 << 200)/DIFFICULTY;coinbase_nonce = 0;while(1){ header = makeBlockHeader(transactions,coinbase_nonce) for (header_nonce=0 ; header_nonce < (1 << 32); header_nonce++){ if ( SHA256(SHA256(makeBlock(header,header_nonce))) < TARGET ) break; } coinbase_nonce++;}
那麼普通電腦運行這段代碼有多快?我用自己的筆記本電腦測試了一下。我的電腦是MacOS,配置是處理器2.9GHz Core i5,內存8G,使用下面代碼測試了一下運算速度
可以看出測試做了100萬次sha256運算用時1.4秒,接近於1GH/s,現在全網算力是13.42 EH/s,是我電腦的百億倍。
GPU挖礦
第二代礦工發現CPU已經無利可圖時,就使用起了GPU。GPU的好處是有著高吞吐量和高並行處理功能,這兩點對比特幣挖礦都十分有利。比特幣挖礦可以進行大量的並行計算,因為你可以同時用不同的臨時隨機數計算多個哈希值。
而且,GPU都可以超頻,這意味著如果你願意承擔顯卡過熱或者故障風險的話,可以讓顯卡以高頻率更快地進行。超頻的好處是可以更快地計算,但是也會引發一些運算錯誤
一個高端的GPU超頻之後可以達到200MH/s,也就是每秒2億次哈希運算。這是CPU不可能達到的量級。但是以現在的難度,就算把100塊顯卡放在一起,也需要幾千年的時間才能挖出來。
GPU挖礦也有缺點。GPU有大量的內置硬體來進行圖像處理,這對比特幣挖礦毫無用處,而且GPU沒有很好地冷卻處理設置,並且非常耗電。
FPGA挖礦
2011年,一種現場可編程門陣列,也就是FPGA第一次用於比特幣挖礦,一些礦工開始使用FPGA代替GPU。
FPGA的原理是追求定製硬體的最佳性能的同時,用戶可以現場調試或者修改硬體參數。相比之下,常用的硬體都是在出廠之前就設計好的,以後無法完成定製而只能永遠做同樣的工作。
FPGA比GPU性能好,很容易冷卻。FPGA可以將運輸速度上升到1GH/s,不過即使這個速度,想挖出一個區塊,也是猴年馬月的事情了。
雖然FPGA性能好,但使用的時間很短,主要是因為,幾乎需要一直超頻使用,這就導致各種報錯和故障,雖然可以現場調試,但是優化很困難,而且一般人也不會進行相應的搭建和編程。而且性能功耗方面,相對於GPU並沒有一個很大的提升。
ASIC礦機
一種專門針對比特幣挖礦的IC晶元,設計, 製造,優化完全是為了比特幣挖礦這一個唯一目的。目前有幾個供應商出售這些晶元,我們可以在市場上買到不同種類的ASIC礦機。
設計ASIC晶元需要非常專業的知識,它們所需的研發周期也比較長,不過ASIC晶元的設計也出乎意料的迅速,還打破了晶元行業的業界記錄。
不過ASIC的更新速度很快,絕大部分早起的ASIC晶元在6個月後就被淘汰。大部分的利潤都是在早起實現的,礦工往往在ASIC晶元的前6個月就已經實現了利潤的一半。這就要求晶元的出貨速度要非常快,不過還說經常出現晶元送到客戶手裡的時候差不多就已經淘汰了。
礦池
比特幣挖礦已經從個人領域轉移到了大型專業挖礦中心。一個挖礦中心的三個重要因素往往是氣候,電費,網速。冷卻是比特幣挖礦最大的挑戰,選擇一個氣候便寒的地方,可以節省大量的冷卻費用,而且電費要便宜,網速也要快。
每個礦池都有一個幣基接收人,和一種分紅規則。分紅規則一般是按照每個礦工的工作量分紅,或者按照礦池實際找到的有效區塊分紅。而且分紅的內容有些礦池包含coinbaise和手續費,有些只包含coinbase。
比特幣挖礦經歷了一個逐步演化的過程:從CPU到GPU,到FPGA,到ASIC。就像歷史上的挖金礦類似,從個人拿著盤子在沙裡淘金,到一小群人用流沙槽來淘金,再到一群人用水沖刷金山來淘金,直到現在機械化挖礦,這裡面的相似點是,很大一部分的利潤都被設備製造商拿走了。
比特幣礦工變得越來越中心化和專業化,整個系統的算力也越來越大,從長期來看,比特幣的獎勵也從固定的挖礦獎勵轉變為交易費為主。這樣的變化,真的不知道將來會如何演化。
推薦閱讀:
TAG:比特幣Bitcoin | btc挖礦 |