Microsoft Enclave EVM (Ethereum
@(Blockchain)[Win10|Ethereum|SGX]
微软在Github发布了一个Ethereum和Intel SGX结合的项目Enclave EVM(eEVM)
本文记录了在Win10 环境下运行测试遇到的一些问题和解决方法。
如果不想了解过多错误纠正过程,可以直接看Step 5、6、8
。
Enclave EVM 介绍
Enclave EVM (eEVM) 是一个开源的、独立的、可嵌入的、c++实现的Ethereum虚拟机。它最初是构建在open enclave SDK之上的可信执行环境TEE
(i.e, SGX enclave)内运行的,以便与微软的Confidential Consortium Framework一起使用。
Enclave EVM (eEVM) is an open-source, standalone, embeddable, C++ implementation of the Ethereum Virtual Machine. It was originally built to run within a TEE (ie, SGX enclave) on top of the Open Enclave SDK, for use with Microsoft's Confidential Consortium Framework.
运行环境
-
系统:Windows 10 教育版 64位
-
IDE:Visual Studio 2017 Professional
SGX编译按官方说明要求是:Visual Studio 2015/2017
-
依赖项:CMake. Minimum version 3.10.
一般VS自带的就可以了, 必须x64编译
-
Solidity:https://github.com/ethereum/solidity/releases
之前学习以太坊的过程一般都是已经安装了solc编译器的
npm install -g solc
不过这种安装方法在本项目运行中会遇到问题,后面会具体说明
接下来就是整个项目的运行测试过程:
Step 1: 下载Enclave EVM(eEVM)项目
下载地址:https://github.com/microsoft/eEVM
直接下载压缩包,找个某个目录解压缩,我选择E:
,那么解压后目录为:E:\eEVM
Step 2:编译eEVM
根据eEVM项目说明:
打开Visual Studio 2017 developer command prompt (VS2017的开发人员命令提示符)。创建.sln和.vcxproj文件,并按如下方式构建静态库和测试。
- 进入eEVM目录,创建
build
文件夹。
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.17
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
D:\Program Files (x86)\Microsoft Visual Studio\2017\Professional>E:
E:\>cd eEVM
E:\eEVM>mkdir build
- 进入
build
文件夹,编译整个项目。
E:\eEVM>cd build
E:\eEVM\build>cmake ..
-- Building for: Visual Studio 15 2017
-- The C compiler identification is MSVC 19.16.27034.0
-- The CXX compiler identification is MSVC 19.16.27034.0
-- Check for working C compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe
-- Check for working C compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe
-- Check for working CXX compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: E:/eEVM/build
build
文件夹目录如下:
编译成功,从x86/cl.exe
可以看到VS是用32位编译的。
实际上,用32位编译会导致后续项目生成错误,如果不想了解错误原因可以直接跳到Step4:重新编译eEVM。
Step 3:生成eEVM项目
创建生成项目debug
。
E:\eEVM>msbuild ALL_BUILD.vcxproj
报错:
“E:\eEVM\build\ALL_BUILD.vcxproj”(默认目标) (1) ->
“E:\eEVM\build\disassembler.vcxproj”(默认目标) (3) ->
“E:\eEVM\build\eevm.vcxproj”(默认目标) (4) ->
(ClCompile 目标) ->
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
E:\eEVM\3rdparty\intx\include\intx/int128.hpp(298): error C3861: “_umul128”: 找不到标识符 [E:\eEVM\build\eevm.vcxproj]
19 个警告
6 个错误
查阅了很多资料是因为VS cmake默认使用x86 32位编译,这个错误必须使用x64 64位编译才可以。因此我们编译的时候需要指定x64编译。
Step 4:重新编译eEVM
首先删除build
目录下的所有文件,重新按照以下命令编译:
E:\eEVM>cd build
E:\eEVM\build>cmake -G "Visual Studio 15 Win64" ..
-- The C compiler identification is MSVC 19.16.27034.0
-- The CXX compiler identification is MSVC 19.16.27034.0
-- Check for working C compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe
-- Check for working C compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe
-- Check for working CXX compiler: D:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: E:/eEVM/build
编译成功,从x64/cl.exe
可以看到VS是用64位编译的。生成的build
目录相同。
Step 5:重新生成eEVM项目
用相同的命令:
E:\eEVM>msbuild ALL_BUILD.vcxproj
可能遇到的错误:
“E:\eEVM\build\ALL_BUILD.vcxproj”(默认目标) (1) ->
“E:\eEVM\build\eevm_tests.vcxproj”(默认目标) (5) ->
(ClCompile 目标) ->
E:\eEVM\tests\rlp.cpp(215): error C2398: 元素“4”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
E:\eEVM\tests\rlp.cpp(216): error C2398: 元素“5”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
E:\eEVM\tests\rlp.cpp(215): error C2398: 元素“4”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
E:\eEVM\tests\rlp.cpp(216): error C2398: 元素“5”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
53 个警告
4 个错误
这个看起来是一个类型转换的错误:
E:\eEVM\tests\rlp.cpp(216): error C2398: 元素“5”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
with
[
_Ty=uint8_t
]
E:\eEVM\tests\rlp.cpp(215): error C2398: 元素“4”: 从“int”转换到“_Ty”需要收缩转换 [E:\eEVM\build\eevm_tests.vcxproj]
with
[
_Ty=uint16_t
]
实际错误的位置是在TEST_CASE_TEMPLATE
中(205-216
行):
我自己是直接打开E:\eEVM\tests
中的rlp.cpp
文件,把类型修改直接扩大。
把uint8_6
和uint16_t
都改成uint64_t
。
保存修改结果。
Step 6:再次重新编译生成eEVM项目
以防万一,还是全部删除build
中的文件,重新编译,再重新生成。
E:\eEVM\build>cmake -G "Visual Studio 15 Win64" ..
E:\eEVM\build>msbuild ALL_BUILD.vcxproj
eEVM项目生成成功,警告可以忽略:
FinalizeBuildStatus:
正在删除文件“sum.dir\Debug\sum.tlog\unsuccessfulbuild”。
正在对“sum.dir\Debug\sum.tlog\sum.lastbuildstate”执行 Touch 任务。
已完成生成项目“E:\eEVM\build\sum.vcxproj”(默认目标)的操作。
PrepareForBuild:
正在创建目录“x64\Debug\ALL_BUILD\”。
正在创建目录“x64\Debug\ALL_BUILD\ALL_BUILD.tlog\”。
InitializeBuildStatus:
正在创建“x64\Debug\ALL_BUILD\ALL_BUILD.tlog\unsuccessfulbuild”,因为已指定“AlwaysCreate”。
CustomBuild:
Building Custom Rule E:/eEVM/CMakeLists.txt
FinalizeBuildStatus:
正在删除文件“x64\Debug\ALL_BUILD\ALL_BUILD.tlog\unsuccessfulbuild”。
正在对“x64\Debug\ALL_BUILD\ALL_BUILD.tlog\ALL_BUILD.lastbuildstate”执行 Touch 任务。
已完成生成项目“E:\eEVM\build\ALL_BUILD.vcxproj”(默认目标)的操作。
已成功生成。
...
56 个警告
0 个错误
整个项目生成成功后,build
文件夹目录下多出了一些文件:
Step 7:运行测试(可选)
在build
中使用命令:
ctest -C debug
报错:
E:\eEVM\build>ctest -C debug
Test project E:/eEVM/build
Start 1: eevm_tests
Process not started
E:/eEVM/tests/unit_test_wrapper.sh
[unknown error]
1/1 Test #1: eevm_tests .......................***Not Run 0.00 sec
0% tests passed, 1 tests failed out of 1
Total Test time (real) = 0.02 sec
The following tests FAILED:
1 - eevm_tests (BAD_COMMAND)
Errors while running CTest
应该是E:/eEVM/tests
目录下脚本文件unit_test_wrapper.sh
参数错误。我查询了一些资料,由于不是很了解,不过没有找出解决方法,有兴趣的可以尝试修改。因为不影响其他测试,我就没有管它了。
也就是Step 7可以忽略不管。
Step 8:3个实例运行测试(必选)
我们可以看到E:\eEVM\samples
下有几个例子,我选择hello_world
、sum
、erc20
三个例子分别说明。
它们都是在
Intel SGX
中运行的。
对于这三个例子,在项目生成成功后也分别生成了debug
文件。在E:\eEVM\build\Debug
中,我们可以看到hello_world.exe
、sum.exe
、erc20.exe
。
进入E:\eEVM\build\Debug
文件夹,打开cmd
:
1. hello_world测试(打印Hello world!)
输入命令:
hello_world.exe
运行成功,屏幕打印Hello world!
:
E:\eEVM\build\Debug>hello_world.exe
Hello world!
2. sum测试(两数求和)
输入命令:
sum.exe 2 3
运行成功,这里都是16进制:
E:\eEVM\build\Debug>sum.exe 2 3
0x2 + 0x3 = 0x5
E:\eEVM\build\Debug>sum 10 12
0xa + 0xc = 0x16
3. erc20测试(智能合约转账)
E:\eEVM\samples\erc20
文件夹下有三个文件:
- ERC20.sol:Solidity编写的智能合约源代码
-
ERC20_combined.json:Solidity编译(solc)
ERC20.sol
生成的json
文件 -
main.cpp:读取合约,在
SGX
中运行合约的main
文件
输入命令:
erc20 E:\eEVM\samples\erc20\ERC20_combined.json
运行成功:
E:\eEVM\build\Debug>erc20 E:\eEVM\samples\erc20\ERC20_combined.json
-- Initial state --
Total supply of tokens is: 0x3e8
User balances:
0x3e8 owned by 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b (original contract creator)
0x0 owned by 0xD8dEA72EA703C7647F4Eaf8CA342Ead51D1AD7EF
-------------------
Transferring 0x14d from 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b to 0xD8dEA72EA703C7647F4Eaf8CA342Ead51D1AD7EF
(succeeded)
Transferring 0x14e from 0xD8dEA72EA703C7647F4Eaf8CA342Ead51D1AD7EF to 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b
(failed)
-- After one transaction --
Total supply of tokens is: 0x3e8
User balances:
0x29b owned by 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b (original contract creator)
0x14d owned by 0xD8dEA72EA703C7647F4Eaf8CA342Ead51D1AD7EF
---------------------------
Transferring 0x9 from 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b to 0x5692079Fa1291630F173cA9C5494C9C2bd07AbA7
(succeeded)
...
Transferring 0x43 from 0xE3367872f7fd5E4Ff0A5eD4A412551B293D29D19 to 0x3Ae16AC485c4B0687D7516008B018c972460348D
(failed)
-- Final state --
Total supply of tokens is: 0x3e8
User balances:
0x2cd owned by 0xEcaED682C12Ab04F8D740Cce950B7C1A1C75837b (original contract creator)
0xb4 owned by 0xD8dEA72EA703C7647F4Eaf8CA342Ead51D1AD7EF
0x9 owned by 0x5692079Fa1291630F173cA9C5494C9C2bd07AbA7
0x5 owned by 0x3Ae16AC485c4B0687D7516008B018c972460348D
0x8 owned by 0x3116BE2D5765CA64e65c375E728d67CA7bC8F5A5
0x51 owned by 0x2AF018a4A69Cf4aEEeD5579e19A82B828B351c29
0x0 owned by 0x922674d873402Fc975F80e597FE657852d8d947C
0x0 owned by 0xE3367872f7fd5E4Ff0A5eD4A412551B293D29D19
-----------------
补充:如何编译自己的合约?
我们可以看到ERC20.sol
必须要有对应的ERC20_combined.json
,才能运行。但是.json
文件时如何得到的呢?
我们可以用Solidity自带的solc
命令编译.sol
文件生成对应的.json
文件。
(1)首先安装solc
。
因为之前有过以太坊的学习,其实都安装过了。命令如下:
npm install -g solc
(2)查看solc
是否安装成功。
$ solcjs --version
0.6.0+commit.26b70077.Emscripten.clang
Windows下solc --version
和solc --help
都会报错,自然所有solc
命令都会报错。原因看Solodity文档。
(3)安装Windows Solidity Release
版本的solc
。
可以自己选择对应版本,下载解压到某个选定的目录。
把所在目录如D:\Program Files (x86)\Solidity
加入环境变量。我把用户变量和系统变量的Path
中都加入了D:\Program Files (x86)\Solidity
。
具体方法:系统->高级系统设置->环境变量->(用户变量/系统变量)->Path->新建。
这时候使用solc
命令可以看到安装成功:
C:\Users\A>solc --version
solc, the solidity compiler commandline interface
Version: 0.6.0+commit.26b70077.Windows.msvc
注意:
其实我最开始这样安装完,solc
命令还是报错,不知道第二天为什么就好了。
如果还是无法使用solc
命令,可以把需要编译的.sol
文件放到刚刚安装solc
的目录下,也就是D:\Program Files (x86)\Solidity
中,在这个文件夹中,直接使用solc --version
和solc --help
是没有问题的,其他的solc
命令也同样可以使用。
(4)编译.sol
文件。
随意选择某个位置,创建一个新文件夹,将ERC20.sol
复制进去。在该文件夹中,打开cmd
使用如下命令:
solc --evm-version homestead --combined-json bin,hashes --pretty-json --optimize ERC20.sol > ERC20_combined.json
可以看到生成了ERC20_combined.json
。
为了对比编译结果,我实际上安装了
solc 0.6.0
和solc 0.4.24
两个版本。不过系统变量添加的是solc 0.6.0
。
因为Solidity更新较快,不同版本编译器的语法要求变化也较大,很多低版本的语法在高版本已无法编译通过。eEVM使用的是solc 0.4.24
。.sol
合约中其实也会指明编译器的版本,必须要与使用的编译器版本匹配才不会报错,不然就会出现错误:
F:\compile_test>solc --evm-version homestead --combined-json bin,hashes --pretty-json --optimize ERC20.sol > ERC20_combined.json
Error: Source file requires different compiler version (current compiler is 0.6.0+commit.26b70077.Windows.msvc - note that nightly builds are considered to be strictly less than the released version
--> ERC20.sol:1:1:
|
1 | pragma solidity ^0.4.0;
| ^^^^
根据报错修改ERC20.sol
文件,有些语法也需要修改。例如:
-
constant
关键字已被删除,需要使用view/pure
。
重新编译即可:
6 高版本json.PNG
对比原始项目中的ERC20_combined.json
文件:
如果你想用solc 0.4.24
编译,就把文件放到solc 0.4.24
目录下,且不需要修改语法,在该目录下打开cmd
编译:
D:\Program Files\Solidity>solc --evm-version homestead --combined-json bin,hashes --pretty-json --optimize ERC20.sol > ERC20_combined.json
D:\Program Files\Solidity>solc --version
solc, the solidity compiler commandline interface
Version: 0.4.24+commit.6ae8fb59.Windows.msvc
得到的json
文件对比,和项目中的原始文件一模一样。
我也用solc 0.4.24
编译了之前以太坊公开拍卖智能合约(truffle + ganache-cli)文章中学习的SimpleAuction.sol
。编译成功:
不过我暂时还没有为SimpleAuction.sol
合约写它的main.cpp
运行测试文件,所以没有放在整个项目中测试。
自定义合约的测试在后续学习中会进行。
本文作者:Joyce
文章来源:https://www.jianshu.com/p/d5ba22d7d655
版权声明:转载请注明出处!