說點閑話
算了下,我大概有10天沒有在幣乎更文了,那這些天,我干什么去了?我覺得有必要跟大家聊聊。暫時離開幣乎,不是因為我偷懶,不想寫文章了,而是我想冷靜下來,把自己學習區塊鏈這2,3個月以來腦子里混亂的東西給理清楚。我想知道自己為什么要寫文章?我學習區塊鏈的目的是什么?我能夠堅持多久?事實上,我不是一個喜歡隨大流的人,所以我不會見到別人日更就去日更,我更不想為了寫作而寫作。好了,現在這幾個問題,我都找到了我自己的答案,所以我回來繼續寫作了。關于那幾個問題的答案,就暫時不細說了,我想說說我這些天干了什么。我去深入了解了幾個我看好的項目,包括eos,gxs,qtum,btm;我還去體驗了幾個平臺,包括,candy.one、pressone、iVeryOne、ONT。我還去把曾經學習過的區塊鏈的書翻過來重新看看,去學習了GO語言的編程(很多區塊鏈項目開發會使用)。
你所知道的工作量證明機制
說的稍微有點多了,現在正式進入到今天的話題比特幣挖礦--工作量證明機制的底層原理到底是什么樣的?說到挖礦和POW工作量證明機制,我相信有不少朋友都會知道一些,比如,比特幣每10分鐘會產生一個區塊;礦工是根據解答一道系統給出的難題來獲得記賬的權利的,算力越高,獲得記賬權利的機會就越大。而我今天主要是想跟大家詳細分析一下礦工們是如何競爭記賬的,也就是說如何競爭解決這道難題的,以及這個經常被我們提及的區塊(block)到底是什么樣的?
我們都知道比特幣的區塊的產生是通過POW(Proof Of Work)工作量證明機制來完成的,整個網絡平均10分鐘就會產生一個區塊,而且伴隨著區塊的產生,系統會獎勵一定數量的比特幣給在這個區塊上記賬的礦工。說道這里,請大家思考2個問題。
問題一:系統獎勵的比特幣的數量是多少?是恒定不變的嗎?
比特幣的創世區塊是在2008年,由中本聰挖出的,按照比特幣白皮書的規定,每挖出一個區塊,系統就會獎勵50個比特幣,每四年,獎勵減半,到現在的話,獎勵是12.5個比特幣。注意:這里的每四年是一個大概值,實際上是說每挖出21萬個區塊獎勵就減半,大家可以自己算算,挖出21w個區塊的時間是3.99年,所以大致是每4年減半。問題二:系統如何來判斷誰擁有這個區塊的記賬權呢?
為了解決這個問題,比特幣系統引入了POW共識機制,也就是工作量證明機制,這也是比特幣系統的靈魂所在。這個算法很簡單,就是系統出一道數學題,誰能夠最先解答出來,誰就會產生一個區塊,并在上面記賬。其實這種機制,我們生活中處處可見,比如我們的各種考試,考證。它的原理是:既然監督你們工作的過程是非常低效的,那好,我不管你是去如何工作的,我根據考試的結果來判斷你是否做了很多的工作。
工作量證明的基本原理
你做了一定難度工作產生了一個結果,系統根據結果來驗證你是否做了相應的工作。大致流程如下:
圖片來源:《區塊鏈:定義未來金融與經濟格局》
舉個例子
給定的一個基本的字符串"Hello, world!",我們給出的工作量要求是,可以在這個字符串后面添加一個叫做nonce的整數值,對變更后(添加nonce)的字符串進行SHA256哈希運算,如果得到的哈希結果(以16進制的形式表示)是以"0000"開頭的,則驗證通過。為了達到這個工作量證明的目標。我們需要不停的遞增nonce值,對得到的新字符串進行SHA256哈希運算。nonce的初始值為0
"Hello, world!0" => 1312af178c253f84028d480a6adc1e25e81caa44c749ec81976192e2ec934c64
...............
"Hello, world!4249" => c004190b822f1669cac8dc37e761cb73652e7832fb814565702245cf26ebb9e6
"Hello, world!4250" => 0000c3af42fc31103f1fdc0151fa747ff87349a4714df7cc52ea464e12dcd4e9
結果是需要4251次運算才能解答正確,當然這里只是一個簡單的例子,實際上比特幣系統的機制與這個小例子類似,但是比它更復雜,也就意味著需要更大的算力才能成功解題。
實際的比特幣系統中又是如何出題和解題的呢?
比特幣采用的是SHA-256算法,這是哈希運算的一種。礦工要計算的工作量就是通過解決下面這個哈希函數的未知參數,大概數學公式是這樣的。
Hash(上一個區塊的Hash值,交易記錄集,隨機數X) = 0000a2a5FD6g
由于比特幣網絡中節點去生成一個區塊是,總是基于目前存在的最新的區塊,所以每個礦工在計算之前已經能夠獲取到上一個區塊的所有信息,所以,Hash()函數的前2個參數都是確定的,最后的值也是確定的,礦工要做的就是去做大量的嘗試計算,找到一個隨機數X,使得Hash的結果以若干個0開頭,當然在每道題中0的個數不確定。哪個節點最先算出,就會產生一個新的區塊,并記賬。
下面是我從https://blockchain.info找的一個區塊#516559,你可以看看Hash值,一共18個0,再看看這個Nonce隨機數,可以看出這次解題是經過了數億次運算才成功。
到這里,我們已經知道礦工們為了獲取系統給出的比特幣,就會去耗費自己的算力和電力來解決難題。這道難題的3個關鍵點是:工作量證明函數、區塊、難度值。
工作量證明函數
工作量證明函數是指這道題的計算方法,在比特幣的網絡中是SHA-256。SHA是一種安全散列算法,主要用于數字簽名。SHA-256是這個函數家族中的一員,它的特點是通過哈希算法運算之后,輸出值為256位。到目前為止,還沒有出現對SHA-256算法的有效攻擊。
區塊
區塊的作用是記載比特幣網絡中合法的交易。區塊包含的交易列表則附加在區塊頭后面,其中的第一筆交易是coinbase交易,這是一筆為了讓礦工獲得獎勵及手續費的特殊交易。下面這張圖是我自己畫的一個關于區塊的簡圖,比特幣挖礦都是基于已存在的最新區塊去生成下一個區塊。區塊主要由區塊頭和交易列表組成。
區塊頭的詳細數據結構如下:
字段 | 描述 | 大小(byte) |
---|---|---|
Version | 版本號 | 4 |
PrevBlockHash | 上一個區塊的哈希值 | 32 |
MerkleRootHash | 該區塊中的所有交易通過Merkle Tree生成的Hash | 32 |
Time | UNIX時間戳,也就是區塊產生的時間 | 4 |
Bits | 難度值,完成比特幣工作量證明目標的難度系數 | 4 |
Nonce | 隨機數,為了找到滿足難度目標所設定的隨機數 | 4 |
區塊包含的交易列表則附加在區塊頭后面,其中的第一筆交易是coinbase交易,這是一筆為了讓礦工獲得獎勵及手續費的特殊交易。
所以一個完整的區塊數據結構如下:
圖片來源:《區塊鏈:定義未來金融與經濟格局》
難度值
難度值是礦工挖礦的難度指標,它表示礦工大概需要多少次哈希運算才能產生一個合法區塊。我們已經知道比特幣的區塊大約每10分鐘生成一個,而全網的算力是在不斷變化的,比特幣系統要讓產生新區塊的時間基本維持在10分鐘,就得不斷去調整挖礦的難度值。通過去不斷的調整難度值,才使得新區塊的產生平均保持在10分鐘。
難度值的調整是在每個完整的節點中獨立發生的,而且是每隔2016個區塊(大概2周的時間)才會進行一次自動調整。具體來說就是實際挖礦的時常和期望時常(每個區塊10分鐘)相比較,如果產生區塊的時常大于10分鐘,就降低難度值,反之,則增加難度值。
這個公式可以總結為如下形式:
新難度值 = 舊難度值 * ( 過去2016個區塊花費時長 / 20160 分鐘 )
工作量證明還需要有一個目標值,計算公式如下:
目標值 = 最大目標值/難度值
最大目標值是固定的:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
目標值是指當前區塊生成所達成目標值的hash值,用來表示礦工的工作量證明,只有當礦工計算出來的hash值小于目標值,才表示挖掘區塊成功。
通過以上內容,我們可以大致總結下比特幣挖礦(工作量證明)的過程。通過不停的變換區塊中的nonce隨機數的值,并將它作為SHA-256哈希運算的輸入,直到找到一個值,可以讓運算之后的哈希值有指定個數的0為前導。0的個數越多,挖礦難度越大。
以下總結來自《區塊鏈:定義未來金融與經濟格局》
比特幣挖礦,也就是解決這道工作量證明難題的步驟大致歸納如下:
1、生成Coinbase交易,并與其他所有準備打包進區塊的交易組成交易列表,通過Merkle Tree算法生成Merkle Root Hash
2、把Merkle Root Hash及其他相關字段組裝成區塊頭,將區塊頭的80字節數據(Block Header)作為工作量證明的輸入
3、不停的變更區塊頭中的隨機數即nonce的數值,并對每次變更后的的區塊頭做雙重SHA256運算(即SHA256(SHA256(Block_Header))),將結果值與當前網絡的目標值做對比,如果小于目標值,則解題成功,工作量證明完成。
該過程可以用下圖表示:
通過以上介紹,我們已經知道,礦工是如何去解題以及怎樣才算是解題成功了。現在我們一起來思考一個問題。
Question
按照上面提到的Hash算法,只要礦工計算出來的區塊的哈希值小于目標值,就算是完成了工作量證明,那么也就有可能差不多在同一時間,有2個以上的礦工都完成了工作量證明,并且把消息廣播出去。那也就意味著同一高度可能存在多個區塊,也就是說主鏈即出現分叉(Fork),但是呢,肯定只能有一個區塊來記賬,那此時比特幣系統又該如何判決呢?
如果遇到分叉時,網絡會根據下列原則選舉出Best Chain:
- 1、不同高度的分支,總是接受最高(即最長)的那條分支
- 2、相同高度的,接受難度最大的
- 3、高度相同且難度一致的,接受時間最早的
- 4、若所有均相同,則按照從網絡接受的順序
等待Block Chain高度增一,則重新選擇Best Chain
產生分叉時,區塊鏈大概是這樣的。
從這幅圖我們可以看出2點,第一:在同一高度可能會產生分叉(fork),第二:有一條最長的鏈(黑色的那條就是)。
這里就要稍微簡單介紹一下比特幣系統的最長鏈機制了。我們知道,每個新區塊的產生是要基于一個以前的區塊,而絕大多數礦工會選擇最長鏈的最后一個區塊來計算下一個區塊,因為只有最長鏈上的區塊才能獲得比特幣系統的認可,并得到挖礦的獎勵。而其他的分支則是無效分枝,不能得到任何獎勵,只能白白的浪費自己的算力和電力。這是保證區塊鏈不發生分裂的重要機制。
所以現在會有很多礦工會選擇抱團組成礦池,這樣才能保持長期成為最長分支。
最后一步,驗證機制
在節點(礦工)完成工作量證明(也就是找到滿足指定哈希值的隨機數nonce)之后,會馬上對全網進行廣播,網絡的節點收到廣播打包區塊,會立刻對其進行驗證。如果驗證通過,其他節點(礦工)將不再競爭打包這個區塊,而是選擇接受這個區塊,并將打包后的數據記錄在自己的賬本中,然后繼續進行下一個區塊的競爭答題中。
感謝以下作者
https://www.cnblogs.com/tinyxiong/p/7791538.html
http://8btc.com/article-160-1.html
http://www.infoq.com/cn/articles/bitcoin-and-block-chain-part02