EOS 合约探索笔记

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

    1. 解锁 : cleos wallet unlock
    1. 在钱包中创建私钥: cleos wallet create_key
      return_public_key : "EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W"
    1. Development Public Key : EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
    1. Import the Development Key
      每个新的 EOSIO 链都有一个默认的系统用户叫 “eosio” ,这个用户按协议来初始化链,包括治理和共识,每一个链都有一个相同的 dev key,系统用户 “eosio“ 需要导入这个 key 去签署交易
      执行:cleos wallet import
      输入:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
      返回: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

创建测试账户(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

    1. Create Test Account
      cleos create account eosio bob EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
      cleos create account eosio alice EOS7rKrA84f8R16Z9mhG3aU7tUQsVuTi4hwjPKabtxU1RAEpQd51W
    1. Public Key
      cleos get account 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 \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 与参数到引擎执行并返回结果的一整套代码逻辑

你可能感兴趣的:(EOS 合约探索笔记)