區塊鏈100講:單挑or羣毆,兩種挖礦方式你要怎麼選?

image

在講什麼是算力時咱們說到:挖礦是做算法運算的過程,從計算機和代碼的角度來講,是反覆執行Hash函數並檢測執行結果的具體過程。挖礦的原理和流程請回顧:區塊鏈100講:知乎千贊回答講清挖礦過程node

而在區塊鏈100講:不作碼農作礦工,該怎麼和爹媽解釋一文中,你們已經很是清楚挖礦是由最開始的CPU挖礦,過分到GPU挖礦,最終演化到當前的ASIC(專業礦機)挖礦時代,本講繼續聊「挖礦」。挖礦的演進是硬件的演進過程,同時也是軟件的演進過程,尤爲是軟硬件對接協議的改進過程,本文重點經過與挖礦有關的幾個核心協議解析其中的邏輯設計和技術實現。算法

1

Setgenerate協議

Setgenerate協議接口表明了CPU挖礦時代。後端

中本聰在論文裏描述了「1 CPU 1 Vote」的理想數字民主理念,在最第一版本客戶端就附帶了挖礦功能,客戶端挖礦很是簡單,固然,須要同步數據結束才能夠挖礦。如今有不少算力很低的山寨幣仍是直接使用客戶端挖礦,有兩種方式能夠啓動挖礦:安全

  • 在配置文件設置gen=1,而後啓動客戶端,節點將自行啓動挖礦。網絡

  • 客戶端啓動後,利用RPC接口setgenerate控制挖礦。數據結構

若是使用經典QT客戶端,點擊「幫助」菜單,打開「調試窗口」,在「控制檯」輸入以下命令:setgenerate true 2,而後回車,客戶端就開始挖礦,後面的數字表明挖礦線程數,若是想關閉挖礦,在控制檯使用以下命令:setgenerate false,可使用getmininginfo命令查看挖礦狀況。函數

節點挖礦過程也很是簡單:性能

構造區塊,初始化區塊頭各個字段,計算Hash並驗證區塊,不合格則nNonce自增,再計算並驗證,如此往復。在CPU挖礦時代,nNonce提供的4字節搜索空間徹底夠用(4字節即4G種可能,單核CPU運算SHA256D算力通常是2M左右),其實nNonce只遍歷完兩個字節就返回去重構塊。區塊鏈

2

getwork協議

getwork協議表明了GPU挖礦時代,需求主要源於挖礦程序與節點客戶端分離,區塊鏈數據與挖礦部件分離。優化

使用客戶端節點直接挖礦,須要同步完整區塊鏈,數據和程序緊密結合,也就是說,若是有多臺電腦進行挖礦,須要每臺電腦都單獨同步一份區塊鏈數據。這其實沒有必要,對於礦工來講,最少只須要一個完整節點就能夠。而以此同時,GPU挖礦時代的到來,也須要一個協議與客戶端節點交互。

image

getwork核心設計思路是:

由節點客戶端構造區塊,而後將區塊頭數據交給外部挖礦程序,挖礦程序遍歷nNonce進行挖礦,驗證合格後交付回給節點客戶端,節點客戶端驗證合格後廣播到全網。

如前所述,區塊頭共80個字節,因爲沒有區塊鏈數據和待確認交易池,nVersion,hashPrevBlock,nBits和hashMerkleRoot這4個字段共72個字節必須由節點客戶端提供。挖礦程序主要是遞增遍歷nNonce,必要時候能夠微調nTime字段。

對於顯卡GPU來講,其實不用擔憂nNonce的4字節搜索空間不足,並且挖礦程序從節點客戶端那裏拿到一份數據後,不該該埋頭工做過久,否則頗有可能這個塊已經被其餘人挖到,繼續挖只能作無用功,對於比特幣來講,雖然設計爲每10分鐘一個區塊,良好的策略也應該在秒級內從新向節點申請新的挖礦數據。對於顯卡來講,運行SHA256D算力通常介於200M~1G,nNonce提供4G搜索空間,也就是說再好的顯卡也能支撐4秒左右,調整一次nTime,又能夠再挖4秒,這個時間綽綽有餘。

節點提供RPC接口getwork,該接口有一個可選參數,若是不帶參數,就是申請挖礦數據,若是帶一個參數,就是提交挖到的塊數據。

不帶參數調用getwork,返回數據以下:

image

Data字段

共128字節(80區塊頭字節 + 48補全字節),由於SHA256將輸入數據切分紅固定長度的分片處理,每一個切片64字節,輸入總長度必須是64字節的整數倍,輸入長度通常不符合要求,則根據必定規則在元數據末端補全數據。其實對於挖礦來講,補全數據是固定不變的,這裏不必提供,外部挖礦軟件能夠自行補齊。甚至連nNonce字段都不須要提供,data最少只須要提供前面的76字節就夠了。nTime字段也是必不可少的,外部挖礦程序須要參照節點提供的區塊時間來調節nTime。

Target字段

即當前區塊難度目標值,採用小頭字節序,須要翻轉才能使用。

其實對於外部挖礦程序來講,有data 和 target這兩個字段就能夠正常挖礦了,不過getwork協議充分考慮各類狀況,儘可能幫助外部挖礦程序作力所能及的事,提供了兩個額外字段,data字段返回完整補全數據也是出於此理念。

Midstate字段

如上所述,SHA256對輸入數據分片處理,礦工拿到data數據後,第一個分片(頭64字節)是固定不變的,midstate就是第一個分片的計算結果,節點幫忙計算出來了。

所以,在midstate字段輔助下,外部挖礦程序甚至只須要44字節數據就能夠正常挖礦:32字節midstate + 第一個切片餘下的12(76-64)字節數據。

Hash1字段

比特幣挖礦每次都須要連續執行兩次SHA256,第一次執行結果32字節,須要再補充32字節數據湊足64字節做爲第二次執行SHA256的輸入。hash1就是補全數據,同理,hash1也是固定不變的。

外部挖礦程序挖到合格區塊後再次調用getwork接口將修改過的data字段提交給節點客戶端。節點客戶端要求返回的數據也必須是128字節。

每次有外部無參調用一次getwork時,節點客戶端構造一個新區塊,在返回數據前,都要把新區塊完整保存在內存,並用hashMerkleRoot做爲惟一標識符,節點使用一個Map來存放全部構造的區塊,當下一個塊已經被其餘人挖到時,當即清空Map。

getwork收到一個參數後,首先從參數提取hashMerkleRoot,在Map中找出以前保存的區塊,接着從參數中提取nNonce和nTime填充到區塊的對應字段,就能夠驗證區塊了,若是難度符合要求,說明挖到了一個塊,節點將其廣播到全網。

getwork協議是最先版本挖礦協議,實現了節點和挖礦分離,經典的GPU挖礦驅動cgminer和sgminer,以及cpuminer都是使用getwork協議進行挖礦。getwork + cgminer一直是很是經典的配合,曾經不少新算法推出時,都快速被移植到cgminer。即使如今,除了BTC和LTC,其餘衆多競爭幣都還在使用getwork協議進行挖礦。礦機出現以後,挖礦速度獲得極大提升,當前比特幣礦機算力已經達到10T/秒級別。而getwork只給外部挖礦程序提供32字節共4G的搜索空間,若是繼續使用getwork協議,礦機須要頻繁調用RPC接口,這顯然不可行。現在BTC和LTC節點都已經禁用getwork協議,轉向更新更高效的getblocktemplate協議。

3

getblocktemplate協議

getblocktemplate協議誕生於2012年中葉,此時礦池已經出現。礦池採用getblocktemplate協議與節點客戶端交互,採用stratum協議與礦工交互,這是最典型的礦池搭建模式。

與getwork相比,**getblocktemplate協議最大的不一樣點是:getblocktemplate協議讓礦工自行構造區塊。**如此一來,節點和挖礦徹底分離。對於getwork來講,區塊鏈是黑暗的,getwork對區塊鏈一無所知,他只知道修改data字段的4個字節。對於getblocktemplate來講,整個區塊鏈是透明的,getblocktemplate掌握區塊鏈上與挖礦有關的全部信息,包括待確認交易池,getblocktemplate能夠本身選擇包含進區塊的交易。

