這篇教程是由以太坊Mist瀏覽器的負責人撰寫,完整地介紹瞭如何開發一個標準的DApp。 ...
-
作者:Alex Van de Sande
-
譯者:王建/蔡佳慧
-
譯者介紹:
王建:萬雲平臺區塊鏈技術專家,擁有多年應用系統架構經驗,目前在區塊鏈落地方面進行積極探索
蔡佳慧:萬雲平臺實習生,區塊鏈技術愛好者,英國帝國理工學院數學專業在讀
這篇教程是由以太坊Mist瀏覽器的負責人撰寫,完整地介紹瞭如何開發一個標準的DApp。
以下是正文:
以太坊並不是那種需要一個STEM文憑(1)才能理解的高深莫測的智能合約應用建立平臺,它的目標其實是成為萬維網中各種應用架構的支柱。在這篇文章里,我們嘗試去闡述如何實現這個目標,並提供一些基本例子來展示如何開始構建一個去中心化的應用。
譯者註:
(1)STEM文憑,指:科學-science,科技-technology,工程-engineering,及數學-mathematics相關文憑。
目標讀者
這篇文章面向有以下背景的讀者:
對於Web技術有基本瞭解,並知道如何構建一個簡單的基於javascript和html的應用。同時,希望使用這些技能為以太坊生態系統構建應用。
沒有伺服器,應用是如何運行的
當前,Web應用中的伺服器所做的工作已經遠超當初的設想。除了提供靜態網頁,它們還保管私有信息,處理用戶驗證,同時還提供複雜數據分析與保存。而用戶電腦(在Web技術剛被髮明的年代,這種設備會被認為是超級電腦)所做的僅僅是載入信息,並展示給用戶而已。
Current server models
與此不同的是,更為去中心化的系統結構則會允許一種更加模塊化的處理方式。在這種方式中,不同的機器與不同的協議將會處理特定的任務,有些屬於用戶方面,而也有些屬於配置於點對點網路中的專用機器方面。因此所有的數據邏輯(什麼會被儲存,誰會去儲存,如何解決衝突等)是由區塊鏈上的智能合約解決的,靜態文檔由Swarm提供,同時實時通信在Whisper上進行。用戶設備保留用戶認證信息並運行程式界面。
幾乎沒有單節點保留大量未加密數據,這麼做將會降低數據泄漏與攻擊的危險。同時,通過將其分散於全網路,也可以降低應用的載入與花銷成本。由於所有這些協議都是去中心化的,任何人都可以連接到網路並開始提供特定服務:比如說,如果用戶在一個功能強大的筆記本電腦上瀏覽,這臺電腦也可以向網路鄰居們提供靜態文件。
Decentralised Server models
一個去中心化的系統結構同時鼓勵創新:由於交互界面脫離於數據,任何人都可以為同一個應用提出一個全新的用戶界面,創建一個更富生機與競爭力的生態系統。可以說,Twitter歷史上最具趣味性及創新力的時期之一便是它作為中央數據中心提供服務,同時任何人都可以創建他們自己的Twitter應用。
觀察它如何運作
如果你想在學習這個應用之前實驗它,我們推薦你下載Mist並閱讀我們關於如何安裝應用並運行的入門教程(下載鏈接:https://github.com/ethereum/mist/releases/tag/v0.9.0)。如果你只是想要看一看完整的應用,你可以直接從Github上將其下載下來(下載鏈接:https://github.com/ethereum/stake-voice)。
Stake Voice running on the Mist Browser
我們現在上手操作
我們將會建立一個叫做“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)或者其它方式來創建你自己的貨幣。
本文為萬雲BasS編譯,未經允許不可轉載。歡迎關註萬雲BasS公眾號,獲取關於區塊鏈技術更多乾貨!