以太坊完整工作原理和运行机制!
以太坊完整工作原理和運(yùn)行機(jī)制!
2018年04月28日 00:00:00閱讀數(shù):26作者 | Preethi Kasireddy
編譯 | 老曹、Aholiab
鏈圈的人提起「以太坊」三個(gè)字想必是如雷貫耳。無(wú)論是以太幣,還是其天才創(chuàng)始人Vitalik Buterin,還是關(guān)于它的各種新聞,想必閉著眼都能看看而談。
即使如此,你可能還是不知道以太坊到底是個(gè)什么東西?它包含了哪些部分?又是基于哪些原理運(yùn)作的?這些你真的都知道嗎?
本文對(duì)以太坊的原理進(jìn)行一次大起底,盡量深入淺出且全面的讓你理解以太坊的本質(zhì)到底是什么。讓你對(duì)以太坊有一個(gè)整體而深刻的認(rèn)識(shí)。
本質(zhì)上來(lái)說(shuō),以太坊就是一個(gè)保存了數(shù)字交易永久記錄的公共數(shù)據(jù)庫(kù)。重要的是,這個(gè)數(shù)據(jù)庫(kù)不需要任何中間方來(lái)維護(hù)和雙方的權(quán)益。相反,它可以作為一種「無(wú)需信任」交易系統(tǒng)來(lái)運(yùn)作,也就是你可以在不需要第三方的情況下進(jìn)行點(diǎn)對(duì)點(diǎn)交易。
說(shuō)來(lái)說(shuō)去,還是這些啊?別急,今天就從技術(shù)層面來(lái)更深入的看看以太坊的機(jī)制到底是什么。在解釋這一概念時(shí),我們盡量不去用復(fù)雜或看著嚇人的數(shù)學(xué)公式,即使不是程序員,也能在閱讀后對(duì)以太坊的運(yùn)營(yíng)原理有更清晰的認(rèn)識(shí)。在閱讀的時(shí)候,你沒(méi)必要去理解文中的每一個(gè)細(xì)節(jié),可以聚焦在寬泛的層面上來(lái)理解以太坊。
區(qū)塊鏈的定義
區(qū)塊鏈?zhǔn)蔷哂小腹蚕頎顟B(tài)的加密安全交易單機(jī)」。聽(tīng)起來(lái)有點(diǎn)拗口,我們來(lái)分析一下。
「加密安全」是指,數(shù)字貨幣的創(chuàng)造是通過(guò)復(fù)雜的數(shù)學(xué)算法來(lái)保證的,而這些算法很難破解,類似于系統(tǒng)的防火墻,你無(wú)法在區(qū)塊鏈中創(chuàng)建虛假的交易或刪除交易等。
「交易單機(jī)」是指,有一個(gè)機(jī)器的單個(gè)實(shí)例,就可以負(fù)責(zé)系統(tǒng)中產(chǎn)生的所有交易。 換句話說(shuō),每個(gè)人都相信「一個(gè)單一的全局真相」。
「共享狀態(tài)」意思是,在這一系統(tǒng)中所存儲(chǔ)的狀態(tài)對(duì)每個(gè)人都是透明和開(kāi)放的。
知道了區(qū)塊鏈的定義,我們就來(lái)看看以太坊區(qū)塊鏈到底是什么?
以太坊區(qū)塊鏈算法
以太坊區(qū)塊鏈本質(zhì)上是一個(gè)為交易服務(wù)的狀態(tài)機(jī)。在計(jì)算機(jī)科學(xué)中,一個(gè)狀態(tài)機(jī)指的是這樣一種東西,它可以讀取一系列的輸入,并基于這些輸入產(chǎn)生一個(gè)新的狀態(tài)。
以太坊狀態(tài)機(jī)的運(yùn)行從一個(gè)「元狀態(tài)」開(kāi)始,這類似于在網(wǎng)絡(luò)上沒(méi)有發(fā)生任何交易之前的一塊空白石板。當(dāng)交易執(zhí)行時(shí),這個(gè)元狀態(tài)就轉(zhuǎn)變?yōu)橐恍┳罱K狀態(tài)。在任何時(shí)候,這個(gè)最終狀態(tài)都代表著以太坊區(qū)塊鏈的現(xiàn)狀。
以太坊系統(tǒng)中運(yùn)行著數(shù)百萬(wàn)筆交易,這些交易被分組歸類為「區(qū)塊」。一個(gè)區(qū)塊包含一系列交易,每個(gè)塊與其前面的區(qū)塊串聯(lián)在一起。
要從一個(gè)狀態(tài)轉(zhuǎn)到另一個(gè)狀態(tài),必須證明交易是有效的。如果一個(gè)交易被認(rèn)為是有效的,就必須通過(guò)一個(gè)驗(yàn)證過(guò)程,這一過(guò)程稱為「挖礦」。挖礦是指一組節(jié)點(diǎn)(即計(jì)算機(jī))消耗它們的計(jì)算資源來(lái)創(chuàng)建一個(gè)有效交易的區(qū)塊。
網(wǎng)絡(luò)中任何聲明自己是「礦工」的節(jié)點(diǎn)都可以嘗試創(chuàng)建和驗(yàn)證區(qū)塊,全世界有許多礦工試圖同時(shí)創(chuàng)建和驗(yàn)證區(qū)塊。每個(gè)礦工在向區(qū)塊鏈提交一個(gè)區(qū)塊時(shí)同時(shí),都要提供一個(gè)數(shù)學(xué)的「證明」,且把這個(gè)證明作為一個(gè)保證:如果這個(gè)數(shù)學(xué)證明存在,則該區(qū)塊必然是有效的。
如果要在主區(qū)塊鏈上添加一個(gè)區(qū)塊,礦工必須比其他競(jìng)爭(zhēng)對(duì)手更快地對(duì)其證明。通過(guò)讓礦工提供數(shù)學(xué)證明來(lái)驗(yàn)證每個(gè)區(qū)塊的過(guò)程被稱為「工作量證明」。
一個(gè)礦工如果驗(yàn)證了一個(gè)新的區(qū)塊,這個(gè)驗(yàn)證工作就會(huì)得到一定數(shù)額的價(jià)值回報(bào)。這個(gè)價(jià)值是多少呢?以太坊區(qū)塊鏈?zhǔn)褂昧艘环N內(nèi)部數(shù)字令牌,叫做「以太幣」。 每當(dāng)一個(gè)礦工證明了一個(gè)區(qū)塊,就會(huì)生成并得到一個(gè)新的以太幣。
你可能會(huì)想:什么每個(gè)節(jié)點(diǎn)都在一條鏈上?礦工如果想創(chuàng)造新的的區(qū)塊鏈怎么辦?
正如我們?cè)谏衔慕o區(qū)塊鏈的定義,區(qū)塊鏈?zhǔn)且粋€(gè)具有共享狀態(tài)的交易單機(jī)。這個(gè)定義決定了,區(qū)塊鏈的當(dāng)前狀態(tài)是一個(gè)單一的全局狀態(tài),每個(gè)人都必須接受。如果擁有多個(gè)狀態(tài)(或鏈條)會(huì)破壞整個(gè)系統(tǒng),因?yàn)槿藗儾豢赡芫湍膫€(gè)狀態(tài)是正確的狀態(tài)達(dá)成一致意見(jiàn)。如果這些鏈條是分開(kāi)的,就會(huì)出現(xiàn)一個(gè)人在一條鏈上有10個(gè)以太幣,在另一條鏈上有20個(gè)的情況。在這種情況下,我們沒(méi)有辦法確定哪一個(gè)鏈條最「有效」,無(wú)法確定哪個(gè)人有多少硬幣。
多條鏈的產(chǎn)生,被稱為「分叉」。因?yàn)榉植鏁?huì)破壞系統(tǒng),因此我們通常會(huì)避免分叉,迫使人們選擇他們「相信」的鏈條。
為了確定哪個(gè)路徑是最有效的,并防止分叉的發(fā)生,以太坊使用了一種叫做「GHOST協(xié)議」的機(jī)制。
GHOST = Greedy Heaviest Observed Subtree
簡(jiǎn)單地說(shuō),GHOST協(xié)議讓我們必須選擇在鏈上做最多計(jì)算的路徑。確定該路徑的一種方法是使用最新區(qū)塊的數(shù)量,來(lái)表示當(dāng)前路徑中的區(qū)塊總數(shù)(不計(jì)算起源塊)。塊數(shù)越多,路徑越長(zhǎng),挖礦的難度越大,最終就一定會(huì)到達(dá)最新區(qū)塊。使用這個(gè)方式讓我們對(duì)當(dāng)前區(qū)塊鏈狀態(tài)的唯一版本達(dá)成一致。
?
到這里,我們就對(duì)以太坊區(qū)塊鏈就有了一個(gè)宏觀的認(rèn)識(shí),接下來(lái)我們就更深入地看看以太坊系統(tǒng)的主要組成部分:
帳戶;
狀態(tài);
Gas與費(fèi)用;
交易;
區(qū)塊;
交易執(zhí)行;
挖礦;
工作量證明。
以太坊的帳戶
以太坊的全球「共享狀態(tài)」是由許多賬戶組成的,它們能夠通過(guò)一個(gè)消息傳遞框架相互通信。每個(gè)帳戶都有一個(gè)與它關(guān)聯(lián)的狀態(tài)和一個(gè)20字節(jié)的地址。以太坊的地址是一個(gè)160位比特的標(biāo)識(shí)符,用于識(shí)別帳戶。
以太坊有兩種賬戶類型:
外部帳戶由私人密鑰控制,沒(méi)有與之相關(guān)的代碼。
合約賬戶由其合約代碼控制,并具有與其相關(guān)的代碼。
?
外部賬戶與合約賬戶
外部賬戶可以通過(guò)創(chuàng)建和使用其私人密鑰簽署一項(xiàng)交易,向其他外部賬戶或其他合約賬戶發(fā)送消息。兩個(gè)外部賬戶之間的消息只是一種價(jià)值轉(zhuǎn)移。但從一個(gè)外部帳戶到一個(gè)合約賬戶的消息會(huì)激活合約賬戶的代碼,使它能夠執(zhí)行各種操作(例如轉(zhuǎn)移代幣、寫入內(nèi)存、生成新的代幣、執(zhí)行一些計(jì)算、創(chuàng)建新合約等)。
與外部賬戶不同,合約賬戶不能自行啟動(dòng)新的交易。相反,合約賬戶只能根據(jù)它們收到的其他交易(從外部賬戶或從另一個(gè)合約賬戶)進(jìn)行交易,這點(diǎn)我們會(huì)在下文進(jìn)行探討。
?
因此我們可以得出結(jié)論:在以太坊區(qū)塊鏈上發(fā)生的任何操作都是由外部控制賬戶的交易引起的。
?
帳戶狀態(tài)
無(wú)論帳戶是哪種類型,帳戶狀態(tài)都由以下四個(gè)部分組成。
nonce:如果帳戶是一個(gè)外部帳戶,這個(gè)數(shù)字代表從帳戶地址發(fā)送的交易數(shù)量。如果帳戶是一個(gè)合約帳戶,nonce是帳戶創(chuàng)建的合約數(shù)量。
balance:這個(gè)地址擁有的Wei(以太坊貨幣單位)數(shù)量,每個(gè)以太幣有1e+18 Wei。
storageRoot?:一個(gè)Merkle Patricia樹(shù)根節(jié)點(diǎn)的哈希,它對(duì)帳戶的存儲(chǔ)內(nèi)容的哈希值進(jìn)行編碼,并默認(rèn)為空。
codeHash:EVM(以太坊虛擬機(jī))的哈希值代碼。 對(duì)于合約帳戶,這是一個(gè)被哈希后并存儲(chǔ)為codeHash的代碼。對(duì)于外部帳戶,codeHash字段是空字符串的哈希。
全局狀態(tài)
我們知道以太坊的全局狀態(tài)包括帳戶地址和帳戶狀態(tài)之間的映射,這個(gè)映射存儲(chǔ)在一個(gè)數(shù)據(jù)結(jié)構(gòu)中,這種結(jié)構(gòu)被稱為Merkle Patricia樹(shù)。
Merkle Patricia樹(shù)是一種由一組樹(shù)狀節(jié)點(diǎn)構(gòu)成的二進(jìn)制結(jié)構(gòu),它包括:
底層有大量的葉子節(jié)點(diǎn),其中包含了潛在的數(shù)據(jù);
一組中間節(jié)點(diǎn),其中每個(gè)節(jié)點(diǎn)是其兩個(gè)子節(jié)點(diǎn)的哈希;
一個(gè)單個(gè)的根節(jié)點(diǎn),也是由它的兩個(gè)子節(jié)點(diǎn)的哈希形成的,代表樹(shù)的頂部。
?
樹(shù)的底部數(shù)據(jù)是通過(guò)把我們想要存儲(chǔ)的數(shù)據(jù)分割成塊后而生成的,然后將這些數(shù)據(jù)塊分成幾個(gè)桶,然后對(duì)每個(gè)桶的進(jìn)行哈希迭代,值到剩下的哈??倲?shù)變?yōu)橐粋€(gè)根哈希。 ?
此外,樹(shù)需要存儲(chǔ)在里面的每一個(gè)值的密鑰。從樹(shù)的根節(jié)點(diǎn)開(kāi)始,密鑰告訴你要遵循哪個(gè)子節(jié)點(diǎn)來(lái)獲取相應(yīng)的值,這些值存儲(chǔ)在葉子節(jié)點(diǎn)中。在以太坊中,狀態(tài)樹(shù)的鍵值對(duì)是地址和相關(guān)帳戶之間的映射,包括每個(gè)帳戶的balance、nonce、codeHash和storageRoot(storageRoot本身就是一棵樹(shù))。
?
同樣的樹(shù)結(jié)構(gòu)也用于存儲(chǔ)交易和收據(jù)。更具體地說(shuō),每個(gè)塊都有一個(gè)「header」,它存儲(chǔ)三個(gè)不同Merkle樹(shù)結(jié)構(gòu)根節(jié)點(diǎn)的哈希,包括:
狀態(tài)樹(shù);
交易樹(shù);
收據(jù)樹(shù)。
?
Merkle樹(shù)能夠高效存儲(chǔ)信息的特性在以太坊系統(tǒng)中十分被看重,我們可以稱之為「輕節(jié)點(diǎn)」或「輕客戶端」,其實(shí)區(qū)塊鏈的節(jié)點(diǎn)有兩種:完整節(jié)點(diǎn)和輕節(jié)點(diǎn)
一個(gè)完整的節(jié)點(diǎn)需要下載完整的鏈,從元區(qū)塊到當(dāng)前的頭部塊,執(zhí)行所有的交易也都包含其中。通常情況下,礦工儲(chǔ)存完整的檔案節(jié)點(diǎn),因?yàn)樗麄儽仨氝@樣做才能完成挖礦的過(guò)程。當(dāng)然,也可以在不執(zhí)行交易的情況下下載完整的節(jié)點(diǎn)。無(wú)論如何,任何完整的節(jié)點(diǎn)都包含整條鏈。
輕節(jié)點(diǎn)的概念與之相對(duì),除非一個(gè)節(jié)點(diǎn)需要執(zhí)行每個(gè)交易或查詢歷史數(shù)據(jù),否則就沒(méi)有必要存儲(chǔ)整個(gè)鏈。這就是輕節(jié)點(diǎn)的意義所在。輕節(jié)點(diǎn)并不下載和存儲(chǔ)完整鏈并執(zhí)行所有的交易,而是只下載從元區(qū)塊到當(dāng)前頭部區(qū)塊的信息,而不執(zhí)行任何交易或檢索任何關(guān)聯(lián)狀態(tài)。因?yàn)檩p節(jié)點(diǎn)可以訪問(wèn)包含三個(gè)樹(shù)的區(qū)塊頭部哈希,所以仍然可以很容易地生成和接收關(guān)于交易、事件、余額等可驗(yàn)證的結(jié)果。
這樣做的原因是因?yàn)镸erkle樹(shù)中的哈希會(huì)向上傳播ーー如果一個(gè)惡意用戶試圖將一個(gè)偽造的交易交換到Merkle樹(shù)的底部,這種變化將導(dǎo)致上面節(jié)點(diǎn)的哈希變化,也將改變上面節(jié)點(diǎn)的哈希值。
?
任何想要驗(yàn)證一段數(shù)據(jù)的節(jié)點(diǎn)都可以使用所謂的「Merkle證明」來(lái)執(zhí)行。一個(gè)Merkle 證明包括:
需要驗(yàn)證的大量數(shù)據(jù)及其哈希值;
樹(shù)的根哈希;
「分支」(所有的參與者的哈希沿著路徑上升,一直到「樹(shù)根」)。
?
任何讀取該證明的人都可以驗(yàn)證樹(shù)上所有的分枝是否一致,因此給定的數(shù)據(jù)塊實(shí)際上位于樹(shù)中的某個(gè)位置。
總之,使用Merkle樹(shù)的好處是,該結(jié)構(gòu)的根節(jié)點(diǎn)依據(jù)樹(shù)中存儲(chǔ)的數(shù)據(jù)進(jìn)行加密,因此根節(jié)點(diǎn)的哈希可以作為該數(shù)據(jù)的安全證明。由于區(qū)塊頭包括狀態(tài)、交易和收據(jù)樹(shù)的根哈希。因此任何節(jié)點(diǎn)都可以在不需要存儲(chǔ)整個(gè)狀態(tài)的情況下,驗(yàn)證以太坊的一小部分狀態(tài),而整個(gè)狀態(tài)的大小可能是無(wú)限的。
Gas和支付
在以太坊中,費(fèi)用的計(jì)算是一個(gè)非常重要的概念。在以太坊網(wǎng)絡(luò)上進(jìn)行的每一筆交易都會(huì)產(chǎn)生費(fèi)用ーー沒(méi)有免費(fèi)的午餐!這筆費(fèi)用被稱為「Gas」。
Gas Price是指:你愿意花在每一個(gè)單位Gas上的以太幣數(shù)量,是用「gwei」來(lái)計(jì)算的。Wei是以太幣中最小的單位,其中1018?Wei代表1個(gè)以太幣。一個(gè)gwei是1,000,000,000 Wei。
每次交易,發(fā)送方都要設(shè)置一個(gè)Gas Limit和Gas Price。Gas Limit和Gas Price代表發(fā)送方愿意為執(zhí)行交易支付的最大金額。
例如,發(fā)送方將Gas Limit設(shè)置為50,000,一個(gè)Gas Price設(shè)置為20 gwei。這意味著發(fā)送者愿意花費(fèi)最多50,000 x 20 gwei,也就是:1,000,000,000,000,000 Wei(0.001以太幣)來(lái)執(zhí)行這一交易。
?
這里需要留意的是,Gas限額是發(fā)送方愿意花錢的最大限度。如果他們的賬戶余額中以太幣的數(shù)量大于這個(gè)最大值,那么他就可以進(jìn)行交易。在交易結(jié)束時(shí),發(fā)送方將被退還的那些未使用的Gas,按原來(lái)的價(jià)格進(jìn)行兌換。
?
如果發(fā)送方?jīng)]有提供執(zhí)行交易所必需的Gas,則該交易運(yùn)行的結(jié)果會(huì)是「余額不足」,并被認(rèn)為無(wú)效。在這種情況下,交易處理中止,其間的產(chǎn)生的任何狀態(tài)都會(huì)發(fā)生逆轉(zhuǎn),這樣就可以在交易發(fā)生之前返回到以太坊區(qū)塊鏈。此外,交易失敗的記錄會(huì)被記錄下來(lái),顯示嘗試過(guò)哪些交易,失敗了哪些交易。由于系統(tǒng)已經(jīng)在Gas用光之前做完了運(yùn)算工作,所以從邏輯上看,Gas不會(huì)被退還給發(fā)送方。
那么,這些Gas的錢到底去哪了呢?發(fā)送方花在Gas上的所有錢都寄給了「受益人」地址,也就是礦工地址。由于礦工們正在努力運(yùn)行計(jì)算和驗(yàn)證交易,所以收到了Gas作為獎(jiǎng)勵(lì)。
?
通常情況下,發(fā)送方愿意支付的Gas價(jià)格越高,礦工從交易中獲得的價(jià)值就越大,礦工們也就越有可能選擇這個(gè)交易。通過(guò)這種方式,礦工可以自由地選擇交易。為了給發(fā)送者設(shè)置Gas Price做參考,礦工們可以直接提出他們執(zhí)行交易所需的最低Gas Price。
存儲(chǔ)費(fèi)用
Gas不僅用于支付計(jì)算的費(fèi)用,還用于支付存儲(chǔ)的使用費(fèi)用。存儲(chǔ)的總費(fèi)用與使用的32字節(jié)的最小倍數(shù)成正比。
存儲(chǔ)費(fèi)用與交易費(fèi)用有一些不同。由于增加的存儲(chǔ)量增加了所有節(jié)點(diǎn)上的以太坊狀態(tài)數(shù)據(jù)庫(kù)的大小,所以存儲(chǔ)數(shù)據(jù)的數(shù)量會(huì)變小。由于這個(gè)原因,如果一個(gè)交易有一個(gè)步驟可以清除存儲(chǔ)中的條目,則可以免除執(zhí)行該操作的存儲(chǔ)費(fèi)用,并且還能因此得到退款。
費(fèi)用的目的是什么?
以太坊工作方式的一個(gè)重要方面是,網(wǎng)絡(luò)執(zhí)行的每一個(gè)操作都同時(shí)受到每個(gè)完整節(jié)點(diǎn)的影響。然而,在以太坊虛擬機(jī)上的計(jì)算步驟非常昂貴。因此,以太坊智能合約更適合簡(jiǎn)單的任務(wù),比如運(yùn)行簡(jiǎn)單的業(yè)務(wù)邏輯或驗(yàn)證簽名和加密其他對(duì)象,而不適合更復(fù)雜的用途,比如文件存儲(chǔ)、電子郵件或機(jī)器學(xué)習(xí),這些都會(huì)給網(wǎng)絡(luò)帶來(lái)壓力。收費(fèi)的目的就是使整個(gè)網(wǎng)絡(luò)不會(huì)因用戶的不當(dāng)使用而變得負(fù)擔(dān)過(guò)重。
除此之外,以太坊是一種圖靈完整語(yǔ)言(圖靈機(jī)是一種能夠模擬任何計(jì)算機(jī)算法的機(jī)器)。這就允許了循環(huán),使得以太坊區(qū)塊鏈容易受到暫停問(wèn)題的影響,因?yàn)樵谶@個(gè)問(wèn)題中,無(wú)法確定一個(gè)程序是否會(huì)無(wú)限運(yùn)行。如果沒(méi)有費(fèi)用,意圖不良的人可以通過(guò)在交易中執(zhí)行一個(gè)無(wú)限循環(huán)來(lái)擾亂網(wǎng)絡(luò),從而產(chǎn)生不良的影響。因此,費(fèi)用保護(hù)了網(wǎng)絡(luò)免受蓄意攻擊。
那么,為什么我們還要支付存儲(chǔ)費(fèi)用呢?就像計(jì)算一樣,在以太坊網(wǎng)絡(luò)上的存儲(chǔ)也是整個(gè)網(wǎng)絡(luò)必須承擔(dān)的一個(gè)成本。
交易與消息
我們?cè)谏厦嬲f(shuō)到,以太坊是一個(gè)基于交易的狀態(tài)機(jī)。換句話說(shuō),不同賬戶之間發(fā)生的交易正是以太坊從一個(gè)狀態(tài)轉(zhuǎn)移到另一個(gè)狀態(tài)的原因。
因此,交易可以看做是一個(gè)由外部擁有的帳戶生成的序列化加密簽名指令,然后提交給區(qū)塊鏈。
交易分為兩類:「消息調(diào)用」和「合約創(chuàng)建」(創(chuàng)建新的以太坊合約的交易)。不管哪一類,所有交易都包含以下組件:
Nonce:發(fā)送方發(fā)送的交易數(shù)量的計(jì)數(shù);
gasPrice:發(fā)送方愿意支付每單位Gas所需執(zhí)行交易的Wei數(shù)量;
gasLimit:發(fā)送方愿意支付的執(zhí)行這一交易的Gas最大數(shù)量。這個(gè)數(shù)額是預(yù)先設(shè)定和支付的;
to:接收方的地址,在創(chuàng)建合約的交易中,合約帳戶地址還不存在,因此使用了空值;
Value:從發(fā)送方轉(zhuǎn)移到收件方的金額,在創(chuàng)建合約的交易中,這個(gè)Value作為新創(chuàng)建合約賬戶內(nèi)的起始余額;
v, r, s:用于生成識(shí)別交易發(fā)送方的簽名;
Init(只存在于創(chuàng)建合同的交易中):用于初始化新合約帳戶的EVM代碼片段,它只運(yùn)行一次,然后被丟棄,當(dāng)init第一次運(yùn)行時(shí),它會(huì)返回帳戶代碼的主體,這個(gè)代碼是與合約帳戶永久關(guān)聯(lián)的一段代碼;
data(只存在于消息調(diào)用中的可選字段):消息調(diào)用的輸入數(shù)據(jù)(即參數(shù))。例如,如果一個(gè)智能合約充當(dāng)域名注冊(cè)服務(wù),那么對(duì)該合約的調(diào)用可能會(huì)有諸如域名以及IP地址等輸入字段。
?
在說(shuō)「賬戶」的時(shí)候,我們看到,交易(包括消息調(diào)用和合約創(chuàng)建的交易),總是由外部賬戶啟動(dòng)并提交給區(qū)塊鏈的。另一種思考方式是,交易是連接外部世界與以太坊內(nèi)部狀態(tài)的橋梁。
?
但這并不意味著一個(gè)合約不能與其他合約對(duì)話。在全局范圍內(nèi)存在的合約,可以與同一范圍內(nèi)的其他合約進(jìn)行交流。它們是以通過(guò)「消息」或「內(nèi)部交易」的方式來(lái)實(shí)現(xiàn)的。我們可以認(rèn)為消息或內(nèi)部交易類似于交易,其主要區(qū)別在于它們不是由外部賬戶所產(chǎn)生的,相反,是由合約產(chǎn)生的,是虛擬對(duì)象。與交易不同,合約不是序列化的,而是只存在于以太坊的執(zhí)行環(huán)境中。
當(dāng)一個(gè)合約將一個(gè)內(nèi)部交易發(fā)送到另一個(gè)合約時(shí),存在于接收方合約賬戶上的關(guān)聯(lián)代碼就會(huì)被執(zhí)行。
?
需要注意的一點(diǎn)是,內(nèi)部交易或消息不包含Gas Limit。這是因?yàn)镚as Limit是由原始交易的外部創(chuàng)建者(即部分外部帳戶)來(lái)決定的。外部賬戶集合的Gas Limit必須足夠高,以便進(jìn)行交易,這包括由這一交易而導(dǎo)致發(fā)生的任何次級(jí)處理運(yùn)行,例如合約對(duì)合約的消息。如果在交易和消息鏈中,特定的消息執(zhí)行耗盡了Gas,那么該消息的執(zhí)行將與執(zhí)行引發(fā)的所有后續(xù)消息一起恢復(fù)。不過(guò),上一級(jí)的執(zhí)行不需要恢復(fù)。
以太坊的區(qū)塊
所有的交易都被組合成「區(qū)塊」,區(qū)塊鏈則包含一系列這樣被鏈接在一起的區(qū)塊。在以太坊中,一個(gè)區(qū)塊包括「區(qū)塊頭」、關(guān)于包含在此區(qū)塊中交易集的信息,與當(dāng)前塊的ommers相關(guān)的一系列其他區(qū)塊頭Ommer解釋
Ommer是什么?
比起比特幣之類的區(qū)塊鏈,以太坊的構(gòu)建方式使區(qū)塊生成時(shí)間要低很多。這樣可以更快地處理交易。然而,縮短區(qū)塊生成時(shí)間的一個(gè)缺點(diǎn)是,礦工們要找到更多相互競(jìng)爭(zhēng)的區(qū)塊解決方案。這些相互競(jìng)爭(zhēng)的區(qū)塊也被稱為「孤兒區(qū)塊」,不能進(jìn)入主鏈。
Ommer的目的是幫助獎(jiǎng)勵(lì)礦工,也包括這些孤兒區(qū)塊。礦工的ommer必須是「有效的」,也就是說(shuō)在目前區(qū)塊的第六代或更小的范圍內(nèi)。六代之后,陳舊的孤兒區(qū)塊就不能再被引用。比起完整的區(qū)塊,Ommer塊獲得的獎(jiǎng)勵(lì)要小一些。盡管如此,礦工們?nèi)匀挥幸欢ǖ膭?dòng)力去挖掘這些孤兒區(qū)塊并獲得回報(bào)。
區(qū)塊頭
回到區(qū)塊本身,之前提到每個(gè)區(qū)塊都有一個(gè)區(qū)塊頭,但到底什么什么是區(qū)塊頭?區(qū)塊頭是區(qū)塊的一部分,包括:
Parenthash:一個(gè)父區(qū)塊頭的哈希(這就是為什么區(qū)塊鏈被稱為區(qū)塊「鏈」);
Ommershash:當(dāng)前區(qū)塊ommer列表的哈希;
beneficiary:收取采礦費(fèi)用的帳戶地址;
Stateroot:狀態(tài)樹(shù)的根節(jié)點(diǎn)哈希;
transactionsRoot:包含在此區(qū)塊中列出的所有交易樹(shù)根節(jié)點(diǎn)的哈希值;
receiptsRoot?:包含本區(qū)塊中列出的所有交易樹(shù)根節(jié)點(diǎn)的哈希的收據(jù);
logsBloom:一個(gè)由log組成的Bloom過(guò)濾器(數(shù)據(jù)結(jié)構(gòu));
difficulty:這個(gè)區(qū)塊的難度水平;
編號(hào):當(dāng)前區(qū)塊的記數(shù)(元區(qū)塊的編號(hào)為0;每個(gè)后續(xù)區(qū)塊的塊數(shù)增加1);
gasLimit:當(dāng)前每個(gè)區(qū)塊的Gas限制;
gasUsed:本區(qū)塊交易所使用的總Gas之和;
時(shí)間戳:這個(gè)區(qū)塊注入的unix時(shí)間戳;
extraData:與此區(qū)塊相關(guān)的其他數(shù)據(jù);
mixHash:當(dāng)與nonce結(jié)合時(shí),證明這個(gè)區(qū)塊執(zhí)行了足夠計(jì)算的哈希值;
Nonce:當(dāng)與mixHash結(jié)合時(shí),證明這個(gè)區(qū)塊已經(jīng)執(zhí)行了足夠計(jì)算的哈希值;
每個(gè)區(qū)塊頭包含三個(gè)樹(shù)結(jié)構(gòu):
狀態(tài)根(stateRoot);
交易根(transactionsRoot);
收據(jù)根(receiptsRoot)。
這些樹(shù)結(jié)構(gòu)只不過(guò)是之前討論過(guò)的Merkle樹(shù)而已,沒(méi)有什么特別的。不過(guò),從上面的描述中可以看到,有一些術(shù)語(yǔ)還需要進(jìn)一步說(shuō)說(shuō)。
日志(Log)
以太坊允許log跟蹤各種交易和消息。合約也可以通過(guò)定義需要記錄的「事件」來(lái)顯式生成log。
一條log包含:
記錄器的帳戶地址;
一系列主題,它們表示此交易所進(jìn)行的各種事件,以及,
任何與這些事件有關(guān)的數(shù)據(jù)。
log存儲(chǔ)在一個(gè)bloom過(guò)濾器中,它以有效的方式存儲(chǔ)海量的日志數(shù)據(jù)。
交易收據(jù)
區(qū)塊頭中存儲(chǔ)的日志來(lái)自于交易收據(jù)中包含的日志信息。就像在商店買東西時(shí)收到收據(jù)一樣,以太坊會(huì)為每筆交易生成一張收據(jù)。不出所料,每張收據(jù)都包含有關(guān)交易的某些信息。 這樣的收據(jù)包括以下內(nèi)容:
區(qū)塊編號(hào);
區(qū)塊哈希;
交易哈希;
當(dāng)前交易所使用的Gas;
在當(dāng)前交易執(zhí)行后,當(dāng)前區(qū)塊中使用的Gas;
執(zhí)行當(dāng)前交易時(shí)創(chuàng)建的日志。
區(qū)塊的難度
區(qū)塊的「難度」用于在驗(yàn)證區(qū)塊的時(shí)間內(nèi)來(lái)加強(qiáng)一致性。元區(qū)塊的難度為131,072,并用一個(gè)特殊的公式來(lái)計(jì)算后面每個(gè)區(qū)塊的難度。如果某個(gè)區(qū)塊比前一個(gè)區(qū)塊更快地被驗(yàn)證,那么以太坊協(xié)議會(huì)增加該區(qū)塊的難度。
該區(qū)塊的難度會(huì)影響nonce,這是一個(gè)哈希,必須在挖礦時(shí)使用工作量證明算法來(lái)計(jì)算。
區(qū)塊的難度與nonce之間的關(guān)系在數(shù)學(xué)上表示為:
這里Hd代表了難度。找到滿足難度閾值的nonce的唯一方法是使用工作量證明算法來(lái)枚舉所有的可能性。 尋找解決方案的預(yù)期時(shí)間與難度成正比,難度越大,找到nonce就越困難,因此驗(yàn)證區(qū)塊的難度就越大,這反過(guò)來(lái)增加了驗(yàn)證新區(qū)塊的時(shí)間。通過(guò)調(diào)整區(qū)塊的難度,協(xié)議可以調(diào)整驗(yàn)證區(qū)塊的時(shí)長(zhǎng)。
另一方面,如果驗(yàn)證時(shí)間變慢,那么協(xié)議就會(huì)減少難度。通過(guò)這種方式,驗(yàn)證時(shí)間可以自我調(diào)整從而保持一個(gè)常量ーー平均每15秒一個(gè)區(qū)塊。
交易的執(zhí)行
看到這,你已經(jīng)來(lái)到了以太坊協(xié)議中最復(fù)雜的部分之一。假設(shè)將一個(gè)交易發(fā)送到以太坊網(wǎng)絡(luò)進(jìn)行處理,如果以太坊狀態(tài)要將你的交易包括在內(nèi),會(huì)發(fā)生什么?
首先,所有交易都必須滿足初始的一組需求才能執(zhí)行。 其中包括以下幾個(gè)部分。
交易必須是正確的RLP格式(RLP是「遞歸長(zhǎng)度前綴」的縮寫,是用于二進(jìn)制數(shù)據(jù)編碼嵌套數(shù)組的數(shù)據(jù)格式,RLP是以太坊使用的序列化對(duì)象的格式)。
有效的交易簽名。
有效的交易nonce,回想一下,一個(gè)帳戶的nonce是從該帳戶發(fā)送的交易的統(tǒng)計(jì),為了有效,交易nonce必須與發(fā)送方帳戶的nonce相等。
交易的Gas限額必須等于或大于交易所使用的內(nèi)部Gas, 內(nèi)部Gas包括:1)為執(zhí)行交易預(yù)先確定的費(fèi)用為21,000 Gas;2)與該交易一起發(fā)送的數(shù)據(jù)Gas費(fèi)用(對(duì)于每一個(gè)等于零的數(shù)據(jù)或代碼的每個(gè)字節(jié)收取4個(gè)Gas,每個(gè)非零字節(jié)的數(shù)據(jù)或代碼為68個(gè)Gas);3)如果這筆交易是一筆合約創(chuàng)建交易,則額外收取32,000 Gas。
?
發(fā)送方的賬戶余額必須有足夠的以太幣來(lái)支付前期的Gas費(fèi)用。前期Gas成本的計(jì)算很簡(jiǎn)單:首先,交易的Gas Limit乘以交易的Gas Price,以確定最大的Gas成本。 然后,這個(gè)最大的成本被算在從發(fā)送方轉(zhuǎn)移到接收方的總額中。
如果交易符合上述有效性的所有要求,那么,就可以進(jìn)入下一個(gè)步驟。
首先,從發(fā)送方的余額中扣除執(zhí)行的前期成本,并將發(fā)送方帳戶的nonce加1。我們可以計(jì)算剩余的Gas,因?yàn)榻灰椎腉as Limit要減去所使用的內(nèi)在Gas。
然后,交易開(kāi)始執(zhí)行。在交易的整個(gè)執(zhí)行過(guò)程中,以太坊都跟蹤「子狀態(tài)」。子狀態(tài)記錄交易中產(chǎn)生的信息,這些信息也是交易完成后所馬上需要用到的。具體來(lái)說(shuō),它包含:
自毀集合:交易完成后將丟棄的一組帳戶(如果有的話);
日志序列:虛擬機(jī)代碼執(zhí)行的存檔和可索引的檢查點(diǎn);
退款余額:交易完成后退還給發(fā)送者賬戶的余額。
一旦處理完交易中的所有步驟,并假定沒(méi)有無(wú)效狀態(tài),則通過(guò)確定向發(fā)送方退還未使用的Gas數(shù)量,來(lái)最終判定最終狀態(tài)。除了未使用的Gas外,發(fā)送方還從上文所述的「退款余額」中退還了一些余額。
一旦發(fā)送者獲得退款:
Gas(以太幣)就會(huì)給到給礦工;
該交易所使用的Gas被添加到區(qū)塊的Gas計(jì)數(shù)器(該計(jì)數(shù)器記錄該區(qū)塊中所有交易使用的總Gas);
刪除自毀集合中的所有帳戶(如果有的話);
最后,只剩下了新的狀態(tài)和已創(chuàng)建交易的一組log。至此,我們就講完了交易執(zhí)行的基本原理,下面再來(lái)看看合約創(chuàng)建的交易和消息調(diào)用之間的一些差異。
合約創(chuàng)建
前面說(shuō)過(guò),以太坊的賬戶分為兩類:合約帳戶和外部賬戶。當(dāng)交易是「契約創(chuàng)建」(Contract Creating)時(shí),意思是,交易的目的是創(chuàng)建一個(gè)新的合約賬戶。
為了創(chuàng)建一個(gè)新的合約帳戶,我們首先使用一個(gè)特殊的公式來(lái)聲明新賬戶的地址,然后通過(guò)以下方式初始化新帳戶:
將nonce設(shè)置為零;
如果發(fā)送方在交易中發(fā)送了一定數(shù)量的以太幣作為價(jià)值,則將帳戶余額設(shè)置為該價(jià)值;
從發(fā)送方的余額中扣除這個(gè)新賬戶余額的增加部分;
將存儲(chǔ)設(shè)置為空;
將合約的codeHash設(shè)置為空字符串的哈希值;
一旦帳戶完成了初始化就可以創(chuàng)建帳戶了,使用與交易一起發(fā)送的init代碼。在執(zhí)行這個(gè)init代碼的過(guò)程中,可能發(fā)生很多情況。根據(jù)合約的構(gòu)造函數(shù),它可能更新帳戶的存儲(chǔ),創(chuàng)建其他的合約賬戶,或其他的消息調(diào)用,等等。
一旦初始化合約的代碼被執(zhí)行就將開(kāi)始消耗Gas,交易使用的Gas不能超出賬戶的余額,一旦超出,將會(huì)出現(xiàn)「Gas耗光」的異常并且退出。如果交易由于Gas耗光的異常而退出。
但是,如果發(fā)送方在交易中發(fā)送了一些以太幣,這時(shí)合約創(chuàng)建失敗也會(huì)退還以太幣嗎?答案是,不會(huì)。
如果初始化代碼執(zhí)行成功,則支付最終的合約創(chuàng)建成本。這是一個(gè)存儲(chǔ)成本,并且與創(chuàng)建合約代碼的大小成正比。如果剩余的Gas不足以支付這筆最終成本,那么這筆交易將再次聲明為一個(gè)「Gas耗光」異常。
如果一切順利,而且沒(méi)有遇到任何異常,那么剩余的Gas都會(huì)退還給交易的原始發(fā)送方,并允許改變狀態(tài)繼續(xù)存在!
消息調(diào)用
消息調(diào)用的執(zhí)行類似于合約創(chuàng)建,但有一些不同之處。
消息調(diào)用的執(zhí)行不包含任何init代碼,因?yàn)闆](méi)有創(chuàng)建新的帳戶。但是,如果這些數(shù)據(jù)是由交易發(fā)送方提供的,它可以包含輸入數(shù)據(jù)。一旦執(zhí)行,消息調(diào)用也有一個(gè)額外的組件,其中包含輸出數(shù)據(jù),如果后續(xù)執(zhí)行需要此數(shù)據(jù),則使用這些數(shù)據(jù)。
如同合約創(chuàng)建一樣,如果由于Gas耗盡或交易無(wú)效(例如堆棧溢出、無(wú)效的跳轉(zhuǎn)目的地或無(wú)效指令),則所使用的任何Gas都不會(huì)退還給原來(lái)的調(diào)用者,取而代之的是,所有剩余的Gas都會(huì)被消耗掉,并且狀態(tài)被重置到余額轉(zhuǎn)移之前的情況。
執(zhí)行模式
現(xiàn)在,我們來(lái)看看在VM中,交易實(shí)際上是如何執(zhí)行的。
實(shí)際處理交易的部分是以太坊自己的虛擬機(jī),被稱為EVM。就像之前定義的那樣,EVM是一個(gè)「圖靈完備」的虛擬機(jī)。唯一的不同是EVM有內(nèi)在Gas的約束。因此,可以完成的計(jì)算總量本質(zhì)上受到所提供Gas數(shù)量的限制。
?
此外,EVM 有一個(gè)基于棧機(jī)器的架構(gòu)。棧機(jī)器是一種使用「后入先出」的堆棧來(lái)保存臨時(shí)值的計(jì)算機(jī)。EVM中每個(gè)棧條目的大小為256位,最大為1024位。
EVM具有內(nèi)存,其中存儲(chǔ)的條目是字地址字節(jié)數(shù)組(word-addressed byte arrays)。 內(nèi)存是易失性的,這意味著它不是永久性的。
EVM還有存儲(chǔ)空間。與內(nèi)存不同,內(nèi)存的存儲(chǔ)是非易失性的,并作為系統(tǒng)狀態(tài)的一部分來(lái)維護(hù)。EVM在一個(gè)虛擬ROM中獨(dú)立存儲(chǔ)程序代碼,只能通過(guò)特殊的指令訪問(wèn)虛擬ROM。這就是EVM與典型的馮·諾伊曼結(jié)構(gòu)的不同,馮·諾伊曼結(jié)構(gòu)中程序代碼是在內(nèi)存或存儲(chǔ)中。
?
EVM也有自己的語(yǔ)言——EVM字節(jié)碼。當(dāng)程序員在以太坊上寫智能合約的時(shí)候,通常用高級(jí)語(yǔ)言寫代碼,比如Solidity。然后,可以編譯成EVM字節(jié)碼,以便EVM可以理解執(zhí)行。
接下來(lái)我們來(lái)看看EVM如何運(yùn)行。在執(zhí)行特定的計(jì)算之前,處理器要確保以下信息是可用且有效的:
系統(tǒng)狀態(tài);
用于計(jì)算的剩余Gas;
擁有執(zhí)行代碼的帳戶地址;
產(chǎn)生此執(zhí)行交易的發(fā)送方地址;
引發(fā)代碼執(zhí)行的帳戶地址(可能與原始發(fā)送方不同);
產(chǎn)生此次執(zhí)行交易的Gas Price;
此執(zhí)行的輸入數(shù)據(jù);
作為當(dāng)前執(zhí)行的一部分,價(jià)值(以Wei為單位)傳遞到這個(gè)帳戶;
要執(zhí)行的機(jī)器碼;
當(dāng)前塊的區(qū)塊頭;
當(dāng)前消息調(diào)用或合約創(chuàng)建的棧深度;
在執(zhí)行開(kāi)始時(shí),內(nèi)存和棧是空的,程序計(jì)數(shù)器歸零。
然后,EVM遞歸執(zhí)行交易,計(jì)算系統(tǒng)狀態(tài)和每個(gè)循環(huán)的機(jī)器狀態(tài)。簡(jiǎn)單地說(shuō),這個(gè)系統(tǒng)狀態(tài)就是全局狀態(tài)。機(jī)器狀態(tài)包括:
可用的Gas;
程序計(jì)數(shù)器;
內(nèi)存的內(nèi)容;
內(nèi)存中的字活躍數(shù);
棧內(nèi)容。
棧中條目是從該系列最左邊的部分中添加或刪除。表現(xiàn)為,在每個(gè)循環(huán)中,從剩余的Gas中減少適當(dāng)?shù)腉as,并且程序計(jì)數(shù)器遞增。
在每個(gè)循環(huán)的結(jié)束時(shí),有三種可能性:
機(jī)器達(dá)到一個(gè)特殊狀態(tài)(例如Gas不足、指令無(wú)效、棧條目不足、棧條目溢出超過(guò)1024、無(wú)效的JUMP/JUMPI等),因此必須停止,任何更改都將被丟棄;
這個(gè)序列繼續(xù)進(jìn)入下一個(gè)循環(huán);
系統(tǒng)被迫停止。
假設(shè)執(zhí)行沒(méi)有達(dá)到一個(gè)特殊狀態(tài),并達(dá)到一個(gè)「可控制的狀態(tài)」或正常停止,那么機(jī)器就會(huì)生成結(jié)果狀態(tài)、保留執(zhí)行后剩余的Gas。
說(shuō)了這么多,終于結(jié)束了以太坊中最復(fù)雜的部分。即使沒(méi)有完全理解這部分,也沒(méi)關(guān)系,除非是從事底層的開(kāi)發(fā)工作,否則并不需要真正理解這些細(xì)節(jié)。
一個(gè)區(qū)塊的最終完成
最后,來(lái)看看多個(gè)交易塊是如何最終完成的。
這里所說(shuō)的「最終」可能是指兩種不同的東西,這取決于區(qū)塊是新的還是已經(jīng)存在的。如果是一個(gè)新區(qū)塊,「最終」指的是挖掘這個(gè)區(qū)塊所需要的過(guò)程。如果是一個(gè)現(xiàn)有的區(qū)塊,那么「最終」指的是驗(yàn)證塊的過(guò)程。在這兩種情況下,對(duì)于要到「最終」?fàn)顟B(tài)的區(qū)塊有以下四個(gè)要求。
驗(yàn)證(如果是挖礦,就是判定)ommer:每個(gè)區(qū)塊頭中的每個(gè)ommer區(qū)塊都必須是一個(gè)有效的區(qū)塊頭,并且在當(dāng)前區(qū)塊的六代以內(nèi)。
驗(yàn)證(如果是挖礦,就是判定)交易:區(qū)塊上的gasUsed數(shù)字必須等于該區(qū)塊中所列交易所使用Gas的累積。
申請(qǐng)獎(jiǎng)勵(lì)(只限于挖礦的情況):受益人地址被授予5以太幣,用于開(kāi)采該區(qū)塊。 (根據(jù)以太坊EIP-649,這5個(gè)ETH的報(bào)酬將很快減少到3個(gè))。此外,對(duì)于每一個(gè) ommer,當(dāng)前區(qū)塊的受益者將額外獲得當(dāng)前區(qū)塊獎(jiǎng)勵(lì)的1/32。最后,ommer區(qū)塊的受益人也可以得到一定數(shù)額的賠償。
驗(yàn)證(如果挖礦,計(jì)算一個(gè)有效的)狀態(tài)和nonce:確保應(yīng)用所有交易和由此產(chǎn)生的狀態(tài)更改,在區(qū)塊獎(jiǎng)勵(lì)應(yīng)用于最終交易的結(jié)果狀態(tài)之后,定義新區(qū)塊的狀態(tài)。通過(guò)檢查這個(gè)最終狀態(tài)來(lái)驗(yàn)證存儲(chǔ)在區(qū)塊頭中的狀態(tài)。
挖礦的工作量證明
將區(qū)塊難度賦予意義的算法叫做「工作量證明」(PoW)。以太坊的工作量證明算法被稱為「Ethash」(之前被稱為Dagger-Hashimoto)。
該算法的公式如下:
這里m是mixHash、n是nonce、Hn是新區(qū)塊的頭(不包括nonce和mixHash組件)、Hn是塊頭的nonce、d是DAG(一個(gè)大數(shù)據(jù)集)。
還記得上面談到的在區(qū)塊頭中存在的mixHash和nonce兩個(gè)字段嗎?
mixHash是一個(gè)哈希,當(dāng)與nonce結(jié)合時(shí),可證明這個(gè)區(qū)塊執(zhí)行了足夠的計(jì)算;
nonce是一個(gè)哈希,當(dāng)與mixHash結(jié)合時(shí),可證明這個(gè)區(qū)塊已經(jīng)執(zhí)行了足夠的計(jì)算
PoW的功能就是評(píng)估這兩個(gè)字段。至于如何使用的PoW函數(shù)來(lái)精確計(jì)算mixHash和nonce說(shuō)起來(lái)有點(diǎn)復(fù)雜,但從總體上看,它的工作原理是這樣的。
每個(gè)區(qū)塊都算出一個(gè)「seed」,每個(gè)「epoch」對(duì)應(yīng)的seed都不相同,一個(gè)epoch相當(dāng)于3萬(wàn)個(gè)區(qū)塊的長(zhǎng)度。在第一個(gè)epoch,seed是一系列32字節(jié)零的哈希。對(duì)于后來(lái)的每一個(gè)epoch來(lái)說(shuō),它都是以前seed哈希的哈希。使用seed,一個(gè)節(jié)點(diǎn)可以計(jì)算一個(gè)偽隨機(jī)的「緩存」。
這個(gè)緩存非常有用,因?yàn)樗怪坝懻撨^(guò)的「輕節(jié)點(diǎn)」成為可能。輕節(jié)點(diǎn)的目的是為了使某些節(jié)點(diǎn)能夠有效地驗(yàn)證交易,而沒(méi)有存儲(chǔ)整個(gè)塊環(huán)鏈數(shù)據(jù)集的負(fù)擔(dān)。一個(gè)輕節(jié)點(diǎn)可以完全基于這個(gè)緩存來(lái)驗(yàn)證交易的有效性,因?yàn)榫彺婵梢灾匦律尚枰?yàn)證的特定區(qū)塊。
使用緩存,節(jié)點(diǎn)可以生成DAG數(shù)據(jù)集,數(shù)據(jù)集中的每個(gè)項(xiàng)都依賴于緩存中的少量偽隨機(jī)選擇(pseudo-randomly-selected)的項(xiàng)。為了成為一名礦工,必須生成這個(gè)完整的數(shù)據(jù)集;所有客戶和礦工都存儲(chǔ)這個(gè)數(shù)據(jù)集,并且數(shù)據(jù)集隨時(shí)間線性增長(zhǎng)。
然后,礦工們可以隨機(jī)抽取數(shù)據(jù)集的片段,然后通過(guò)數(shù)學(xué)函數(shù)將它們混合成一個(gè)mixHash。礦工將反復(fù)生成mixHash,直到輸出低于預(yù)期目標(biāo)的nonce。當(dāng)輸出滿足這個(gè)要求時(shí),這個(gè)nonce被認(rèn)為是有效的,并且塊可以添加到鏈上。
挖礦作為一種安全機(jī)制
總體而言,PoW的目的是以一種安全加密方式證明工作量,基于特定的計(jì)算量生成某些輸出(即nonce)。這是因?yàn)槌烁F舉所有可能性之外,沒(méi)有更好的辦法來(lái)找到低于要求閾值的nonce。重復(fù)應(yīng)用哈希函數(shù)的輸出具有均勻分布,因此我們可以確信,找到這樣一個(gè)nonce所需的平均時(shí)間取決于難度閾值。難度越大,解決問(wèn)題的時(shí)間就越長(zhǎng)。這樣,PoW算法對(duì)難度概念賦予了真實(shí)的意義,這個(gè)概念被用來(lái)增強(qiáng)區(qū)塊鏈的安全。
那么,區(qū)塊鏈安全又是指什么?很簡(jiǎn)單:就是要?jiǎng)?chuàng)建一個(gè)每個(gè)人都信任的區(qū)塊鏈。正如先前在本文中討論的那樣,如果存在一個(gè)以上的鏈,用戶將對(duì)其失去信任,因?yàn)樗麄儫o(wú)法合理地確定哪一個(gè)鏈?zhǔn)恰赣行У摹规?。為了讓一組用戶接受存儲(chǔ)在塊環(huán)鏈上的基本狀態(tài),需要一個(gè)大家都相信的且單一規(guī)范的區(qū)塊鏈。
而這正是PoW的作用:它確保一個(gè)特定的區(qū)塊鏈可以保持規(guī)范,使攻擊者難以創(chuàng)建新的區(qū)塊,或者覆蓋歷史的某一部分(例如擦除交易或創(chuàng)建虛假的交易),或者對(duì)一個(gè)分叉進(jìn)行維護(hù)。為了驗(yàn)證他們的區(qū)塊,攻擊者需要比網(wǎng)絡(luò)中的其他任何人都更快地解決nonce問(wèn)題,這樣網(wǎng)絡(luò)就會(huì)相信他們的鏈條是最重鏈(基于之前提到的GHOST協(xié)議的原則)。這是基本上不可能的,除非攻擊者擁有超過(guò)一半的網(wǎng)絡(luò)挖掘能力,因此這種情況被稱為「51%攻擊」。
挖礦作為一種財(cái)富分配機(jī)制
除了確保一個(gè)安全的區(qū)塊鏈環(huán)境,對(duì)那些為了提供這種安全而消耗算力的人,Pow還是一種分配財(cái)富的方式?;叵胍幌?#xff0c;礦工在開(kāi)采一個(gè)區(qū)塊時(shí)會(huì)得到獎(jiǎng)勵(lì),其中包括:
「獲勝」區(qū)塊獲得的5以太幣(不久將改為3以太幣)的獎(jiǎng)賞;
該區(qū)塊所包括的交易在區(qū)塊內(nèi)消耗的Gas成本;
將ommer作為區(qū)塊的一部分的額外獎(jiǎng)勵(lì)。
從長(zhǎng)遠(yuǎn)來(lái)看,為了確保PoW機(jī)制在安全和財(cái)富分配方面的使用是可持續(xù)的,以太坊努力培養(yǎng)它的兩個(gè)特性:
讓盡可能多的人能夠接觸到它,換句話說(shuō),人們不應(yīng)該需要專門的硬件來(lái)運(yùn)行算法,這樣做的目的是使財(cái)富分配模型盡可能開(kāi)放,以便任何人都可以根據(jù)自身的情況提供計(jì)算能力,以換取以太幣。
減少單個(gè)節(jié)點(diǎn)(或小集)產(chǎn)生不成比例利潤(rùn)的可能性,任何節(jié)點(diǎn),如果能夠獲得不成比例的利潤(rùn),就意味著節(jié)點(diǎn)對(duì)規(guī)范區(qū)塊鏈的確定有很大的影響,這會(huì)降低網(wǎng)絡(luò)的安全性。
在比特幣區(qū)塊鏈網(wǎng)絡(luò)中,與上述兩個(gè)屬性有關(guān)的一個(gè)問(wèn)題是,PoW算法是一個(gè) SHA256哈希函數(shù)。這類函數(shù)的弱點(diǎn)在于,它可以通過(guò)使用專門的硬件更有效地解決問(wèn)題,也就是所謂的ASIC。
為了解決這一問(wèn)題,以太坊選擇了將PoW算法按順序存儲(chǔ)到內(nèi)存硬件中。這意味著這個(gè)算法是經(jīng)過(guò)設(shè)計(jì)的,所以計(jì)算nonce需要大量的內(nèi)存和帶寬。大量的內(nèi)存需求使得計(jì)算機(jī)很難同時(shí)使用它的內(nèi)存來(lái)同時(shí)發(fā)現(xiàn)多個(gè)nonce,而且高帶寬的要求使得即使是超級(jí)計(jì)算機(jī)也很難同時(shí)發(fā)現(xiàn)多個(gè)nonce。這減少了集中化的風(fēng)險(xiǎn),也為正在進(jìn)行驗(yàn)證的節(jié)點(diǎn)創(chuàng)建了一個(gè)更公平的機(jī)制。
需要注意的是,以太坊正在從PoW機(jī)制過(guò)渡到PoS機(jī)制,這又是另一個(gè)話題了,希望可以在今后的文章中探討。
結(jié)束語(yǔ)
終于到底了,這篇文章是不是有很多東西需要消化?
如果真的對(duì)以太坊感興趣,建議可以多讀幾次。我也是親自閱讀了以太坊的白皮書和代碼,然后才搞清楚以太坊要做的究竟是什么。還是那句話,你無(wú)需理解文章的每一個(gè)細(xì)節(jié),只要力求對(duì)整理原理有把握就很不錯(cuò)了。
總結(jié)
以上是生活随笔為你收集整理的以太坊完整工作原理和运行机制!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三天竟然爆发两起大漏洞事件!我们来教你如
- 下一篇: 区块链去中心化的生命之源:“DPOS(委