getblocktemplate 在被開發出來後並不是一成不變,在隨後發行的各個版本客戶端都有所升級改動,主要是增添一些字段,不過核心理念和核心字段不變。目前比特幣客戶端返回數據以下,考慮到篇幅限制,交易字段(transactions)只保留了一筆交易數據,其實根據當前實際狀況,待確認交易池實時有上萬筆交易,目前區塊基本都是塞滿的(1M容量限制),加上額外信息,所以每次調用getblocktemplate基本都有1.5M左右返回數據,相對於getwork的幾百個字節而言,不可同日而語。

image

來簡單分析一下其中幾個核心字段, Version,Previousblockhash,Bits這三個字段分別指區塊版本號,前一個區塊Hash,難度,礦工能夠直接將數值填充區塊頭對應字段。

Transactions,交易集合,不但給了每一筆交易的16進制數據,同時給了hash,交易費等信息。 Coinbaseaux,若是有想要寫入區塊鏈的信息,放在這個字段,相似中本聰的創世塊宣言。

Coinbasevalue,挖下一個塊的最大收益值,包括髮行新幣和交易手續費,若是礦工包含Transactions字段的全部交易,能夠直接使用該值做爲coinbase輸出。

** Target**,區塊難度目標值。

Mintime,指下一個區塊時間戳最小值,Curtime指當前時間,這兩個時間做爲礦工調節nTime字段參考。 

Height,下一個區塊難度,目前協議規定要將這個值寫入coinbase的指定位置。

礦工拿到這些數據以後,挖礦步驟以下:

  • 構建coinbase交易,涉及到字段包括Coinbaseaux,Coinbasevalue,Transactions,Height等,固然最重要的是要指定一個收益地址。

  • 構建hashMerkleRoot,將coinbase放在transactions字段包含的交易列表以前,而後對相鄰交易兩兩進行SHA256D運算,最終能夠構造交易的Merkle樹。因爲coinbase有不少字節可供礦工隨意發揮,此外交易列表也可隨意調換順序或者增刪,於是hashMerkleRoot值空間幾乎能夠認爲是無限的。其實getblocktemplate協議設計的主要目標就是讓礦工得到這個巨大的搜索空間。

  • 構建區塊頭,利用Version,Previousblockhash,Bits以及Curtime分別填充區塊頭對應字段,nNonce字段可默認置0。

  • 挖礦,礦工可在由nNonce,nTime,hashMerkleRoot提供的搜索空間裏設計本身的挖礦策略。

  • 上交數據,當礦工挖到一個塊後噹噹即使用submitblock接口將區塊完整數據提交給節點客戶端,由節點客戶端驗證並廣播。

**須要注意的是:**與上文提到的GPU採用getwork挖礦同樣,雖然getblocktemplate給礦工提供了巨大搜索空間,但礦工不該對一份請求數據挖礦過久,而應循環適時向節點索要最新區塊和最新交易信息,以提升挖礦收益。

4

POOL

**挖礦有兩種方式,一種叫SOLO挖礦,另外一種是去礦池挖礦。**前文所述的在節點客戶端直接啓動CPU挖礦,以及依靠getwork+cgminer驅動顯卡直接鏈接節點客戶端挖礦,都是SOLO挖礦,SOLO比如本身獨資買彩票,不輕易中獎,中獎則收益所有歸本身全部。去礦池挖礦比如合買彩票,你們一塊兒出錢,能買一堆彩票,中獎後按出資比率分配收益。

理論上,礦機能夠藉助getblocktemplate協議連接節點客戶端SOLO挖礦,但其實早已沒有礦工會那麼作,在寫這篇文章時,比特幣全網算力1600P+,而當前最早進的礦機算力10T左右,如此算來,單臺礦機SOLO挖到一個塊的機率不到16萬分之一,礦工(人)投入真金白銀購買礦機、交付電費,不會作風險那麼高的投資,顯然投入礦池抱團挖礦以下降風險,得到穩定收益更加適合。所以礦池的出現是必然,也不可消除,不管是否破壞系統的去中心化原則。

