安裝 EOS :
$ brew tap eosio/eosio
$ brew install eosio
安裝 EOS 工具鏈:
$ brew tap eosio/eosio
$ brew install eosio
工具鏈文檔:https://eosio.github.io/eosio.cdt/1.6.0/
開發環境搭建
啓動節點
- 啓動 keosd :
keosd &
- 啓動 nodeos :
nodeos -e -p eosio \
--plugin eosio::producer_plugin \
--plugin eosio::chain_api_plugin \
--plugin eosio::http_plugin \
--access-control-allow-origin='*' \
--contracts-console \
--http-validate-host=false \
--verbose-http-errors >> nodeos.log 2>&1 &
創建開發錢包(Create Development Wallet):
- 1.創建錢包(僅測試用):cleos wallet create --to-console
return_password :PW5J3thuJq6RuoeuAj4YvinoccKaKQsyJmc8UfqkZGUthVe5vimvK
錢包(Wallet) 並不存儲 token ,僅僅存儲私鑰,並用私鑰來簽署交易
2.打開錢包:
cleos wallet open
cleos wallet list- 解鎖 : cleos wallet unlock
- 在錢包中創建私鑰: cleos wallet create_key
return_public_key : "EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W"
- 在錢包中創建私鑰: cleos wallet create_key
- Development Public Key : EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
- Import the Development Key
每個新的 EOSIO 鏈都有一個默認的系統用戶叫 “eosio” ,這個用戶按協議來初始化鏈,包括治理和共識,每一個鏈都有一個相同的 dev key,系統用戶 “eosio“ 需要導入這個 key 去簽署交易
執行:cleos wallet import
輸入:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
返回: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
- Import the Development Key
創建測試賬戶(Create Test Account)
在
wallet
裏可以導入private-key
, 由private-key
可以推導出public-key
,一個賬號有個最長12個字符的account name
,賬號對應的權限是有其對應的key
決定的,基本的有ownner
和active
這兩類key
.
TODO:owner/active分別代表什麼?
帳戶是一組授權,存儲在區塊鏈上,用於識別 from / to。
我們將使用 cleos create account
創建兩個賬戶 bob 和 alice
- Create Test Account
cleos create account eosio bob EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
cleos create account eosio alice EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
- Create Test Account
- Public Key
cleos get account alice
- Public Key
創建hello合約 (1.6.0):
在當前目錄創建名爲 hello 的合約模版:
編譯合約:編譯後會在 build/hello 目錄下生成 wasm 和 abi 等信息
eosio-init -path=./ -project=hello
cd hello/build ; cmake ..
make
編譯結果包含 hello.wasm 和 hello.abi 文件在 hello/build/hello 中,
部署hello合約
合約部署是指部署到一個 account 上,這個賬戶將成爲合約的接口
查看本地已解鎖的可用公鑰 : cleos wallet keys
$> cleos wallet keys
[
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W"
]
爲合約創建一個 account : cleos create account
$> cleos create account eosio hello EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W -p eosio@active
executed transaction: 18b84d215c6aeebaf82050d1c7be64971995e2d257eed2916017880d1f7ddbfb 200 bytes 216 us
# eosio <= eosio::newaccount {"creator":"eosio","name":"hello","owner":{"threshold":1,"keys":[{"key":"EOS7rKrA84f8R16Z9mhG3aU7tUQ...
部署hello合約到鏈上: cleos set contract
注意 CONTRACTS_DIR
需要是絕對路徑
$> cleos set contract hello CONTRACTS_DIR/hello -p hello@active
Reading WASM from /Users/liangc/bin/eosdemo/hello/build/hello/hello.wasm...
Publishing contract...
executed transaction: 9d8f62fe22c48d322459ac4c5136339aef0202d2616288c51a8ae6b270b4c349 760 bytes 3758 us
# eosio <= eosio::setcode {"account":"hello","vmtype":0,"vmversion":0,"code":"0061736d0100000001370b60027f7f0060017e0060017f00...
# eosio <= eosio::setabi {"account":"hello","abi":"0e656f73696f3a3a6162692f312e3100010268690001026e6d046e616d6501000000000000...
warning: transaction executed locally, but may not be confirmed by the network yet
執行hello合約(push an action): cleos push action
$> cleos push action hello hi '["bob"]' -p bob@active
executed transaction: eab9a201c73785b635d3e11c9aad3a137d0f462eaa56461b5aa63938f30a51bb 104 bytes 1458 us
# hello <= hello::hi {"nm":"bob"}
>> Name : bob
EOS合約虛擬機
EOS-WASM 引擎代碼
https://github.com/EOSIO/eos/tree/master/libraries/wasm-jit
一個小玩具(非生產環境)
https://github.com/wasmerio/kernel-wasm
Building and running it
To build it, you'll need CMake and LLVM 4.0. If CMake can't find your LLVM directory, you can manually give it the location in the LLVM_DIR CMake configuration variable. Note that on Windows, you must compile LLVM from source, and manually point the LLVM_DIR configuration variable at <LLVM build directory>\lib\cmake\llvm
.
ubuntu deps
sudo apt install -y git make bzip2 automake libbz2-dev libssl-dev doxygen graphviz libgmp3-dev autotools-dev libicu-dev python2.7 python2.7-dev python3 python3-dev autoconf libtool curl zlib1g-dev sudo ruby libusb-1.0-0-dev libcurl4-gnutls-dev pkg-config patch
build eos
依賴安裝完成後編譯:scripts/eosio_build.sh
會在如下路徑找到目標靜態庫:eos/build/libraries/wasm-jit/
到此爲止吧,因爲這個 wasm-jit 的 main 函數已經落後 WAVM 了,他是 fork 自 WAVM ,所以直接使用 WAVM 也可以運行 eos 的 wasm 合約
WAVM 引擎編譯與使用
這個模塊是 wasm 的執行引擎,可以單獨編譯成一套工具集
編譯這個模塊需要配置 LLVM_DIR
環境變量,指向 ${LLVM_HOME}/lib/cmake/llvm/
假設我們的 LLVM_HOME=/usr/lib/llvm
則 export LLVM_DIR=/usr/lib/llvm/lib/cmake/llvm/
編譯
$> git clone https://github.com/WAVM/WAVM.git
$> cd WAVM; mkdir build; cd build; cmake ..
$> make -j4
$> export PATH=`pwd`/bin:$PATH
這時在 bin 目錄下可以看到如下工具集
$> ll bin/
-rwxrwxr-x 1 liangc liangc 560472 7月 10 14:14 wavm-as*
-rwxrwxr-x 1 liangc liangc 630672 7月 10 14:15 wavm-compile*
-rwxrwxr-x 1 liangc liangc 22720 7月 10 14:14 wavm-c-test*
-rwxrwxr-x 1 liangc liangc 487944 7月 10 14:14 wavm-disas*
-rwxrwxr-x 1 liangc liangc 914784 7月 10 14:15 wavm-run*
-rwxrwxr-x 1 liangc liangc 691552 7月 10 14:15 wavm-run-wasi*
...
開發時主要會用到以下幾個工具
- wavm-as : 將 wast 轉爲 wasm
- wavm-disas : 將 wasm 轉爲 wast
- wavm-run : 用來執行 wasm / wast
關於 wast 的 s 表達式
https://developer.mozilla.org/zh-CN/docs/WebAssembly/Understanding_the_text_format
emcc (emscripten) 編譯器
emcc 用於將 c/c++ 編譯成 wasm ,需要依賴 llvm
安裝:
$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install sdk-incoming-64bit binaryen-master-64bit
$ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
神祕的編譯指令:
https://github.com/emscripten-core/emscripten/blob/1.29.12/src/settings.js#L388
識別一個 wasm 文件的標識爲前 8 個字節
0000000: 0061 736d ; WASM_BINARY_MAGIC
0000004: 0d00 0000 ; WASM_BINARY_VERSION
編寫測試代碼
研究到這,其實已經可以擺脫 eos 來使用 wavm 執行 eos 提供的 wasm 代碼了,但是 eos 封裝了一整套的庫文件,還有整個合約函數的代理函數,導致我們無法通過 eos 合約編譯出來的 wasm 的導出函數直接調用合約,因爲我們不知道正確的參數是什麼。
TODO :還要繼續閱讀 eos 提交一個 action 與參數到引擎執行並返回結果的一整套代碼邏輯