希望屏幕面前的你在閱讀之后能明白默克爾樹到底是什么,以及它在以太坊中的作用;能理解“世界狀態(tài)”和“賬戶狀態(tài)”的概念;能在腦海中勾勒出交易以及區(qū)塊的結(jié)構(gòu)。
默克爾樹
在討論以太坊的主要數(shù)據(jù)對象之前,我想先向各位簡要介紹一下默爾克樹到底是什么,以使得它得以發(fā)揮作用的屬性特征。
黃皮書中假設(shè)由定制的默克爾-帕特里夏樹維護世界狀態(tài)和交易。附錄 D 描述了這個數(shù)據(jù)結(jié)構(gòu)。
默克爾-帕特里夏樹有許多有意思的屬性,如果你想更深入地了解其在以太坊中的應(yīng)用,我推薦你閱讀這篇文章。
在默克爾樹中,由葉子節(jié)點保存區(qū)塊數(shù)據(jù)的哈希,而由非葉子節(jié)點保存其子節(jié)點的哈希。
-默克爾樹示意圖(包括節(jié)點以及他們之間的關(guān)系)-
默克爾樹所指向數(shù)據(jù)的任何改動都會引起節(jié)點哈希的變化。由于每一個父節(jié)點中所保存的哈希值都取決于子節(jié)點所包含的數(shù)據(jù),所以子節(jié)點中數(shù)據(jù)的變更都會引起父節(jié)點哈希的變化。并且這樣的影響是連鎖反應(yīng),從葉子節(jié)點直達根節(jié)點的。因此對葉子節(jié)點所指向數(shù)據(jù)的改動會引起根節(jié)點所保存哈希的變化。由上述結(jié)構(gòu)特征,我們可以引申出兩條重要的屬性:
1. 在判斷兩棵默克爾樹所指向數(shù)據(jù)是否完全相同時,我們不需要比較每個葉子節(jié)點,而只需比較根節(jié)點所保存的哈希。
2. 在判斷特定數(shù)據(jù)是否被樹所指向時,我們可以使用 默克爾證明 技術(shù)。此處不對該技術(shù)作過多介紹,只需知道這是證明數(shù)據(jù)存在于默克爾樹中的一種簡單、高效的方法。
第一種屬性的重要之處在于,我們能夠僅利用根節(jié)點的哈希值,就標(biāo)示某一時刻整棵樹所指向的數(shù)據(jù)。這意味著僅通過保存根節(jié)點的哈希值就能標(biāo)示區(qū)塊(無需儲存區(qū)塊鏈中所有的數(shù)據(jù)),且維護數(shù)據(jù)的不可篡改。
至此我們理清了默克爾樹中根節(jié)點哈希的作用,下面來介紹以太坊中的主要對象。
世界狀態(tài)
世界狀態(tài)是地址(賬戶)到賬戶狀態(tài)的映射。雖然世界狀態(tài)不保存在區(qū)塊鏈上,但在黃皮書的描述中,世界狀態(tài)也由樹來保存數(shù)據(jù)(此樹也被稱為狀態(tài)數(shù)據(jù)庫或者狀態(tài)樹)。世界狀態(tài)可以被視作為隨著交易的執(zhí)行而持續(xù)更新的全局狀態(tài)。以太坊就像一個去中心化的計算機,世界狀態(tài)則是這臺電腦的硬盤。
以太坊中所有的賬戶信息都體現(xiàn)在世界狀態(tài)之中,并由世界狀態(tài)樹保存。如果你想知道某一賬戶的余額,或者某智能合約當(dāng)前的狀態(tài),就需要通過查詢世界狀態(tài)樹來獲取該賬戶的具體狀態(tài)信息。下文中我也會簡要介紹這些信息是如何存儲的。
-世界狀態(tài)樹與賬戶存儲-
賬戶狀態(tài)
以太坊中有兩種賬戶類型:外部所有賬戶(Externally Owned Accounts 簡稱 EOA)以及合約賬戶。我們用來互相收發(fā)以太幣、部署智能合約的賬戶就是 EOA 賬戶,而部署智能合約時自動生成的賬戶則是合約賬戶。每一個智能合約都有其獨一無二的以太坊賬戶。
賬戶狀態(tài)反映了一個以太坊賬戶的各項信息。例如,它存儲了當(dāng)前賬戶以太幣的余額信息、當(dāng)前賬戶發(fā)送過的交易數(shù)量。..每一個賬戶都有賬戶狀態(tài)。
下面就來看看賬戶狀態(tài)中都包括什么:
nonce
從此地址發(fā)送出去的交易數(shù)量(如果當(dāng)前為 EOA 賬戶)或者此賬號產(chǎn)生的合約創(chuàng)建操作(現(xiàn)在先別管合約創(chuàng)建操作是什么)。
balance
此賬號所擁有的以太幣數(shù)量(以 Wei 計量)。
storageRoot
賬戶存儲樹的根節(jié)點哈希值(稍后介紹賬戶存儲是什么)。
codeHash
對于合約賬戶,就是此賬戶存儲 EVM 代碼的哈希值。對于 EOA 賬戶,此處留空。
賬戶狀態(tài)中不容忽視的一個細節(jié)是,上述對象在內(nèi)的所有對象都可變(除了 codeHash)。舉例來說,當(dāng)一個賬戶向其他賬戶發(fā)送以太幣時,除了 nonce 會增加,賬戶的余額也會相應(yīng)改變。
而 codeHash 的不可變性使得,如果部署了有漏洞的智能合約,也無法修復(fù)更新此合約。對應(yīng)的,只能部署一個新合約(而有漏洞的版本會一直存在于區(qū)塊鏈上)。這也是為什么使用 Truffle 進行智能合約的開發(fā)和部署十分必要,并且用 Solidity 編程時要遵循 最佳實踐 的要求。
賬戶存儲樹是保存與賬戶相關(guān)聯(lián)數(shù)據(jù)的結(jié)構(gòu)。該項只有合約賬戶才有,而在 EOA 中, storageRoot 留空、 codeHash 則是一串空字符串的哈希值。所有智能合約的數(shù)據(jù)都以 32 字節(jié)映射的形式保存在賬戶存儲樹中。此處不再贅述賬戶狀態(tài)樹如何維持合約數(shù)據(jù)。賬戶狀態(tài)中的 storageRoot 區(qū)域負責(zé)維持賬戶存儲樹根節(jié)點哈希值。
-賬戶狀態(tài)與賬戶存儲樹-
交易
交易推動當(dāng)前狀態(tài)到下一狀態(tài)的轉(zhuǎn)變。在以太坊中有三種交易:
1. EOA 之間傳輸值的交易(例如,改變發(fā)送方和接收方余額大?。?。
2. 發(fā)送消息來調(diào)用合約的交易(例如,通過發(fā)送消息調(diào)用來觸發(fā) setter 方法,以設(shè)置合約中的值)。
3. 用于部署合約的交易(由此創(chuàng)建了合約賬戶)。
(從技術(shù)角度來講,前兩種交易是一樣的。..它們都是通過消息調(diào)用來改變賬戶狀態(tài)的交易,只不過一個是 EOA 賬戶,一個是合約賬戶。此處將交易分為三種是為了方便讀者的理解。)
交易由以下部分組成:
nonce
此賬戶發(fā)出的交易序號數(shù)(校對注:可以粗略理解為“這是該賬戶的第幾筆交易”)。
gasPrice
執(zhí)行此交易、進行計算時為每單位 gas 所支付的費用(以 Wei 計量)。
gasLimit
執(zhí)行此交易時可以使用的最大 gas 數(shù)量。
to
· 如果此交易用于傳送以太幣,此處為接收以太幣的 EOA 地址。
· 如果此交易用于向合約發(fā)送消息(例如,調(diào)用智能合約中的方法),此處為合約的地址。
· 如果此交易用于創(chuàng)建合約,此處值為空。
value
· 如果此交易用于收發(fā)以太幣,此處為接收賬戶以 Wei 計量的代幣數(shù)量。
· 如果此交易用于發(fā)送對合約的消息調(diào)用,此處為向接收此消息智能合約所給付的 Wei 數(shù)量。
· 如果此交易用于創(chuàng)建合約,此處為合約初始化時賬戶存放的以 Wei 計量的以太幣數(shù)量。
v, r, s
在交易的密碼學(xué)簽名中用到的值,可以用于確定交易的發(fā)送方。
data(只用于價值傳輸以及向智能合約發(fā)送消息調(diào)用)
發(fā)送消息調(diào)用時附帶的輸入數(shù)據(jù)(例如,假設(shè)你想要執(zhí)行智能合約中的 setter 方法,數(shù)據(jù)區(qū)就應(yīng)該包括 setter 方法的標(biāo)識符,以及你想要設(shè)定的參數(shù)值)。
init(只用于合約創(chuàng)建)
用于初始化合約的 EVM 代碼。
別想著一下子就把這些概念消化完。.. 必須對以太坊的內(nèi)部機理有更深的認識才真正理解、使用像 data 區(qū)、init 區(qū)這樣的概念。
相信不出你的意料,區(qū)塊中所有的交易也是存儲在默克爾樹中的。并且這棵樹的根節(jié)點哈希值由區(qū)塊頭保存!下面我們就來剖析一下以太坊區(qū)塊結(jié)構(gòu)。
區(qū)塊
區(qū)塊分為兩部分,即區(qū)塊頭和區(qū)塊體。
區(qū)塊頭就是以太坊中的區(qū)塊鏈部分。它保存了前一個區(qū)塊(也可稱為父區(qū)塊)的哈希值,通過區(qū)塊頭的連接形成了一條由密碼學(xué)背書的鏈。
區(qū)塊體包含了此區(qū)塊中記錄的一系列交易,以及叔塊(ommer)區(qū)塊頭列表。
-以太坊區(qū)塊的抽象示意圖-
下面就來介紹區(qū)塊頭包括哪些部分。
parentHash
前一個區(qū)塊的區(qū)塊頭哈希值。每個區(qū)塊都包含前序區(qū)塊的哈希值,一路可回溯至鏈上的創(chuàng)世塊。這也就是維護數(shù)據(jù)不會被篡改的結(jié)構(gòu)設(shè)計(任何對前序區(qū)塊的篡改都會影響后續(xù)所有區(qū)塊的哈希值)。
ommersHash
叔塊頭以及部分區(qū)塊體的哈希值。
beneficiary
因為挖到此區(qū)塊而獲得收益的以太坊賬戶。
stateRoot
世界狀態(tài)樹的根節(jié)點哈希值(在所有交易被執(zhí)行后)。
transactionsRoot
交易樹根節(jié)點的哈希值。這棵樹包含了區(qū)塊體的所有交易。
receiptsRoot
每當(dāng)交易執(zhí)行時,以太坊都會生成對應(yīng)結(jié)果的交易收據(jù)。此處就是這個交易收據(jù)樹的根節(jié)點哈希。
logsBloom
布隆過濾器,用于判斷某區(qū)塊的交易是否產(chǎn)生了某日志。這避免了在區(qū)塊中存儲日志信息(節(jié)省了大量空間)。
difficulty
此區(qū)塊的難度值。這是當(dāng)前區(qū)塊挖礦難度的度量值(此處不對此概念的細節(jié)和計算作介紹)。
number
前序區(qū)塊的總數(shù)。這標(biāo)示了區(qū)塊鏈的高度(即區(qū)塊鏈上有多少區(qū)塊)。創(chuàng)世區(qū)塊的 number 為 0 。
gasLimit
每一個交易都需要消耗 gas 。gas limit 標(biāo)示了該區(qū)塊所記錄的所有交易可以使用的 gas 總量。這是限制區(qū)塊內(nèi)交易數(shù)量的一種手段。
gasUsed
區(qū)塊中各條交易所實際消耗的 gas 總量。
timestamp
區(qū)塊創(chuàng)建時的 Unix 時間戳。謹記由于以太坊網(wǎng)絡(luò)去中心化的特性,我們不能信任這個值,特別是撰寫智能合約、涉及到時間相關(guān)的商業(yè)邏輯時不能依靠這個值。
extraData
能輸入任何東西的不定長字節(jié)數(shù)組。當(dāng)?shù)V工創(chuàng)建區(qū)塊時,可以在這個區(qū)域添加任何東西。
mixHash
用于驗證一個區(qū)塊是否被真正記錄到鏈上的哈希值。
nonce
和 mixHash 一樣,用于驗證區(qū)塊是否被真正記錄到鏈上的值。
哎呀。..真是講到我嘴都酸了。..建議你別著急,慢慢吸收!不過我要再次強調(diào),閱讀本文不應(yīng)以記住每一個名詞及其作用為目標(biāo)(在谷歌上這些都能搜到)。我的寫作初衷是想用一種簡單的方式(至少比黃皮書簡單)介紹以太坊對象的方方面面,來幫助新手理解那些專業(yè)名詞代表什么。把這篇文章當(dāng)作“笨方法學(xué)以太坊對象”就好了!
結(jié)論
讓我們簡要回顧一下學(xué)到了什么!總體而言,以太坊有四種前綴樹:
1. 世界狀態(tài)樹包括了從地址到賬戶狀態(tài)之間的映射。 世界狀態(tài)樹的根節(jié)點哈希值由區(qū)塊保存(在 stateRoot 字段),它標(biāo)示了區(qū)塊創(chuàng)建時的當(dāng)前狀態(tài)。整個網(wǎng)絡(luò)中只有一個世界狀態(tài)樹。
2. 賬戶存儲樹保存了與某一智能合約相關(guān)的數(shù)據(jù)信息。由賬戶狀態(tài)保存賬戶存儲樹的根節(jié)點哈希值(在 storageRoot 字段)。每個賬戶都有一個賬戶存儲樹。
3. 交易樹包含了一個區(qū)塊中的所有交易信息。由區(qū)塊頭(在 transactionsRoot 區(qū)域)保存交易樹的根節(jié)點哈希值。每個區(qū)塊都有一棵交易樹。
4. 交易收據(jù)樹包含了一個區(qū)塊中所有交易的收據(jù)信息。同樣由區(qū)塊頭(在 receiptsRoot 區(qū)域)保存交易收據(jù)樹的根節(jié)點哈希值;每個區(qū)塊都有對應(yīng)的交易收據(jù)樹。
我們今天討論的對象有:
1. 世界狀態(tài): 以太坊這臺分布式計算機的硬盤。它是從地址到賬戶狀態(tài)的映射。
2. 賬戶狀態(tài): 保存著每個以太坊賬戶的狀態(tài)信息。賬戶狀態(tài)同樣保存著賬戶狀態(tài)樹的 storageRoot,后者包含了該賬戶的存儲數(shù)據(jù)。
3. 交易: 標(biāo)示了系統(tǒng)中的狀態(tài)轉(zhuǎn)移。它可以是資金的轉(zhuǎn)移、消息調(diào)用或是合約的部署。
4. 區(qū)塊: 包括對前序區(qū)塊(parentHash)的鏈接,并且保存了當(dāng)執(zhí)行時會在系統(tǒng)中產(chǎn)生新狀態(tài)的交易。區(qū)塊同時保存了 stateRoot 、transactionRoot 、 receiptsRoot 、 世界狀態(tài)樹的根節(jié)點哈希、交易樹以及對應(yīng)的交易收據(jù)樹。
我想用一張圖來表示文中提及的各種概念信息。
-區(qū)塊、交易、賬戶狀態(tài)對象以及以太坊的默克爾樹-
根據(jù)我的經(jīng)驗,直接從黃皮書中學(xué)習(xí)以太坊并不方便,且需要巨大的耐心。如前所述,本文的主要目標(biāo)就是用區(qū)塊鏈初學(xué)者能聽得懂的語言描述以太坊的主要對象。
評論
查看更多