編者按:本文系 Qtum 的 鍾文斌講師,在由掘金技術社區主辦,以太坊社區基金會、以太坊愛好者與 ConsenSys 協辦的 《開發者的以太坊入門指南 | Jeth 第三期 - 上海場》 活動上的分享整理。Jeth 是圍繞以太坊技術開發主題的系列線下活動。每期 Jeth 會邀請以太坊開發領域的優秀技術團隊和工程師在線下分享技術乾貨。旨在爲開發者提供線下技術交流互動機會,幫助開發者成長。前端
歡迎添加稀土君微信:xitujun,回覆「以太坊」進羣和講師交流。git
1小時搞明白以太坊 DAPP 開發 - 熊麗兵 | Jeth 第三期github
鍾文斌,本科畢業於上海交通大學,中國科學院碩士,現任 Qtum 量子鏈中國首席開發工程師,主要負責 Qtum Core 和 Qtum x86 虛擬機等開發,對區塊鏈基本原理有較爲深刻理解。在加入 Qtum 以前就任於 SYNOPSYS 任高級研發工程師,有超過四年的大型軟件開發經驗。web
你們好。我是鍾文斌,來自 Qtum。爲何我能來說以太坊智能合約開發?由於 Qtum 自己是支持以太坊這套虛擬機的,至關於兼容吧,因此咱們也算是有一些瞭解。今天我會講如下幾個話題。數據庫
首先,爲何咱們要智能合約?智能合約到底長什麼樣?最後咱們說以太坊智能合約全棧走一回。DApp 做爲一個 APP,在用戶點擊那個按鍵以後,它到底發生了什麼?咱們今天都會涉及到。編程
智能合約你們應該知道,不管是比特幣以太坊仍是不少如今的須要挖礦的鏈,他們都在進行挖礦這麼一個行爲。那挖礦是什麼?我今天就不作深刻解釋了,可是至少你們知道挖礦是很是浪費資源的。後端
那這麼浪費資源究竟是爲了什麼呢?安全
爲何咱們好好的跑在服務器上的 app,須要變成 DApp?它實際上是一個社會科技。整個社會之因此存在,是由於人與人之間要協做。在不存在協做的狀況下,多是我本身作一個獨立開發者,能夠作任何事情。當我須要跟個人朋友或者合做夥伴去合做的時候,我就須要互相信任。這些信任是須要成本的,合做的範圍越大信任的成本就越高。好比說我和個人親朋好友合做,那基本上我是很是信任他的。再往大說,咱們要在整個社區合做,好比說整個掘金社區要一塊兒作一件事情,咱們可能就須要更大的信任。服務器
這個信任最重要的一點在哪裏?就是不要侵犯別人的利益,而且保障本身的利益。熙熙攘攘皆爲利益往來,因此沒有利益的合做,就不大須要信任,可是最須要信任的地方是哪裏?每每就是有利益的地方,有錢的地方。因此不管是社區城市國家,甚至全球都須要這麼一種協做。要實現協做就會有成本。微信
區塊鏈能作什麼?下降互相傷害的風險,那友誼的小船就不會翻,因此說它就是使可以令人們可以達成信任,也就是說可以在利益上達成一致,你們能夠不用擔憂別人騙個人錢。
我剛纔說,這是一個Social Technology,就是說以前咱們全部人都在基於信任作事情,但實際上信任的門檻是很是高的。剛剛你們都已經互相認識了,可是我想問一下你信任對方嗎?這是很是難的。可是你信任你的父母嗎?你應該是信任你父母的,這是在長時間的積累下,纔有這樣一種信任。
因此信任是很難創建的。人們想到法律,用法律來保障人之間的信任,但這遠遠不夠。還有就是咱們一開始是親友的一些人情,到後面變成市場。咱們一開始的協做多是咱們兩我的,最後演變成更多的人蔘與,就須要更健全的法律。或許咱們能夠用智能合約來實現這一切。
這個是以前經合組織發佈的,一些國家的政府開銷佔整個 GDP 的比重。
咱們能夠看到這36% 到58% 不等,這是個很是高的一個比例。這些比例在作什麼?就是使你們可以協做。也就是說讓你們可以信任政府,或者信任這些組織,可以作一些事情。這就是信任的成本。因此智能合約就是,咱們用程序用代碼來代替咱們人工實現這些信任,讓智能合約做爲一個信任和協做的工具。
以上就是簡單地介紹了一下智能合約作什麼,爲何咱們須要去挖礦?它其實就是說可以讓人創建起信任。
它說是一種合約,實際上就是一段程序。你們應該知道 AWS LAMBDA。通常咱們去開發一個業務邏輯,在開發業務邏輯的同時,咱們還須要去維護後臺的一些服務器,去維持這個業務邏輯。AWS LAMBDA 能夠實現這麼一個功能,你只須要關注你的業務邏輯,而後你把業務邏輯放到 AWS LAMBDA 這個平臺上,以後,用戶只要調用這個業務邏輯,他就能夠用了。你不用去管這個服務器在哪運行或怎樣,最後就是用戶用了多少計算能力,他就付多少費。
相似就是這麼一個架構。這個其實跟區塊鏈的理念有那麼一點像。區塊鏈或者說以太坊,也是這樣的一個平臺。你只須要關心你智能合約寫了什麼,但最後它跑在區塊鏈上,你不須要去關心,但每一個用戶須要爲調用這個智能合約付費。
這就是一個智能合約,是一個計數器,你們應該都能看懂。
第一行,是 Solidity 的版本號。Solidity是如今智能合約最主流的一個編程語言。這合約的名字叫 simple counter,就是一個簡單的計數器。它很簡單,裏面有個 counter,有個 function,就是對這個 counter 進行一個加加的操做,好像跟普通的 JS 的程序沒什麼太大區別。 但實際上智能合約和它有很大的區別。
它在操做的這個 counter,其實是在操做一個數據庫。就是說若是是一個類的一個實例,通常是放在內存裏面,內存清掉以後,這個 counter 的全部數據都不存在。實際上在這個合約上面,這個 count 是記錄在數據庫裏面的,因此你每進行一次加加,其實是進行了一次讀寫,對數據庫進行了一次讀寫。它和普通的 JS 稍微有點不同。
咱們再看一個更好的例子。這個例子是我我的很是喜歡的。
這個叫作功德香火鏈。這個的需求其實很簡單,就是說你捐贈香火,咱們在區塊鏈上給你計一次功德,給你念一句阿彌陀佛。你們感覺一下這佛光。
其實這個例子咱們簡化一下,它有三個需求。
首先咱們要初始化,設定這個鏈上有一個管理員,好比說方丈,方丈管錢。每一個人都應該可以捐贈功德。因此每一個人都要可以捐贈,而且這部分錢只有方丈能夠動,不是每一個人均可以取出來的。因此說若是你在剛纔說的 AWS LAMBDA 上面去作這樣一個東西,是沒有人會信任你的。你能夠隨意改這裏面的數據,你也不知道我有沒有記你的功德,這錢用在哪你也不清楚。可是智能合約它最厲害的地方就是說它跟錢相關,而且可以讓別人相信這個錢沒有被亂用,這是怎麼作到的呢?待會咱們講全棧的時候會解釋,但如今咱們先來看看這個合約。
這個合約經過剛纔需求分析,其實就這麼十幾行。咱們稍微把它分解來說一講。首先第一個需求,咱們要設定管理員。 這個就是至關於合約的初始化的一個函數。
這邊有兩個比較關鍵的地方,一個就是 msg.sender,至關於當前調用那個合約的用戶。你在區塊鏈上放一個合約,每一個人均可以建造一個這樣的鏈,因此你怎麼知道這個鏈是否是某個大師發佈的呢?那這個大師要公佈一下這個他所建立這個合約的地址。每一個人均可以建立一個不一樣地址的合約,可是隻有這個大師,他公佈的纔是你們想要捐贈功德的地方。因此這個 msg.sender 就是當前合約建立者的地址。咱們把建立這個合約的這我的設爲 owner,就是管理員。
第二個需求就是每一個人都必須可以捐贈。
有幾個比較關鍵地方,這邊有個屬性叫 payable,就是說這個合約是能夠往裏面打錢的。 我剛纔說過智能合約最厲害的地方就是它能夠管錢,因此你能夠經過設置 payable 的屬性,往這個 function 裏面打以太坊。這個 msg.sender 就跟剛纔不同了,他固然仍是調用合約的這我的,但如今是調用合約的人就變成了捐贈者,他往裏面捐錢,而後他會作一個 assert,說你捐贈的金額必須大於0.001以太,否則就不夠香火錢。你敬贈完以後,若是知足條件,那我就給你念一下阿彌陀佛,而後給你記錄一條日誌,你們均可以在鏈上看到你捐了錢,你被唸了一句阿彌陀佛。
最後一個需求是說只有方丈能夠取錢。
這邊有一個 require,當前調用 withdraw 這個 function 的人必須是管理員。咱們一開始建立合約的時候就建立了管理員,就是這個方丈。一旦認證經過,方丈就能夠取這麼多的錢到某個帳戶。這邊還能夠再插入一個日誌,好比說去翻新佛像,相似這樣的事情。這就是一個很是簡單的智能合約的例子,它與普通的 APP 不一樣之處就在於它全部東西都記錄在區塊鏈上,它是公開透明的,你們能夠驗證這個合約確實存在。並且你能夠看到往裏面打的每一筆錢,任何人都沒有辦法修改,包括這個 owner,他只能提款,他也不能修改裏面發生的全部轉帳的行爲。
咱們還回到這個智能合約這個東西。咱們剛纔講到都是跑在以太坊上的智能合約,以太坊的虛擬機就是智能合約的執行環境,叫 EVM,Ethereum Virtual Machine。它有一些什麼特性呢?
一是調用合約由用戶承擔計算費用。 不管是方丈創造那個合約,仍是你去捐贈,仍是方丈去取錢,它都須要一個叫作 gas 的手續費,這個手續費都是調用合約的人去付。
二就是用戶可以徹底掌握這個權限。 你的捐贈行爲和方丈的提現行爲,都由他們本身控制,經過什麼控制?經過客戶端的一個簽名,你掌握了私鑰,你就能夠對它進行簽名,簽名以後服務端去驗證,經過以後再在整個區塊鏈網絡上去廣播,再去驗證。因此說每一個人它本身控制了本身全部的權限,不存在說像AWS lambda 同樣,你掙的錢就至關於給了這個平臺。可是這個是放在一個合約裏面,你們都能看到的,都能驗證的一個環境裏面。
另一點就是性能低下。 以太坊網絡其實全球有將近2萬個節點,那比特幣網絡可能有將近1萬多個全節點。一個2萬多臺機器的網絡,可能計算功能應該是特別強大的,但實際上並非。它的性能取決於網絡上性能最差的那臺計算機,爲何?由於每一個節點都要重複計算。你對一個合約的調用,每一個節點都須要計算一遍,每一個節點都至關於存儲了一份徹底的拷貝,它須要去達成全網的一個共識。這就是爲何我可以信任這個網絡,由於即便少數的人在做弊,咱們大多數人都還在驗證大多數人所認可的事實。因此咱們能夠相信比特幣或者以太坊這個網絡。可是這它的性能實際上是很低下的,由於每一個節點在作的事情實際上是如出一轍。
慢,剛纔已經介紹過。
貴,每一個調用合約的行爲,你都須要付 gas。
矬,就是它性能也不好。
咱們訪問一個網頁,至關於發出一個網絡請求,服務器就把全部信息發給咱們,這個請求很是簡單,這個整個交互的過程很是簡單,生命週期很是短。可是在以太坊上在比特幣上全部的交互都是經過 transaction,交易來完成的。整個交易生命週期很是複雜,還須要通過全部節點的全網驗證,並且中間會出現不少各類各樣的錯誤。並且它也沒有這種網絡請求,也沒有可靠的隨機源。
最使人髮指的一點就是合約一旦部署了是無法更新的。你能夠刪除某個合約,可是你不能更新。一旦出了 bug,問題會很是嚴重。普通的軟件出了 bug,可能就是一個運營事故。可是以太坊的 bug 出現過幾回,都是動輒幾千萬美金。好比說 Parity 那個事件,它裏面的一些合約被刪掉,那個錢雖然理論上說沒有丟,可是它所在的某個地址上,全部人都沒有辦法再把這錢取出來,1.5 億美金就被凍結了。因此說智能合約上的一個小小的瑕疵,均可以形成很是大的金融損失。但這也是它的魅力所在,它可以管錢,它跟錢相關。人之間的共識信任不少是創建在這種利益之上。
按照套路,我如今就要講它意義何在了,實際上我也還沒想清楚。因此說這是拋出來一個開放性的問題。
我剛纔已經介紹了去中心化平臺大概是什麼樣子,它的特色是什麼,但它的意義何在呢?我不想去評論一些什麼,由於整個行業都還在思考。去年的我若是在這個時間點說,我會說它可能會要改變世界,可是今年一年的事情發生下來,去中心化應用這條路,到底最後能不能走通,我我的目前保持觀望態度。因此課程咱們還繼續講,可是意義何在,但願你們聽完以後本身去思考。咱們這個世界到底到底需不須要全部東西都是去中心化? 我認爲確定不是,我認爲多是一箇中間狀態,但去中心化必定有它的意義所在,至少咱們如今擁有比特幣能夠不須要一箇中心化的機構實現一個全球的那麼一個價值流轉。至少咱們有以太坊,它使咱們可以在你們互相不認識的狀況下,進行 ICO,進行融資,這是一個很是偉大的創舉。
咱們剛纔說到了智能合約,舉了兩個例子,那若是它變成一個應用,它最後在鏈上到底發生了什麼呢?咱們再舉一個例子。
這個是一個很是簡單的智能合約,就是一個簡單的 set 跟 get ,一個簡單的存儲,而且得到值的這麼一個應用。
一個應用,它自己可能從前端到後端有這麼一些東西,因此我待會也會從前端到它怎麼進行一個 RPC 調用,怎麼樣進行 ABI 的編碼,合約怎麼樣運行。而後在 EVM 上是變成怎麼樣運行的,最後是怎麼樣放到那個數據庫裏面。因此這一點從這個一路我都會講下來。
咱們先來看看,這是 Howard 同窗寫的,關於web 2.0 和 web 3.0。
Web 2.0就是如今你們所熟知 Web 的整個框架。那類比於 DApp 的話,咱們暫時把它稱爲 Web 3.0。
前端 Web 裏面多是 HTML 服務,那在 DApp 開發裏面,咱們可能就是一個 DApp 或者 Web 3.0,其實沒有太大區別。
那剛纔說了 Web 2.0 多是網絡請求,但在 Web 3.0 裏面全部東西都是經過合約,經過 transaction 交易去觸發的。
Web 2.0 裏面數據的組織方式多是 JSON,在以太坊上多是 ABI 編碼。
在服務器端咱們能夠經過這些請求,咱們能夠進行一些操做,或者實現一些業務邏輯,那在所謂的 Web 3.0 裏面,它其實就是經過智能合約來處理這些業務邏輯。
在 Web 2.0 裏面咱們可能會有操做系統,Web 3.0 都是以太坊虛擬機。實際上它是把虛擬機跟操做系統作了一個混合,區分的不是很是的明確,既有虛擬機要作的一些事情,也有操做系統層面的一些事情。
那在 Web 2.0 裏面,咱們可能有數據庫,在 DApp 開發裏面也有數據庫,是經過 Merkle Tree 的方式去組織起來的。實際上在以太坊裏面合約存儲並非 Merkle Tree,是 MPT,Merkle Patricia Tree。咱們能夠把它簡化成 Merkle Tree,其實指導思想是同樣的。
因此前端其實要作的事情很簡單,就是展現鏈上數據,或者是 DApp 的一個入口。
咱們在本地須要作的事情就是簽名,全部東西都是一筆交易,你能夠在這一筆交易裏面發送以太坊,也能夠在這筆交易裏面去調用合約。
咱們平時可能接觸到跟區塊鏈比較相關的一些應用,那大概分爲這兩類。就是像 coinbase,binance 那些交易所。這個平臺實際上並非一個 DApp,雖然它跟區塊鏈相關,處理區塊鏈的一些交易,但實際上它是一個徹底中心化的平臺,全部的數據都在他的服務器上面,全部的請求,甚至你的幣都是打給他們平臺。
另外就是 myetherwallet,imtoken 這種手機端的或者網頁端的錢包軟件,每一個用戶本身可以徹底掌握私鑰,不用把錢把以太坊比特幣打給任何一箇中心機構,用戶徹底掌握這筆錢的動向,因此它更像一個去中心化的應用。
咱們來看一下它傳遞的參數,咱們剛纔看到一大串那個data,它是什麼呢?這個 data 的前四個字節,實際上就是選擇調用哪個 function。這四個字節是怎麼來的?
對 set 這個函數的原型作一個 SHA 的操做,它會變成很長的一串哈希。咱們取前面四個字節做爲這個函數的標識。因此你看到 data 的前四個字節就能肯定,我如今調用的是這個 set 函數。後面的這個數據就是咱們要傳入的參數,就是666。具體到以太坊的虛擬機怎麼處理這麼一段東西呢?
那寫在哪裏?它其實是寫在一個數據庫裏面。可是這個數據庫會經過 Merkle Tree 的數據結構,反映到區塊上面。Merkle Tree 是個二叉樹,它全部的節點的值都是下面兩個子節點的哈希。因此一旦發生某一個值的改變,整個樹相關路徑上的哈希都會發生改變,最後的根也會發生改變。這整個樹的根的哈希至關於全部這些數據的簽名,或者標識。一旦某個數據發生了任何改變,整個 root 哈希也會發生改變。剛纔咱們把 666 這個數據寫到一個地方,而後這個整個哈希就發生改變,咱們從新計算出一個根哈希的值。這個值就放在區塊鏈上。區塊鏈它每一個區塊除了包含全部的交易以外,最重要的一塊,它有一個區塊頭。這個區塊頭有幾個結構,一個是它包含上一個區塊的一個哈希值。以此類推,我這個哈希值標識了前面全部的區塊全部的交易。若是別人想騙我,說他改變了前面的某一筆交易,那我這個哈希的驗證就不會經過,它會被整個區塊鏈網絡認出來,說這個是篡改的。咱們之因此說區塊鏈是不可篡改的,就是由於有這樣一個結構。
那另一個東西就是咱們剛纔說到 Merkle Tree 的根。Merkle Tree 的根就是全部交易的哈希值的一個標識,一旦這些標識被確認以後,這個根也就惟一肯定了。而後這邊有個 nounce,就是咱們所謂的挖礦的關鍵。所謂的挖礦,實際上是在計算符合某一個難度要求的哈希值。爲何比特幣要去挖礦,首先比特幣想實現一個去中心化的網絡。在中心化的網絡裏面,我須要服從一箇中心化組織。可是在去中心化的網絡裏面那我聽誰的?我產生一個一個新的區塊,我應該服從誰挖出來的那個區塊呢?那就讓你們一塊兒算一個值,這個值是一個哈希值,它沒有任何取巧的辦法,只能經過增長算力來解決這個問題。把前一個區塊的哈希加上這個 Merkle Tree 的這個根,再加上區塊頭的一些信息,這個 nounce 是惟一能夠改變的變量,你經過改變 nounce 從 0 到 一個很是很是大的值,你能夠一直在算某個哈希。一旦這個哈希符合某一個難度要求,好比說前面 10 位爲零或者 11 位爲零,它就至關於知足了全網共識的難度要求。在這個難度要求下,你產生的這個區塊就是合法的,你就能夠向全網廣播。一旦你是全網第一個算出這個哈希值的人,你就成爲最新的這個區塊生產者,能夠得到比特幣或者以太坊的獎勵,也就是說你挖到礦了。比特幣或者以太坊,能夠經過這樣的方式實現比較分散的分發(假設礦池不存在)。還有就是能夠保證隨機性。在一個去中心化的、你們誰都不信誰在網絡裏面,若是某一我的固定去產生區塊,他很快就會被攻擊好比 DDoS 之類。他一旦不能產生新的區塊,整個網絡就會癱瘓。經過這個方式能夠很是隨機的讓全部人都有機會生產下一個區塊,攻擊者徹底沒法預測下一個產生區塊的是誰,那他就沒法去攻破這個網絡。 因此說我認爲有兩點,一就是幣的分發,二就是保證隨機性。 咱們剛纔說到數據庫,保存這個數據的 transaction,最後反映到這個 Merkle Tree 上,最終經過一個哈希的方式存在鏈上。隨着這個鏈愈來愈長,至關於每一個區塊都有前面全部鏈條的證實,它就變成了全網共識,沒有人可以改變,也沒有人可以去僞造。 這就是爲何咱們剛纔 set 了一個666,它不會存在某一臺服務器上,或者是幾臺服務器上,或者某我的可以去更改這個666。由於全球一萬多個以太坊的節點都在他們本地的數據庫上記錄了,我這個合約裏面這個值就是六六。即便你某幾我的想去改他,也不能夠打破這個共識。包括剛纔那個捐贈功德香火鏈也同樣,全部人都知道了,你這位仁兄是念了五句阿彌陀佛的,這個方丈是取了這筆錢來幹嗎的。他不會因爲任何我的或者少數人的做弊發生任何的改變。剛纔這個過程就是咱們從前端到ip到最後的存儲,看了一遍,以太坊上智能合約是怎麼樣去運行的,它最後到底產生了一個怎樣的效果。
咱們剛纔講到都是圍繞以太坊,可是不得不說以太坊的虛擬機並非一個特別好的一個虛擬機,固然它是爲了智能合約專門設計的一個將來安全性實驗的一個虛擬機。目前以太坊虛擬機還有如下缺點:
業界有不少人在作新的虛擬機,好比說比較火的 WebAssembly、EOS 他們都在作。能夠支持 JS 網絡編程。而後好比說 RChain 這個項目,他本身搞了一個 Rholang 就是新的編程語言。 咱們 Qtum 也在作新的虛擬機,是一個 x86 虛擬機。相信你們應該都聽過 x86 指令集。基本上咱們如今全部的設備至少是非移動設備,仍是用英特爾的 CPU,他支持的就是這個指令集。大部分編程語言,大部分的工具都可以被編譯成 x86 指令集的可執行目標文件。也就是說若是咱們在區塊鏈上支持了這個虛擬機,那目前大部分的主流語言和主流的你們熟悉的工具,就能夠直接被拿來使用來編寫這個智能合約。因此說可能這個能夠給你們帶來一些便利,咱們也但願如此。
還有就是說,以太坊的虛擬機跟操做系統層實際上是混合在一塊兒的,這在編程當中可能帶來了不少的困擾,因此說咱們會把它進行一個分層的設計。另外整個智能合約它是無法更新的,可是在 Qtum 裏面咱們能夠作到這一點。就是咱們有一個至關於分佈式自治協議,那經過這個協議咱們能夠但好比說咱們有一些標準庫。那整個業界,固然我這邊沒有列全,也各類各樣的項目都在作這個虛擬機。但不能否認目前這個以太坊仍是最流行或者是最成功的一套虛擬機,也是最成功的一個智能合約運行環境。
我今天分享就到這裏。這是咱們GitHub地址:qtumproject,供你們參考。