礦池的核心工做是給礦工分配任務,統計工做量並分發收益。礦池將區塊難度分紅不少難度更小的任務下發給礦工計算,礦工完成一個任務後將工做量提交給礦池,叫提交一個share。假如全網區塊難度要求Hash運算結果的前70個比特位都是0,那麼礦池給礦工分配的任務可能只要求前30位是0(根據礦工算力調節),礦工完成指定難度任務後上交share,礦池再檢測在知足前30位爲0的基礎上,看看是否碰巧前70位都是0。

礦池會根據每一個礦工的算力狀況分配不一樣難度的任務,礦池是如何判斷礦工算力大小以分配合適的任務難度呢?調節思路和比特幣區塊難度同樣,礦池須要藉助礦工的share率,礦池但願給每一個礦工分配的任務都足夠讓礦工運算必定時間,好比說1秒,若是礦工在一秒以內完成了幾回任務,說明礦池當前給到的難度低了,須要調高,反之。如此下來,通過一段時間調節,礦池能給礦工分配合理難度,並計算出礦工的算力。

image

礦池一直都是一個矛盾的存在,毫無疑問,礦池是中心化的,如上圖所示,全網算力集中在幾個礦池手裏,網絡雖然幾千個節點同時在線,但只有礦池連接的幾個點擊擁有投票權,其餘節點都只能行使監督權。礦池再一次將礦工至於「黑暗」之中,礦工對於區塊鏈再次變得一無所知,他們只知道完成礦池分配的任務。

關於礦池,還有一個小插曲,在礦池剛出現時,反對聲特別強烈,不少人悲觀的認爲礦池最終會致使算力集中,危及系統安全,甚至置比特幣於死地。因而有人設計並實現了P2P礦池,力圖將「抱團挖礦」去中心化,代碼也都是開源的,但因爲效率遠不如中心化的礦池沒能吸引太多算力,所謂理想很豐滿,現實很骨感。

推薦幾個比較成熟的開源礦池項目,有興趣的讀者可自行研究:

  • PHP-MPOS,早期很是經典的礦池,很穩定,被使用最多,尤爲山寨幣礦池,後端使用Stratum Ming協議,源碼地址

  • node-open-mining-portal,支持多幣種挖礦,源碼地址

  • Powerpool,支持混合挖礦,源碼地址

運行一個礦池須要考慮的問題不少,好比爲了獲得最及時的全網信息,礦池通常對接幾個網絡節點,並且最好分佈在地球的幾大洲。另外提升出塊率,下降孤塊率,下降空塊率等都是礦池的核心技術問題,本文不能一一展開討論,接下來只詳細討論一個問題,即礦池與礦工的具體配合工做方式——stratum協議。

5

Stratum協議

礦池經過getblocktemplate協議與網絡節點交互,以得到區塊鏈的最新信息,經過stratum協議與礦工交互。此外,爲了讓以前用getwork協議挖礦的軟件也能夠鏈接到礦池挖礦,礦池通常也支持getwork協議,經過階層挖礦代理機制實現(Stratum mining proxy)。須知在礦池剛出現時,顯卡挖礦仍是主力,getwork用起來很是方便,另外早期的FPGA礦機有些是用getwork實現的,stratum與礦池採用TCP方式通訊,數據使用JSON封裝格式。

image

先來講一下getblocktemplate遺留下來的幾個問題:

  • **礦工驅動:**在getblocktemplate協議裏,依然是由礦工主動經過HTTP方式調用RPC接口向節點申請挖礦數據,這就意味着,網絡最新區塊的變更沒法及時告知礦工,形成算力損失。

  • 數據負載:如上所述,現在正常的一次getblocktemplate調用節點都會反饋回1.5M左右的數據,其中主要數據是交易列表,礦工與礦池需頻繁交互數據,顯然不能每次分配工做都要給礦工附帶那麼多信息。再者巨大的內存需求將大大影響礦機性能,增長成本。

Stratum協議完全解決了以上問題。

Stratum協議採用主動分配任務的方式,也就是說,礦池任什麼時候候均可以給礦工指派新任務,對於礦工來講,若是收到礦池指派的新任務,應當即無條件轉向新任務;礦工也能夠主動跟礦池申請新任務。

