區塊鏈2.0架構:以太坊區塊鏈的介紹

chunlin192發表於2018-08-16

比特幣的區塊鏈架構主要圍繞支援虛擬貨幣的實現,雖然它有一定的靈活性,但用來支撐虛擬貨幣以外的應用場景還顯得非常侷限。近年來,區塊鏈逐漸引起IT業界的關注,並逐漸成為獨立於比特幣的一個平臺架構,其重要性越來越受到重視。區塊鏈2.0的概念也隨之產生。其核心理念是把區塊鏈作為一個可程式設計的分散式信用基礎設施,支撐智慧合約應用,以與過去比特幣區塊鏈作為一個虛擬貨幣支撐平臺區別開來。具體說來就是,不僅僅把區塊鏈作為一個去中心化的虛擬貨幣和支付平臺,而是通過增加鏈上的擴充套件性功能,把區塊鏈的技術範圍擴充套件到支撐一個去中心化的市場,交易內容可以包括房產的契約、權益及債務憑證、智慧財產權,甚至汽車、藝術品等。

區塊鏈2.0提供一套新的協議(區塊鏈2.0協議)支撐新型的去中心化應用。如果用網際網路協議來做類比,區塊鏈1.0就相當於TCP/IP協議,而區塊鏈2.0就相當於HTTP、SMTP和FTP等高階協議。甚至有把區塊鏈1.0比做電話,而區塊鏈2.0相當於智慧電話的比喻。在比特幣後,出現很多被稱為區塊鏈2.0的平臺,其中,最具代表性的是以太坊平臺。下面簡單介紹一下以太坊架構。

以太坊的設計主要還是以比特幣架構為基礎。前面幾章已經介紹了以太坊的基本架構,本章不再詳細敘述,下面只對和比特幣架構不同的幾個主要方面做重點討論。以太坊架構圖3-9所示。

1.賬戶設計

比特幣沒有賬戶的概念。每個使用者的餘額都是從他們在區塊鏈上的UTXO計算出來的。以太坊則有兩種型別的賬戶:一種是外部所有賬戶(EOA),另一種是合約(Contract)賬戶。外部所有賬戶就是我們一般意義上的使用者賬戶,它由私鑰控制。合約是一種特殊的可程式設計賬戶,合約存在以太坊區塊鏈上,它是程式碼(它的功能)和資料(它的狀態)的集合。合約受程式碼控制並由外部所有賬戶啟用。

以太坊的設計是將區塊鏈作為一個通用的管理物件狀態轉換的去中心化平臺,賬戶就是有狀態的物件。外部所有賬戶的狀態就是餘額,而合約賬戶的狀態可以是餘額、程式碼執行情況,以及合約的儲存。以太坊網路的狀態就是所有賬戶的狀態,該狀態由每個區塊的交易來更新,同時需在全網形成共識。使用者和以太坊區塊鏈的互動需要通過對賬戶的交易來實現。

每個以太坊的外部所有賬戶由一對金鑰定義,一個是私鑰,一個是公鑰。區塊鏈的EOA賬戶由它們的地址來做索引。取公鑰的後20位作為地址,這和比特幣的地址不一樣。每個公私鑰對被編碼存放在一個金鑰檔案(Keyfile)中。金鑰檔案採用JSON格式,可以用文字編輯器開啟來看。金鑰檔案的私鑰都是用在建立賬戶時輸入的口令來加密的。金鑰檔案存在以太坊節點的資料目錄中的keystore子目錄中。金鑰檔案需要經常備份,否則如果失掉金鑰檔案,賬戶裡的以太幣也就無法找回了。

合約賬戶可以執行圖靈完備的計算任務,也可在合約賬戶之間傳遞訊息,合約編譯成以太坊虛擬機器位元組碼(EthereumVirtual Machine Bytecode),並記錄在區塊鏈上。

外部所有賬戶可以通過傳送交易到合約來實現對合同的呼叫。這需要提供幾個引數,例如EOA的地址、合約的地址,以及資料。資料部分包括需要呼叫的合約裡的方法(method)以及其傳遞的引數。這個需要用到Application Binary Interface(ABI)來作為傳遞資料的編碼和解碼的標準。關於ABI的詳細資訊可以參考以太坊wiki網頁https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI 。

2.區塊鏈設計

