EOS 合约探索笔记

2019-07-15  本文已影响0人  cc14514

安装 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/

开发环境搭建

启动节点

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):

创建测试账户(Create Test Account)

wallet里可以导入private-key, 由private-key可以推导出public-key,一个账号有个最长12个字符的account name,账号对应的权限是有其对应的key决定的,基本的有ownneractive这两类key.
TODO:owner/active分别代表什么?

帐户是一组授权,存储在区块链上,用于识别 from / to。
我们将使用 cleos create account 创建两个账户 bob 和 alice

创建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*
...

开发时主要会用到以下几个工具

关于 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 与参数到引擎执行并返回结果的一整套代码逻辑

上一篇下一篇

猜你喜欢

热点阅读