如今最核心的問題是如何讓礦工得到更大的搜索空間,若是參照getwork協議,僅僅給礦工能夠改變nNonce和nTime字段,則交互的數據量不多,但這點搜索空間確定是不夠的。想增長搜索空間,只能在hashMerkleroot下功夫,若是讓礦工本身構造coinbase,那麼搜索空間的問題將迎刃而解,但代價是必要要把區塊包含的全部交易都交給礦工,礦工才能構造交易列表的Merkleroot,這對於礦工來講壓力更大,對於礦池帶寬要求也更高。

Stratum協議巧妙解決了這個問題,成功實現既能夠給礦工增長足夠的搜索空間,又只須要交互不多的數據量,這也是Stratum協議最具創新的地方。

image

再來回顧一下區塊頭的6個字段80字節,這個很關鍵,nVersion,nBits,hashPrevBlock這3個字段是固定的,nNonce,nTime這兩個字段是礦工如今就能夠改變的。增長搜索空間只能從hashMerkleroot下手,這個繞不過去。Stratum協議讓礦工本身構造coinbase交易,coinbase的scriptSig字段有不少字節可讓礦工自由填充,而coinbase的改動意味着hashMerkleroot的改變。從coinbase構造hashMerkleroot無需所有交易,如上圖所示,假如區塊將包含13筆交易,礦池先對這13筆交易進行處理,最後只要把圖中的4個黑點(Hash值)交付給礦工,同時將構造coinbase須要的信息交付給礦工,礦工就能夠本身構造hashMerkleroot(圖中的綠點都是礦工自行計算得到,兩兩合併Hash時,規定下一個黑點表明的hash值老是放在右邊)。按照這種方式,假如區塊包含N筆交易,礦池能夠濃縮成log2(N)個hash值交付給礦工,這大大下降了礦池和礦工交互的數據量。

Stratum協議嚴格規定了礦工和礦池交互的接口數據結構和交互邏輯,具體以下:

1. 礦工訂閱任務

啓動挖礦機器,使用mining.subscribe方法連接礦池

image

返回數據很重要,礦工需本地記錄,在整個挖礦過程當中都用到,其中: b4b6693b72a50c7116db18d6497cac52:給礦工指定初始難度, ae6812eb4cd7735a302a8a9dd95cf71f:訂閱號ID 08000002:學名Extranonce1 ,用於構造coinbase交易 4:學名Extranonce2_size ,即Extranonce2的長度,這裏指定4個字節Extranonce1,和 Extranonce2對於挖礦很重要,增長的搜索空間就在這裏,如今,咱們至少有了8個字節的搜索空間,即nNonce的4個字節,以及 Extranonce2的4個字節。

2. 礦池受權

image

在礦池註冊一個帳號 ,添加礦工,礦池容許每一個帳號任意添加礦工數,並取不一樣名字以區分。礦工使用mining.authorize 方法申請受權,只有被礦池受權的礦工才能收到礦池指派任務。

3. 礦池分配任務

image

以上每一個字段信息都是必不可少,其中: bf:任務號ID,每一次任務都有惟一標識符

前一個區塊hash值,hashPrevBlock:

4d16b6f85af6e2198f44ae2a6de67f78487ae5611b77c6c0440b921e00000000:

學名coinb1 ,構造coinbase的第一部分序列數據:

01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008

學名coinb2 ,構造coinbase的第二部分序列數據:

072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000

學名merkle_branch,交易列表的壓縮表示方式,即上圖的黑點:

["76cffd68bba7ea661512b68ec6414438191b08aaeaec23608de26ac87820cbd02016","e5a796c0b88fe695949a3e7b0b7b1948a327b2f28c5dbe8f36f0a18f96b2ffef2016"]

00000002:區塊版本號,nVersion 1c2ac4af:區塊難度nBits 504e86b9:當前時間戳,nTime 有了以上信息,再加上以前拿到的Extranonce1 和Extranonce2_size,就能夠挖礦了。

4. 挖礦

構造coinbase交易

用到的信息包括Coinb1, Extranonce1, Extranonce2_size 以及Coinb2,構造很簡單:

Coinbase=Coinb1 + Extranonce1 + Extranonce2 + Coinb2

