2019-07-19 使用c语言编写ewasm

以太坊ewasm测试链下使用c语言编写ewasm合约

1、 合约的创建

a) 搭建开发环境(ubuntu18)

i. llvm安装

这个不要自己编译,耗时太久,虚拟机上可能编译不过,直接下载安装
打开网站llvm ,选择最新版安装,本文安装8.0

$ wget -c http://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
$ tar xJvf clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
$ pwd
$ vim ~/.bashrc
export PATH=$PATH:..clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04/bin
$ source ~/.bashrc
$ clang --version

ii. wabt安装

    git clone https://github.com/webassembly/wabt.git
    mkdir wabt/build
    cd wabt/build
    cmake .. -DBUILD_TESTS=OFF
    make -j4

iii. pywebassembly安装

    git clone https://github.com/poemm/pywebassembly.git

iv. binaryen安装

    git clone https://github.com/WebAssembly/binaryen.git
    cd binaryen
    mkdir build
    cd build
    cmake ..
    make -j4
    sudo make install

v. rust安装

curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env
cargo install chisel

b) 编写合约

i. 参考代码

C代码:https://github.com/poemm/C_ewasm_contracts
Rust代码:https://github.com/ewasm/rust-ewasm.git
Nim代码:https://github.com/status-im/nimplay

ii. 编写c代码

首先需要获取代码:

git clone https://github.com/poemm/C_ewasm_contracts.git

目的只是为了复制其中的几个文件
新建目录evmc,复制两个文件到这里

mkdir evmc
cd evmc
cp ../C_ewasm_contracts/src/ewasm.h .
cp ../C_ewasm_contracts/src/ewasm.syms .

在当前目录下编写hello.c:

#include "ewasm.h"
typedef unsigned char BYTE;             // 8-bit byte

void main()
{
    char hello[] = "hello world!";
    BYTE buf[32];
    memcpy(buf,hello,sizeof(hello));
    finish((i32ptr*)buf,32);
}

由于以太坊环境无法printf,这里只能通过finish返回给调用者,其中的ewasm.h文件是从https://github.com/poemm/C_ewasm_contracts里面复制出来的

iii. 编译

clang -cc1 -O3 -emit-llvm -triple=wasm32-unknown-unknown-wasm hello.c -o hello.ll
opt -O3 hello.ll -o hello.ll
llc -O3 -filetype=obj hello.ll -o hello.o
wasm-ld hello.o -o hello.wasm --no-entry -allow-undefined-file=ewasm.syms -export=main

这个时候获取的wasm不符合以太坊ewasm的两个规则,只能导入ethereum库,只能导出main和malloc两个函数,因此无法使用,我们需要手动修改一下

iv. 修改wasm

先转换wasm为wast,修改后,再改为wasm

wasm-dis hello.wasm -o hello.wast

打开文件hello.wast:
修改:

(import "env" "finish" (func $finish (param i32 i32)))

为:

(import " ethereum" "finish" (func $finish (param i32 i32)))

找到:

(export "__heap_base" (global $global$1))
(export "__data_end" (global $global$2))

删除这两行
然后把wasm转换为wast

wasm-as hello.wast -o hello.wasm

这个过程太麻烦,写个脚本test.sh搞定:

wasmfile=$1
filename=${wasmfile%.*}
wastfile=${filename}".wast"
wasm-dis $wasmfile -o $wastfile
# generate file.wat with Wabt's wasm2wat, then:
sed -i -e 's/"env"/"ethereum"/g' $wastfile
sed -i -e 's/"_main"/"main"/g' $wastfile
sed -i '/_heap_base/d' $wastfile
sed -i '/_data_end/d' $wastfile
wasm-as $wastfile -o $wasmfile

调用:

./test.sh hello.wasm

c) 合约后期处理

这个时候的wasm还是不能直接使用,需要通过哨兵合约的检测,就必须使用chisel,编写chisel.yml,内容如下:

ewasm:
        file: "hello.wasm"
        output: "hello_deployer.wasm"
        trimexports:
                preset: "ewasm"
        verifyimports:
                preset: "ewasm"
        verifyexports:
                preset: "ewasm"
        repack:
                preset: "ewasm"
        deployer:
                preset: "memory"

然后执行:
chisel run
获得文件hello_deployer.wasm,这个文件就是用来发布的合约

d) 合约转化为16进制数据

执行命令:

hexdump -v -e '"" 1/1 "%02x" ""' hello_deployer.wasm

就可以转换成功

复制内容,制作发布合约的rpc:

{
    "jsonrpc": "2.0",
    "id": 171,
    "method": "eth_sendTransaction",
    "params": [
        {
            "data": "0x0061736d0100000001090260027f7f0060000002130108657468657265756d0666696e697368000003030200010503010001071102046d61696e0002066d656d6f727902000a0e0202000b0900410041b10110000b0bb801010041000bb1010061736d0100000001090260027f7f0060000002130108657468657265756d0666696e697368000003030201010405017001010105030100020615037f01419088040b7f00419088040b7f00418d080b071102066d656d6f72790200046d61696e00020a36020300010b3001017f230041206b2200240020004100290085083700052000410029008008370300200041201000200041206a24000b0b1401004180080b0d68656c6c6f20776f726c642100",
            "from": "1AdrP7vxBYFVW27rrscPbwoziSr3WtPNin",
            "gas": "0x47b760"
        }
    ]
}

其中data数据就是hexdump得到的内容,注意前面多加了个0x

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352