挖礦到底是在讓電腦計算什麼

2017年12月比特幣匯率創新高來到 20000鎂/1比特幣

很多人就此一窩蜂買礦機、買顯卡,希望也可以參與到挖礦帶來的收益

(當然現在比特幣的難度已經不是個人礦機、顯卡可以挖得動的了)

我當時為了理解區塊鏈的原理也有試著去挖門羅幣
(因為筆電只有CPU,門羅幣是唯幾還能用CPU挖的幣別)

回到主題,現在已經弄懂整個近年來很熱門的區塊鏈的概念了

所以想分享自己所理解的給還不知道什麼是挖礦的人

 

什麼是區塊鏈

在中本聰發表比特幣使用的區塊鏈之前,伺服器基本上都是centralized network的架構,如圖:

公司/法人/機構會架好中央伺服器,用戶如果要存取資料就必須連到這台伺服器

如果這台伺服器遭到損會或竄改,那只好跟資料say goodbye了(如果都沒有備份的話)

舉例:
小明是雪山銀行的存戶,在雪山銀行裡存了一百萬

今天銀行被駭客入侵了,駭客把小明的資產改成了一萬

小明此時欲哭無淚,因為他辛苦耕耘存下的退休金瞬間縮水一百倍
(假設今天銀行伺服器沒有log、備份、銀行也沒有參與存款保險)

 
相對於centralized network架構下的伺服器

比特幣或其他的加密貨幣使用的區塊鏈是一種分散式儲存的架構,又稱分散式帳本

分散式帳本 DLT(Distributed Ledger Technology)

分散式帳本的概念是讓資料庫中的資料並不依賴儲存於單一伺服器中

而是像圖中這樣各節點都有存有一份資料庫的副本

每個節點三不五時會互相跟左右鄰居節點同步最新的資料

而且同步時,資料必須是多數節點都存在該一致的資料才會將此資料寫進自己的節點上

如此一來,分散式帳本可以達成

  • 去中心化
    每個節點都有一份資料庫的副本
  • 不可竄改性
    同步的資料採用多數決,如果只有一、兩個節點出現不一樣的資料,並不會被其他節點認可同步
  • 可追蹤性
    區塊鏈的資料結構是只能一直新增資料,不能修改舊有資料或刪除,所以可以一直往前追朔資料的歷史變化(等等會介紹它的資料結構)

 
如果今天小明的存款是像比特幣這種採用分散式帳本的加密貨幣

就不會發生伺服器被駭的這種慘案了,幫他QQ

 

區塊的資料結構

當了解區塊鏈採用的是一種分散式儲存的架構後

現在來談談區塊鏈是以什麼樣的資料結構在各節點中儲存

這是區塊鏈的一個區塊的面貌

Tx0Tx1Tx2Tx3是交易(Transaction)的縮寫

下圖是比特幣第532790區塊真實的交易紀錄,也就是上面說的Tx0Tx1、…

所有的區塊data都是交易紀錄

假如今天小明的存款是像比特幣這種採用分散式帳本的方式儲存,帳戶總餘額就會是:

  • 上個月的薪資所得(公司轉帳進小明帳戶的一筆交易)
  • 這個月的薪資所得(公司轉帳進小明帳戶的一筆交易)
  • 扣掉前天ATM領錢(一筆交易)

把小明開戶以來所有的交易金額(收入支出)加總出來

 
有了交易Tx0Tx1…後,把相鄰交易的hash碼再兩兩hash一次

重複這個動作一直到只剩下一個hash碼,我們稱這個hash碼為Merkle Root Hash

Merkle Root Hash存放於區塊的header,其它存於區塊的header的資訊還有Block No、Previous Hash、Timestamp、Nonce、…等等的

 
產生Merkle Root Hash的目的是利用hash牽一髮而動全身的特性,來防止區塊內的交易被有心人偷修改

因為修改任一交易資料都會導致Merkle Root Hash產生變化

比起逐筆交易比較是否一致

只要簡單跟鄰居節點比較Merkle Root Hash就可以知道所同步的區塊裡的交易是否一致

大大提升了驗證效率

 

區塊是怎麼鏈起來的

在上一段嚐過hash的優點後,為了把區塊鏈起來,必須在每個區塊記錄前一個區塊是誰,我們直接把上一個區塊hash起來

乾脆利落,只需要一個變數的空間就可以描述完上一個區塊,這也就是Previous Hash這個變數的值

只要不停地把新的交易包進新的區塊,產生Merkle Root Hash、紀錄最後的區塊至Previous Hash、選擇適合的Nonce,依照這樣的模式鏈下去,就是我們看到的比特幣區塊鏈了

 

何謂挖礦

還記得區塊鏈是採用分散式帳本的概念

在每個節點中都存有一份資料庫的副本,使得資料庫中的資料並不依賴儲存於單一伺服器中

那又為什麼這些節點為什麼要乖乖地消耗他自己的電力維持整個區塊鏈的運作呢

The answer is reward(獎勵).

 
這些幫忙維持整個區塊鏈的運作的節點將新的交易包進新的區塊

當節點發佈打包好的區塊受到其他大眾節點的承認、成為最新的區塊鏈區塊時,就會被給予一定數量的reward,例如比特幣

聽起來好像很容易嘛,Nope,「打包」這個動作本身是有難度的

為了避免各個節點自己打包自己的都不去理其它節點產出的新的區塊

所以訂出了一個規定:要被大家所承認的新區塊,其hash必須是以一堆0開頭

例如比特幣第532790區塊的hash是
0000000000000000003376f38cfe378afd3790c22f0be62abbcc8446c07071d4

至於是多少個0就要看整個區塊鏈當時的difficulty是多少

 
那要怎麼讓區塊的hash值是一堆0開頭呢

沒有捷徑,就是努力的try

藉由固定Previous Hash、Merkle Root Hash、…等等,只一直替換Nonce來重新計算新的區塊hash

來試出到底哪個Nonce可以得出一堆0開頭的區塊hash

這就是俗稱的挖礦,就好比拿著十字鎬不停地對著同一個地方挖掘,期待哪一天挖出鑽石(一堆0開頭的hash)

舉個簡單的例子來說明:如果difficulty要求區塊的hash至少要7個0開頭

PrevHash:0000009a2e... Root:6d6a73... Nonce: 數字這個字串假裝成我們的區塊hash

拿去進行SHA256(比特幣用的hash算法),數字從0、1、2、…一直往上試

試了16次連開頭第一位是0都沒有呢(16次的期望值至少會中1次吧)

為了有實驗家的精神,我們持續的hash,直到開頭有7個0的hash為止
(嘗試一筆就印出一行太雜亂,改成每10萬筆印出一次提示、如果有符合直接印出)

終於,Nonce從0、1、2、…一直到1889028時出現了以7個0為開頭的hash了
0000000c98695b6e789f32e2f0fa3b80c33f19f86366debdc77f6e9d802d1058

我們可以使用Nonce等於1889028這個結果打包發佈區塊給鄰近的節點

各節點收到後,會再hash一次該區塊,看開頭是否有7個0

如果驗證無誤即承認這是合法的區塊,才會串加到自己區塊鏈副本的尾端

而此時我們就會獲得reward當作努力打包的獎賞

(其實開頭才7個0還算少唷,看看比特幣,人家第532790區塊的hash可是18個0開頭)

 
為了控制出產一個區塊的時間好讓各節點都在維護同一條區塊鏈

訂定了區塊的hash必須是n個0開頭這一條規則

正是所有挖礦者為了取得區塊打包reward所在追求達成的目標

看完後是不是能體會到挖礦到底是在讓電腦計算什麼了呢


發佈留言