1. 程式人生 > >深入解讀理解區塊鏈

深入解讀理解區塊鏈

      一提到比特幣、區塊鏈,能讓我們最先想到的就是去中心化,分散式資料庫/賬本,但是什麼是去中心化,或者什麼是區塊鏈,卻未必都能說得清。很多人對於區塊鏈的認識就止步於此。網上查一查什麼是區塊鏈,各種專業詞彙撲面而來,什麼點對點網路,什麼工作量證明機制(PoW),什麼數字簽名、共識演算法,把人看得雲裡霧裡,也未必真能搞得懂。實際上,區塊鏈就是這樣的一種技術,它並非是從零開始,而是基於已有的這些技術,經過巧妙的結合生成的。如果要搞懂區塊鏈,就要搞明白這些東西是怎麼結合在一起的。所以這篇文章主要在巨集觀的基礎上,在技術層面做更進一步的深入。

如何理解區塊鏈

      首先,引入區塊鏈的理念:將一個基於節點的去中心化共識協議與工作量證明(PoW)機制結合在一起。節點通過PoW機制獲得參與到系統的權利,每隔一段時間將交易打包到區塊中,從而創建出不斷增長的區塊鏈。

      這裡主要有兩個概念:去中心化和工作量證明機制。其實比特幣的去中心化體現的可能更明顯,這個之前我又寫過一篇解讀作為最早區塊鏈技術的比特幣以及區塊鏈所帶來的改變

      如何去中心化:區塊鏈系統中的每一個區塊,負責記錄交易資訊,每個使用者的收支情況都被永久的儲存在區塊中供他人查詢。每個節點都會儲存一份完整的交易資料,所有這些節點組成了區塊鏈的分散式資料庫系統,任何一個節點的資料出現問題,都不會影響整個系統的運轉。

      工作量證明機制:工作量證明(Proof Of Work,簡稱PoW),簡單理解就是一份證明,用來確認你在系統中做過一定量的工作。相較於低效的監測工作的整個過程,通過對工作結果進行認證來證明完成了相應的工作量,則是一種非常高效的方式。例如我們通過完成工作中的各項任務來證明我們為公司創造了價值,從而得到公司的認可。而這種"工作證明"一般都會花費一定的時間才能得到。

工作量證明機制(PoW)

      工作量證明機制,是一種應對拒絕服務攻擊(DoS)和其他服務濫用的經濟對策。它要求發起者進行一定量的運算作為代價,也就意味著需要消耗計算機一定的時間。例如現在網站登入時都需要輸入的驗證碼(滑塊或者拼圖),都採用的是這種CAPTCHA模式。

      類似於CAPTCHA,雜湊現金(HashCash)的原理是在郵件的訊息頭中增加一個包含收件人地址、傳送時間和salt隨機數的hashcash stamp的雜湊值,但是滿足前20位都是0的雜湊值才是合法的。這就需要傳送者在正式傳送前需要通過調整salt的值進行多次計算,在滿足該條件後才能成功傳送。但是我們不希望傳送者在算出這個stamp後繼續複用,所以HashCash規定了過期的stamp是非法的(即傳送時間 > stamp時間)。

      區塊鏈也是採用了類似hashcash的工作量證明方法,對區塊頭中的資料做雙重SHA256運算( 即SHA256(SHA256(HEADER)) ),與當前網路的目標值做對比,如果小於目標值,則完成工作量證明。

      這裡對PoW做了較多的解釋,是為了便於理解PoW是如何應用在區塊鏈上的。挖礦也是通過PoW進行的。在比特幣系統中,節點完成工作量證明後,就代表獲得這個區塊的交易記賬權。系統會通過PoW機制讓礦工們競爭記賬權,誰在單位時間內執行的運算更多(擁有更高的算力),誰就有更高的概率獲得區塊的記賬權。獲得記賬權的礦工將把該區塊廣播到網路中,全網其他節點在驗證區塊滿足特定的條件後,其區塊會被連結在主鏈上,從而在全網範圍內形成對當前網路狀態的一次共識,該礦工也會得到系統獎勵的一定數量的代幣。所有的區塊通過這種形式連結在一起,形成了區塊鏈的主鏈,從創世區塊到當前生成的最新區塊,所有歷史交易資料都是公開透明的。

      上面提到了區塊是用於記錄交易資訊的,區塊頭中的資料參與了PoW的過程。那麼接下來有必要進一步分析區塊的內容了。

