各位好,上次我與 @antonsteemit探討了分散式系統:
DA-ChainTalk #6 — 從分散式去到去中心化系統
這次談POW共識機制的詳細內容,以供您對於共識機制,有更多的認識。
此一系列以「DA-ChainTalk」的名稱開頭,您亦可從 #da-chaintalk來追蹤我們的文章。謝謝!
Image Source - pixabay
DA-ChainTalk #7 — 挖礦,交易的確認與共識的形成。
前言
在我們之前的系列文章「分散式系統」、「從分散式到去中心化」中,就提到過共識問題的由來,以及現在「共識機制」在去中心化的區塊鏈中,扮演什麼重要的角色。而其中,最廣為人之的共識演算法就是區塊鏈開山始祖比特幣所使用的Proof of Work - 工作量證明了。相信大家就算不知道POW是什麼,也聽過礦工、挖礦吧。今天,就讓我們一起來仔細看看「礦工們」平常都是怎樣在運作的吧!
Image Source: http://bitcoindaily.org/bitcoin-guides/what-is-bitcoin-mining/
背景介紹
在了解整個系統運作方式之前,要先對一些基本的術語有所理解。
1. Hash Function 雜湊函數:
所謂的雜湊函數就是一個特別的函數,可以把任何input轉換成統一規格的雜湊值output,並且擁有一些特性:
- 可以輕易的由輸入(Input)算出輸出值(Output),但是難以從結果回推原本的輸入值。
- 只要輸入值有些微的變動,就會產出完全不同的輸出值。也就是說這之間是沒有規律的。
2. Full Node (完整節點/全節點)
其實在一般區塊鏈的網路中提到的「Node」,通常指的就是Full Node,也就是一個完整的節點。完整節點的工作就是保存了所有有史以來的交易資料(帳本),並且能夠驗證一個別人傳來的「區塊」是否為有效。當然,如果裡面包含了非法的雙花交易,區塊就會是無效的。至於驗證的細節,我們等一下會介紹。
3. Mining Node 挖礦節點
可以理解為「有在挖礦的全節點」。
其實所有的節點都有權力提交區塊到區塊鏈網路中,讓其他節點驗證。在比特幣的設計裡,每個節點同時都可以是「Mining Node」,也就是同時在試著找到新區塊的節點。但是到了今天,Mining Node其實非常的少,大部分的Mining Node也不是憑著一己之力在挖礦,而是透過Mining Pool - 「礦池」來統整全世界大家GPU的算力,一起提高找到區塊的可能。
好了,大概我們需要知道的角色就是這些了,我們可以來看看POW是如何運作的。
Proof of Work
首先,說到「寫區塊」這件事情,其實就是簡單的記帳。但因為區塊鏈是一個去中心化的網路,並沒有一個中心伺服器來統籌分配誰有權力來寫區塊,所以就必須改為一種類似「競賽」的方式來完成「寫帳本權力」的分配。因為每次寫帳本的人有錢可以拿,所以如果沒有這樣一個規定的話,就會天下大亂囉!而Proof of Work的設計,就是將寫帳本的權力交給優先解出一個計算難題的人。
還記得我們前面說的Hash嗎?我們每丟一個input進去,就會產生一個隨機的數字出來。這個計算難題其實單純到不行,就是「猜數字」。誰最先猜出一個數字(Nonce),把他跟想要提交的區塊的內容一起丟到Hash之後,產出的結果數字小於「Difficulty」的規定數字,就算是猜對了。
我們剛剛提到的Mining Node,在做的就是這件事情。每當有人有交易提交到區塊鏈上時,他們會被放到一個叫做mempool的地方,而這些挖礦節點就會從mempool裡面提取交易,自己先驗證他們的交易紀錄,確定合法之後就打包到新的區塊裡面(如果他們沒有先驗證的話,未來區塊提交出去也會被拒絕接受,所以一定會自己先驗證)。由於區塊容量有限,而且加上每個Mining Node的Mempool不是即時同步,所以每個挖礦節點所選取的交易可能不同。這也是為什麼網路塞車時,我們可以付比較高的手續費,讓礦工優先打包我們的交易。
除了要選擇好的交易之外,挖礦節點還需要把前一個區塊的header資料也一起放進來,這是為了讓每個區塊有「順序性」,並且不能夠竄改以前的交易紀錄。因為一旦我們竄改了前面的交易,涵蓋交易的區塊header就會改變,後面的區塊也都全部會變得「不合法」。
所以我們可以看到下圖中,一旦一個挖礦節點決定好了要放進區塊的交易,並由看準了前一個區塊的header,把兩者合併之後,就會開始尋找這個Nonce值,一旦這些東西加上Nonce值,最後可以由Hash產出一個夠小的數,就算是成功「挖到礦」了。
Image Source: https://www.supportsages.com/bitcoin-mining/
在現在的比特幣世界裡,每當一個Mining Node決定好區塊內容之後,就會透過礦池,把這個算nonce的工作發包給全世界各地想要合作的電腦。現在這些擁有特殊軟體程式以及GPU配備的電腦被稱為「礦工」,因為他們真的只是底層工人,幫忙暴力法嘗試各種可能的解。一旦這個「礦池」中的一個人算出了答案,大家會按照算力平分區塊獎勵。因此,實際上我們常說的「礦工」,並不是一個節點,只是一個「聽命於挖礦節點的小工人」罷了。網路上有些人也會把Mining Node稱為Miner,這只是觀察尺度的不同而已。
區塊的驗證
當然,在挖礦節點成功找到一個Nonce之後,它就會把這個節點廣播出去給所有的Full Node驗證。Full Node的驗證過程也很簡單,只要看看區塊內的交易是不是都合法,再確定所有東西用你找到的Nonce一起Hash過後有沒有符合Proof of Work難度規定,就可以決定區塊合不合法。如果覺得這個區塊合法,Full Node就會把他加到區塊鏈上,並且廣播出去讓其他人知道。當然,如果你是一個Mining Node,發現有人比自己快解出最新區塊了,那麼你應該趕緊重新打包一個區塊並開始驗證,因為這時候「最新的區塊」已經改變了,在大家都更新了最新區塊之後,你遲來一步的區塊就不會被接受。
Longest Chain
但是仍然有可能遇到一種情況,就是兩個節點幾乎同時找到合法的新區塊,並從世界的兩端開始廣播。這時全網可能有一些節點收到了Block_A
是第100個區塊,而另外一些人收到Block_B
是第100個區塊。這是,要怎麼決定誰是正確的呢?
答案是,不用現在決定。
其實整個比特幣系統,付給Mining Node手續費的方法很有趣,是由每個挖礦節點自己把這筆「手續費付給自己」的交易放到區塊中一起打包。也就是Node_A
會在它的區塊中紀錄 Fee 1 BTC to Node_A
,Node_B
則會紀錄Fee 1 BTC to Node_A
。所以當這兩個相衝突的區塊同時被不同節點接受時,整個網路就出現了短暫的分岔,同時出現兩個 Block_100
,裡面紀錄的交易有手續費等些微不同。
這時,剛剛產出Block_A
的挖礦節點Node A肯定選擇相信自己的區塊是正確的,因為裡面紀錄的它有成功拿到手續費,所以他便會用這個區塊的header繼續下一個區塊的挖礦。同理Block_B也會相信自己挖出的區塊。而其他的Mining Node,我們剛剛說過,他通常會相信「先收到的新區塊」,因為對這些挖礦節點來說分秒必爭,一旦他們看到新的合法區塊就會先用他開始計算下一個區塊。至於一般的Full Node呢,不一定,看心情。不過大家同時都會收到另外一個版本的區塊,也都會稍微留意一下這兩個區塊的最新狀況。
如果其中一個支鏈一直都沒有收到新的區塊,代表可能根本就只有少數人看到這個支鏈,大家都放棄它了,所以就基本可以確定可以不用理他。但也有可能兩個支鏈都持續有人在提交區塊,那就代表「事態還不明朗」,兩邊都有可能是對的。但是要記得的是,一旦一個支鏈被棄用了,同時也就代表找到上面區塊的礦工都做白工了,所以Mining Node會非常在意自己現在在挖的鏈,到底是不是會被大家選擇的鏈,而他們判斷的方式就是看看「哪個支鏈長」。長的支鏈通常代表著有更多的節點把他當作正確版本,而且很有可能再未來依然比你更長。所以這些挖礦節點出於「利益」考量,在一條支鏈明顯較有優勢之後,就會選擇轉換到那一條支鏈上為它「挖新礦」。這也是為什麼,儘管短期內來看可能有支鏈存在,但時間一長,所有節點依然可以取得共識,何者為大家都同意的比特幣帳本。
難度變化
比特幣的難度設計也是十分巧妙,試想,如果一個區塊鏈只有100台電腦當礦工,那他挖出礦的速率應該是10000台電腦的百分之一,也就是需要100倍的時間才能產生一個區塊,這豈不是太弱了嗎?為了讓出塊速度保持約略相等,比特幣的程式設定字懂調整難度的機制,每隔一段時間,就會重新計算現在的全網算力,並且調整這個Difficulty的值,難度提昇可以想像成「選擇一個較小的Target」值,要找到一個Nonce使得hash值小於Target就越困難。例如一開始難度較低時,Target = 1,000,000,000,只要hash完的值小於他就算成功。隨著多了很多礦工加入網路,Target可能變成1,000,000,那麼如果hash出來的值= 334,934,123,就不再小於10,000,000,不能被視為「成功解題」。透過這個動態調整的機制,可以使比特幣系統至今仍然維持穩定的出塊速度。
Image Source: https://www.supportsages.com/bitcoin-mining/
交易Confirmed?
最後我們來說說,究竟什麼時候一筆交易可以被當作Confirmed了呢?
其實就像我們在「分散式系統」中的介紹一樣,一筆交易究竟是否「完成」,全看Client端怎麼定義。而Client端如何定義就是屬於「速度」與「一致性」的取捨了。通常我們在交易所入金時中會看到1/6 Confirmed
這種字樣,其實意思就是「已經有幾個區塊加在這筆交易之上」。像我們剛剛說的,區塊鏈中存在著支鏈,也有可能有惡意散布的區塊,因此並不是所有交易一旦寫入區塊中就確定完全沒有問題。不過一般人沒有能力自己驗證,純粹從一個旁觀者的角度來看,我們只能用「有多少區塊被寫在這筆交易之上」來判斷,這是不是一筆合法的交易。這跟SPV Proof的概念有點像,我們間接透過「有多少Proof of Work」被加在這個區塊之後,來猜測這個區塊合法的可能性。基本上如果後面又接了六七個區塊以上,就已經幾乎可以確定正確無誤了,所以,我們在交易時要等待一段「確認時間」,等的就是這個。
小結
好啦,終於說完了PoW,這大概就是比特幣完整的共識過程了。雖然現在PoW已經慢慢退流行,但是了解PoW之後,也更有助於我們學習其他共識演算法啦!如果有任何問題或是覺得有寫錯的地方也歡迎留言討論指教,希望這篇文章對大家有幫助囉~
#da-chaintalk
This page is synchronized from the post: ‘DA-ChainTalk #7 — 挖礦,交易的確認與共識的形成。’