比特幣採用Merkle樹來將交易的雜湊值按一定演算法組成二叉樹狀結構 1 ,頂層節點的雜湊值相當於整個交易清單的指紋,可以用來校驗交易清單。中本聰採用Merkle樹設計,也是為了輕量級節點能通過SPV(簡化支付驗證)方式來方便地校驗交易。SPV不用下載整個交易清單,而是隻需要區塊報文頭中交易清單頂層節點的雜湊值,以及與自身節點相關的交易,然後可以通過向其他節點查詢其他相鄰交易,就可以完成對某個交易是否包含在區塊鏈中某個區塊的驗證。 區塊鏈的核心原理 http://www.868qkl.com/shenme/9.html 以太坊的區塊鏈的每個區塊不但儲存著交易清單,還儲存最新的狀態。以太坊作為一個通用的區塊鏈程式設計平臺,引入了賬戶概念,由此它也帶來更為複雜的校驗和查詢需求。例如要查詢賬戶的餘額或判斷一個賬戶是否存在,光用比特幣的Merkle樹就滿足不了要求。因此以太坊採用Merkle Patricia樹來實現對交易和狀態的校驗和查詢 [2] 。下面看看交易和狀態面臨的問題。

以太坊的狀態包含一個鍵值表(key-value map),其中鍵是地址,值是賬戶裡宣告的變數,包括餘額、隨機數(nonce)、程式碼和賬戶的儲存(儲存也以一棵樹的形式來組織)。與交易資料只能增不能改不一樣,賬戶的狀態經常被改變,其餘額、隨機數經常變。

另外,新的賬戶也經常被插入,鍵在儲存裡也被經常插入和刪除。因此Merkle樹不適合這種情況,而需要一種可以在插入、更新和刪除操作後快速計算新的樹根雜湊值,而不需要重新計算整棵樹的資料結構。同時,樹的深度是有限的,即使在有攻擊者試圖通過故意發很多交易來儘量增加樹的深度的情況下,不然一個攻擊者可以通過操縱樹的深度,以使得每個更新都變得非常慢,來對平臺實施拒絕服務攻擊。

還有一個要求是樹的根雜湊只是與樹的資料有關,而與更新的順序無關。不同的更新順序或者甚至重新計算整個樹的根雜湊值都不會改變樹的根雜湊值。Patricia樹是符合這些要求的資料結構。

簡單來說,以太坊的賬戶的狀態由鍵值表(Key-Value Map)來表示,在Patricia樹裡,鍵被編碼成向下訪問樹的路徑。在以太坊的Patricia裡,每個節點有16個子節點,所以路徑用十六進位制來編碼。例如,鍵“dog”的十六進位制編碼是6461567,所以要訪問鍵“dog”所對應的值,就必須先從根節點開始,向下到第6個節點,然後再由該節點向下到第4個節點,以此類推,一直到最後。

在區塊鏈的區塊報文頭中,不像比特幣那樣僅僅存放一個交易清單的Merkle樹根雜湊值,而是存放了3個根雜湊值:一個是交易的Merkle根雜湊值,另外一個是狀態的根雜湊值,還有一個是收據的根雜湊值。 另外一個和比特幣的不同是,以太坊的區塊鏈中的每個區塊儲存區塊鏈號和區塊難度。

3.PoW機制

以太坊的PoW(工作量證明)演算法叫Ethash演算法(是一個經過修改的Dagger-Hashimoto演算法),該演算法主要尋找一個隨機數作為輸入,使得運算結果小於一個特定的難度門檻。PoW機制的前提是,不存在比逐個試更好的找到該隨機數的方法,同時驗證結果必須非常方便且成本小。由於雜湊運算的結果是均勻分佈(Uniform Distribution)的,所以可以保證,通常找到該隨機數的時間取決於難度門檻。這樣的話可以通過控制難度來控制在網路上找到一個新區塊的時間。以太坊是通過動態調控難度來達到平均每15s在全網中找到一個新區塊

的。每15s的“心跳”基本上是全網更新系統狀態的節奏,並保證當攻擊者的計算能力不超過全網的計算能力的一半時,攻擊者無法改寫交易記錄或進行分叉(以便進行雙花交易)

。這就是所謂的“51%”攻擊。網路上的礦工的挖礦收入期望直接反映他們擁有的計算力,或者雜湊速率在整個網路中的佔比。

比特幣的工作量證明機制依靠的僅僅是CPU計算難度問題,以太坊的Ethash工作量證明機制加入記憶體難度,使得它具有抵抗單憑雜湊運算優化的ASIC挖礦機的屬性。記憶體難度是通過

