乾貨 l 如何爲Mist創建無服務器應用

【本文做者:Alex Van de Sande,譯者:王建(萬雲平臺區塊鏈技術專家)/蔡佳慧(萬雲實習生區塊鏈技術愛好者),國內首次刊登於萬雲微信公衆號】javascript

以太坊並非那種須要一個STEM文憑(指:科學-science,科技-technology,工程-engineering,及數學-mathematics相關文憑。)才能理解的高深莫測的智能合約應用創建平臺,它的目標實際上是成爲萬維網中各類應用架構的支柱。在這篇文章裏,咱們嘗試去闡述如何實現這個目標,並提供一些基本例子來展現如何開始構建一個去中心化的應用。html

 

目標讀者java

這篇文章面向有如下背景的讀者:git

對於Web技術有基本瞭解,並知道如何構建一個簡單的基於javascript和html的應用。同時,但願使用這些技能爲以太坊生態系統構建應用。github

 

沒有服務器,應用是如何運行的web

當前,Web應用中的服務器所作的工做已經遠超當初的設想。除了提供靜態網頁,它們還保管私有信息,處理用戶驗證,同時還提供複雜數據分析與保存。而用戶計算機(在Web技術剛被髮明的年代,這種設備會被認爲是超級計算機)所作的僅僅是加載信息,並展現給用戶而已。數據庫

與此不一樣的是,更爲去中心化的系統結構則會容許一種更加模塊化的處理方式。在這種方式中,不一樣的機器與不一樣的協議將會處理特定的任務,有些屬於用戶方面,而也有些屬於配置於點對點網絡中的專用機器方面。所以全部的數據邏輯(什麼會被儲存,誰會去儲存,如何解決衝突等)是由區塊鏈上的智能合約解決的,靜態文檔由Swarm提供,同時實時通訊在Whisper上進行。用戶設備保留用戶認證信息並運行程序界面。編程

 

幾乎沒有單節點保留大量未加密數據,這麼作將會下降數據泄漏與攻擊的危險。同時,經過將其分散於全網絡,也能夠下降應用的加載與花銷成本。因爲全部這些協議都是去中心化的,任何人均可以鏈接到網絡並開始提供特定服務:好比說,若是用戶在一個功能強大的筆記本電腦上瀏覽,這臺電腦也能夠向網絡鄰居們提供靜態文件。json

一個去中心化的系統結構同時鼓勵創新:因爲交互界面脫離於數據,任何人均可覺得同一個應用提出一個全新的用戶界面,建立一個更富生機與競爭力的生態系統。能夠說,Twitter歷史上最具趣味性及創新力的時期之一即是它做爲中央數據中心提供服務,同時任何人均可以建立他們本身的Twitter應用。後端

 

觀察它如何運做

