深入理解區塊鏈


 

      一提到比特幣、區塊鏈,能讓我們最先想到的就是去中心化,分布式數據庫/賬本,但是什么是去中心化,或者什么是區塊鏈,卻未必都能說得清。很多人對於區塊鏈的認識就止步於此。網上查一查什么是區塊鏈,各種專業詞匯撲面而來,什么點對點網絡,什么工作量證明機制(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的Hash201wBlock2Hash0mzc合並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架構中,每個節點的地位都是對等的,都具有相同的功能,無主從之分。節點通過將硬件資源以服務的形式共享到網絡中,這些共享的資源可以被其他節點直接訪問。一個節點既可充當服務器的角色,又是服務請求方,故節點越多,網絡中可提供的資源就越多。而CSBS這些模式都是以中心應用服務器為核心的,由用戶向中心服務器發起請求,中心服務器處理請求后再將結果返回給用戶。用戶之間的通信也需要通過中心服務器轉發來完成。所以P2P網絡中的核心思想也是去中心化。除了這個特點,P2P網絡還具有擴展性強、健壯性、高性價比、負載均衡、隱私保護等特點。我們日常使用的BT下載就是采用P2P讓客戶端之間進行數據傳輸。BT下載是通過BitTorrent協議(一種中心索引式的P2P文件分分析通信協議),讓你在下載其他用戶資源的同時,也為其他用戶提供上傳。所以下載的人越多,可連接到的節點就越多,下載速度就越快。

 

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

 

結語
      通過以上的內容可以發現,組成區塊鏈的這些技術實際上早已有着廣泛的應用,只是我們之前並未那么密切的關注過,而區塊鏈只是將這些技術巧妙的結合到了一起。理解了這些技術的原理后,我們就可以揭開區塊鏈神秘的面紗,去進一步窺探其中的奧秘。
 
參考資料:
《區塊鏈技術指南》  鄒均/張海寧著
Ethereum white paper

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM