官术网_书友最值得收藏!

2.4 區(qū)塊鏈運行機制

比特幣作為一種新型的數(shù)字貨幣,其發(fā)行、所有權(quán)證明、存儲和安全性等各種問題,均是通過區(qū)塊鏈這個底層技術(shù)得以可靠運行至今。現(xiàn)在的很多區(qū)塊鏈應用都借鑒了比特幣區(qū)塊鏈網(wǎng)絡(luò)中的一些設(shè)置。下面以比特幣為例,介紹區(qū)塊鏈的基本原理和運行機制。

2.4.1 區(qū)塊結(jié)構(gòu)

每個數(shù)據(jù)區(qū)塊包含區(qū)塊頭和區(qū)塊體。區(qū)塊頭封裝了當前版本號、前一區(qū)塊哈希值、當前區(qū)塊PoW要求的隨機數(shù)(nonce)、時間戳以及Merkle根信息。區(qū)塊體則包括當前區(qū)塊經(jīng)過驗證的、區(qū)塊創(chuàng)建過程中生成的所有交易記錄,這些記錄通過Merkle樹的哈希過程生成唯一的Merkle根并記入?yún)^(qū)塊頭。下面分別詳細介紹Merkle樹和區(qū)塊的組成。

1. Merkle樹

Merkle樹,又被翻譯為默克爾樹,也被稱為Merkle Hash Tree,因為樹中的每個節(jié)點存儲的都是哈希值。Merkle樹可以是二叉樹或多叉樹,根據(jù)實際需要決定。

一個區(qū)塊需要攜帶的交易信息實際上是一個很大的值,如果存儲這些原始信息要求更多的存儲空間,具體應用中并不劃算。Merkle樹提供了一種更簡易的表示方式,不僅使得用較小的存儲空間容納更多的數(shù)據(jù)信息成為可能,實現(xiàn)了交易信息的快速歸納,而且提供了利用部分交易的哈希值就能夠驗證全部交易的方法。同時利用哈希的形式表示提高了安全性,某個交易中,哪怕只更改了一個小數(shù)點,最后展現(xiàn)出來的Merkle根也是完全不一樣的。以比特幣網(wǎng)絡(luò)中的區(qū)塊鏈為例,Merkle樹被用來歸納一個區(qū)塊的所有交易信息,具體結(jié)構(gòu)如圖2-16所示。

如圖2-16所示,Merkle樹按層歸納交易信息。葉子節(jié)點通過對交易信息進行哈希運算,獲得交易的哈希值。兩個不同的交易哈希進行二次哈希,生成中間節(jié)點。逐層往上,遞歸地對節(jié)點進行哈希運算,最終獲得將所有交易信息的哈希值放入Merkle根節(jié)點,存儲在區(qū)塊頭中,無論交易數(shù)量,最終的交易信息都只占據(jù)32字節(jié)。

具體的流程大致可描述如下:

(1)將未包含在之前區(qū)塊中的未存儲在Merkle樹中的交易數(shù)據(jù)進行哈希,將哈希值存儲在相應的葉子節(jié)點中:

H~A~=SHA-256(SHA-256(交易A))

(2)串聯(lián)相鄰的葉子節(jié)點的哈希值,再進行哈希。這些節(jié)點就被歸納為父節(jié)點。

H~AB~=SHA-256(SHA-256(H~A~+H~B~))

圖2-16 Merkle樹結(jié)構(gòu)示意圖

(3)遞歸完成類似過程。

(4)直到最后只剩下頂部一個節(jié)點,即Merkle根部節(jié)點,將其存儲在區(qū)塊頭。

Merkle樹的存儲結(jié)構(gòu)在另一方面也簡化了驗證特定交易的流程,大幅度提升了驗證速度。如圖2-17所示,節(jié)點只需要下載區(qū)塊頭,然后通過驗證該特定交易到Merkle根的路徑的哈希值,即可完成特定交易的驗證。例如節(jié)點需要驗證交易K的相關(guān)信息,節(jié)點只需要下載HK、HL、HIJ、HKL、HIJKL、HMNOP、HIJKLMNOP、HABCDEFGH和Merkle根的哈希值。如果不使用Merkle樹結(jié)構(gòu),即使存儲的均為哈希序列,也需要獲取全部的交易信息,對所有交易進行遍歷,而這些交易信息可能就有幾個G的大小。Merkle樹結(jié)構(gòu)只需要計算log2N個32字節(jié)的哈希值即可完成特定交易的驗證,這種驗證方法又被稱作簡單支付驗證(SPV)。

圖2-17 Merkle樹結(jié)構(gòu)圖

2. 區(qū)塊結(jié)構(gòu)

區(qū)塊鏈的基本組成單位是區(qū)塊,區(qū)塊類似于賬本中的賬頁。以比特幣為例,一個區(qū)塊可以看作由兩部分組成,包含基礎(chǔ)字段信息的區(qū)塊頭和跟在區(qū)塊頭之后的一長串存儲為Merkle樹形式的交易數(shù)據(jù),如圖2-18所示。

圖2-18 區(qū)塊字段示意圖

除過區(qū)塊頭和交易信息,區(qū)塊中還包含表明該區(qū)塊大小的字段、記錄交易數(shù)量的交易計數(shù)器。具體表示如表2-4所示。

表2-4 區(qū)塊結(jié)構(gòu)

區(qū)塊頭是一個區(qū)塊中最重要的部分。主要包括版本信息字段、父區(qū)塊哈希值、Merkle樹根、時間戳、難度目標和nonce值。

(1)版本信息標識了該區(qū)塊中交易的版本和所參照的規(guī)則。

(2)父區(qū)塊哈希值實現(xiàn)了區(qū)塊數(shù)據(jù)間的鏈狀連接。

(3)Merkle樹的根值實現(xiàn)了將區(qū)塊中所有交易信息逐層成對地整合歸納,最終通過一個哈希值將所有信息包含在區(qū)塊頭中。

(4)時間戳以UNIX紀元時間編碼,即自1970年1月1日0時到當下總共流逝的秒數(shù)。

(5)難度目標定義了礦工需要進行挖礦的工作量證明的難度值,根據(jù)實際新區(qū)塊挖掘出的速度,難度目標值會進行調(diào)整,最終保證平均10min出一個新區(qū)塊。

(6)nonce是一個隨機值,初始值為0,礦工挖礦就是找到一合適的nonce值,使得區(qū)塊頭的哈希值小于難度目標。

區(qū)塊主體中主要存儲交易信息,礦工將經(jīng)過全網(wǎng)驗證的交易通過Merkle樹的方式表示。如圖2-18所示,假設(shè)有8筆交易,分別為交易1、交易2、…、交易8,Merkle樹首先對交易內(nèi)容進行哈希計算,每筆交易得出對應的哈希值,然后再對交易哈希值進行兩個一組的哈希計算,以此類推,最后的哈希值就是存儲在區(qū)塊頭中的Merkle根。Merkle根通過哈希計算的方式實現(xiàn)了對區(qū)塊中所有交易記錄的有效總結(jié)。另外,根據(jù)哈希運算的特性,Merkle根能夠快速驗證交易數(shù)據(jù)的完整性和準確性,只要有人對其中一筆交易進行了篡改,哪怕只有一個小數(shù)點,Merkle根便會直觀地顯示出來。

2.4.2 區(qū)塊產(chǎn)生

比特幣作為一種P2P形式的去中心化數(shù)字貨幣,并不依靠特定的貨幣機構(gòu)發(fā)行,而是通過特定的算法實現(xiàn)了一套去中心化的發(fā)行機制。比特幣只能通過礦工的挖礦行為產(chǎn)生,系統(tǒng)通過將比特幣作為獎勵激勵礦工參與記賬,挖掘產(chǎn)生新的區(qū)塊。區(qū)塊頭中的難度目標、時間戳和nonce字段與礦工之間的挖礦競爭息息相關(guān)。

挖礦的過程是找到一個使整個區(qū)塊的哈希值能夠小于區(qū)塊頭中難度目標的理想nonce值,通過不斷重復試驗nonce值的過程被稱作工作量證明,簡要表示為:

    {
    if Hash(區(qū)塊頭)<難度目標
    挖礦成功;
    else
    nonce+1;
    }

難度目標是一個動態(tài)值,系統(tǒng)根據(jù)新區(qū)塊的產(chǎn)生速度進行調(diào)節(jié),理想目標是平均10分鐘產(chǎn)生一個新區(qū)塊。但實際上系統(tǒng)并不是每次產(chǎn)生新區(qū)塊后都要對生成速度進行瞬時調(diào)整,而是將最新生成的2016個區(qū)塊的花費時長與20 160分鐘(理想平均10分鐘產(chǎn)生一個新區(qū)塊的總時間)進行比較。根據(jù)實際時長和期望時長的比值,系統(tǒng)會決定是否進行難度調(diào)整。為了防止難度目標變換過快,每個周期的調(diào)整幅度必須小于一個固定因子,一般設(shè)定為4,當比較值大于4時,就按照4倍進行調(diào)整,進一步的調(diào)整會在下一個周期完成。

New Difficulty=Old Difficulty?(Actual Time of Last 2016 Blocks/20160 minutes)

一個新區(qū)塊的產(chǎn)生時間取決于礦工的算力,隨著礦工算力的日益增長,出塊的難度也會日益增加,最終目的都是保證平均10分鐘一塊的出塊速度。而難度是對礦工挖礦困難程度的一種度量。目標是一個256位的數(shù)值,難度的計算公式為:

difficulty=difficulty_1_target/current_target

difficulty_1_target=

0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

difficulty_1_target為定值,由此能夠計算出不同目標哈希實際區(qū)塊的產(chǎn)生難度。

從另一方面來說,哈希值是由數(shù)字和大小字母組成的字符串,每一位都有62種可能性。每種字符出現(xiàn)的概率是相等的,那么第一位出現(xiàn)0的概率為1/62,理論上需要嘗試62次哈希運算才會出現(xiàn)理想的結(jié)果。如果前兩位均為0,那么需要進行622次嘗試,前n位為0,則需要62n次嘗試。隨著前n位0的個數(shù)的增加,難度目標的越來越小,而難度隨之增加。類似于擲骰子,目標為6時,投擲出的點數(shù)有5/6的可能滿足小于點數(shù)的條件;當目標為2時,只有1/6的概率滿足條件。

依據(jù)現(xiàn)在比特幣網(wǎng)絡(luò)的難度,礦工至少需要嘗試1015次,才能找到一個合適的nonce值,使得目標區(qū)塊的哈希符合條件。從現(xiàn)在的挖礦市場來看,更多的算力被大型礦池公司所壟斷,以個人為單位的礦工基本不可能贏得這場競爭。

2.4.3 區(qū)塊連接

在比特幣區(qū)塊鏈網(wǎng)絡(luò)中,每一個區(qū)塊都在區(qū)塊頭中存儲了父區(qū)塊哈希值字段,父區(qū)塊哈希由對前一個區(qū)塊的區(qū)塊頭數(shù)據(jù)進行哈希運算得出,新區(qū)塊通過父哈希和現(xiàn)在網(wǎng)絡(luò)中的主鏈進行連接。區(qū)塊間通過父區(qū)塊哈希字段實現(xiàn)了區(qū)塊間的鏈狀結(jié)構(gòu),區(qū)塊間的這種數(shù)據(jù)結(jié)構(gòu)也被稱為區(qū)塊鏈。

按照平均10分鐘產(chǎn)生一個新區(qū)塊的速度,礦工從交易池中選取未被主鏈包含的交易記錄通過Merkle樹的形式進行打包存儲,不同礦工產(chǎn)生的新區(qū)塊中包含的交易記錄可能會存在差異,但這些交易記錄均為未被全網(wǎng)承認的待確認交易。

當?shù)V工成功得出新區(qū)塊的nonce值,會將新區(qū)塊向全網(wǎng)廣播,每個節(jié)點都會對新區(qū)塊的內(nèi)容進行獨立校驗,確認無誤后會將新區(qū)塊組裝進節(jié)點現(xiàn)在存儲的區(qū)塊鏈中。

節(jié)點會查看新區(qū)塊的父哈希字段,從已存在的區(qū)塊鏈中找出父區(qū)塊。如果已存在的區(qū)塊中找不到父區(qū)塊,那該類新區(qū)塊會被當作孤塊存儲在孤塊池中,直到找到它的父區(qū)塊,或者因為孤塊池中的存儲飽和被節(jié)點隨機丟棄。當相鄰的兩個區(qū)塊在很短的時間內(nèi)被挖掘出來,一些節(jié)點因為距離原因首先收到子區(qū)塊,那么新區(qū)塊就會被投入到孤塊池中。

礦工挖掘的新塊如果未能被成功納入主區(qū)塊鏈,那么就不會得到系統(tǒng)提供的挖礦獎勵。因此在算力競爭中,如果有兩個區(qū)塊幾乎在同一時間被挖掘出來,那么此時起到?jīng)Q定性作用的就是區(qū)塊的傳播速度。一般情況下,具有較多節(jié)點連接的區(qū)塊所挖掘的新區(qū)塊有更大的概率獲得勝利,從而能夠?qū)崿F(xiàn)讓下一個區(qū)塊接續(xù)在自己的區(qū)塊之后,獲得系統(tǒng)的挖礦獎勵。

TradeBlock曾對此做過一項調(diào)研分析(TradeBlock,主要提供數(shù)字貨幣區(qū)塊鏈數(shù)據(jù)挖掘和研究分析),如圖2-19所示。在2015.04.23~2015.06.10,平均每天產(chǎn)生1%的孤塊,即有約為1%的孤塊率。而對于產(chǎn)生孤塊的比較典型的原因是由于礦工節(jié)點連接的節(jié)點數(shù)目較少,當全網(wǎng)活躍的比特幣節(jié)點大約有6000個時,只要連接節(jié)點達到3000個,那么一個新區(qū)塊贏得孤塊競賽的概率為90%。似乎在孤塊競賽中獲得成功的區(qū)塊通常是第一個被廣播到全網(wǎng)的。

圖2-19 TradeBlock網(wǎng)站截圖

在調(diào)查中同時發(fā)現(xiàn),區(qū)塊的傳播速度和容納的交易數(shù)量成負相關(guān)。這很容易理解,每個接收到新區(qū)塊的節(jié)點都需要獨立對區(qū)塊進行校驗。但就交易記錄,節(jié)點需要將新區(qū)塊中包含的交易記錄和自身交易池中存儲的交易記錄進行對比,那么一旦區(qū)塊中的交易數(shù)量越多,除了會延長數(shù)據(jù)傳播的時間,還會因為每筆交易在網(wǎng)絡(luò)中的跳動花費更多的時間。在連接相同節(jié)點數(shù)量的情況下,區(qū)塊大小和傳播時間存在直接關(guān)系。一個700KB的區(qū)塊傳播需要17s,但是200KB的區(qū)塊傳播只需要6s,所以礦工可能為了降低挖礦收益的風險,選擇在相同區(qū)塊容積下打包更少的交易。這種風險同時提醒比特幣或其他區(qū)塊鏈應用的社區(qū)在面對擴容問題的時候,不能只將期望值放在擴充區(qū)塊容積上,而是需要更多其他的方法和思路。

2.4.4 區(qū)塊傳播

通過coinbase的獎勵機制,比特幣實現(xiàn)了節(jié)點自發(fā)保持實時在線的狀態(tài)去完成記賬工作。但是賬本儲存在每個節(jié)點中,去中心化需要保證每個節(jié)點中的數(shù)據(jù)一致,需要防止某些被篡改的惡意賬本影響整個網(wǎng)絡(luò)的交易。因此礦工成功算得工作量證明解后,需要將區(qū)塊內(nèi)容進行全網(wǎng)廣播,只有獲得其他礦工節(jié)點的驗證通過后,新挖掘的區(qū)塊才能加入?yún)^(qū)塊鏈。同時每個節(jié)點都會獨立地對新區(qū)塊進行校驗,如果區(qū)塊中包含無效信息,該節(jié)點就會將該區(qū)塊丟棄,各節(jié)點的獨立校驗會確保只有有效的區(qū)塊內(nèi)容才能在網(wǎng)絡(luò)進行傳播,不會造成資源的浪費。

基于比特幣采用的P2P分布式網(wǎng)絡(luò)協(xié)議,臨近節(jié)點會首先接收到廣播信息。當節(jié)點接收到新區(qū)塊后,會依照驗證標準對所有字段信息進行驗證。驗證內(nèi)容包括:

(1)區(qū)塊數(shù)據(jù)結(jié)構(gòu)的有效性。

