編者按:本文系 Qtum 的 Howard 葉倍宏講師,在由掘金技術社區主辦,以太坊社區基金會、以太坊愛好者與 ConsenSys 協辦的《開發者的以太坊入門指南 | Jeth 第二期 - 杭州場》 活動上的分享整理。Jeth 圍繞以太坊技術開發主題的系列線下活動。每期 Jeth 會邀請以太坊開發領域的優秀技術團隊和工程師在線下分享技術乾貨。旨在爲開發者提供線下技術交流互動機會,幫助開發者成長。前端
Howard 是《Deep Dive Into Ethereum Virtual Machine》一書的做者,該書深度剖析了 Solidity 和以太坊的原理。目前,Howard 任 Qtum 量子鏈 DApp 平臺核心工程師,負責開發工具和數據庫。Howard 在創業界擁有10年的產品開發經驗,而且對構建去中心化產品充滿熱情。他也是本次活動的出品人。數據庫
你們好,很榮幸今天跟你們分享一下以太坊智能合約的一些開發經驗,在開始以前,我今天先給你們先講一個高層面的介紹,從前端到後端介紹一下以太坊的技術棧;而後以後咱們兩位老師會給你們去介紹一些細節。因此個人這場分享只須要你們腦海裏有個對以太坊的概念便可,具體細節後面咱們兩位老師會給你們更精彩的講解。編程
我今天就先介紹一下智能合約以及它存在的理由,而後帶你們看一下智能合約長什麼樣子,最後會帶你們梳理以太坊的整個架構,從前面面對用戶的DApp到後面的存儲數據庫。後端
有位區塊鏈先驅者提了這樣一個概念:技術讓人跟人之間去協做。咱們我的本身跟本身協做,可是我可能多作一點事情,會找個人朋友找個人親人去合做,以此讓我作更大的事情,這樣咱們須要一些合做,我信任個人兄弟,我信任個人同窗這種類型的合做。更多的合做咱們跟以太坊的愛好者咱們掘金的事情咱們互相的愛好及把咱們捆綁在一塊兒讓咱們作更大的事情,再更大一點在一個城市,這個時候咱們要有法律,咱們須要各類政府部門,機關,就算我不認識你,我不認識買我產品的人,但我能夠經過咱們的合約去保證咱們合做的可行性,更大一點就是國家跟國家、國際法院的合做等,這些跨邊界的合做是更復雜的體系。人類的文明跟技術是隨着這個合做的複雜性而增加的。瀏覽器
咱們要儘可能的信任別人,他講這些東西是科技,咱們從人跟人之間的信任上升到法律,因此咱們開始講法律時就不須要說起信任。從人情到市場,我可能願意跟人合做,到市場咱們開始講價格,咱們有價格的協調機制,就不須要講人情了。咱們點對點的對話,必需要認識你這我的我纔有辦法跟你協做,多對多的撮合市場機制,這是一個持續演化的過程。安全
因此咱們開始講這些事情的時候,會牽扯到社會擴容,社會的擴容是須要成本的,咱們須要有政府,須要有法院,須要有警察機構。上圖中咱們能夠看到OECD政府的GDP佔比是從36%到58%不等。咱們雖然沒有買單、沒有直接的去支付這些成本,可是實際上這些東西在政府開銷上佔了很大比重。那區塊鏈作的事情他是由於取代信任的機制,即以計算機替代人工成爲核心的概念。因此說智能合約他具體就是一個計算機程序,它來替代靠人工運營的這些機構。服務器
接下來咱們可看一下智能合約具體是什麼東西。第一個例子就是亞馬遜的 LAMBDA 服務,LAMBDA一個特性是你在LAMBDA這個平臺寫程序的時候,你只是去寫你的業務邏輯,而這個業務邏輯你直接上傳到 LAMBDA 平臺上面,好像只是一個服務器的回調。只要有請求進來它就調用這個回調,計算完成後就直接終止了,你要本身去部署一個服務器,沒有邏輯。LAMBDA 這個平臺讓你直接把服務器的這個業務邏輯放在平臺上面,徹底不用去管後面對應哪些具體服務器,一有請求進來,並把 LAMBDA 啓動,這個跟智能合約的架構很是像。微信
咱們把這個合約的這些變量理解成一個數據庫,咱們可能日常在寫一個加法的類型,它只是存在於類型裏面,你的倘若死掉了,這個內存就清空了。在智能合約裏面,雖然它是變量,可是你是寫在鏈上面,而這個數據庫恰巧是特別昂貴的數據庫。咱們類比成 Java 的僞代碼,咱們會想象後面每個合約它有一個相對應的數據存儲,它是一個對象,是一個數據庫,在這個方法裏面剛纔講了遞增的方法,它只是去操做這個數據庫,在這個鍵修改它裏面的值,因此你每次去改一個變量實際上是對數據庫作一個操做,並且這個操做是特別昂貴的操做,能夠給一個概念,普通全部的這些指定是要費用的,普通的一個紙幣,好比說加減乘除,大概是2到5個不等,存儲的話是2萬個,大概算是5000倍的倍增。網絡
咱們看一個更完整的例子,功德香火鏈,這個例子大概介紹了智能合約很是本質的一個東西。爲何要寫智能合約,咱們並非只是爲了寫這個數據,他之因此牛逼是由於他裏面有金融屬性,你們能夠相信你,若是在我本身的亞馬遜 LAMBDA 上搞一個功德香火鏈是沒有人相信的,我在數據庫裏面能夠隨便修改,但若是咱們改爲在智能合約中就變成是一個去中心化、不須要信任的一個程序。數據結構
你們來看一下這個東西,有一些需求,他初始化的時候咱們要設定管理員,任何人咱們都容許他捐款,最後要用這個款項的時候咱們容許管理員取款,而後讓他寫出全部取款他的去處去了哪裏。
這個就是咱們整個智能合約的代碼,就十幾行而已,這上面大概有兩點須要留意,有合約屬性,擁有者的姓名,咱們會用這個屬性來存儲他的管理員,咱們控制了管理員權限才能夠進行修改。下方分別是捐款和取款的函數,咱們接下來把這兩個函數分開講解。
初始化設定管理員,因此說這邊咱們是要把數據存起來,咱們要知道誰是管理員,在建立這個合約的時候它是用一筆交易建立的,即有一個錢包去付錢而後去說這筆交易誰建立的。這裏的屬性指出當前用戶的身份,這一筆交易的操做者以及合約的操做者。咱們這邊作的事情很簡單,在建立這個合約的時候咱們把當前的操做者存儲在這個數據庫裏面,有了這個東西以後咱們就能夠驗證正在操做的人是否是管理員。
接下來咱們開始作這個核心的東西,即任何人均可以轉款,以後你要作衆籌讓別人給你轉錢,這個東西就涉及到金融的屬性了。咱們看到這個函數也是同樣,在操做這個把錢的用戶,咱們要記下來,也就是要記下這個功德;PAYABLE 它只是通常拿來處理跟金錢相關的東西,這裏是處理存進來的錢。這裏要有個斷言,要確認這筆錢必需要大於0.001,由於我不想要太少,太少就看不上、不想要;最後這邊有一個日誌,說咱們把這個輸出和這個功德記下來,而後保佑發送這個錢的人,這個日誌就記在鏈子上面了。報錯是直接退款,他沒有知足這一個條件這筆交易就失敗了,他捐了錢就打回本來的賬號,固然這個真實的合約你會作各類其餘的需求,理念上就是你先檢查知足了你的需求以後,你再去操做你的業務邏輯,而後最後你就能夠輸出記錄這個事情。我認爲比較有意思的事情,這個合約他有一個相對應的賬號,這個賬號合約有多少錢,你看裏面的業務邏輯並無顯性的說把這個錢給這個合約,你這個隱性只是說這一筆交易進來了,只喜歡這個邏輯,而後最後就會給這個賬號,可是你不須要代碼直接說這個事。
那咱們接下來更深刻的看一下,DApp全棧走一回,咱們用一個簡單的例子而後走到最後面的區塊鏈上面存儲的數據。這個合約中,我有一個變量,有一個值,而後我惟一要作的事情就是修改這個值或者是讀取這個值,這個就是個人一個簡單的智能合約。
咱們會從前端開始,咱們看一下從前端再遞增RPC,這個是ABI的編碼,咱們一下子再展開來講,這個合約就是他的業務邏輯,EVM最後到區塊鏈存儲,咱們一個一個展開來再說。
那咱們看看前端,前端要作的事情就是展示鏈上的數據,重點仍是同樣,用戶在本地簽名以後再把數據提交到鏈上,這個權利是握在用戶的手上,咱們能夠比較一下WEB服務和純客戶端的兩個概念,你們熟悉這個應用就是幣安這種平臺作交易,實際上這些不夠造成這些權限的控制都在平臺手上,像錢包這種東西纔是比較正兒八經去中心化,你說了話不算,是用戶控制權限。在這兩個極端去糾結若是我真的要作一個去中心化應用的話,它的用戶體驗會不好很難用;好處是中心化的服務,用戶體驗好且反應快,可是就是出了事的話那你們都一鍋掀了,如今是在兩個極端裏面去糾結怎麼作。
因此我調用這個方法從個人錢包去打這個數據,而後咱們以後會把這個數據去展開,它也是一個RPC,這裏面的數據傳給智能合約的數據,咱們來展開看一下。
我把剛剛那個東西調用到網絡上面,我就能夠看到這一筆交易,這個就會把交易裏面的一些信息顯示出來,我花了多少 Gas,而後裏面傳了一些數據。
咱們看 ABI 的編碼,咱們能夠拆開兩部分,這個 60fe47b1 他也是調用方法,這個是他的方法名而後拼接在一塊兒去取這個前面四個字節就是這個方法的選擇器,我調調用智能合約的時候前面四個字節指定我要調用哪些方法,後面那些就是我傳參,就是用這個編碼出來的,雖然666其實只須要2個字節,可是他ABI編碼的設計必需要32個字節,因此說這裏能夠看到他是有必定的浪費的。剛剛傳到數據上來以後EVM的節點就會把智能合約的代碼加在這個裏面去執行,這個是咱們剛剛設定的方法,傳值進去進行修改。
咱們能夠看一下EVM的字節碼,剛剛看到這個是智能合約,這個智能合約最後經過編譯器會編譯到字節碼,他基本上是從上到下一個一個執行的。咱們要關注的是有兩個能夠關注的,上面這邊60fe47b1這個就是咱們選擇器,我先判斷一下是否是這個方法,是這個方法的話我跳到這邊來去繼續執行。因此說這個就是咱們SED方法,最下面咱們存儲數據了,這點是一個關鍵點,咱們剛剛是要存到value這個屬性,這個屬性他能夠理解爲建值,他直接是映射到0的位置,我用0去存儲,最終把這個數據存儲到內存裏面去,因此說這是整個合約最關鍵的指令,存儲數據。
咱們把剛剛說的那些東西從EVM字節碼變成代碼,這個是我發的時候他裏面會帶着一些數據,這個數據就是有一個指令,而後我取前面四個字節這個就是我要選擇的方法,若是匹配了這個字節我就跳到tag這邊,這邊我要取參數,我也是從這裏去取,我直接從四個字節之後取32個字節出來,這個就是個人蔘數,而後最後我把我讀出來的參數存到這個位置,這個就是咱們剛剛合約作的事情。
咱們下面分析一下sstore這個指令是在幹啥,咱們剛剛作的事情就是把數據存在第一個位置,L1這個位置,這個位置能夠是無限多的,我存在這個位置以後他就會更改,其實最上面的這個就是個人版本號,個人版本號他是取這兩邊的,而後每個節點都同樣,這邊的 hash 是由下面來更改的,若是我更改了這裏面的數據,這邊的 hash 會變,而後致使最上面的這個版本號也變了,因此說直接把這個 hash 當成版本號就能夠了。若是我去改動這邊的數據那經過這個路徑去改變最上面的版本,下面這邊是我存儲數據的地方,我任何地方存儲的數據都會影響到最上面的版本號,跟 top 的版本控制有點像。
這邊就是咱們存儲數據的數據結構,接下來咱們看一下這個數據結構最後是如何融入到鏈裏面去,這個就是我們的區塊鏈,裏面會存着版本號,像說你去 GitHub 上面看一個項目,會有歷史更新文檔,會講這個版本號修改了什麼,這個版本號修改了什麼。這個就數據結構相似於一個版本,每一個版本會去記錄這一個相對應的版本號是什麼,而後從這個版本號能夠取出相對版本全部的數據。
再回顧一下剛纔提到的,咱們從前端經過RPC,這個是以太坊節點提供的服務,經過到RPC調用這個節點,調用裏面的數據是由ABI編碼結構化,而後傳給合約,合約處理這個數據,最後這個合約是相對應字節碼,而後由EVM解析,解析的結果一般就是存出去要麼就是給別的賬號打錢,大概就是這樣。
區塊鏈的現況你們體會一下,有點天下大亂的樣子,區塊鏈的新世界,這個是咱們對將來的小展望,如今大概是5000萬個用戶在炒幣,可能將來十年區塊鏈會增加到10億用戶,像手機同樣普及。若是這個事成真,每一個人都會有一些數據的資產,變得像手機同樣普及,這樣的話咱們要討論。這就牽扯到擴容,擴容的話有幾種方案我如今比較看好側鏈和跨鏈的方案,若是咱們要作產品那就考慮說這個到底怎麼樣作出好的產品給人用,因此說如今不少正在驅動的區塊鏈產品很難用被各類噴;再一個是隱私的問題,區塊鏈就是公開賬本,毫無隱私可言。
智能合約發現了不少的問題,智能合約在安全上或者是在可用性上面他學習成本是至關高的,由於它是不一樣的平臺,所用的編程語言也與其餘語言不一樣,一切都要從頭開始學。如今咱們能夠看到一些新一代的智能合約平臺能夠出現了,像WEB 3.0是在瀏覽器裏面作一個接近底層的版本。因此說咱們能夠看到像以太坊生態圈裏面truebit在嘗試而後像rholang這類項目,它也解決了合約併發的問題,像咱們公司量子我如今作一個虛擬機,這個是模擬了CPU的架構,咱們但願說經過這個架構能夠支持一些比較底層的開發去作智能合約,而後咱們會比較關注像操做系統和虛擬機的分層,如今你去分析EBM的原理,它是字節碼,裏面會看到一些屬於操做系統的的這個指令,它實際上是建在虛擬機裏面,這個也是一個技術上的一些問題。剛剛也提到了一個問題,就是智能合約到底能不能更新,應該怎麼更新,這也是如今行業裏面討論的問題,咱們會採用一個像DGP這種方式,咱們經過投票去讓用戶選擇這個智能合約應該怎麼更新。歡迎你們跟我交流,謝謝你們。