在演算法設計中要求選擇由隨機數和區塊報文頭決定的一部分固定資源,這些資源一般是幾個GB的資料,叫“有向無環圖”(DAG)。每30000個區塊後需要有一個全新的DAG。這相當

於一個125小時的視窗,或5.2天,稱為一個epoch。這個圖需要一段時間才能生成。因為DAG只和區塊鏈深度相關,因此可以提前生成。如果沒有現成的,以太坊的客戶端需要等生成

了DAG後才能產生新的區塊。這樣的話在每個epoch轉換的時候,如果客戶端不預先生成DAG,網路就會出現大規模的延遲。當一個礦工節點第一次啟動時,需要等DAG生成之後才能開

始挖礦。

以太坊的Go語言實現程式geth和C語言實現的挖礦程式ethminer都實現自動DAG生成,並在epoch轉換的過程中維護兩個DAG。以太坊的Ethash演算法可以在較慢的CPU環境中進行雜湊運

算,但在挖礦節點上可以通過增加記憶體和頻寬來提升挖礦速度。對記憶體的高要求使得大型礦的礦主沒有太大的比較性超線性收益;對頻寬的高要求使得用堆超快的計算單元來共享存

儲的方法並不能帶來更好的收益。這樣對礦池挖礦來說沒有太多好處,因此以太坊從設計上希望避免出現像比特幣那樣的礦池算力集中化的問題。

類似比特幣,以太坊的挖礦靜態收益將隨著時間推移而逐漸減少,目前靜態收益是每挖到一個區塊獲得5以太幣。未來礦工的收益將主要依靠傳送交易的使用者支付的“燃料”來獲取

收益。以太坊的礦工獎勵制度比比特幣複雜。很多參考資料沒有給出具體的獎勵數額,有些甚至是錯誤的,例如對挖到“叔區塊”的礦工獎勵的描述,有些資料認為是(7/8)

×5=4.375以太幣,其實這是不準確的。筆者參考了計算獎金的原始碼,具體的獎金機制描述如下。

每當一個礦工挖到一個區塊,他將獲得5.0以太幣(Ether)的靜態收益,同時獲得在區塊上的“燃料”(gas),價值取決於當前的“燃料”價格。另外礦工也獲得一個將“叔區塊

”(uncle)包含進區塊鏈的額外獎勵,相當於每包含一個uncle區塊將獲得(1/32)×5以太幣的收益。而產生“叔區塊”的礦工將按下面的公式獲得獎勵:

挖到“叔區塊”礦工獎勵=(叔區塊ID+8-當前區塊ID)×5/8

例如,假設當前區塊ID是1600,叔區塊ID是1598,那麼挖到叔區塊1598的礦工將獲得(6/8)×5,等於3.75以太幣。如果叔區塊的ID是1599,那麼挖到叔區塊1599的礦工將獲得

(7/8)×5,也就是4.375以太幣的獎勵。

注意:所謂“叔區塊”,是指符合難度條件,但區塊裡的交易不被確認的區塊,或叫“廢塊”(Stale)。比如礦工A挖到一個符合難度規定的合規區塊a,而幾乎同時礦工B也挖到符

合標準的區塊b,但由於網路延遲,區塊b沒有被確認,成了廢塊,而a成了網路共識的區塊,被包括在區塊鏈中。由於以太坊產生區塊的速度比比特幣產生區塊的速度要快很多,因

此在網路繁忙的時候,相對於比特幣系統更容易出現“廢塊”。在比特幣系統中,生產廢塊的礦工只能自認倒黴,是沒有獎勵的。而在以太坊中,產生“叔區塊”的礦工和將“叔區

塊”包括在區塊鏈上的礦工都能得到獎勵。這樣產生廢塊的算力也被包括進來,有效地增強了安全性,使得攻擊者不容易追上一個帶“叔區塊”的主鏈。同時通過給“叔區塊”獎勵

,也避免出現像比特幣那樣計算力高度集中的礦池,因為礦池相對來說不像單個挖礦節點那樣容易產生廢塊。嚴格說來,“叔區塊”是在當前連結區塊往前推最多6個的“祖先”廢

塊,每個區塊最多能連結兩個“叔區塊”。

以太坊採用一個與比特幣不同的演算法叫GHOST(幽靈)來構建區塊鏈。GHOST的全稱是Greedy Heaviest Observed Subtree,中文直譯是“貪婪最重觀察子樹”。嚴格來說,以太坊的

區塊鏈不是一個鏈條,而像一棵樹,它包含前面提到的“叔區塊”。

