07-BTC-挖礦

聲明:本文是要點筆記,介紹和系列筆記均收錄在專題:區塊鏈技術與應用

全節點簡介

  • 一直在線,
  • 在本地硬盤上維護完整的區塊鏈信息,
  • 在內存裏維護 UTXO 集合,以便快速檢驗交易的正確性,
  • 監聽比特幣網絡上的交易信息,驗證每個交易的合法性,
  • 決定哪些交易會被打包到區塊裏,
  • 監聽別的礦工挖出來的區塊,驗證其合法性,
  • 挖礦
    • 決定沿着那條鏈挖下去?
    • 當出現等長的分叉的時候,選擇哪一個分叉?

輕節點簡介

  • 不是一直在線,
  • 不用保存整個區塊鏈,只要保存每個區塊的塊頭,
  • 不用保存全部交易,只保存與自己相關的交易,
  • 無法檢驗大多數交易的合法性,只能檢驗與自己相關的那些交易的合法性,
  • 無法檢測網上發佈的區塊的正確性,
  • 可以驗證挖礦的難度,
  • 只能檢測哪個是最長鏈,不知道哪個是最長合法鏈。

比特幣網絡中大部分節點都是輕節點,如果只是轉賬而不是挖礦的話,沒必要用全節點。挖礦過程中,如果你聽到別人發佈了一個區塊,該區塊是合法的,也是在延長最長合法鏈。這時候你該怎麼辦?

應該停止挖礦,然後重新在本地組裝一個候選區塊,再重新從頭開始挖礦。因爲如果沿着新發布的交易往下挖的話,那麼本地組裝的區塊中包含的交易就會發生變化,有些交易可能已經被包含到新發布的區塊裏了。另外 block header 的內容也會發生變化,像 block header 裏有交易所組成的 merkle tree 的根哈希值,還有指向前一個區塊的指針,這些也都會發生變化。

這樣做是不是有些可惜?挖礦的一個性質是無記憶性,無論是繼續挖原來的區塊,還是停下來挖一個新組裝出來的區塊,成功的概率是一樣的。只要還沒有挖到符合要求的 nonce 值,前面已經挖了多長時間都是無所謂的。

即使挖到了合法的區塊,發佈到區塊鏈上,也不能保證勝利了。有可能你發佈的區塊最終沒有成爲最長合法鏈,可能存在一些衝突情況,別人可能同時發佈一些合法的區塊,或者存在一些你不知道的雙花(double spending),使得你的區塊中的某些交易變成衝突的。

比特幣是怎麼保證安全的?兩個方面:1. 密碼學;2. 共識機制。

別人沒有你的私鑰,就沒有辦法僞造你的簽名,所以不能把你賬上的錢轉走。(前提是系統中擁有大多數算力的礦工是好的,是遵守協議的,不會接受那些沒有合法簽名的交易。如果沒有這些,密碼學上的保證也就沒有用武之地。)

比如:你去銀行取錢,按照規定取錢得出示合法的證件,銀行工作人員才能把錢給你。合法的證件就相當於密碼學上的簽名,密碼學的性質保證了別人沒有辦法僞造你的簽名,也就沒有辦法僞造你的身份。產生私鑰以及簽名的時候,都要有好的隨機源,產生的隨機數要足夠隨機。但有這些也不是足夠的,銀行工作人員要足夠自覺,不能把錢交給那些沒有合法證件的人,只有這兩條合在一起,才能保證別人不能把你賬上的錢轉走。

挖礦的設備:挖礦設備演化趨勢是越來越趨於專業化,最早的時候用的是普通的 CPU 挖礦,像家裏計算機、筆記本電腦。但如果買一臺計算機專門用來挖礦是非常不划算的,計算機當中的大部分內存都是閒置的,挖礦只用到其中很小一部分內存,CPU 當中的大部分部件也是閒置的,因爲挖礦當中計算哈希值的操作只用到了通用 CPU 當中的很少一部分指令。硬盤和其他很多資源也都是閒置的,所以隨着比特幣挖礦難度的提高,用 CPU 挖礦,用通用計算機挖礦顯得性價比太低。

