eosio.cdt:EOS智能合約工具集


目前EOS已經迎來了1.5.x時代,很多內容都有了較大的改變。其中智能合約的工作流程發生了改變,EOSIO為智能合約提供了獨立且功能完整的工具集eosio.cdt。該工具集基於WASM平台,可解耦於eos系統,更便攜地完成智能合約的開發編譯。此外eosio.cdt在底層優化上已經超脫於eos系統,使用了更新的對LLVM有了更佳地支持,未來在性能方面會有較大提升。本章講重點介紹eosio.cdt工具集,在該工具集的基礎上,分析研究eos現有的官方智能合約例子。

關鍵字:eos,eosio.cdt,hello,bbt腳本,李嘉圖合約,合約更新,合約調試

hello

首先,在本機安裝eosio.cdt。官方推薦的安裝方式有很多,筆者推薦采用源碼安裝的方式。

$ git clone --recursive https://github.com/eosio/eosio.cdt
$ cd eosio.cdt
$ ./build.sh
$ sudo ./install.sh

編譯

hello合約的源文件內容:

#include "hello.hpp"
using namespace eosio;

ACTION hello::hi( name user ) {
   print_f( "Hello % from hello", user );
}

EOSIO_DISPATCH( hello, (hi) )

下面開始編譯example/hello合約。執行eosio.cdt剛剛安裝的命令eosio-cpp編譯合約,傳入hello.cpp文件。執行命令:

eosio-cpp -abigen hello.cpp -o hello.wasm

將會生成兩個文件:

  • abi文件,是合約的描述文件,是可讀的json結構,其中包含了合約的備注、版本、結構、接口或動作以及狀態庫的table,這些內容是由編譯工具eosio-cpp通過合約源文件生成的。
  • wasm文件,內容不可讀,用於將合約部署運行在wasm平台上。

部署

合約成功編譯以后,可以在鏈上部署運行。使用前文介紹的bbt腳本快速構建一個多節點EOS網絡環境,然后執行:

cleos set contract useraaaaaaaa examples/hello/ hello.wasm hello.abi

這時會報錯:

Error 3080001: Account using more than allotted RAM usage

說明useraaaaaaaa賬戶的內存容量不夠,需要再購買一些。執行命令購買內存:

cleos system buyram useraaaaaaaa useraaaaaaaa "10 SYS"

然后再次執行前面的合約部署命令,內存充足以后,hello合約被成功部署。

執行

下面嘗試執行hello合約。使用命令:

cleos push action useraaaaaaaa hi '["evsward"]' -p useraaaaaaaa

同步跟蹤EOS節點的日志輸出,會發現有hello合約的信息打印出來。

debug 2018-12-20T12:13:20.233 thread-0  apply_context.cpp:28          print_debug          ] 
[(useraaaaaaaa,hi)->useraaaaaaaa]: CONSOLE OUTPUT BEGIN =====================
Hello evsward from hello
[(useraaaaaaaa,hi)->useraaaaaaaa]: CONSOLE OUTPUT END   =====================

要注意開啟節點的合約調試選項:--contracts-console

合約編寫

下面來研究如何利用eosio.cdt完成合約的編寫。首先嘗試修改hello.cpp。前面的測試中,執行hello合約時是不限制輸入參數的內容的,可以增加檢驗將輸入參數改為有效用戶。

#include "hello.hpp"
using namespace eosio;

ACTION hello::hi( name user ) {
   require_auth(user);
   print_f( "Hello % from lwb", user );
}

EOSIO_DISPATCH( hello, (hi) )

加入了一行代碼require_auth(user);用來校驗用戶的權限,如果輸入參數不是有效用戶名或者傳入的權限與輸入用戶不一致則會報錯,下面來演示如何更新hello合約以及執行最新代碼。仍然是編譯、部署、執行三步:

  • eosio-cpp -abigen hello.cpp -o hello.wasm
  • set contract useraaaaaaaa ../hello/ hello.wasm hello.abi
  • push action useraaaaaaaa hi '["evsward"]' -p useraaaaaaaa

此時第三步的運行命令將會執行失敗,因為不存在名為"evsward"的有效賬戶,因此修改命令:

push action useraaaaaaaa hi '["useraaaaaaaa"]' -p useraaaaaaaa

即可執行成功,這行命令末尾的-p參數不可省略,因為hello合約修改后增加了對賬戶權限的校驗。目前這個參數是hello合約的部署者,如果傳入其他有效賬戶並附屬其權限,也是可以執行成功的。

push action useraaaaaaaa hi '["useraaaaaaab"]' -p useraaaaaaab

傳入的參數改為了b結尾的賬戶,同時附屬了其權限,該action也會成功執行。輸出日志為:

Hello useraaaaaaab from lwb

李嘉圖合約

通過以上對權限hello的測試,似乎能夠察覺出某種深意,即有效賬戶useraaaaaaaa的動作是由自身簽名(通過-p參數)的,useraaaaaaab賬戶的hi動作也是其自身簽名。這種該執行其合法綁定者來關聯該合約的每一個action的合約,被成為李嘉圖等價的合約,簡稱李嘉圖合約。

合約更新的結論

上面更新一個合約時,是使用相同的部署者重新部署修改后的合約。在EOS中,合約一旦被部署者部署,該合約的所有動作均通過部署者來發起。此外,一個部署者可以多次部署同一個合約,同時也可以部署不同的多個合約,以最后一次部署為准。這部分可以通過部署者code來檢查:

cleos get code useraaaaaaaa

輸出該賬戶的code,code就是對應部署的合約的hash。

code hash: ddf06bb75dadfb0b598df0047f5e469891dafce125e0224f869dc8d8e2f5d770

當部署者部署新的合約時,該code會被更新。

合約調試

由於智能合約的運行平台的特殊性,目前暫無法去到WASM平台通過斷點的方式調試合約的字節碼,因此官方給出的調試方法是通過日志,正如上面所展示的內容那樣,官方稱之為Caveman debugging,也自嘲了智能合約的原始調試手段。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM