安装 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 与参数到引擎执行并返回结果的一整套代码逻辑
网友评论