編者按:本文系 登鏈科技 CTO 的熊麗兵 講師,在由掘金技術社群主辦,以太坊社群基金會、以太坊愛好者與 ConsenSys 協辦的 《開發者的以太坊入門指南 | Jeth 第三期 – 上海場》 活動上的分享整理。Jeth 圍繞以太坊技術開發主題的系列線下活動。每期 Jeth 會邀請以太坊開發領域的優秀技術團隊和工程師線上下分享技術乾貨。旨在為開發者提供線下技術交流互動機會,幫助開發者成長。
歡迎新增稀土君微信:xitujun,回覆“以太坊”進群和講師交流。
本場分享視訊回放連結(B 站)
分享整理傳送門
講師介紹
熊麗兵,北京航空航天大學碩士,先後加入創新工場及獵豹移動,全面負責數款千萬級使用者開發及管理工作,2014年作為技術合夥人參與建立酷吧時代科技。2016年重心投入區塊鏈技術領域,目前在登鏈科技任 CTO ,是全網訪問量最大的區塊鏈技術部落格《深入淺出區塊鏈》博主,對底層公鏈技術,區塊鏈技術落地都有深入研究。
謝謝大家,很高興能夠和大家分享一些知識經驗,今天主題就是
《1小時搞明白以太坊 DAPP 開發》,
我們直接進入主題,先介紹我自己,之前在創業工場、獵豹移動做工程師,然後現在區塊鏈行業瞎折騰。
這是我分享的內容,第一個先介紹什麼是區塊鏈的應用,再簡單的實現一個DAPP。
什麼是去中心化的應用?
我們做一個對比,現在我們先來看一下APP的架構,就是我們平時接觸到的。平時接觸的是一個個前端,例如APP、H5、小程式等,這個前端後面一般都會有一個相關的伺服器,不管是前端顯示的內容或者一些動作,它其實都是會有一些對應的請求傳送到伺服器裡面,然後伺服器收到這個請求之後會有一些回應,再發到前端的應用,就是這樣一個簡單的架構。
作為一個去中心化的應用,它的前端表現都是一樣的,其實有時候我們在跟客戶做應用時,他說:“咦!你這個看上去好像和我們看到的應用完全一樣,沒什麼區別啊。 ”其實實際也是如此,關鍵他的後端不一樣。關於這個疑問,我們有時候會在介面上加一行字,“此資料經過全網同步”,然後他們表示這就是去中心化應用,但其實關鍵是連線前端的這個後端的節點,它不但是一個伺服器,而是後端它連著的一個網路,不管你是連線到任何一個節點,它在理論上都是一樣的。
實際上你的應用是在一個網路上面,當前端請求傳送到後端的時候,後端連線的節點會把這個請求擴散到整個網路。所以只有當真正的請求達到了全網的一個共識之後,它這個請求才算是真正的生效。這就不像你只有一個伺服器時的,只能它說了算。
去中心化的交易所和中心化的交易所有什麼不一樣?
在中心化的交易所中,你所有的錢都不是在你的錢包裡面,而是在中心化交易所的錢包裡面,理論上它是可以為所欲為的,但是去中心化它是不一樣,你的錢是在你們自己的錢包裡面的,而且你的所有交易都是經過全網共識的,並不是說它自己的節點,所以這個交易是受我們自己控制的,這就是去中心化的應用和中心化的應用的一個最大的不同。
在中心化應用裡面,通常我們傳送一個請求是可以直接拿到結果,而去中心化應用要經過全網的共識,通常當你前端有一個請求發到節點,節點告訴你,因為我收到這個請求,它並不能立馬處理並拿到結果,這也是一個開發去中心化應用裡比較大的不同點,所以如果我們要想拿到這一個請求的相關狀態,一般是通過事件Event。還有一點在去中心化應用裡面,通常這個請求叫交易,這個交易和我們開發普通應用的時候是不同的,它是經過使用者私鑰的簽名,這些就是幾個明顯的不同點。
接下來涉及到具體開發的一個過程,下面圖片中展示了 APP 和 DAPP 比較圖。
前端部分和客戶端部分其實基本上是一樣的,
前端使用者:一般通過在知道我們普通開發APP的時候,它是通過一個HTTP的請求發到伺服器再清空某轉發的話,最後它會呼叫到對應的後臺的程式中;在對應的去中心化中的地位中智慧合約大概相當於我們之前在寫普通應用中一個後端的服務程式這樣的角色。
不同點是通常在開發DAPP的時候這個傳送請求不再是HTTP,而是RPC(遠端呼叫)的一種方式,其中這個節點EVM就相當於我們平時在寫DAPP中它的Nginx/Apache這樣的一個角色。
智慧合約,它其實是跑在一個節點上,或者說都跑到一個EVM上,當然這個EVM其實它就是在節點上的。
我們要開發一個去中心化應用最主要做的是三部分 :
-
前端部分的編寫
-
智慧合約部分的編寫
-
前端和智慧合約的互動
我要實現這樣一個簡單的DAPP,它是在區塊鏈上,儲存需要名字和年齡,通過這個更新它會把這個內容同步到區塊鏈中。
如何實現簡單的DAPP?
需要三個部分要寫 :
-
編寫智慧合約部分,相當於我們在寫後端的服務程式
-
編寫前端的部分,這次展現的是Web形式,其實也有其他形式
-
實現前端與合約互動
什麼是智慧合約?
智慧合約其實是以太坊的一個程式,它是程式碼和資料(狀態)的集合。而編寫智慧合約的語言是Solidity,如果我們用圖中舉例,把contract變成一個class,這就和我們寫其他的語言基本上是一樣的,就用contract定義hello,用function定義hello這樣的一個函式,這個只有一個簡單功能,它可以把一個字串返回出來,這就是一個最簡單的合約。
你既然要編寫一個合約或程式必然需要用到相關的工具 :
-
Remix它是編寫Solidity的一個IDE,這是一個Web 形式的IDE.
-
MetaMask錢包,它可以負責幫你把傳送的交易做一個簽名
-
Ganache節點,在開發中我們需要連線到一個節點,如果我們每次都直接連線到以太坊的節點,這個過程是非常慢的。所以我們可以使用Ganache這樣模擬的一個節點,可以方便我們進行開發
我定義了一個合約,剛剛在前面有提到兩個部分,一是保持一個名字,二是保持一個年齡。那麼這個合約就有兩個變數,這兩個變數在智慧合約裡面它叫做狀態變數,它的內容就會存在區塊鏈的網路上,然後由你定義的兩個方法,一個叫set,一個叫get,set就是用來設定這兩個變數的內容,get是用來獲取。
(演示)我現在來教大家合約如何去編譯部署
首先開啟Remix裡面(前面提及的工具中IDE Remix),地址:remix.ethereum.org/ ,
現在我們看到的就是IDE,然後中間是編輯程式碼的區域,右邊這邊有Compile它其實是我這邊勾成的,所以它是會自動去部署。部署的時候有一個叫環境的選擇,它其實就是關聯到MetaMaskq提供的一個環境。
我們現在來部署一下,它其實也是提交交易的一個過程,所以它會彈出來提示讓我們去付多少錢Gas,然後同時也會完成一個簽名的過程。部署好了之後,我們就可以對合約相應的函式進行呼叫,而此時合約的編譯和部署都已經完成了。然後我們這邊可以設定一個內容,它其實會發起一個交易,所以每次發起一個交易的時候,因為這個交易是使用者發起的,所以需要使用者的確認,這也是一個簽名的過程。現在智慧合約部分就寫完了,這相當於我們在寫程式的時後端部分。
現在我們再來看看前端部分, 上圖中這個info是由我來顯示內容的,兩個input是需要使用者去輸入內容,一個button去更新內容,當使用者點選這個button更新的時候,我們就把資料提交到以太坊的網路中。
需要提及的是潛在部分,有幾個關鍵地方就是引入了幾個庫,其中一個是web3,它是就是用來和節點進行互動的一個庫。然後這部分是我們需要去編寫的,就是和合約進行互動的部分,web3它就是和合約進行互動的。我們之前有一個RPC,就是從平時我們寫應用的時候是用HTTP請求,但是在我們編寫DAPP的時候,它是RPC的一個請求,其實web3它是對RPC的一個封裝。
web3是和以太坊節點互動的一個庫,它可以用來獲取到節點的狀態,還有賬號的資訊以及呼叫建立合約事件等等 。
它也是對RPC的一個封裝,它其實有很多個語言的實現,我們現在要用到的是它的JavaScript版本的實現web3.js,我們在開發一些其他的,比如說你開發一個安卓的應用,可能就要需要用到web3j,或者是你開發其他的就是非web形式的話,可能就要用到其他版本的封裝。
要實現前端和合約的互動,首先我們需要把這個web3匯入進來,之後我們要對web3做一個初始化。
之後我們就需要用到合約的一些資訊去初始化例項化合約,這有一個叫web3.eth.contract(ABI)就是智慧合約提供的一些介面的描述。
在我們編譯智慧合約的時候,其實編譯器會為我們生成ABI。我們編碼的時候就可以把這個ABI的資訊拷貝出來。我們在例項化合約的時候需要把這個ABI的資訊填入進來,告訴我們的WEB3要連線的這個合約到底有哪些函式?ABI的大概作用就是這些。
我們需要連線到的這個合約的地址是什麼?這個地址就是我們在部署之後,它會為我們生成一個地址,這就是它要關聯的哪一個合約的地址。我們這個初始化合約部分就完成了,接著我們可以使用合約的例項去呼叫合約的相關函式。
我們可以拿到info,它對應的就是一個合約的例項,達到這個合約的例項之後,就可以用這個例項來呼叫合約對應的方法,前面提及我們合約裡面有一個set一個get,現在可以通過這個例項來呼叫get,get它其實是一個info的過程,所以我們傳播的一個函式,這個函式從這個result裡面就可以拿到getinfo裡面它返回的結果。
setinfo它有兩個引數,一個name和一個get,這個get和set就是對應我們剛剛編寫合約的兩個方法。我可以再次開啟合約來做一個比對,剛剛我們的程式碼裡面有個set,一個get。
在web3裡面使用例項的話,它就可以來呼叫到這兩個方法,然後我在這個介面的這個app.js裡面,我們在初始化合約之後就會呼叫這個getinfo,它其實就是通過合約的例項來呼叫的,因為getinfo返回的是兩個內容,另外它在js裡面這邊就是一個陣列了,然後通過 下標result[0] 拿到名字,下標result [1] 拿到年齡,之後就可以把它設定到這個頁面上。
Setinfo是當我們去點選更新按鈕之後,它會去呼叫setinfo。現在我們其通過這麼以上的操作之後,這個最簡單的DAPP就已經實現了。
接下來我們可以來執行一下。
(演示)現在儲存之後,這個值就已經拿到了區塊鏈上的資訊,其實這個資訊就是之前我在部署合約時設定的這兩個內容。當我們的頁面關聯上對應的合約的地址以及連線到對應的節點,它就可以拿到這個資料。這就是一個最簡單的DAPP。但其實這個開發的過程是有點複雜,因為我們還要去複製它的ABI、節點的資訊等,因此有的時候這樣的開發過程非常麻煩,但這可以讓我們去了解DAPP開發的一個流程。所以實際上在開發的時候,我們可能需要藉助一些其他的一些框架,就是常用的兩框架是一個Truffle,一個叫Embark。
我這邊可以使用這個Truffle框架來做個演示,剛剛我們是在Remix裡面做了這樣一個編譯,其實我們可以使用Truffle來去簡化這個過程,這樣的話就不用說頻繁的去切換這個環境,我們可以直接在這個裡面(演示通過命令列 truffle compile 編譯)去完成這個操作。我們可以直接在這邊編譯,之後它會在build資料夾下給我們生成一個對應合約名字的Json檔案,這裡面就是有ABI的資訊。
我們使用truffle-contract來初始化合約的時候需要用到ABI的資訊,然後我們也同樣去再做一個部署,部署之後它也會為我們在這個編譯好的個Json檔案裡面去生成對應的地址,原來我們在初始化合約的時候在app.js裡面其實需要很多硬編碼的一些內容,包括地址以及ABI的資訊,但是我們使用Truffle提供這樣的contract的一個抽象的話,就可以讓我們免去這些過程。
我這邊把index.html裡面的這個APP.JS換成另外一個app_tf.js,也就是它使用Truffle框架的js在這裡面的話,我們就可以不用硬編碼的去去複製ABI或者地址,直接使用通過或獲取到它生成的一箇中間的檔案,節省時間,很方便,通過這種方式來例項化合約。
我們接下來再來測試一下,因為剛剛我們在truffle裡面重新的去部署了合約,所以現在這個合約的狀態是0,因為它預設值是0,然後如果是一個字串的話,它就是空的一個字串,我們隨便可以寫一個來更新測試一下。因為要提交交易,所以要使用者的一個確認。現在這樣的一個DAPP就完成了。
程式碼的地址為: github.com/xilibi2003/…
歡迎大家跟我交流,下面是我的微信,也可以關注登鏈學院,我們提供了很多區塊鏈視訊課程,謝謝大家!