(2)區(qū)塊大小和各字段有效長度的合法性,在長度限制要求之內(nèi)。

(3)是否擁有正確的nonce值,區(qū)塊頭的哈希值需滿足當前目標值。

(4)驗證區(qū)塊頭中的MerkleRoot是否由區(qū)塊交易得到,根據(jù)區(qū)塊交易數(shù)據(jù)進行Merkle樹重構(gòu),需與區(qū)塊數(shù)據(jù)中保持一致。

(5)對時間戳顯示時間進行校驗。

(6)區(qū)塊的第一個交易為coinbase交易,其他交易都不是。

(7)遍歷區(qū)塊中所有交易,檢查交易的合法性。

以上校驗標準可以從比特幣核心客戶端的CheckBlock函數(shù)中獲得,源代碼如下:

只有當上述所有標準都確保無誤,鄰近節(jié)點才會繼續(xù)新區(qū)塊的傳播行為,最終直到全網(wǎng)大部分節(jié)點接收新區(qū)塊的信息。

2.4.5 最長鏈原則

比特幣區(qū)塊是依靠礦工們不斷進行數(shù)學運算而產(chǎn)生的,每個區(qū)塊都必須引用其上一個區(qū)塊,因此最長的鏈也是最難以推翻和篡改的,所以節(jié)點永遠認為最長鏈才是有效的區(qū)塊鏈,只有在最長鏈上挖礦的礦工才能夠獲得獎勵,即比特幣最長鏈原則。

1. 區(qū)塊的選擇

對于比特幣區(qū)塊鏈生態(tài)系統(tǒng)而言,網(wǎng)絡(luò)允許任何人都可以進行數(shù)據(jù)的讀取和寫入,參與者不需要經(jīng)過審查和批準就能夠進行比特幣交易和新區(qū)塊的挖掘開發(fā)。而在沒有第三方機構(gòu)的控制評定下,比特幣網(wǎng)絡(luò)在面對可能出現(xiàn)的差異時,需要能夠進行仲裁的方法。

在所有礦工參與的挖掘新區(qū)塊的算力競爭中,可能會出現(xiàn)兩名礦工在較短的時間差內(nèi),在幾乎相同的時間算得同一新區(qū)塊的工作量證明解,并各自向全網(wǎng)廣播,將新區(qū)塊傳播給相鄰節(jié)點。其余節(jié)點會率先驗證接收到區(qū)塊信息。通常將未被全網(wǎng)承認的但已經(jīng)傳播的區(qū)塊稱為候選區(qū)塊。結(jié)果會造成一些節(jié)點收到一個候選區(qū)塊,而另一些節(jié)點收到了另一個候選區(qū)塊,這兩個候選區(qū)塊可能包含的交易大致相同,只是在交易順序上有些不同。這時網(wǎng)絡(luò)中就會出現(xiàn)兩個不同版本的區(qū)塊鏈,即區(qū)塊鏈分叉,大致如圖2-20所示。

區(qū)塊鏈網(wǎng)絡(luò)需要在沒有第三方干涉的情況下,對類似分叉的這種可能出現(xiàn)的差異情況進行判定。比特幣網(wǎng)絡(luò)中按照最長鏈原則解決此類問題,因為總有一方能夠搶先發(fā)現(xiàn)新的工作量證明解并傳播出去,所有節(jié)點會統(tǒng)一接收更長的鏈,在已經(jīng)分叉的情況下重新達成共識。最長鏈指的是該條鏈累計的工作量證明最大,一般情況下,也是包含最多區(qū)塊的鏈條,這條最長的區(qū)塊鏈通常被稱為“主鏈”。在比特幣主鏈上其實也存在著分支,這些分支被當作備用鏈,如果新添加的區(qū)塊使備用鏈累積了更多的工作量,那么這條備用鏈將被作為新的主鏈。實際上,去中心化程度越高的區(qū)塊鏈因為開放程度高,允許任何人對區(qū)塊數(shù)據(jù)進行寫入和讀取,引起分叉的風險就越大。

圖2-20 區(qū)塊鏈分叉示意圖

2. 區(qū)塊的組裝

節(jié)點接收到新的區(qū)塊數(shù)據(jù),需要將新區(qū)塊和原本的區(qū)塊鏈數(shù)據(jù)進行組裝,區(qū)塊間通過區(qū)塊頭的父哈希字段實現(xiàn)鏈狀連接。

通過驗證的區(qū)塊,節(jié)點會根據(jù)新區(qū)塊的父哈希字段,在已有的區(qū)塊中找尋其父區(qū)塊。在大多數(shù)情況下,這個父區(qū)塊都是主區(qū)塊鏈的最后一個區(qū)塊,即頂點區(qū)塊,這樣新區(qū)塊就實現(xiàn)了對原本區(qū)塊鏈的延長。但有時候,新區(qū)塊也有可能延長了備用鏈,此時根據(jù)最長鏈原則,比較現(xiàn)有的主區(qū)塊鏈和備用鏈的工作量難度,如果備用鏈累計的工作量證明更大或難度更高,那么節(jié)點將收斂于備用鏈,備用鏈會成為新的主區(qū)塊鏈,現(xiàn)有的主區(qū)塊鏈則變?yōu)閭溆面湥环駝t保留原有的區(qū)塊鏈為主鏈;如果出現(xiàn)節(jié)點現(xiàn)有的區(qū)塊信息中沒有收到的新有效區(qū)塊的父區(qū)塊的信息,那么該區(qū)塊就會被保存在孤塊池中,直到它的父區(qū)塊被找到。

例如圖2-21所示,當有兩名礦工在幾乎同時都求得了工作量證明解,立即傳播他們的新區(qū)塊(分別是#3458和#3458')到網(wǎng)絡(luò)中。當這兩個區(qū)塊傳播時,一些節(jié)點首先收到#3458,一些節(jié)點首先收到#3458',這兩個候選區(qū)塊(通常這兩個候選區(qū)塊會包含幾乎相同的交易)都是主鏈的延伸,就會分叉出有競爭關(guān)系的兩條鏈。收到#3458區(qū)塊的挖礦節(jié)點會立刻以這個區(qū)塊為父區(qū)塊來產(chǎn)生新的候選區(qū)塊#3459。同樣,收到#3458'區(qū)塊的挖礦節(jié)點也會以這個區(qū)塊為父區(qū)塊開始生成新的候選區(qū)塊#3459'。假設(shè)以#3458'為父區(qū)塊的工作量證明首先解出,即新區(qū)塊#3459'先被廣播,當原本以#3458為父區(qū)塊求解的節(jié)點在收到#3458'和#3459'之后,會立刻將該鏈作為主鏈(因為#3458那條鏈已經(jīng)不是最長鏈了)繼續(xù)挖礦。節(jié)點也有可能先收到其他節(jié)點發(fā)來的#3459",再收到#3458",收到#3459"時,會被認為是“孤塊”(因為還找不到#3459"的父區(qū)塊#3458")保存在孤塊池中,一旦收到父塊#3458"時,節(jié)點就會將孤塊從孤塊池中取出,并且連接到它的父區(qū)塊,讓它作為區(qū)塊鏈的一部分。

無論哪種情況,節(jié)點選擇都是當前工作量證明最大、難度累計最多的鏈,所有節(jié)點最終會在全網(wǎng)范圍內(nèi)達成共識,暫時性差異也會得到解決。比特幣將區(qū)塊間隔設(shè)計為10分鐘,是在更快速的交易確認和更低的分叉概率間做出的妥協(xié)。更短的區(qū)塊產(chǎn)生間隔會讓交易確認更快地完成,也會導致更加頻繁的區(qū)塊鏈分叉。與之相對地,長的間隔會減少分叉數(shù)量,卻會導致更長的確認時間。

圖2-21 區(qū)塊的組裝

主站蜘蛛池模板: 友谊县| 商丘市| 永宁县| 如东县| 双流县| 马龙县| 白河县| 嘉黎县| 昭苏县| 长汀县| 长泰县| 汶川县| 双鸭山市| 竹北市| 恩施市| 若羌县| 温泉县| 曲周县| 射洪县| 永清县| 留坝县| 舒城县| 曲松县| 邯郸县| 衡山县| 谢通门县| 达日县| 邯郸市| 托里县| 巫溪县| 东辽县| 安达市| 高平市| 民勤县| 南丹县| 日照市| 蓬溪县| 房产| 龙川县| 綦江县| 黄梅县|