區塊的組成

      每個區塊由區塊頭和區塊體兩部分組成。區塊頭中主要包含前一個區塊的Hash地址(Prevhash)、時間戳(Timestamp)、隨機數(Nonce)、當前區塊的目標Hash值(CurrentTarget)。Merkle樹的根值(Merkle Root)等資訊;區塊體中則包含了具體的交易數量(TX NUM)和自上一個區塊生成以來發生的所有交易的列表。這個交易列表就是記賬本,每一筆交易都會被永久地記入區塊中,任何人都可以查詢。而且交易都會伴隨數字簽名,確保交易不可篡改及真實有效性,所有交易都將通過Merkle樹的Hash運算產生一個唯一的Merkle根值記錄到區塊頭中(Merkle樹是一種資料結構,後面將做介紹)。

狀態轉移與UTXO交易模式

      從技術的角度出發,比特幣記賬本可以看做是一個狀態轉移的系統。持有人對現存的所有比特幣的持有情況,可以理解為系統當前的一種狀態。例如:小明有100個比特幣,表示在當前的狀態下,小明持有100個比特幣。當小明想進行交易時,比如給小王轉20個比特幣,就需要以當前的狀態(擁有100個比特幣)和發起的交易(給小王轉20個比特幣),通過狀態轉移,生成新的狀態(小明有80個比特幣,小王有20個比特幣)。這個狀態轉移可以看做是一個函式:

APPLY(STATE, TRANSACTION) => NEW_STATE

表示小明給小王轉賬的交易:

APPLY({XiaoMing: 100, XiaoWang: 0}, "send 20 from XiaoMing to XiaoWang") => {XiaoMing: 80, XiaoWang: 20 }

      可以發現,交易的過程就是一個從輸入到輸出的過程,一個資金流轉的過程,並且創世區塊和後來挖礦產生的獎勵區塊不適用於這個公式(創世區塊是整個鏈上的第一個區塊;挖礦的獎勵區塊是憑空產生的,是發行代幣的方式)。除此之外,其他的交易都必須要依據現有的輸入來產生新的輸出。而現有的輸入是從何而來的,必然是從這個持有人在上一筆交易中的輸出得到的。稍微有點繞,按照上面的例子,假如小王要給小李再轉5個比特幣,這筆交易的輸入(5個幣)必須是上一筆交易(小明給小王轉賬)中未被使用的輸出(20個幣)。這個未被使用的交易輸出也叫做UTXO(Unspent TX Output),是比特幣交易的基本單位。也可以簡單理解為空閒的、未被佔用的金額,就像已經花出去的錢(你上一筆交易的UTXO)是不可能再花一遍的(已成為別人的UTXO)。一筆交易可以包括一個或多個輸入和一個或多個輸出,每個輸入包含一個對現有UTXO的引用和與持有者私鑰建立的密碼學簽名;每個輸出包含一個新的加入到狀態中的UTXO。

對於交易中的每個輸入和狀態,有如下的定義:

1.如果引用的UTXO不在當前的狀態中,則會返回錯誤;如果簽名與引用的UTXO的持有者簽名不一致,也會返回錯誤。

2.如果所有輸入的UTXO總額與所有輸出的UTXO總額不等,會返回錯誤。

3.返回的新狀態NEW_STATE中,移除了所有輸入的UTXO,增加了所有輸出的UTXO。

