摘要
1、用solc 将solidity 代码编译成evm 字节码
2、用evm2wasm 将evm 转化成wasm和wast 格式
准备开发环境
1、安装solidity
mac 上通过brew 安装
$ brew install solidity
或者参照安装教程
https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source
然后命令行输入
$ solc --version
如果安装成功会打印出来solc版本号
note:如果实在不愿意用命令行工具,也可以考虑使用在线编辑器https://remix.ethereum.org/
2、安装evm2wasm
首先确保已经安装nodejs,然后下载源码 https://github.com/ewasm/evm2wasm
clone下来后,先修改根目录下的package.json 文件
"wabt": "^1.0.0"
改为
"wabt": "1.0.0"
然后,在根目录输入
$ npm install
下载依赖库可能会比较慢,可执行js文件是 bin/evm2wasm.js
正式开工
1、solc 编译solidity 智能合约
创建一个solidity智能合约hello.sol,文件内容如下
pragma solidity ^0.5.4;
contract HelloWorld {
function helloWorld() external pure returns (string memory) {
return "Hello, World!";
}
}
在hello.sol 所在目录输入编译命令
$ solc --bin hello.sol -o hello
输出文件HelloWorld.bin 位于hello 目录下,将它重命名,以方便后续操作。可以看到输出文件内容是hex 格式的evm字节码。
$ mv hello/HelloWorld.bin hello.evm
$ cat hello.evm
608060405234801561001057600080fd5b50610139806100206000396000f3fe6080604052348
01561001057600080fd5b5060043610610048576000357c01000000000000000000000000000
0000000000000000000000000000090048063c605f76c1461004d575b600080fd5b6100556100
d0565b604051808060200182810382528381815181526020019150805190602001908083836
0005b8381101561009557808201518184015260208101905061007a565b5050505090509081
0190601f1680156100c25780820380516001836020036101000a031916815260200191505b50
9250505060405180910390f35b60606040805190810160405280600d81526020017f48656c6c6
f2c20576f726c64210000000000000000000000000000000000000081525090509056fea16562
7a7a72305820fd3ae219ac96e3ff3152d3d6afc304cec55cc9685c2ecfa46f05e9dc69bafd6e0029
solc 这个工具功能很强大,忍不住想尝试一下获取智能合约abi 的功能,虽然在下文中并没有卵用。
$ solc --abi hello.sol
======= hello.sol:HelloWorld =======
Contract JSON ABI
[{"constant":true,"inputs":[],"name":"helloWorld","outputs":
[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"}]
2、evm2wasm 转换成wasm
由于 bin/evm2wasm.js 这个工具只支持二进制格式的evm字节码,所以需要对它进行一点儿改造,使之可以接受hex 格式的输入。
bytecode = Buffer.from(bytecode, 'hex')
只需要把上述代码下边添加一行代码即可。
bytecode = Buffer.from(bytecode, 'hex')
bytecode = Buffer.from(bytecode.toString(), 'hex')
接下来执行命令把wast 格式转换成wasm 格式,前面的绝对路径请自行修改!!!
/Users/ff/dev/install/evm2wasm-master/bin/evm2wasm.js -e hello.evm -o hello.wasm
用十六进制编辑器打开生成的wasm 文件。
0061736D 01000000 01080260 017E0060 00000213 01086574 68657265 756D0675
73654761 73000003 02010105 040100F4 03062106 7F014100 0B7F0141 600B7F01
41000B7F 0041A888 020B7E01 42000B7E 0142000B 07110206 6D656D6F 72790200
046D6169 6E00010A 37013501 027F417F 21000240 03400240 23024504 40410124
020C0105 23004100 46044000 05230021 01410024 0020010E 00020B0B 0B0B0B0B
3、evm2wasm 转换成wast
命令与转换成wasm 类似,前面的绝对路径请自行修改!!!
/Users/ff/dev/install/evm2wasm-master/bin/evm2wasm.js -e hello.evm -o hello.wast --wast
这是生成的wast 文件。
$ cat hello.wast
(module
(import "ethereum" "useGas" (func $useGas (param i64)))
(global $cb_dest (mut i32) (i32.const 0))
(global $sp (mut i32) (i32.const -32))
(global $init (mut i32) (i32.const 0))
;; memory related global
(global $memstart i32 (i32.const 33832))
;; the number of 256 words stored in memory
(global $wordCount (mut i64) (i64.const 0))
;; what was charged for the last memory allocation
(global $prevMemCost (mut i64) (i64.const 0))
;; TODO: memory should only be 1, but can't resize right now
(memory 500)
(export "memory" (memory 0))
(func $main
(export "main")
(local $jump_dest i32) (local $jump_map_switch i32)
(set_local $jump_dest (i32.const -1))
(block $done
(loop $loop
(block $0
(if
(i32.eqz (get_global $init))
(then
(set_global $init (i32.const 1))
(br $0))
(else
;; the callback dest can never be in the first block
(if (i32.eq (get_global $cb_dest) (i32.const 0))
(then
(unreachable)
)
(else
;; return callback destination and zero out $cb_dest
(set_local $jump_map_switch (get_global $cb_dest))
(set_global $cb_dest (i32.const 0))
(br_table $0 (get_local $jump_map_switch))
))))))))