爲啥能夠這樣,由於礦池幫礦工作了不少工做,礦池已經構建了coinbase交易,系列化後在指定位置分割成coinb1和coinb2,coinb1和coinb2包含指定信息,好比coinb1包含區塊高度,coinb2包含了礦工的收益地址和收益額等信息,可是這些信息對於礦工來講可有可無,礦工挖礦的地方只是Extranonce2 的4個字節。另外Extranonce1是礦池寫入區塊的指定信息,通常來講,每一個礦池會寫入本身礦池的信息,好比礦池名字或者域名,咱們就是根據這個信息統計每一個礦池在全網的算力比重。

構建Merkleroot

利用coinbase和merkle_branch,按照上圖方式構造hashMerkleroot字段。

構建區塊頭

填充餘下的5個字段,如今,礦池能夠在nNonce和Extranonce2 裏搜索進行挖礦,若是嫌搜索空間還不夠,只要增長Extranonce2_size爲多幾個字節就可垂手可得解決。

5. 礦工提交工做量 當礦工找到一個符合難度的shares時,提交給礦池,提交的信息量不多,都是必不可少的字段:

slush.miner1:礦工名字,礦池用以識別誰提交的工做量 bf:任務號ID,礦池在分配任務以前,構造了Coinbase等信息,用這個任務號惟一標識 00000001:

Extranonce2 504e86ed:nTime字段 b2957c02:nNonce字段

礦池拿到以上5個字段後,首先根據任務號ID找出以前分配任務前存儲的信息(主要是構建的coinbase交易以及包含的交易列表等),而後重構區塊,再驗證shares難度,對於符合難度要求的shares,再檢測是否符合全網難度。

6. 礦池給礦工調節難度

礦池記錄每一個礦工的難度,並根據shares率不斷調節以指定合適難度。礦池能夠隨時經過mining.set_difficulty方法給礦工發消息另其改變難度。

image

如上,Stratum協議核心理念基本解析清楚,在getblocktemplate協議和Stratum協議的配合下,礦池終於能夠大聲的對礦工說,讓算力來的更猛烈些吧。

6

Auxpow

在挖礦的發展歷史上,還出現了一個天馬行空的事情,即混合挖礦(Merge Mining)。域名幣(Namecoin)最早使用混合挖礦模式,掛靠在比特幣鏈條上,礦工挖比特幣時,能夠同時挖域名幣,後來狗狗幣(Dogecoin)也支持混合挖礦,掛靠在萊特幣(Litecoin)鏈條上。混合挖礦使用Auxiliary Proof-of-Work (AuxPOW)協議實現,雖然混合挖礦不怎麼流行,可是協議設計的很精巧,最初看到協議時我不由感嘆社區的力量之偉大,這種都能想出來。

以域名幣的混合挖礦舉例,比特幣做爲父鏈(Parent Blockchain),域名幣做爲輔鏈(Auxiliary Blockchain),AuxPOW協議的實現無需改動父鏈(比特幣固然不會爲了域名幣作任何改動),但輔鏈須要作針對性設計,好比狗狗幣改成支持混合挖礦時就進行了硬分叉。

image

AuxPOW的實現得益於比特幣Coinbase的輸入字段,中本聰當初不知有意無心,在此處只規定了長度限制,留了一片未定義區域。這片區域後來對比特幣的發展產生深遠影響,不少升級和優化都盯上這片區域,好比上文講的Stratum協議。中本聰相似的有意無心狀況還有不少,好比交易的nSequence字段,也是由於沒有明肯定義,被黑客盯上引起的「延展性」問題成了「門頭溝」倒閉的替罪羊。再好比說nNonce,若是一開始定義的字節大一些,你比方說32字節,挖礦的演進就不須要以上討論的那麼多協議。

AuxPOW協議核心理念不一樣的地方在於:

對於經典的POW區塊,規定只有難度符合要求才算一個合格的區塊,AuxPOW協議對區塊難度沒有要求,但附加兩個條件:

  • 輔鏈區塊的hash值必須內置於父鏈區塊的Coinbase裏。

  • 該父鏈區塊的難度必須符合輔鏈的難度要求。

