大概整整兩年前辐赞,我從一篇介紹“區(qū)塊鏈”技術(shù)的文章里知道了“以太坊”這個項(xiàng)目部翘,當(dāng)時當(dāng)然沒想到它會對我個人產(chǎn)生如此大的影響。在其后這兩年時間里响委,我投入了大量的時間和精力來學(xué)習(xí)它新思、研究它窖梁,做了多次技術(shù)分享,甚至還寫了講解智能合約開發(fā)的書夹囚、開發(fā)了關(guān)于智能合約開發(fā)的在線課程纵刘;所以不管未來我們各自的走向如何,以太坊都已經(jīng)在我生命中留下了重重的一筆荸哟。在我們相識兩周年之際彰导,我覺得我總該要寫點(diǎn)兒什么。
新年的這第一個月我過的很充實(shí):只感了兩次冒敲茄,每次大概半個月……。本來我是計劃在月底前寫完技術(shù)專題“工程師眼中的比特幣和以太坊”的山析,可惜也無奈地再次被教育了:“年齡不是問題堰燎,但身體是問題∷窆欤”所以臨近月底只能以這篇文章勉強(qiáng)交個作業(yè)吧秆剪。
2017 年底的時候,我曾在簡書發(fā)過一篇博客爵政,介紹“以太坊是什么”仅讽,但那是一篇對以太坊 Homestead 官方文檔的翻譯稿節(jié)選〖匦客觀地講洁灵,當(dāng)時我本人對以太坊的理解也還不是非常深入透徹,所以這篇原創(chuàng)的“再談:以太坊是什么”還是有一些參考價值的掺出,我相信這篇文章也許比一年前的那篇翻譯稿更好懂一些徽千,而且真正講出了一些“本質(zhì)性”的基本概念。
當(dāng)然汤锨,這不是一篇 hardcore 的技術(shù)文章双抽,我的初衷是基于我本人對以太坊的理解确丢,從概念上給那些還不是很清楚地知道“以太坊是什么”的朋友做一個簡單的掃盲简肴。這也是我寫這個新的技術(shù)專題的初衷:我希望讓更多軟件工程師能了解區(qū)塊鏈、了解智能合約稚补,希望有更多的人能真正搞懂一些最基本的概念柬泽,并以此為契機(jī)深入到區(qū)塊鏈和智能合約的世界中慎菲。因?yàn)楸疚牡闹黧w內(nèi)容選自我的技術(shù)專題“工程師眼中的比特幣和以太坊”,所以文中對比特幣系統(tǒng)技術(shù)細(xì)節(jié)的引述可能會略顯突兀锨并、缺少鋪墊钧嘶;如果你對比特幣的技術(shù)細(xì)節(jié)還不了解,也可能會引起一些迷惑琳疏,對此我也表示歉意有决。不過我還是希望你能喜歡本文的內(nèi)容和講解方式闸拿;此外如果能給我提供任何形式的反饋,我也將感激不盡书幕。
完整閱讀本文約需要 15 到 20 分鐘新荤。
時間已經(jīng)來到了 2019 年 1 月,相信對很多人來講台汇,“區(qū)塊鏈”這個詞恐怕已經(jīng)不陌生了苛骨,并且大概也已經(jīng)聽過“比特幣”的名號;不過苟呐,如果有人問你:“以太坊是什么”痒芝,你能夠很清晰、準(zhǔn)確地給他解釋清楚嗎牵素?
我想如果你看過“以太坊白皮書(Ethereum White Paper)”严衬,你大概會用它的標(biāo)題來回答這個問題:“A Next-Generation Smart Contract and Decentralized Application Platform”,翻成中文就是“下一代的智能合約和去中心化應(yīng)用程序平臺”笆呆。沒錯请琳,這很權(quán)威,也很準(zhǔn)確赠幕。但是俄精,我想即使對于軟件工程師來講,這個答案中引入的兩個新概念“智能合約”和“去中心化應(yīng)用程序”其實(shí)也并不那么“一目了然”榕堰。顯然竖慧,我們不應(yīng)該用未知的概念去解釋其他未知的概念。不過我想這仍然稱得上是一個不錯的開端逆屡,就讓我先沿著這個思路聊聊“智能合約”和“去中心化應(yīng)用程序”吧测蘑。
什么是智能合約
智能合約(Smart Contract)這個詞最初是由一位美國的計算機(jī)科學(xué)博士尼克薩博(Nick Szabo)在他 1997 年發(fā)表的一篇論文中提出來的。智能合約指的是一種基于計算機(jī)技術(shù)實(shí)現(xiàn)的康二,可以免除人工干預(yù)而自動執(zhí)行碳胳、自動校驗(yàn)、自動基于外部指令給出回應(yīng)的具有交互性或者互操作性的合約沫勿;其本質(zhì)是一種計算機(jī)程序挨约。這個概念本身相對比較抽象,所以尼克薩博本人在后來的一些訪談中曾經(jīng)用自動取款機(jī)或者自動售貨機(jī)來作為智能合約的物理實(shí)例产雹;它們就是基于某些公開的诫惭、眾所周知的規(guī)則,能夠根據(jù)用戶的指令和實(shí)際業(yè)務(wù)數(shù)據(jù)的狀態(tài)給出可預(yù)期的回應(yīng)的這樣一種應(yīng)用程序蔓挖。
比如我們?nèi)プ詣邮圬洐C(jī)購買某種商品夕土,我們先要選擇商品和購買數(shù)量,如果自動售貨機(jī)中庫存不足,它應(yīng)該會給出相應(yīng)的提示怨绣;如果庫存充足角溃,它會提示用戶進(jìn)行實(shí)際支付,比如用現(xiàn)金或者電子支付篮撑;如果支付金額不足减细,它會給出提示,并繼續(xù)等待赢笨,直到支付金額足夠或者用戶取消交易;如果支付金額足夠茧妒,它們就會吐出正確數(shù)量的商品萧吠,并進(jìn)行找零。自動售貨機(jī)在這整個過程中對用戶操作的響應(yīng)應(yīng)該是確定的桐筏、可預(yù)測的纸型、可自動完成的,當(dāng)然也應(yīng)該是正確的九昧。那么能夠基于實(shí)際情況給出這些正確響應(yīng)的程序,就可以認(rèn)為是智能合約毕匀。
當(dāng)然铸鹰,其實(shí)這個過程并不“智能”,從某種意義講皂岔,也并不是“合約”蹋笼。所以這個詞從其誕生開始就有一些爭議,尤其是它會給一些不明所以的用戶某種程度的誤解躁垛。從本質(zhì)來看剖毯,所謂“智能合約”實(shí)際上只是一種可以基于某種狀態(tài)數(shù)據(jù)自動給出回應(yīng)的應(yīng)用程序而已。不過出于歷史原因教馆,“智能合約”的叫法還是被業(yè)內(nèi)接受并延用了下來逊谋。
智能合約有什么用
這里我僅舉兩個最簡單的例子來解釋智能合約的意義。
首先是一個租房合約的例子土铺。比如我和房東訂立了一個租房合約胶滋,約定我每月付給房東 1000 元房租,合約期限為一年悲敷。在沒有智能合約的情況下究恤,這個合約的履行是需要很多人工介入的,我付錢的動作必須由我主動完成后德;如果出現(xiàn)意外情況部宿,也需要第三方的介入才能解決,比如中介機(jī)構(gòu)的居間調(diào)停乃至民事訴訟瓢湃、強(qiáng)制執(zhí)行等等理张。而如果有一種無需信任的智能合約平臺赫蛇,這整個過程就可以變?yōu)橄旅孢@樣:
我和房東可以在某個智能合約平臺上訂立一個智能合約,創(chuàng)建合約的時候涯穷,我將一年的租金鎖定到合約里棍掐,然后從訂立合約開始,每經(jīng)過一個月拷况,房東可以從合約中提取一個月的租金作煌,直到合約期限完結(jié)或者經(jīng)雙方確認(rèn)中止合約,合約自動給我退回剩余未支付的租金赚瘦。這樣的場景是可以在像以太坊這樣的智能合約平臺上簡單實(shí)現(xiàn)的粟誓,這整個過程無需任何第三方介入,并且可以保證執(zhí)行的過程嚴(yán)格按照約定的條件完成起意。
請注意鹰服,這個過程是“無需信任(trustless)”的。也就是合約雙方不需要相互認(rèn)識乃至相互信任揽咕,而是基于一種不可篡改悲酷、不可抵賴、不可逆轉(zhuǎn)的自動化的技術(shù)方案保證了整個過程的可信性亲善,同時不需要任何第三方的介入设易。這就是智能合約帶來的最重要的特性。
當(dāng)然蛹头,這個例子中的一些細(xì)節(jié)是和我們普遍采用的人工處理的方式有差異的:比如我要支付的一年的租金是需要在訂立合約時就要鎖定到合約里的顿肺,而不是可以像人工操作的方式那樣每月提供;又比如要中止合約時是需要雙方確認(rèn)的渣蜗,如果有一方故意不進(jìn)行確認(rèn)屠尊,那么合約會被鎖死,這需要事先考慮到耕拷,并在合約中設(shè)計相應(yīng)的解決方法讼昆。不過即使存在實(shí)操上的差異,這種自動化的骚烧、不可抵賴的智能合約選項(xiàng)依然稱得上是一種進(jìn)步控淡。
第二個例子是一個簡單的保險。比如某地區(qū)的一個農(nóng)民可以與某保險公司訂立一份合約止潘,合約條款大概可以是這樣:該農(nóng)民于今年 6 月 30 日前支付 x 元保險費(fèi)給保險公司掺炭;如果今年 7 月到 9 月某地區(qū)的平均降雨量不足 100 毫米,則農(nóng)民可以在 9 月 30 日之后得到 y 元的保險賠償凭戴;否則無需賠償涧狮。
這個保險,同樣可以用像以太坊這樣的智能合約平臺簡單地實(shí)現(xiàn):農(nóng)民和保險公司可以在 6 月 30 日之前訂立合約,農(nóng)民將 x 元者冤、保險公司將 y 元同時鎖定到這個合約中肤视;在 9 月 30 日之后,農(nóng)民或者保險公司都可以向合約申請執(zhí)行涉枫;合約可以自動從無利益關(guān)系的第三方公共服務(wù)(比如氣象臺網(wǎng)站)獲取 7 月到 9 月的降水量信息邢滑;如果降水量低于 100 毫米,則將 x + y 元支付給農(nóng)民愿汰,反之則將 x + y 元支付給保險公司困后。這整個過程同樣無需人工介入,可以基于智能合約自動完成衬廷。
這個例子中提到的“無利益關(guān)系的第三方公共服務(wù)”摇予,通常是通過一種區(qū)塊鏈系統(tǒng)/智能合約平臺以外的獨(dú)立數(shù)據(jù)源來提供的。這是因?yàn)閰^(qū)塊鏈系統(tǒng)本身無法產(chǎn)生或者直接獲取某些特定的數(shù)據(jù)吗跋,比如天氣數(shù)據(jù)侧戴、股票價格等等,那么就需要獨(dú)立的“鏈外”數(shù)據(jù)提供方來提供具體的數(shù)據(jù)跌宛。這種提供鏈外數(shù)據(jù)的服務(wù)酗宋,也就是所謂的“預(yù)言機(jī)(Oracle)”。因?yàn)楸疚闹皇菕呙ば再|(zhì)疆拘,這里不再具體展開了蜕猫。
所以,從邏輯概念上看入问,智能合約可以理解為一種會經(jīng)過“技術(shù)公證”的狀態(tài)存儲和狀態(tài)轉(zhuǎn)換(也就是程序執(zhí)行)丹锹,以此來確保這個過程“無需信任”稀颁。(稍后我會從技術(shù)角度來解釋這個概念芬失。)
去中心化應(yīng)用程序又是什么
在理解了智能合約的概念之后,再來理解去中心化應(yīng)用程序就比較容易了匾灶。
目前的絕大多數(shù) Web 應(yīng)用棱烂,其用戶數(shù)據(jù)都是保存在由某個公司、組織或者個人控制的“服務(wù)器”或者“服務(wù)器組”之中的阶女,這些應(yīng)用中的絕大部分業(yè)務(wù)計算颊糜,也是由這些服務(wù)器或者服務(wù)器組來提供的;所以這種模式秃踩,可以認(rèn)為是一種“中心化(centralized)”的模式衬鱼。
那么“去中心化應(yīng)用程序(Decentralized Application)”,也就是將數(shù)據(jù)保存到“基于點(diǎn)對點(diǎn)網(wǎng)絡(luò)的時間戳服務(wù)器(即區(qū)塊鏈)”這樣的憔杨,并不是由中心化的公司或組織控制的服務(wù)中鸟赫,并且由這樣的“去中心化”服務(wù)來提供具體的業(yè)務(wù)數(shù)據(jù)計算能力的一種應(yīng)用程序。“去中心化應(yīng)用程序”也可以簡單地理解為是基于智能合約進(jìn)行狀態(tài)追蹤和計算的一種應(yīng)用程序抛蚤。
這里的“基于點(diǎn)對點(diǎn)網(wǎng)絡(luò)的時間戳服務(wù)器”的說法是出自比特幣白皮書台谢,這也是“區(qū)塊鏈”一詞的原始出處。
當(dāng)然岁经,對于一個應(yīng)用程序來講朋沮,并不是所有運(yùn)算都需要用智能合約來實(shí)現(xiàn),通常也不應(yīng)該這樣設(shè)計缀壤;而是應(yīng)該根據(jù)業(yè)務(wù)需求樊拓,將那些需要做“全網(wǎng)公證”的狀態(tài)計算在智能合約中實(shí)現(xiàn),來使應(yīng)用程序獲得某些“無需信任”的可信性诉位。
好了骑脱,在了解了智能合約和去中心化應(yīng)用程序的基本概念之后,我相信你已經(jīng)大概知道以太坊是什么了苍糠。這里再重復(fù)一下:以太坊就是一個智能合約和去中心化應(yīng)用程序平臺叁丧。 不過,我還有第二種答案岳瞭。請你稍安勿躁拥娄,讓我嘗試基于以太坊的總體設(shè)計思路和技術(shù)方案概要來慢慢為你揭曉。
以太坊的誕生
與比特幣不同瞳筏,以太坊白皮書的作者不是匿名的稚瘾,它的初稿是由 Vitalik Buterin 于 2013 年底完成的。Vitalik 在 1994 年出生于俄羅斯姚炕,后來隨父母移居加拿大摊欠,在寫出以太坊白皮書的時候,他只有 19 歲柱宦,剛剛從滑鐵盧大學(xué)大一輟學(xué)些椒。不過,在他寫出以太坊白皮書之前掸刊,他已經(jīng)是一個知名的比特幣研究者和寫作者免糕,他也是在 2011 年創(chuàng)刊的世界上第一個加密貨幣期刊——Bitcoin Magazine 的聯(lián)合創(chuàng)始人∮遣啵可以說石窑,以太坊白皮書并不是像比特幣白皮書那樣“憑空出現(xiàn)的”。Vitalik 本人從 2013 年下半年就開始思考如何對比特幣的腳本系統(tǒng)進(jìn)行擴(kuò)展來支持“通用目的”的計算任務(wù)蚓炬。
2013 年 12 月松逊,Vitalik 完成了以太坊白皮書,并在小范圍內(nèi)進(jìn)行了分享肯夏,引起了一些業(yè)內(nèi)人士的關(guān)注经宏,其中就包括了“精通比特幣(Mastering Bitcoin)”一書的作者 Andreas M. Antonopoulos楼咳,但他當(dāng)時在忙于寫作精通比特幣,所以并未直接參與以太坊創(chuàng)建初期的具體工作烛恤。真正在工程上幫助 Vitalik 實(shí)現(xiàn)了以太坊這個偉大構(gòu)想的則是 Gavin Wood 博士母怜。
Gavin Wood 博士是英國約克大學(xué)的計算機(jī)科學(xué)博士,在以太坊項(xiàng)目最初的兩年里缚柏,他是在工程上貢獻(xiàn)最大的人:他于 2014 年 1 月完成了以太坊的 PoC-1(即第一個概念驗(yàn)證程序苹熏,也是以太坊的 C++ 客戶端的最初原型);隨后在 3 月發(fā)表了以太坊黃皮書(即以太坊協(xié)議的細(xì)節(jié)說明和技術(shù)手冊币喧,是實(shí)現(xiàn)以太坊客戶端的基礎(chǔ)技術(shù)資料轨域,在工程上具有極其重要的指導(dǎo)意義,它也是我們了解和學(xué)習(xí)以太坊協(xié)議技術(shù)細(xì)節(jié)的主要參考資料)杀餐;同年 8 月公布了專門為智能合約開發(fā)而設(shè)計的高級語言 Solidity干发。
2015 年 7 月 30 日,以太坊主網(wǎng)正式上線史翘,創(chuàng)世區(qū)塊產(chǎn)生枉长,世界上第一個成功的公共智能合約平臺才真正誕生。
以太坊的開創(chuàng)意義在于:它借鑒了由比特幣系統(tǒng)創(chuàng)造出來的“通過工作量證明算法達(dá)成共識的琼讽、基于點(diǎn)對點(diǎn)網(wǎng)絡(luò)的時間戳服務(wù)器”(也就是所謂的“區(qū)塊鏈”)必峰,構(gòu)建出了一種可以執(zhí)行“通用目的”計算任務(wù)的基礎(chǔ)設(shè)施,將“區(qū)塊鏈”的可編程性提升到了一個新的高度钻蹬;創(chuàng)造出了真正的“智能合約”平臺吼蚁。
區(qū)塊鏈范式
從技術(shù)層面講,我們可以把類似于比特幣這樣的问欠、通過分布式共識進(jìn)行“公證”的公共賬本系統(tǒng)(也就是所謂的“區(qū)塊鏈”)抽象地理解為一個“狀態(tài)轉(zhuǎn)換系統(tǒng)(state transition system)”肝匆。這種系統(tǒng)會維持一個“全局的狀態(tài)”(我們用 S 來表示),然后通過系統(tǒng)中發(fā)生的“交易”(我們用 tx 來表示)來進(jìn)行相應(yīng)的狀態(tài)轉(zhuǎn)換以達(dá)到一個“新的全局狀態(tài)”(我們用 S' 來表示)顺献。那么這種狀態(tài)轉(zhuǎn)換就可以抽象地表示為:Apply(S, tx) = S'
旗国,其中的 Apply 即“狀態(tài)轉(zhuǎn)換函數(shù)”。
下圖是比特幣中的狀態(tài)轉(zhuǎn)換示意:
圖中用 <txid>:<output_index>
的形式來表示某個 UTXO:其中 txid
即交易哈希滚澜,用來標(biāo)識某個具體的交易粗仓;output_index
即交易生成的輸出(UTXO)的索引嫁怀。
UTXO设捐,即 Unspent Transaction Output,是基于比特幣的數(shù)據(jù)模型產(chǎn)生的一個術(shù)語塘淑。比特幣中的交易都是由若干輸入(Input)和若干輸出(Output)組成的萝招。按照協(xié)議約定,一個輸入必定是某個歷史交易的某個輸出的引用存捺,通過在輸入中包含特定的“解鎖腳本(unlocking script)”來對歷史交易的輸出中指定的“鎖定腳本(locking script)”進(jìn)行解鎖槐沼,以此來“消耗/使用(spend)”相應(yīng)的輸出曙蒸。那些未被任何“輸入”引用過的“輸出”就是 UTXO。
如上圖所示岗钩,比特幣中的交易會消耗/使用若干 UTXO纽窟,并通過合并和拆分來生成等量的新的 UTXO。上圖中的實(shí)例就是通過 7b53ab84 這個交易的第 1 個輸出和 3ce6f712 這個交易的第 2 個輸出來生成了 3 個新的 UTXO兼吓,即 bb75a980 這個交易(也就是上圖中這個交易)的輸出 0臂港、1 和 2。于是视搏,系統(tǒng)整體的狀態(tài)审孽,就從 5 個 UTXO 變?yōu)榱?6 個 UTXO。
所以浑娜,比特幣系統(tǒng)其實(shí)就是一個對當(dāng)前系統(tǒng)中所有可用的 UTXO 的狀態(tài)記錄佑力,它通過一個具體交易來對當(dāng)前可用的若干 UTXO 進(jìn)行合并和拆分來生成新的 UTXO,并將系統(tǒng)狀態(tài)轉(zhuǎn)換為新的 UTXO 集合筋遭;同時打颤,這個過程是在一個點(diǎn)對點(diǎn)網(wǎng)絡(luò)中進(jìn)行“全網(wǎng)公證”的。
考慮到像比特幣這樣的“區(qū)塊鏈”系統(tǒng)是以區(qū)塊為單位來打包記錄交易的漓滔,我們其實(shí)已經(jīng)可以對“區(qū)塊鏈”下一個技術(shù)上的定義了:“區(qū)塊鏈”瘸洛,其實(shí)就是一個通過交易來觸發(fā)狀態(tài)變動,并以區(qū)塊為單位來記錄狀態(tài)變動的狀態(tài)轉(zhuǎn)換系統(tǒng)次和。剛剛介紹過的狀態(tài)轉(zhuǎn)換范式 Apply(S, tx) = S'
反肋,也就是所謂的“區(qū)塊鏈范式(blockchain paradigm)”。
請注意踏施,這是一個通用的范式石蔗,它適用于比特幣,也適用于以太坊畅形,并且同樣適用于其他類似于比特幣和以太坊這樣的基于“區(qū)塊鏈”的分布式共識賬本系統(tǒng)养距。而不同的區(qū)塊鏈系統(tǒng)的差別就在于如何表示系統(tǒng)中的狀態(tài)以及如何定義狀態(tài)轉(zhuǎn)換函數(shù)(也就是交易)。
那么日熬,對于目標(biāo)是要實(shí)現(xiàn)一個“智能合約平臺”的以太坊來講棍厌,使用比特幣的 UTXO 模型來保存系統(tǒng)狀態(tài)和構(gòu)造交易數(shù)據(jù)可行么?
以太坊的“賬戶模型”和“存儲”
在剛剛介紹智能合約的概念時我提到過:智能合約其實(shí)可以看作是一種用于記錄和修改“狀態(tài)”的應(yīng)用程序竖席。從計算機(jī)科學(xué)的角度來看耘纱,這其實(shí)就是“狀態(tài)機(jī)(state machine)”。每個智能合約毕荐,都可以看作是一個自定義的狀態(tài)機(jī)束析。那么對于“智能合約平臺”而言,最關(guān)鍵的特性就是允許用戶自定義狀態(tài)機(jī)憎亚,同時保證這些自定義狀態(tài)機(jī)可以自動地员寇、正確地弄慰、不可篡改地執(zhí)行,且執(zhí)行過程應(yīng)該被進(jìn)行“技術(shù)公證”蝶锋,以此來保證合約參與方之間“無需信任”陆爽。
很明顯,“技術(shù)公證”的問題已經(jīng)被比特幣解決了:我們只需要把所有自定義狀態(tài)機(jī)的狀態(tài)數(shù)據(jù)保存到區(qū)塊鏈上扳缕,通過工作量證明算法達(dá)成共識墓陈,實(shí)際上就實(shí)現(xiàn)了對自定義狀態(tài)數(shù)據(jù)的“全網(wǎng)公證”。但是第献,如何將“自定義狀態(tài)”保存到區(qū)塊鏈上呢贡必?比特幣的 UTXO 模型能夠做到么?
簡單地說庸毫,參考業(yè)內(nèi)到目前為止的研究和工程實(shí)踐成果仔拟,基于 UTXO 模型來保存自定義狀態(tài)數(shù)據(jù)大概是可行的,但相對而言會非常復(fù)雜飒赃,或者需要一些特殊的簡化或限制利花。(因?yàn)槠颍@里不做詳細(xì)解釋了载佳。)所以以太坊采用了簡單直接的“賬戶模型(account model)”炒事,這與我們已經(jīng)非常熟悉的大部分中心化軟件系統(tǒng)中所使用的數(shù)據(jù)模型非常相似。
在以太坊的賬戶模型中蔫慧,用“地址(address)”來作為賬戶的全局唯一標(biāo)識挠乳,將自定義狀態(tài)數(shù)據(jù)與地址進(jìn)行綁定來實(shí)現(xiàn)快速查找、增刪和修改姑躲;這種思路就像我們在傳統(tǒng)的業(yè)務(wù)系統(tǒng)中所使用的賬戶數(shù)據(jù)模型那樣睡扬,通過唯一的用戶賬戶標(biāo)識來關(guān)聯(lián)所有業(yè)務(wù)數(shù)據(jù)。這可以說是一種為了實(shí)現(xiàn)通用應(yīng)用平臺而進(jìn)行的工程上的設(shè)計妥協(xié)和技術(shù)簡化黍析。
在賬戶模型中卖怜,每個賬戶都有一個表示其可用“余額(balance)”的字段,來記錄其以太幣(以太坊協(xié)議中的代幣)數(shù)量阐枣。而在比特幣系統(tǒng)中马靠,一個所謂的“賬戶”是可以持有(使用)多個 UTXO 的,我們在客戶端或者錢包中看到的“賬戶余額”實(shí)際上是這個賬戶持有的(可以使用的)所有 UTXO 的比特幣數(shù)量之和蔼两。比特幣中的交易是對可用 UTXO 的合并和拆分甩鳄,而不是像賬戶模型這樣直接對余額數(shù)值進(jìn)行增減。
以太坊中的“賬戶”宪哩,邏輯上分為兩種:EOA(External Owned Account娩贷,即由外部用戶基于橢圓曲線數(shù)字簽名的私鑰控制的賬戶)和 Contract Account(即合約賬戶)第晰。不過從基礎(chǔ)數(shù)據(jù)上看锁孟,這兩種賬戶是一樣的彬祖,它們的區(qū)別僅在于賬戶是否與合約代碼相關(guān)聯(lián):如果一個賬戶沒有關(guān)聯(lián)代碼,它就是 EOA品抽;否則它就是合約賬戶储笑。
應(yīng)該注意到,對于自定義狀態(tài)機(jī)來講圆恤,需要持久化保存的應(yīng)該是自定義狀態(tài)數(shù)據(jù)和用來修改狀態(tài)數(shù)據(jù)的可執(zhí)行代碼突倍,這其實(shí)就是所謂的“合約狀態(tài)”和“合約代碼”。對于智能合約平臺來講盆昙,必須能夠持久化地保存這兩種數(shù)據(jù)羽历。基于賬戶模型淡喜,以太坊使用了一個全局的數(shù)據(jù)結(jié)構(gòu)來保存所有的合約狀態(tài)和合約代碼秕磷。因?yàn)楹霞s是可以由用戶自定義的,所以保存這些數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)必須是可以進(jìn)行高效的動態(tài)查找炼团、增刪和修改的澎嚣,并且是可以進(jìn)行簡單驗(yàn)證的。以太坊中就使用了一種叫做 Merkle Patricia Tree(簡稱 MPT)的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)這一點(diǎn)瘟芝。
MPT 與比特幣系統(tǒng)使用的 Merkle Tree 類似易桃,也是一種“哈希樹”,所以它們具有相同的特性:任意葉節(jié)點(diǎn)數(shù)據(jù)的變動都會導(dǎo)致根節(jié)點(diǎn)哈希的變動锌俱,所以根節(jié)點(diǎn)哈衔钪#可以用來標(biāo)識樹中所有數(shù)據(jù)的某個特定的版本∶澈辏基于這個原理贩汉,就可以在點(diǎn)對點(diǎn)網(wǎng)絡(luò)的參與者之間通過由各個客戶端分別維護(hù)的一個全局 MPT 的根節(jié)點(diǎn)哈希來驗(yàn)證所有自定義狀態(tài)數(shù)據(jù)、賬戶余額和代碼數(shù)據(jù)的版本一致性锚赤。這個全局的 MPT 也就是以太坊的“狀態(tài)樹(state tree)”匹舞,它相當(dāng)于比特幣系統(tǒng)中所有可用 UTXO 的全集。
以太坊中用來保存所有自定義狀態(tài)數(shù)據(jù)的全局 MPT 被稱為“存儲(storage)”线脚,它是獨(dú)立于“狀態(tài)樹”之外的另一個全局 MPT赐稽,但因?yàn)槠涓?jié)點(diǎn)哈希是作為賬戶數(shù)據(jù)的一個字段來保存的,所以它實(shí)際上也是“狀態(tài)樹”的一部分浑侥。
以太坊中的每個合約賬戶都可以在“存儲”中使用若干“存儲單元(storage slot)”:每個合約的代碼中可以自定義若干狀態(tài)數(shù)據(jù)姊舵,每個狀態(tài)數(shù)據(jù)對應(yīng)一個或多個“存儲單元”;這些存儲單元都可以通過簡單的尋址算法進(jìn)行存取操作寓落。這就是以太坊的持久化數(shù)據(jù)存儲方案括丁。
以太坊中的“狀態(tài)轉(zhuǎn)換”
基于“賬戶模型”和“存儲”,以太坊中的狀態(tài)轉(zhuǎn)換自然也就有了不同的形式伶选。下圖是以太坊中的狀態(tài)轉(zhuǎn)換示意:
圖中演示了以太坊中的一個由交易引發(fā)的狀態(tài)轉(zhuǎn)換:在初始狀態(tài) State 中史飞,14c5f8ba尖昏、bb75a980、892bf92f 和 4096ad65 代表了 4 個賬戶地址构资,其中 14c5f8ba 和 4096ad65 是 EOA抽诉,bb75a980 和 892bf92f 則為合約賬戶(因?yàn)橛嘘P(guān)聯(lián)代碼)。然后圖中所示的交易吐绵,其邏輯意義也很簡單迹淌,即從 14c5f8ba 向 bb75a980 發(fā)送 10 以太幣,并附加了一些額外的數(shù)據(jù) Data己单,這個 Data 數(shù)據(jù)的意思是將目標(biāo)合約的第 2 個“存儲單元”的數(shù)值設(shè)定為“CHARLIE”唉窃。這個交易的執(zhí)行會產(chǎn)生一個新的狀態(tài) State',其中 14c5f8ba 地址的余額減少了 10 以太幣纹笼,bb75a980 地址的余額增加了 10 以太幣句携,并且 bb75a980 地址的第 2 個“存儲單元”的數(shù)值變?yōu)榱恕癈HARLIE”。
很明顯允乐,因?yàn)榛A(chǔ)數(shù)據(jù)模型的改動矮嫉,以太坊中的狀態(tài)轉(zhuǎn)換與比特幣中的狀態(tài)轉(zhuǎn)換幾乎完全不同。與之相應(yīng)地牍疏,構(gòu)造交易蠢笋、驗(yàn)證數(shù)據(jù)等等的邏輯自然也會完全不同。當(dāng)然鳞陨,這里只是一個示意介紹昨寞,實(shí)際上在以太坊的交易中附加的 data 是一種“可執(zhí)行代碼”,是可以由用戶自定義的厦滤,用戶可以用這些具體的代碼來執(zhí)行任意的計算任務(wù)援岩;這種方式與在比特幣交易的輸入和輸出中附加腳本代碼是類似的。
以太坊中的“可執(zhí)行代碼”
在以太坊協(xié)議中掏导,我們可以在交易的 data 字段中附加一種特殊的“可執(zhí)行代碼”來完成任意的計算任務(wù)享怀,這種“可執(zhí)行代碼”是在一個虛擬的執(zhí)行環(huán)境中運(yùn)行的。與比特幣腳本系統(tǒng)的執(zhí)行環(huán)境類似趟咆,以太坊的這種虛擬執(zhí)行環(huán)境也是基于“棧(stack)”的添瓷;但以太坊的虛擬執(zhí)行環(huán)境還提供了可以供應(yīng)用程序在運(yùn)行時使用的臨時存儲空間“內(nèi)存(memory)”和剛剛介紹過的永久存儲機(jī)制“存儲(storage)”。這就使以太坊的虛擬執(zhí)行環(huán)境有了更強(qiáng)的計算能力值纱,更像是一種“虛擬的計算機(jī)”鳞贷,這個虛擬的執(zhí)行環(huán)境就是大名鼎鼎的“以太坊虛擬機(jī)(Ethereum Virtual Machine,簡稱 EVM)”虐唠,EVM 也是以太坊被稱為“世界計算機(jī)(World Computer)”的由來搀愧,它也是以太坊與比特幣相比在技術(shù)層面的最大創(chuàng)新。
以太坊協(xié)議中的這種可以在 EVM 中運(yùn)行的“可執(zhí)行代碼”就是所謂的“EVM 字節(jié)碼”。EVM 字節(jié)碼是以太坊計算能力的根本咱筛,這是一種“圖靈完備(Turing-complete)”的操作碼系統(tǒng)搓幌。以太坊的高級開發(fā)語言 Solidity 就可以編譯為 EVM 字節(jié)碼,然后在 EVM 中運(yùn)行眷蚓;這種方式與其他編譯型的高級語言是類似的鼻种,就像 Java 語言和 Java 虛擬機(jī)字節(jié)碼的關(guān)系那樣反番。
EVM 字節(jié)碼的圖靈完備性沙热,也是其與比特幣的腳本系統(tǒng)相比最大的區(qū)別。圖靈完備性標(biāo)志著 EVM 字節(jié)碼可以用來完成任意的計算任務(wù)罢缸,同時因?yàn)?EVM 中還提供了臨時存儲機(jī)制和永久存儲機(jī)制篙贸,這才使以太坊成為了真正的可以完成“通用目的(general propose)”計算任務(wù)的“智能合約平臺”。
小結(jié)
至此枫疆,我想我可以再回答一下“以太坊是什么”這個問題了:以太坊其實(shí)就是“區(qū)塊鏈”+“以太坊虛擬機(jī)”爵川。 就本文的目的而言,你記住這個答案就夠了息楔。
當(dāng)然寝贡,以太坊并不像本文中說的這么簡單,還有許許多多的技術(shù)細(xì)節(jié)等待著你去學(xué)習(xí)理解值依,文中所提及的術(shù)語大多也可以進(jìn)行更多的技術(shù)解讀圃泡。但就像我在引言中說的那樣,本文的目的僅僅是去嘗試解釋一些最基本愿险、最重要的概念颇蜡,幫助你進(jìn)入?yún)^(qū)塊鏈和智能合約的世界。希望你讀完本文之后能有些許收獲辆亏。我也要感謝能耐著性子看到這里的朋友风秤!
彩蛋:
本文中的兩個插圖都是從以太坊白皮書中抄來的,細(xì)心的你可能會發(fā)現(xiàn):以太坊的狀態(tài)轉(zhuǎn)換示意圖中交易數(shù)據(jù)的 From 地址寫錯了扮叨!是的缤弦,你沒看錯,就是寫錯了彻磁。如果你發(fā)現(xiàn)了這個錯誤甸鸟,我必須恭喜你,你是個細(xì)心人兵迅,大概是做技術(shù)的人才抢韭。而沒有發(fā)現(xiàn)的朋友可能需要檢討一下了……。
當(dāng)然恍箭,也請不要多想刻恭,我引用這個錯誤的圖片,僅僅是因?yàn)槲也粫?PS,然后還懶鳍贾,所以這個鍋只能 V 神背了……鞍匾。