Merkle樹

      Merkle樹是資料結構中的一種樹結構,可以是二叉樹,也可以是多叉樹,具有樹的所有特點。由於Merkle樹中會進行Hash運算,所以也被稱為Hash樹。在瞭解Merkle樹之前,先來看看Hash演算法及HashList。

      Hash演算法是一種可以將任意長度的資料轉換成固定長度字串的演算法。是一種安全雜湊演算法。最顯著的特點是幾乎不可逆、無衝突。Hash演算法最常見的應用就是對資料完整性的校驗。例如我們在下載一些檔案時,資源提供方會給出一個MD5或者SHA的值,這個值實際上就是資源在經過Hash運算後的值,使用者下載資料後,可以對資料進行Hash,然後跟這個值比對,如果相同,就說明資料在傳輸過程中無損壞或篡改。

      缺點:當下載較大的檔案時,如果出現Hash值不匹配的情況,那麼就要重新下載整個檔案。

      這種通過對整個檔案進行Hash運算來判斷資料是否損壞的方法,效率很低下。如果將檔案分割成一個個小的資料塊,分別對其做Hash,就得到了HashList。在點對點網路中傳輸資料時,會從多個節點同時下載資料。假設某些節點網路不穩定或者資料不可信,那麼為了驗證資料的準確性,就會採用HashList,如果某些資料塊損壞了,只需要重新下載這些小的資料塊即可,無需重新下載整個檔案。

      通常在下載資料前,會先從可信資料來源那裡獲取一個Root Hash值。Root Hash是將HashList中每個資料塊的Hash值拼接到一起,再做一次Hash運算所得到的值。這個值用來校驗HashList是否正確。得到Root Hash後,會再下載該資料的HashList。判斷HashList正確後,才開始檔案資料的下載。最後將下載的資料塊做Hash後與HashList做比對,如果出現不一致,則說明資料被損壞,需要重新下載該資料塊。

 

      然後回過頭來再看Merkle樹,它的底層與HashList一樣,都是將資料分成小資料塊,然後分別計算其Hash值。但是再往上一層就不同了,它不是把所有的Hash值合併到一起做Hash,而是將兩個相鄰的Hash值拼接在一起進行Hash運算,產生一個新的Hash。例如Block1的Hash值201w與Block2的Hash值0mzc合併Hash後產生新的3ali Hash值。而如果兩兩匹配後出現孤立的Hash值,則直接將其做Hash,例如Block5。最終產生一個Root Hash值,通常稱為Merkle Root。

     同樣,在下載前,會先從可信資料來源中獲取正確的Merkle Root,然後再從其他節點下載Merkle樹,通過Merkle Root來辨別Merkle樹的真偽。如果發現不匹配,則從其他節點繼續下載該Merkle樹,直到獲得一個與可信Merkle Root相匹配的Merkle樹。

      由於Merkle樹是逐級分支的,所以它可以從任意一個分支開始下載並驗證。考慮Root->d063->09yk->a8b5->Block3這個分支,如果對這個分支的Hash值驗證通過後,就可以下載Block3的資料了。而在HashList中需要先得到整個Hash值列表後才能使用Root Hash驗證。

 

      在區塊鏈系統中,最下層的葉節點中存放的是交易資料,每個中間層的節點都是它的兩個子節點的Hash,根節點也是它的兩個子節點的Hash,代表Merkle樹的頂部。如果有攻擊者惡意篡改交易資料,或者篡改Merkle樹的某一部分,必然導致上層節點的Hash值變動,最終導致驗證不通過。

 

      瞭解了Merkle樹的結構後,如果我們要查詢某一筆交易,那麼順序是怎樣的呢?首先,可以根據區塊頭中的時間戳確認交易存在的具體區塊。而Merkle Root也是放在區塊頭中的,如果我們從Merkle Root開始向下查詢,假設底層有n筆交易資料,那麼找到所需的步驟為log2(n),其實就是演算法中的二分查詢。簡化支付驗證(Simplified Payment Verification)就是利用這種方案,實現了輕量級的錢包客戶端,只需下載區塊頭及相關交易的分支,即可對交易進行確認。但是它也存在一些缺點:

1.容易遭到全節點的拒絕服務,所以要保證較多的與全節點的連線,而且要保證這些節點是可信的;

2.spv客戶端向全節點請求的交易必須與它的金鑰一致,這樣全節點會看到該客戶端的相應使用者的公鑰,造成隱私洩露。

P2P網路

      P2P網路即對等網路,是一種去中心化的分散式應用架構。這種網路結構與目前傳統的CS(Client/Server)、BS(Browse Server)結構的本質區別是,網路中不存在中心節點/伺服器。在P2P架構中,每個節點的地位都是對等的,都具有相同的功能,無主從之分。節點通過將硬體資源以服務的形式共享到網路中,這些共享的資源可以被其他節點直接訪問。一個節點既可充當伺服器的角色,又是服務請求方,故節點越多,網路中可提供的資源就越多。而CS、BS這些模式都是以中心應用伺服器為核心的,由使用者向中心伺服器發起請求,中心伺服器處理請求後再將結果返回給使用者。使用者之間的通訊也需要通過中心伺服器轉發來完成。所以P2P網路中的核心思想也是去中心化。除了這個特點,P2P網路還具有擴充套件性強、健壯性、高性價比、負載均衡、隱私保護等特點。我們日常使用的BT下載就是採用P2P讓客戶端之間進行資料傳輸。BT下載是通過BitTorrent協議(一種中心索引式的P2P檔案分分析通訊協議),讓你在下載其他使用者資源的同時,也為其他使用者提供上傳。所以下載的人越多,可連線到的節點就越多,下載速度就越快。

      在BT架構中,我們發現還是存在一個"中心伺服器",該伺服器的作用並非提供下載服務,而是對釋出的torrent檔案進行統一管理。torrent檔案本質上是一個索引檔案,包含了Tracker資訊(釋出資源的伺服器的位置)和檔案資訊(檔名、大小、Hash值等),這些資訊根據BitTorrent協議內的B編碼規則進行編碼。torrent檔案中的Hash資訊是對每一塊要下載的檔案內容的加密結果。使用文字工具開啟.torrent檔案,就可以看個大概(亂碼是SHA1校驗碼):

 

結語

      通過以上的內容可以發現,組成區塊鏈的這些技術實際上早已有著廣泛的應用,只是我們之前並未那麼密切的關注過,而區塊鏈只是將這些技術巧妙的結合到了一起。理解了這些技術的原理後,我們就可以揭開區塊鏈神祕的面紗,去進一步窺