所以挖礦轉入第二代設備:GPU。GPU 效率相比 CPU 提高了很多,主要用於大規模的並行計算。但 GPU 用來挖礦還是有點浪費了,GPU 是用於通用並行計算而設計的,用來挖礦的話有很多部件仍然是出於閒置狀態,比如說用於浮點數計算的部件。這些部件對於深度學習來說是很重要的,但比特幣的操作只用到了整數挖礦。所以 GPU 雖然效率提高了很多,但仍然有不小的浪費。這些年 GPU 價格漲得很快,有些人歸因於深度學習的火熱,其實有很多 GPU 是用來挖礦的。不過有一個好消息,隨着比特幣挖礦難度的提升,用 GPU 挖礦已經划不來了,已經超過了 GPU 的算力範圍,所以 GPU 現在可以更多的用於深度學習、遊戲應用的服務。

有一些新開發的加密貨幣,有的還在用 GPU 挖礦,而現在更多用 ASIC 芯片挖礦,這是專門爲了挖礦而設計的芯片。上面沒有多餘的電路邏輯,整個芯片就是爲了比特幣挖礦、計算哈希值的操作而設計的。它的性價比是最高的,這個芯片除了挖礦,什麼事都幹不了,而且爲某一種加密貨幣設計的 ASIC 芯片,只能挖這一種加密貨幣。除非這兩個加密貨幣用同一個 mining puzzle。

有些加密貨幣剛發行的時候,爲了解決冷啓動問題,會故意用一個已有的加密貨幣的 mining puzzle,比如說跟比特幣一樣的 mining puzzle,這樣可以吸引更多的人來挖礦,這種情況叫 merge mining。除了這種情況,其他都是一個芯片只能爲一個加密貨幣挖礦。ASIC 芯片生產週期差不多需要一年,但跟其他通用芯片相比,ASIC 芯片研發速度已經是非常快的了。

在這麼長的生產週期裏面,如果比特幣價格出現劇烈變化的話,前期投入的研發費用可能就打水漂了。從歷史上看,比特幣的價格變化是比較劇烈的。曾經發生好幾次,比特幣的價格在幾個月之內,下跌了 80%,然後又慢慢恢復。

如果比特幣價格大幅度下降的話,挖礦可能是賠本的,可能還抵不上電費。即使在比特幣發展的黃金時期,價格不斷上漲,這時挖礦是有利可圖的。但是競爭也是越來越激烈的,定製的 ASIC 芯片可能用不了幾個月就過時了。一款 ASIC 礦機剛上市的時候大部分的利潤是在它上市的前兩個月獲得的,因爲這個時候,它的算力在同類產品中是最強的。再往後隨着更強的礦機出現,它就可能被淘汰掉。所以購買 ASIC 礦機的時機很重要,現在都是要提前預定的。有些不良廠商,ASIC 礦機生產出來之後,不是立即提供給消費者,而是自己先用來挖礦一段時間,賺取比特幣。等到最賺錢的黃金時間,如兩個月過去之後,再把礦機發給用戶。當比特幣系統中算力突然有一個很大的提升,就說明某個大公司生產出了新一款的 ASIC 礦機。所以在挖礦熱潮中真正賺錢的不一定是挖礦的用戶,而可能是賣礦機的大廠商。

挖礦機的變化趨勢,是從通用變得越來越專用,CPU 是通用計算,GPU 是通用並行計算,ASIC 是專用計算。ASIC 一旦過時就作廢了,不像 CPU 和 GPU 還能做其他工作。很多人覺得這是不好的,是跟去中心化的理念是不相符的,也違背了比特幣設計的初衷。最民主的情況是,大家都用家裏的 CPU 計算機挖礦。後來改爲 GPU 噪音是很大的。而有些新的加密貨幣設計的是 Alternative mining puzzle。而設計它的出發點是 asic resistance(抗 asic 芯片化),目的是讓通用的計算機也能參與挖礦的過程。

挖礦的另一個趨勢是大型礦池的出現,單個礦工,即使用了 ASIC 芯片,挖礦從平均收益上看是有利可圖的,但是收入是非常不穩定的。比特幣系統中平均每 10 分鐘出一個區塊,這是說比特幣系統中,所有的礦工做一個整體來看,平均 10min 會產生一個區塊。但如果具體到某一個礦工來說,他可能要挖很長時間,如他用一個礦機可能要挖一兩年。這樣子就好像是買彩票,挖到了就是中了一個大獎。單礦工還有其他問題,他除了挖礦之外還要承擔全節點的其他責任(就是本文最開始對全節點介紹的那些)。

