開發EOS智能合約

http://www.qkljw.com/article/1856.html
在CSDN、柏鏈道捷(PDJ Education)、HelloEOS、中關村區塊鏈產業聯盟主辦的「EOS入門及最新技術解讀」專場沙龍上,柏鏈道捷(PDJ Education)CTO、副總裁康爍,作了「如何在EOS上開發智能合約」的精彩演講。演講中,康爍從EOS環境的搭建、錢包和賬號的創建及管理、智能合約的開發步驟作了詳細的講解,希望對你有所幫助。
康爍簡介:

康爍,柏鏈道捷(PDJ Education)CTO、副總裁、清華阿爾山區塊鏈研究中心高級工程師。曾受邀參加2015LLVM開發者大會,展示了自研的Android模擬器項目。主持開發的開源項目SkyEye在國內外有衆多用戶,是知名的開源項目之一。主持開發的開源項目Android_S2E項目被華爲公司內部使用,目前主要從事區塊鏈底層系統開發工作。

以下爲康爍在EOS入門及最新技術解讀專場沙龍的精彩分享。

我分享的角度可能更多是從一個EOS智能合約的入門者或者開發者的角度去分析我對EOS的初步認識。

在這之前我編譯過EOS,然後開發了一些智能合約,包括之前把以太坊的一些智能合約做了移植。對於這裏面,我有自己的一些看法。

我主要是做系統軟件出身,之前在操作系統、虛擬機、編譯器、安全等領域都有一些項目實戰,我自己現在主持和維護了兩個開源項目:

1、SkyEye。這是一個比較知名的開源虛擬機項目,如果大家在網上用Google和百度搜索這個項目,可以看到用戶還是比較多的,包括國內或者國外。

2、Android s2e。這個項目主要做的是符號執行,它可以檢測安全漏洞。

大概在去年的時候,以太坊的智能合約被爆出大概有幾千個漏洞。其實就是用符號執行的方法,把智能合約的好多漏洞都掃描出來了。而我做的這個項目是可以對Android的整個操作系統做符號分析,並且這個項目在華爲內部得到使用。

所以,我對操作系統或者說編譯器方面是蠻有經驗的。我想先從系統軟件從業者的角度,分享一些對EOS的看法。

EOS和以太坊很像,EOS很明確的說明它就是一個區塊鏈的操作系統,BM在博客中也是說過的。

可以這樣比喻,EOS就相當於內置激勵系統的Windows/Linux/MacOS,這是它的一個定位。包括以太坊也有自己的定位,Vitalik在2014年第一次說以太坊想法的時候,他就很明確的說了,以太坊就是一個全球計算機,這些都是創始人本人提出的一個想法。

EOS環境搭建和啓動節點

下面從EOS入門的環境搭建、編譯運行一個智能合約、發送一些Aigsen,給大家做一些展示,希望能讓非技術人員也有一些收穫。

首先下載EOS環境搭建和啓動節點。這一步其實還是比較簡單的,但是對於非技術人員,最大的障礙就是,現在用EOS,不管是在MacOS還是Linux,基本都是在命令行下操作,這一點和以太坊還是不太一樣。因爲以太坊有一個瀏覽器插件,可以用一些圖形化的IDE去操作,這樣對非技術人員或者前端人員,可能他不太熟悉這個命令行命令的人都是比較友好的。

EOS環境的搭建和節點啓動分爲以下兩步:

第一步:用Git克隆,下載EOS的源代碼

使用命令:

git clonehttps://github.com/EOSIO/eos --recursive

下載源代碼,時間會比較長,大概1-3小時,另外,下載編譯對計算機內存要求最少要有8GB。

下載編譯之後,裏面有三個應用程序,這三個應用程序也都是命令行的:

1、Cleos;

2、Nodeos;

3、Keosd。

這三個應用程序之間有什麼關係呢?我們現在使用的前端,怎麼使用EOS呢?

-Cleos,它是一個命令行程序。在前端使用EOS是通過Cleos輸入命令,給EOS下達指令。

-Nodeos,其實它就是挖礦客戶端。在啓動Nodeos之後,它自然就會產生區塊。

-Keosd,它是在後端啓動。它的目的主要是管理錢包,可以創建私鑰。

爲什麼分成Nodeos和Keosd?

我理解的是,Keosd可以認爲是個輕客戶端,因爲有時候只需要進行錢包操作,不需要挖礦,就可以啓動Keosd。

第二步:節點啓動

在第一步下載編譯都做完之後,就可以啓動一個節點開始愉快的挖礦了!下面是啓動節點的命令:

cd build/programs/nodeos

./nodeos -e -p eosio –plugin eosio::wallet_api_plugin –plugineosio::chain_api_plugin –plugin eosio::account_history_api_plugin

整個EOS是插件式結構,需要有一個主程序,其它像錢包管理、區塊鏈等都是一個插件。

輸入上邊命令後啓動了一個節點,同時啓動了一些插件,會打印一些基本信息,以及挖礦的信息。

EOS創建和管理錢包

節點啓動後我們要做的第一件事兒是什麼呢?就是我們首先要有賬號,但是有賬號的前提是什麼呢?倒不是先創建賬號,而是先要有自己的一組私鑰,有了私鑰纔能有賬號,有賬號的前提還是要有錢包。所以,最開始我們是創建錢包,錢包是用來管理我們的密鑰的。

第一步:創建錢包

使用命令:Cleos wallet create,就可以創建一個錢包。像以太坊、比特幣這些已經比較成熟了,使用一些客戶端可以去創建錢包。

如果你想用不同的參數,可以在命令後邊加上-N,-N指定你的錢包名稱是另外一個錢包名稱,可以創建不同的錢包,然後每個錢包都可以管理一組密鑰。

第二步:創建一組祕鑰

創建好錢包,就可以創建一組密鑰,創建命令爲:

cleos create key

第三步:祕鑰導入錢包

在第二步創建的密鑰,只是生成一組公鑰、私鑰,還需要把公鑰、私鑰導入錢包,才能讓錢包把公鑰和祕鑰管理起來。

導入命令爲:

cleos wallet import

可以在命令後面指定錢包,這樣就可以把第二步創建的一組公鑰、私鑰直接導入指定的錢包。

第四步:查看錢包中的祕鑰

使用以下命令就可以查看是不是成功的把祕鑰導入錢包了:

cleos wallet keys

我覺得不太懂技術的非技術人員,可能以後也要懂技術,因爲你最後玩比特幣,也會了解什麼是私鑰、什麼是公鑰、什麼是256位的二進制賬號。大家剛開始可能學起來比較痛苦,可能也要逐漸有個習慣的過程。

這樣就都做完了,我創建了一組密鑰,密鑰包括公鑰和私鑰,然後我把這組公鑰又放到剛纔我創建的錢包裏面了。

創建好錢包、密鑰之後,接下來我們可以做什麼事兒呢?

EOS創建和管理賬號

創建好錢包、密鑰之後,接下來你就可以創建賬號了,賬號是什麼?賬號保存在區塊鏈上的人類可讀的標誌符。

創建賬號的命令:

$ cleos createaccount eosio ${new_account} ${owner_key} ${active_key}

其中eosio是超級用戶,需要靠超級用戶來創建其它的新用戶,eosio後面就是你的新用戶的用戶名。

除了新的賬號之外,命令後面還有兩個key:

1、Owner key

2、Active key

Owner key是什麼意思呢?Owner key表示分配給新賬號的一個Owner認證的公鑰。Active key是分配給新賬號一個Active認證的一個公鑰。

至於這兩個認證,我後面會給詳細介紹,這是兩個主要的權限。我創建一個賬號,如果這個賬號要有Owner的權限和Active的權限,就必須要用這兩個key才能實現。

我們來總結一下剛纔的操作,我們剛纔操作是調用Cleoscreate account創建了一個賬號,這個賬號的命名規則遵守下邊兩個規則:

1、小於13個字符;

2、僅包含這些字符:.12345abcdefghijklmnopqrstuvwxyz

另外,剛纔給大家說到Owner key和Active key的概念。Owner key的概念就是你賬號的所有控制權限,你只要有了Owner key,你可以對這個賬號的任何東西做任何的事兒,這是它的所有控制權。

而Active key只掌握了你的賬號資金的訪問權限,也就是你如果有了Active這個權限的話,你可以對這個賬號的資金進行轉移,但是你不能轉移這個賬號的所有權,或者不能做超過這個Active權限其它的權利。

如果簡單的理解,Owner key就是對這個賬號的最高權限,Active只是用來轉移資金而已。這也是與以太坊智能合約開發的一個區別,以太坊賬號的權限其實沒有這麼細分,它就只有一個賬號,我只要有這個賬號的公鑰和私鑰,我就可以做任何事情。

EOS的權限和許可

對於EOS的權限和許可,分得非常細。

「Permission」我沒有翻譯成權限,我這裏覺得它更像一種叫做「許可」,它是一個操作允許的權限,可以建立很多permission。比如允許你轉賬,允許你發微博或者允許你做其他事。它是通過permission來控制你的操作,可能不同的用戶有不同的permission。

Threshold是某個許可需要的閾值。比如你要做一件事兒,它可能有個閾值,這個閾值是一個量化,你必須要達到這個閾值纔可以進行相應的操作。

Weight表示權重。賬號必須對應某個許可擁有的權重,就是你的權重要大於你的閾值,然後這件事兒你就可以做。

在permission許可裏面有兩種許可:

-owner許可;

-active許可。

這兩個叫native(原生)的permission,另外還有public的permission。

下面通過兩個例子來解釋他們之間的關係與區別:

permission account weight threshold
owner

1

EOS5EzTZZQQxdrDaJAPD9pDzGJZ5bj34HaAb8yuvjFHGWzqV25Dch 1
active

1

EOS61chK8GbH4ukWcbom8HgK95AeUfP8MBPn7XRq8FeMBYYTgwmcX 1

第一個例子, owner許可的閾值是1,它裏面有一個賬號,這個賬號是用它的公鑰來代表的,然後這個賬號的權重是1,這樣你的權重是大於等於閾值的,所以可以用owner的賬號和權限。

active許可裏面有一個賬號,它的權重也是等於這個閾值,所以可以用active的賬號和權限。

這兩個賬號,一個是有owner權限,一個是有active權限,因爲它們的權重和閾值是大於等於這個值的,對應的賬號與權限都是可以使用的。

permission account weight threshold
owner

2

@bob 1

@stracy 1
active

2
@bob 1

@stracy 1
publish

2

@bob 2

@stracy 2

第二個例子,除了owner的permission之外,你還可以有一個publish permission。它們之間有什麼區別呢?

當你創建任何一個賬號,這個賬號都有owner的許可和active的許可。其他的許可就是你可以自己定義,來讓不同的用戶,擁有不同的許可組合,這樣就可以很靈活的去管理不同的賬號。

所以這一點,EOS考慮的比較比較細緻一點,但是以太坊或者比特幣沒有做到這麼細緻,以太坊或者比特幣擁有一個賬號就可以做任何事情。

這裏面再細一點來講,這裏面的owner的閾值是R,bob賬號的權重只有1,stracy賬號的權重也只有1,如果它倆單獨的去獲得owner許可相關的操作,它們是獲得不了的。但是,如果bob和stracy加起來大於等於2,就是這兩個賬號聯合起來大於等於2的,這兩個賬號就可以做這個操作的,其實這有點像投票。

我覺得這個權限或許可的限制,和我們傳統的操作系統是不太一樣的。我們傳統的操作系統好像沒有這種聯合簽名可以達到兩個權重來執行owner的相關操作。

active這也是一樣的,如果bob賬號是1,stracy賬號是1,如果active需要的閾值是1的話, bob賬號和stracy賬號是單獨都可以做active許可相關的操作,就是轉移資金。

另外,publish就是一個定製化許可。我們每個用戶也可以定義自己某些允許的一些操作。publish這裏面的閾值是2,bob賬號是2,stracy賬號是2,這兩個賬號也可以單獨做publish許可相關的操作。而publish的權限可能是比如發佈一些消息、發佈一些微博的操作。

通過以上兩個例子,給大家展示了EOS對權限設置的設計有多細緻。

EOS智能合約

EOS的智能合約裏面有一個action(動作)和transaction(交易)的概念。

對於我們以太坊開發者來說,基本上只有transaction的概念。如果我只要執行一種操作,而且是隻讀操作,就不需要簽名。如果需要劃資金,有一些寫的操作,那就需要用戶用公鑰對這個操作去簽名,然後pos的一個transaction,這是以太坊的概念。

對於EOS,它多了一個action的概念,action其實它也是對一個智能合約中的某個函數的調用。transaction是由一個或者多個action組合而成的關係,就是在一個transaction裏,可以包含多個action,這樣你可以在一個transaction裏籤一次名,就可以調多個函數,做一組操作。

部署智能合約

部署智能合約的示例代碼如下:

$ cleos set contract eosio build/contracts/eosio.bios -p eosio

其中,eosio是要部署的賬號,就是你用哪個賬號去部署智能合約;

build/contracts/eosio.bios表示的是路徑;

eos.bios是生成一個智能合約的目錄。

運行Token合約

第一步,Token智能合約部署,代碼如下:

cleos set contracteosio.token build/contracts/eosio.token -p eosio.token

第二步,調用create函數,代碼如下:

$ cleos push actioneosio.token create ‘[ “eosio”, “1000000000.0000 EOS”, 0, 0, 0]’ -p eosio.token

調用create函數,設定到幣的最大數目,開始創建我的token。

怎麼調用一個action呢?我們都是通過cloes命令行調用action,不過後面跟的參數不一樣。push action,這兩個都是固定的,後面是合約的名稱。

eosio是賬號名,後面數字表示設定token總量是10億,幣的名稱是EOS幣,後面有3個0,代表的是三個參數:can freeze、can recall、can whitelist。這3個參數設置爲0,一共傳了5個參數,通過這樣的方法,去調用整個的合約create的函數。

第三步,轉移100個pdj幣到user用戶,代碼如下:

$cleos push actioneosio.token issue '[ "user", "100.0000 EOS","memo" ]' -p eosio

Issue這個操作是用來發幣,它後面跟了3個參數:

一個是user,表示這個幣發給誰;

數字表示要給這個用戶轉多少錢,我這裏轉了100多個user的token;

最後一個參數是是一個備註,相當於轉賬留言。

第四步、從user用戶轉移25個PDJ幣給tester用戶,代碼如下:

$cleos push actioneosio.token transfer '[ "user", "tester", "25.0000EOS", "m" ]' -p user

這是一個轉賬合約的運行過程,先部署合約,然後調用create,可以轉賬,既可以轉到user,也可以從一個user用戶轉到test用戶,整個過程在user wiki文檔上也寫得比較清楚的。

調試智能合約

現在user官方網站推薦的一個調試方法就是print,把信息打印出來。這個必須要我們搭建本地節點,因爲如果沒有本地節點,相當於你print打印在別人的節點上,你根本看不到這個打印信息是什麼,所以說你必須要搭建一個本地節點。搭建本地節點後,你運行智能合約,就會看到print出來的輸出結果。

EOS智能合約的RPC接口

其實智能合約整個只完成了DApp最核心的一部分,就是基本上和資金有關係的一些關鍵操作,其實大部分的接口、界面,還得我們用JavaScript、HTML去做。

那我們這些DApp其它寫界面的操作,怎麼去調用智能合約呢?都是通過user智能合約RPC接口調用,智能合約的RPC接口文檔鏈接是:https://eosio.github.io/eos/group__eosiorpc.htm

RPC的接口我們除了用C++或者用編程的方法去調用一些接口,我們可以用curl這種最簡單的方法去調用這個接口。curl它相當於模擬了一個瀏覽器的操作,我可以向我的運行節點的RPC端口發消息。

這裏面我可以給大家展示,我列了3個。

1.get_info:獲得節點信息。通過調用這個接口,它會返回我運行節點,比如說server version,就是我運行節點這個節點的版本號;head blocknum,是我當前挖到哪個塊了。

用法:

curl http://127.0.0.1:8888/v1/chain/get_info
  1. get_block:獲得一個塊的信息。調用該接口,指定塊號(blocknum),就可以獲得指定塊的詳細信息。

用法:

$ curl http://127.0.0.1:8888/v1/chain/get_block -X POST -d'{"block_num_or_id":5}'

3.get_account:獲得某個賬號的信息。調用這個接口,可以獲得當前我的一個賬號信息

用法:

$ curlhttp://127.0.0.1:8888/v1/chain/get_account -X POST -d'{"account_name":"inita"}'

EOS智能合約編程示例:HelloPDJ

下面有一個編程示例,給大家展示一下我怎麼樣寫智能合約的。它這個智能合約可以用C語言(一種計算機程序語言)來寫,也可以用C++(一種計算機程序語言)來寫,這裏面我就用C++來寫。示例代碼如下:

// hello.cpp源代碼 #include<eosiolib/eosio.hpp> #include <eosiolib/print.hpp> using namespace eosio; class hello : public eosio::contract {
public: using contract::contract;
/// @abi action     void hi( account_name user )              {print( “Hello, ”, name{user} ); }

};
EOSIO_ABI( hello, (hi) )

如果我自己寫了一個智能合約,怎麼去編譯和部署呢?編譯的步驟大概是這樣的:

第一步,編譯hello文件

$ eosiocpp -o hello.wasthello.cpp

$ eosiocpp -g hello.abihello.cpp

第二步,創建賬號

$cleos create account eosio hello.codeEOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4 ...

第三步,部署合約

cleos set contract hello.code../hello -p hello.code

第四步,調用合約

cleos push action hello.codehi '["user"]' -p user

關於開發的一些感受

最後,我想談談我個人開發EOS智能合約的一些感受,在開發EOS智能合約整個使用和編譯比較流暢,基本沒有碰到問題,感覺系統還是比較穩定可靠的。但是,編寫複雜一點的智能合約感覺無從下手,文檔還是偏少,有些無關大雅的小錯誤。此外,我認爲使用C++寫智能合約門檻有點高,不知道未來的走勢如何?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章