在比特幣系統中,礦工按一定的優先順序把未確認的交易打包到新發現的區塊上。交易的優先順序按交易額和鏈齡(指UTXO存在的時間)來決定。交易額越大、鏈齡越高,優先順序就越高

。交易費用是使用者的輸入和輸出之差。如果輸入和輸出之差為零,隨著交易發生的時間越來越久,其在交易池的優先順序會逐漸升高。因此一般來說,即使付給礦工零交易費用的交易

都有機會被礦工包含在區塊鏈上。當然個別礦工可以有自己的規則,可以拒絕零交易費的交易。而在以太坊平臺,不提供“燃料”的交易不會被執行,也不會被包含在區塊鏈上。以

太坊的交易費用按以下公式計算:

Total cost=gasUsed×gasPrice

其中gasUsed是執行該交易所消耗的燃料,燃料的價格由使用者和礦工決定,一般來說在使用者建一個交易的時候,可以提一個燃料價格。在以太坊釋出的第一版本Frontier(前線)中

,以太坊客戶端的預設燃料價格是0.05e12wei,大約是一億分之五個以太幣。礦工一般不會接受低於普遍價的燃料價格。

4.計算和圖靈完備

以太坊作為通用的區塊鏈平臺,需要提供比比特幣更強大的計算能力。前面說過,從安全形度出發,比特幣的設計專門選擇一個不具圖靈完備性的指令碼引擎,目前能通行的比特幣腳

本指令也不多,但在虛擬貨幣的應用場景已經是綽綽有餘了。而在以太坊上,一個和比特幣非常大的不同點就是選擇了圖靈完備的計算環境——以太坊虛擬機器(EVM)。這就意味著

在EVM上可以做所有的能想得到計算,包括無限迴圈。EVM指令包括一個JUMP的跳轉指令,可讓程式跳回前面的程式程式碼,也可以像條件判斷語句那樣做條件跳轉,當滿足一定條件時

將程式跳轉到另一個地方執行。另外,一個合約可以呼叫其他合約,這提供了潛在的遞迴呼叫的功能。這就很自然地會導致一個問題:一個搞破壞的使用者能否通過強制礦工或全節點

進入死迴圈而將他們基本關掉呢?這個其實也是一個“停機問題”,也就是說,通常沒有任何辦法去判定一個程式會否停機。以太坊怎麼解決這個問題呢?它首先要求每個交易要給

出最大的計算步驟,交易的發起人要提供Gas作為交易費以供礦工把交易加進區塊。如果實際執行超過了該最大計算步驟,計算將被終止,而交易費會歸挖到區塊的礦工所有。因此

以太坊採用經濟的方法來保證以太坊平臺的安全。

以太坊網路的每個節點都執行EVM並執行合約程式碼,因此以太坊就像一個並行執行的“世界電腦”,在所有的節點上同時進行賬戶的狀態轉換,並形成網路層面對所有賬戶狀態的共

識。雖然這種P2P的執行方式並不是最高效的,但卻是最有安全保障的,可以說,這部“世界電腦”永不停機。

5.EVM高階語言

比特幣不提供高階語言的支援,以太坊則提供高階語言讓使用者編寫智慧合約。以太坊的高階語言最後會編譯成在EVM中執行的EVM位元組碼(bytecode),部署在以太坊區塊鏈上。以太

坊提供3種程式語言:Solidity、Serpent和LLL。

·Solidity類似JavaScript語言,是目前以太坊上最流行的智慧合約程式語言。

·Serpent類似Python程式語言,它結合了低階語言的效率和易用的程式設計方式。Serpent用LLL語言來編譯。

·LLL是Lisp Like Language的簡稱,顧名思義是一個像Lisp的語言。它有些像組合語言,設計得非常簡約,基本上就是在EVM上的一個微小的封裝。

另外一個類似C的語言Mutan已經基本棄用,不再被維護。

6.以太坊P2P網路

(1)RLPx協議

以太坊網路節點間的通訊採用DΞVp2p線上協議。節點間採用RPLx [3] 編碼及認證的通訊傳輸協議來傳輸訊息包,即提供傳送和接收訊息的協議功能。節點可以自由地在任何TCP端

口釋出和接受連線,預設的埠是30303。目前正式版的RLPx實現了以下功能:

·單一協議的UDP節點發現

·ECDSA簽名的UDP

·加密握手/認證

·節點永續性

·加密/認證TCP

·TCP幀處理

相關文章