所以要引入礦池,所謂的礦池,就是把這些礦工組織起來,作爲一個整體。礦池的架構一般是一個全節點,會驅動很多礦機。一個礦池有一個礦主,叫 pool manager。下面連了很多礦工,這些礦工只負責計算哈希值,全節點的其他職責都由礦主來承擔。他負責監聽網上的交易,把這些交易組織打包成區塊,同時要看一看有沒有其他的節點搶先發布區塊,如果有的話看怎樣進行調整.....

ASIC 芯片只能負責計算哈希值,它不能幹全節點的其他功能。礦池的出現還爲了解決另一個問題:礦工的收入不穩定。單個礦工的收入是不穩定的,所以大家一起幹,有了收益再進行分配。

那麼收益該如何分配?礦池一般有兩種組織形式,一種是像大型數據中心那樣,有的互聯網公司,有成千上萬個服務器,大的礦池裏面也有成千上萬的礦機,這些礦機如果是屬於同一個機構的話,那麼收入怎麼分配就不重要了。

但也有礦機是來自不同機構的,即第二種組織方式:分佈式的。礦工和礦主不在同一個地方,可能分散在世界各地,那麼礦工要加入一個礦池,就是按照礦池規定的通訊協議跟礦主進行聯繫。礦主把計算哈希值的任務分配給他,礦工計算完之後,把結果反饋給礦主,將來獲得出塊獎勵時再一起分配。

如果礦工是來自五湖四海的,不是屬於同一個機構的,那麼利益該怎麼分配?平均分配行不行?比如每個礦工挖到一個區塊,得到了出塊獎勵,然後平分給其他礦工,這樣行嗎?不行,因爲會有礦工偷懶。因此要按礦工的貢獻大小進行分配,也就是這裏同樣需要工作量證明。那該怎麼證明每個礦工做了多少工作呢?

爲什麼礦工的收入不穩定,因爲挖礦太難了,如果把挖礦的難度降低之後,挖礦就會變得穩定了。怎麼降低難度呢?以前的要求是,礦工要找到一個 nonce,用 nonce 計算 block header 的哈希值,前面至少有 70 個 0 纔是合法的區塊。降低挖礦難度之後,比如說前面只要有 60 個 0 就行了,這樣挖礦,叫作 share,這個 share 又叫做 almost valid block。礦工挖到 share 或 almost valid block 之後,把它提交給礦主。礦主拿到這個區塊有什麼用呢?用來證明礦工所做的工作量,而沒有其他用途。礦主無法得到區塊獎勵以及任何好處。所以礦主就統計每個礦工提交了多少這樣的 share,將來等到某個礦工真正挖到了合法的區塊之後,再將出塊
獎勵按照每個礦工所做的工作量,提交的 share 數目進行分配。

這樣做爲什麼是可行的?每個礦工挖到礦的概率取決於他嘗試的 nonce 數目,嘗試的 nonce越多,能找到的 share 就越多。

有沒有可能一個礦工挖到一個合法的區塊之後,不把它提交給礦主,而是自己偷偷摸摸發佈出去,得到出塊獎勵?即使將挖到的 share 提交,但挖到了合法區塊就不提交?不可能,因爲每個礦工的任務是由礦主分配的,礦主負責組裝好一個區塊,然後交給礦工去嘗試各種 nonce,而且挖礦僅僅調 nonce 是不夠的,還需要調整 coinbase parameter。所以礦主會把不同的 coinbase parameter 所對應的 nonce 值的範圍交給不同的礦工去嘗試。那麼這個區塊裏包含什麼?coinbase transaction 裏面有收款人的地址,這個地址填的是礦主的地址,即 pool manager 的地址,所以礦工挖到區塊之後,如果他不提交給礦主,自己發不出去是沒有用的。
裏面的收款地址是礦主的,他取不出錢來。所以只要是當初按礦主給分配的任務進行挖礦的,就不可能偷區塊獎勵。

如果他一開始就不管礦主的任務,自己組裝一個區塊,偷偷把收款地址改成自己地址,會怎樣?那樣他提交 share 給礦主的話,礦主是不認的,因爲裏面交易列表被改過了,coinbase transaction 裏面的內容發生了變化,算出的 merkle tree 的根哈希值也是不一樣的。這種情況下,礦主是不會給他工作量證明的。那就相當於礦工一開始就單幹,跟礦池是沒關係的。

雖然不可能偷區塊獎勵,但會不會有人搗亂,比如平時挖到一個 share,提交給礦主,作爲工作量證明。等他挖到一個真正合法的區塊之後,把它扔掉。這是有可能的,雖然沒有經濟好處,但有可能是別的礦池派來的臥底,不想讓這個礦池得到區塊獎勵。這些礦工還是會有分紅,分的是別的礦工挖出來的區塊獎勵。

礦工轉換礦池是很容易的,加入一個礦池就是按照這個礦池的協議跟這個礦主聯繫,礦池把組裝好的區塊信息發給礦工,礦工來嘗試各種 nonce 值就可以了。

所以這就是礦池帶來的危害,如果沒有礦池,想要發動 51%的攻擊,攻擊者要投入大量的成本來購買到足夠的礦機,能夠達到系統中半數以上的算力。有了礦池之後,他可能只佔很小一部分比例的算力,只要能夠吸引到足夠多的礦工,足夠多的不明真相的羣衆加入到他的礦池裏來就行了。

一般來說,礦池的礦主要收取一定比例的出塊獎勵作爲管理費。礦主也要按照比例收取管理費,有的是按照出塊獎勵的比例,也有的是抽取交易費。有的一些有惡意的礦池在發動攻擊之前,可能故意把管理費降得特別低,甚至是賠本賺吆喝,吸引足夠多的礦工加入之後就可以發動攻擊了。這是大型礦池的一個弊端,使得 51%的攻擊更加容易了。

假如某個礦池佔到了半數以上的算力,他具體能夠發動哪些攻擊呢?一個最常見的就是分叉攻擊。假如一個區塊鏈,其中一個區塊包含了一個大筆的交易,又等了幾個確認區塊之後,自認爲已經安全了。然後這時就可能有人在該交易前面的區塊發動分叉攻擊。

看上去好像追趕的道路是很漫長的,但如果擁有 51%的算力,最終還是可以成功攻擊。另外,不要把 51%當成絕對的門檻,有可能不到 51%就可以。算力都是估計的,而且算力還在不斷變化。

攻擊者還能做什麼壞事?還可以做封鎖境域(boycott)。比如說,攻擊者不喜歡某個賬戶,懷疑某個賬戶參與非法交易,想把這個賬戶封鎖掉,所有跟這個賬戶相關的交易都不讓上鍊。假如 A 把某個交易 A→B 發佈到區塊鏈上,攻擊者就會馬上進行分叉,產生一個不包含這個交易的區塊,所有跟 A 有關的交易也都不包含進去。

這種攻擊跟分叉攻擊區別是什麼?他沒必要等後面幾個確認區塊。這時候,如果攻擊者等待確認區塊,是爲了讓 B 放心,B 以爲後面有六個確認區塊,已經沒事了。然後攻擊者再發動分叉攻擊。而如果目的是爲了 封鎖境域(boycott)的話,就沒有必要等後面區塊生成。A→B 交易一上鍊,馬上進行分叉,越早越好,因爲攻擊者是希望別人沿着他的鏈往下挖的。

前面講過,有些有惡意的節點故意不把某些交易寫入區塊裏,是可以的。但沒有關係,後面的區塊還是會包含的。但是如果這個壞人擁有 51%的算力的話,他可能仗着自己算力強,公開抵制他想抵制的交易。這樣別的礦工也不敢隨便把交易打包進去了。

那麼攻擊者有沒有可能掌握 51%的算力後,把別人賬上的錢轉走。這是不可能的。因爲他沒有別人賬戶的私鑰,沒有辦法僞造簽名。如果他仗着算力強,強行把一個沒有合法簽名的交易發佈到區塊鏈上,會有什麼樣的結果?會造成分叉。因爲誠實的礦工會沿着另外一個分叉去挖,不會沿着他發佈的區塊往下挖。所以盜幣是不可能的。

總結:礦池的出現減輕了礦工的負擔,礦工只需要挖礦,計算哈希值就行了,別的事情都由礦主來完成。礦工的收入分配也更加穩定。但礦池的出現也有危害,發動 51%的攻擊變得容易了。他不一定自己有這麼強的算力,只要動員召集這些算力就可以了。

這有點類似於雲計算中的 on demand computing。平時不需要維護很大的計算機羣,需要用的時候,可以隨時召回來。而礦池的情況,是 on demand mining。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章