若是你想在學習這個應用以前實驗它,咱們推薦你下載Mist並閱讀咱們關於如何安裝應用並運行的入門教程(下載連接:https://github.com/ethereum/mist/releases/tag/v0.9.0)。若是你只是想要看一看完整的應用,你能夠直接從Github上將其下載下來(下載連接:https://github.com/ethereum/stake-voice)。

 

咱們如今上手操做

咱們將會創建一個叫作「Stake Voice」的很是簡單的應用。其主旨是容許以太幣投注人對任何他們想投的事情進行投票,同時這個應用將會計算全部贊成與不一樣意這個陳述的以太幣總和。

下面代碼是這個應用裏用Solidity語言編寫合約,Solidity是一種相似於javascript的語言,很是簡單:

第一行創建了合約名稱,同時第二行建立了一個命名爲「LogVote」的事件,它將會在日誌文件中記錄如下內容:

  • 將會被投票的提案的哈希值

  • 投票者是贊成仍是反對提案

  • 投票者的地址

函數「vote」接着會啓動日誌,應用程序稍後會計數。它同時會檢查確保沒有意外發送的以太幣。當任何以太幣被存入智能合約時,「匿名」函數會被執行,並會自動拒絕接收以太幣。

若是你想要學習關於Solidity更多的編程內容,咱們推薦你從以太網solidity教程( https://ethereum.org/dao)開始,閱讀官方文檔頁面( https://solidity.readthedocs.io/en/latest/)並在你的瀏覽器上嘗試在線編譯器( https://ethereum.github.io/browser-solidity/#version=soljson-latest.js)。

大體上就是如此了:你選擇一個哈希值,選擇一方而後運行Vote()。因此這又如何轉化成一個投票應用?

 

無服務器架構

遵循KISS原則,咱們正在製做儘可能小卻仍然可以使用的產品。這意味着咱們不會使用數據庫來儲存提案,也不會使用普通javascript與純粹html以外的功能。

所以,咱們將使用應用自己的URL來保存提案文本,而且咱們會使用URL來向用戶展現提案內容,再生成一個用來檢測投票的哈希值。用戶可使用社交媒體來分享他們想要辯論的提案,或者直接使用連接。

 

從基礎開始

拿出你最喜歡的html框架,並在你本地機器上創建一個簡單網站,而後在Mist上打開它。Mist上全部的頁面均可以訪問一個名叫web3的javascript對象,這也是你的主要工做區域。咱們要作的第一件事就是檢查web3是否存在:

一些應用開發者也許會想要去加載他們本身的web3對象,以保證向前的兼容性。要作到這些,只須要在</body>標籤前加上:

而後在初始函數上加上這個去加載你自定義的web3提供方(provider):

 

從區塊鏈上加載信息

你檢查到你鏈接到區塊鏈網絡上了嗎?可是究竟是哪個區塊鏈網絡呢?是主體(main)以太坊網絡嗎?也許是一個測試網絡(testnet)或者是一個私有(private)網絡?或許將來某一天,你會分叉(fork)一個以太坊源碼,構建一個屬於你本身的全新品牌區塊鏈。檢查網絡的最好辦法是查看你想要加載的合約地址中是否包含了代碼。

此外,爲了執行一個合約你須要知道兩個基本事項:它的地址和ABI(ABI是使用json編碼的接口文檔)。

如今有了上面這些內容,你就可以在啓動函數上檢測合約是否存在了:

你甚至能夠遞歸地運行這條命令,嘗試用不一樣的地址去鏈接(假定你測試網絡上)。一旦你找到你的合約,你就能夠在這裏加載它了:

你用web3對象建立的javascript對象,可以直接在瀏覽器中執行全部以太坊命令。若是你僅僅想要加載一個合同的實例,你甚至能夠在一行代碼裏作到:

 

用戶鑑別

獲取用戶帳戶披露了這個用戶的大量信息:帳戶餘額中有多少以太幣和其餘代幣,以及其交易歷史。所以,默認讓全部應用獲取這一信息將會建立一個超級cookie,因爲對隱私的侵犯,這是不能夠接收的。另外一方面,要求用戶爲每個網站建立一個帶有登陸信息的帳戶,這不只對用戶來講是一個痛苦,並且把你的隱私交給第三方來掌控,這種方式將會讓個第三方變成一個可被黑客隨意掘取的巨大蜂蜜罐。

面對這一困境,多數用戶選擇將本身我的信息及驗證信息交由一個幾十億美圓公司處理。隱私權不該該爲了取得實用性而妥協:用戶應該在掌控他們的我的信息的同時,可以輕鬆地驗證身份信息以登入任何應用。

使用Mist,應用不擁有關於用戶的信息,除非用戶決定公佈其自身信息給應用。當你想要查詢本身的帳戶信息,你應該調用getAccounts函數:

目前,返回對象是一個數組,其中包含了用戶擁有本地訪問權限的簡單帳戶,可是在將來,其中還會包含用戶用於自身識別的智能合約帳戶。這將會使得用戶擁有權限來訪問目前只供給集中式驗證器(centralized authenticators)的特性,好比雙重身份驗證或者雲備份。用戶一樣將會擁有權限來訪問將來針對智能合約的改進,好比在你遺失密鑰的時候容許一些受信任的朋友來給你訪問帳戶的權限,或者對於不活動帳戶行使自動繼承權。

每個將來的以太坊瀏覽器將會解決用戶如何嚮應用辨別自身的問題。在Mist中咱們由兩種方式:要麼用戶能夠經過敲擊「connect」按鍵(目前僅叫作「no accounts」按鍵)來啓動它,或者應用能夠經過調用「requestAccount」api來要求身份驗證。

注意:這個列表上的帳戶僅僅只是用戶聲明擁有密鑰的帳戶,可是用戶並無提供證實,所以你能夠展現一個不一樣的界面,可是不要給用戶發送任何與帳戶有關的加密信息。若是須要用戶證實他們的身份,你須要讓用戶對信息簽名,同時Mist也會在將來支持它,請注意這會要求用戶作一個額外步驟--輸入密碼。因此只在必要的時候,你纔會須要用戶簽名。

 

投票

一旦你有了合約對象,投票就僅僅只是從javascript中調用它。調用函數會下面這段代碼處提供操做器將會解決用戶們如何嚮應用辨別會包含用戶們彈出一個Mist交易面板,用戶能夠在面板上檢查交易內容,並輸入密碼。

所以,首先咱們要建立兩個能夠調用投票函數的可點擊對象:

注意咱們調用的一個函數參數爲true,另外一個則爲false。投票函數能夠像下面這麼簡單:

「Ethervote」是咱們以前建立的對象,而且「vote」是它函數中的一個,對應着合約函數的一個:

根據函數的要求,咱們須要傳入兩個參數,並增長包含交易信息的第三個對象,好比:誰發送了此交易,以及兩個可選項:包含多少gas或者購買gas的費用。

由此,這將會建立一個面板,以要求用戶確認交易——可是多數狀況下它會返回一個錯誤信息,由於目前web3.eth.accounts對象默認是一個空數組,因此你須要檢查其是否爲空,若爲空,則從用戶處請求帳戶:

你應該只在用戶初始化一項操做的狀況下請求帳戶:無中生有地顯示一項交易只會理所固然地激怒用戶,更可能使他/她關閉你的應用。若是咱們觀察到應用對於這一功能的濫用行爲,咱們能夠對於什麼時候彈出警報施加更爲嚴格的要求。

 

查看合約

最後,爲了累計全部的投票,咱們須要查看合約事件,以及投票內容。爲了完成這些工做,在咱們實例化「ethervote」後咱們須要去運行這個函數一次來查看事件:

上述代碼會從第180萬(這是合約被上傳的時間點)高度讀取全部的區塊,沒讀取一個區塊時,都會執行receivedEvent()函數;而且,每產生一個新區塊時,這個函數就會被再次觸發,因此你不須要連續調用。那麼,這個函數到底有什麼用呢?

從初始solidity合約中,你能夠看到LogVote帶有三個參數,proposalHash,Pro和Addr:

因此這個函數的做用是它會使用函數web3.eth.getBalance來檢查投票地址當下的以太幣餘額。全部的餘額都會返回以wei爲單位的數字,也就是一個以太幣的1/1000000000000000000,這對於這個特定的應用並不是很是的有用,因此咱們也使用另外一個包含的web3函數來將其轉換爲任何咱們須要的以太幣單位。這裏,咱們會使用finney,也就是一個以太幣的一千分之一。

接下來,這個函數將會保存投票者的餘額及位置於一個以用戶地址爲Key的Map上。因此若是有人投了兩次票,只有他們最後的意見會被保留。

另外咱們還能鑑別用戶,並展現他們是否投票。

 

累積票數

最後,咱們應該加入一個獨立的函數來計算票數的總數:

爲何咱們會想要經過一個獨立的函數來累積票數呢?由於票數權重是創建在每個帳戶的當前餘額之上的,咱們應該對於每個新區塊從新計算餘額,即便咱們並無收到新的事件。爲了作到這個,你能夠增長這個函數,使它每收到一個新區塊時就會自動執行;

最後,直到加到最終的總數爲止。咱們以前已經在同步模式下使用了eth.getBalance,在此模式下,應用會等待前一個操做的結果再繼續。此處,由於咱們能夠對於每個區塊調用大量操做,咱們將會在異步模式下運行它:你能夠異步調用getBalance函數,等到節點返回後,再進行票數統計。

就像你根據代碼所做的同樣,應用所作的就是在循環投票地址中的每個並獲得它們的餘額,只要它返回結果,它會將其加到支持或反對陣營中,並計算總和。

 

額外的好處

一些附加說明:當沒有事件時,什麼也不會被返回,而且投票也不會被計算,因此你應該對依賴於區塊鏈上事件的全部函數增長一個超時函數。

如今你能夠隨意地使用全部你現有的網絡開發工具來施展你想要的任何魔法。使用數字來構建一個漂亮的3D可視化效果或者關聯你最愛的社交媒體來分享最佳問題。

Mist也嘗試提供一些基本的導覽,以及UI方式來簡化你的代碼。若是你想要你的應用不包含header而且佔據mist應用的全部高度,只要將這個加入到你的<head>標籤:

而且若是你想要使用Mist自身來導覽?你的應用,你可使用Mist.menu對象:

以太坊強大的一點是你能夠在不須要許可的狀況下,擴展這項簡單的合約功能:你能夠把每一個額外的功能放到一個獨立的合約裏,讓每一個獨立合約的功能簡單且能夠更輕鬆的調試。這也意味着別人能夠在他們本身的應用中使用你建立的合約並增長新的功能。同時,全部的應用使用相同的數據和後端。

你能夠在Github上(https://github.com/ethereum/stake-voice)在線體驗這個應用,可是這不是權威的規範,只是它衆多可能接口中的一個。同一個應用也可能在你的電腦上或一個IPFS網絡( https://ipfs.io)中做爲一個本地html文檔工做,而且在將來它可使用Swarm技術,在Mist裏直接下載應用。

 

關於如未嘗試的一些建議:

  • 建立當前可用發言列表。任何人均可以經過查看提案文本的sha3來檢查它們,因此你不須要任何許可。

  • 建立線性化的評論,在這裏用戶能夠回覆評論並經過投票來表達支持或反對,就像一個基於Reddit的去中心化的投票制。

  • 除了使用以太幣餘額,你還可使用一些其它的以太坊代幣,好比TheDAO或者Digix Gold來給你的問題加權。由於全部合約保存的原始位置是發送方,你能夠檢查所有發送方的餘額。或者也許你能夠基於信譽(reputation)、甚至是業力(karma)或者其它方式來建立你本身的貨幣。

相關文章
相關標籤/搜索