將輔鏈區塊的hash值內置於父鏈的Coinbase,實際上是利用父鏈做存在證實。這樣就能夠實現間接依靠父鏈的算力來維護輔鏈安全。通常來講,父鏈的算力比輔鏈大,於是知足父鏈難度要求的區塊必定同時知足輔鏈難度要求,反之則不成立。這樣一來,不少原本在父鏈達不到難度要求的區塊,卻達到輔鏈難度要求,礦工g=廣播到輔鏈網絡,在輔鏈得到收益,何樂而不爲。

AuxPOW協議對兩條鏈都有一些數據結構方面的規定,對於父鏈,要求必須在區塊的coinbase的scriptSig字段中插入以下格式的44字節數據:

image

對於輔鏈,對原區塊結構改動比較大,在nNonce字段和txn_count之間插入了5個字段,這種區塊取名AuxPOW區塊。

image

**混合挖礦要求父鏈和輔鏈的算法一致,是否支持混合挖礦是礦池的決定,礦工不知道是否在混合挖礦。**礦池若是支持混合挖礦,須要對接全部輔鏈的節點。

將輔鏈區塊hash值內置在父鏈的Coinbase,意味着礦工在構造父鏈Coinbase以前,必先構造輔鏈的AuxPOW 區塊並計算hash值。若是隻挖一條輔鏈,狀況較爲簡單,若是同時挖多條輔鏈,則先對全部輔鏈在挖區塊構造Merkleroot。礦池能夠將特定的44字節信息內置於上文Stratum協議中提到的Coinb1中,交給礦工挖礦。對礦工返回的shares重構父鏈區塊和全部輔鏈區塊,並檢測難度,若是符合輔鏈難度要求,則將整個AuxPOW區塊廣播到輔鏈。

輔鏈節點驗證AuxPOW區塊邏輯過程以下:

  • 依靠父鏈區塊頭(parent_block)和區塊Hash值(block_hash,本字段其實不必,由於節點能夠自行計算),驗證父鏈區塊頭是否符合輔鏈難度要求。

  • 依靠Coinbase交易(coinbase_txn)、其所在的分支(coinbase_branch)以及父鏈區塊頭(parent_block),驗證Coinbase交易是否真的被包含在父鏈區塊中。

  • 依靠輔鏈分支(blockchain_branch),以及Coinbase中放Hash值的地方(aux_block_hash),驗證輔鏈區塊Hash是否內置於父鏈區塊的Coinbase交易中。

經過以上3點驗證,則視爲合格的輔鏈區塊。

7

Conclusion

中本聰最初設計比特幣時但願全部節點都採用CPU挖礦,通常認爲只有這樣才能充分保證區塊鏈的去中心化特徵,比特幣在CPU時代安全度過了萌芽階段。getwork和cgminer將挖礦帶入GPU時代,國內顯卡曾經一度脫銷,全網算力迅速提高了一個檔次,CPU挖礦慘遭淘汰。隨着愈來愈多人蔘與挖礦,全網算力不斷上升,催生了抱團挖礦(礦池)。然而GPU時代的繁榮歷史也沒能持續多久就被getblocktemplate,stratum以及礦機帶入了ASIC時代。

getwork實現了數據與挖礦分離,getblocktemplate給外部挖礦程序提供了最大自由度,完全解決了外部挖礦程序與節點交互的可擴展性問題(scalability problems),主要用於礦池與網絡節點對接。stratum不但解決了搜索空間不足的問題,同時也解決了礦池與礦機交互數據量大的問題。getblocktemplate和stratum這兩個協議使大型礦池,大規模礦場,大算力礦機成爲可能,今後挖礦產業進入一個全新階段,此後挖礦的演進主要集中於幾個方向:礦池的設計優化與穩定運行,礦場的科學部署,以及礦機工藝升級,提高算力,下降功耗等。

內容來源:區塊鏈兄弟

活動推薦

主題:Blockathon,挑戰區塊鏈開發,敢不敢來!(點擊瞭解詳情)

5月25-27日,Blockathon2018北京站,招募100名開發者一塊兒挑戰區塊鏈開發。

開發者免費,報名需審覈。識別下圖二維碼或點擊「閱讀原文」便可報名參加。

image

點擊「閱讀原文」便可報名。

相關文章
相關標籤/搜索