1. 程式人生 > >1分鐘瞭解“挖礦”的本質

1分鐘瞭解“挖礦”的本質

上一篇《1分鐘瞭解區塊鏈的本質》,介紹了什麼是區塊鏈,區塊鏈是一個沒有管理員,每個節點都擁有全部資料,高可用的分散式儲存系統。

文章的留言裡,不少朋友會用比特幣來解釋區塊鏈,那區塊鏈與比特幣是什麼關係?

區塊鏈是分散式儲存,比特幣是基於該儲存的應用,其他諸如萊特幣,以太幣都是基於區塊鏈的電子貨幣應用。理論上,使用上層應用來解釋底層儲存是不合適的。

640?wx_fmt=png

如上圖,mysql是底層儲存,wechat是上層應用,用wechat來解釋mysql是不合適的。

今天,從技術的角度出發,聊聊什麼是區塊鏈裡的“挖礦”。

先說結論,區塊鏈挖礦的本質是啥?

生成一個區塊,鏈入區塊鏈的過程,就是挖礦。挖礦的人,就是礦工。

什麼是區塊(

block)?

:如《1分鐘瞭解區塊鏈的本質》裡所述,區塊是一塊儲存空間,可以儲存資料。

640?wx_fmt=png

如上圖,區塊分為區塊頭header區塊體body

區塊體(body)存了些什麼?

想存什麼存什麼,和上層應用有關,就像mysql裡存什麼依賴於上層應用。例如比特幣使用的區塊鏈,區塊體裡儲存的是比特幣交易記錄。

區塊頭(header)存了些什麼?

:區塊頭裡儲存了和這個區塊,以及區塊鏈相關的一些元資料

640?wx_fmt=png

如上圖,區塊頭裡的三個常見屬性:

  • 前一個區塊的雜湊值

  • 區塊生成的時間戳

  • 隨機數

什麼是區塊鏈(blockchain)?

區塊是怎麼鏈起來的?

struct node{

         node* prev; // 前一個節點

         int time; // 時間戳

         int nonce; // 隨機數

         void* node_body; // 儲存資料

}node;

640?wx_fmt=png

連結串列,節點指標可以作為這個節點的唯一標識,下一個節點通過儲存上一個節點的指標,將連結串列鏈起來。

640?wx_fmt=png

與之類似,區塊的雜湊可以作為區塊的唯一標識,下一個區塊通過儲存上一個區塊的雜湊,將區塊鏈起來,這就是區塊鏈。

講完區塊與區塊鏈的概念,接下來講挖礦,也就是區塊的生成

在此之前,先說說區塊鏈的三個特性

  • 歷史生成的區塊是無法改變的,即“區塊鏈只能像寫日誌一樣追加寫,不能像mysql一樣隨機寫”

  • 只能在最新的區塊後面生成新區塊,即“必須先完成同步全網最新的區塊鏈資料這項工作,才能啟動新區塊生成這項工作”

  • 新區塊的生成很難,必須滿足一定條件的新區塊才有效

假如已經同步了最新的區塊鏈資料,要滿足什麼條件,才算生成一個新的區塊,才算“挖礦”成功呢?

對最新的區塊頭進行兩次SHA256計算,得到的256bit雜湊結果,高位48bit必須是0x00000000FFFF,才算挖礦成功

畫外音:這句話很重要,是這篇文章的核心。

為什麼大家都說“挖礦”很難?

由符合條件的雜湊值,倒推出區塊頭,填入相應的“前一塊區塊雜湊值”“時間”“隨機數”不就可以了嗎?

:額,這,,,雜湊(SHA256是一個雜湊演算法)是不可逆的。例如MD5

md5(string) = md5_result

大家都知道:

  • 由字串,算出對應的md5值很容易,但md5值反推出字串是不可能的

  • 可以認為雜湊的結果是完全隨機的,要得出前48bit必須是0x00000000FFFF的雜湊結果,就如同連續拋48次硬幣,每次都得到我們想要的結果,其概率為(1/2)^48

可以看到,這就好比在一座山上隨手撿起一塊石頭,正好是一塊金子,我猜測,這也正是把生成新區塊叫做“挖礦”的原因。

那應該怎麼找到符合條件的區塊頭呢,從而成功挖到礦呢?

窮舉法

區塊頭裡有個隨機屬性nonce,將這個屬性0開始,遍歷到2^32,來計算區塊頭的雜湊值,如果得到的雜湊結果符合條件,則挖礦成功。

其虛擬碼如下:

byte[32] = PrevBlockHash; // 上一個區塊的雜湊

for(int i=0 to 2^32){ // 遍歷所有整數

  int time=now(); // 時間戳

  blockHeader= new(byte[32], time, i); // 生成區塊頭

  hashResult= SHA256D(blockHeader); // 計算雜湊值

  if(hashResult>>208 == 0x00000000FFFF){ //雜湊符合預期

    echo“bingo”; // 挖到礦啦

}

}

看上面的演算法,只要程式執行時間足夠久,總能挖到礦呀?

:錯,如果別人計算能力強,在你挖到礦之前,如果別人先生成了新區塊,廣播到了區塊鏈網路,你本地不是最新的區塊鏈,你挖到的礦就作廢啦,此時你要放棄之前所有的工作,先向網路同步最新的資料,再重新開始挖。

有什麼方法可以提升挖礦的速度呢?

:從架構的角度出發

  • “快取”是無效:每個區塊的雜湊值都不一樣,每個時間戳都不一樣,歷史計算過的值無法通過“查表”來節省時間

  • scale up有效:增強單CPU的計算能力,使用GPU代替CPU,使用特殊的晶片計算SHA256D等優化都是有效的,但scale up總是有極限的,單機總會遇到瓶頸

  • scale out有效:單機不行,來並行,一臺機器不行,搞叢集,這就是為什麼會有這麼多的礦場

640?wx_fmt=jpeg

如上圖,這是西藏高原上的一個比特幣礦場,廉價的電力讓無數礦工趨之若鶩。

綜上,區塊鏈裡,什麼是挖礦?

在最新區塊鏈的資料上,生成一個符合條件的區塊,鏈入區塊鏈的過程,就是挖礦

關於區塊鏈與挖礦,大家或許還有不少疑問:

  • 如何保證資料的一致性

  • TM有病吧,挖這玩意有什麼意義,不是純浪費電嗎

  • 這和比特幣有什麼關係

  • 比特幣怎麼保證總量有限

這些疑惑,下一個一分鐘,再和大家解釋。

希望這很短的一分鐘,大家瞭解了挖礦的本質。

前序文章: