以太坊EVM实用程序
Evmlab的Python项目详细描述
EVM实验室实用程序
此软件包包含与以太坊虚拟机交互的各种工具。
项目结构
Folder | Description |
---|---|
docs | Project documentation |
evmlab | The evmlab package |
utilities | Example utilities and proof-of-concepts |
files | Sample trace files and trace logs |
output | output directory for artefacts |
templates | Web application templates (currently used with reproducer) |
containers | Docker container files |
安装
来源:
考虑创建一个virtualenv。
#> virtualenv -p python3 .env3
#> . .env3/bin/activate
#> python3 -m pip install -r requirements.txt
#> python3 setup.py install
#> python3 -m evmlab # verify installation
来自PIP:
托多:发布到pip!
#> python3 -m pip install evmlab
#> python3 -m evmlab[consolegui,abidecoder,docker] # verify installation
evmlab附带一个命令行实用程序,可以通过调用python3 -m evmlab <subcommand> <args>
编译器
“编译器”是一个构建evm二进制文件的工具,它使用pythonic方法使用汇编来构造程序。
下面是一个测试ecdsaRecover
:
p=compiler.Program()p.mstore(0,0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e)v=0x000000000000000000000000000000000000000000000000000000000000001bp.mstore(32,v)p.mstore(64,0x723841761d213b60ac1cbf063207cbeba6c2725bcaf7c189e63f13d93fc1dc07)p.mstore(96,0x789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02)p.call(0xfff,1,0,0,0x80,0x80,0x20)p.rreturn(140,20)code=p.bytecode()
下面是将JUMPDEST
填充到程序中的示例:
p=compiler.Program()p.jump(0x3)p.jumpdest()p.rreturn()foriinrange(0,20000):p.op(JUMPDEST)returnp.bytecode()
vm
vm模块包含运行任意虚拟机的一些抽象,主要是gethevm
和奇偶校验的parity-evm
。
醚链
etherchain
包包含用于与etherchain api交互的api。
再现
一个示例应用程序是reproduce.py
,它可以将链上事务作为一个完全本地事件重新生成,并在evm
中运行它。
应用程序需要一个txhash
,并且
- 从api获取事务数据。
- 将(源、目标)标记为需要提取
- 在源代码处获取余额和nonce,添加到
genesis
- 在
evm
上执行事务
- 如果事务有任何外部到达ops(balance、extcodecopy、call等),
- 根据需要添加这些帐户以获取
- 返回到3,直到执行不会导致获取更多帐户。
- 保存事务跟踪和起源
Opviewer
“opviewer.py”是一个类似于跟踪查看器的简单调试器。它可以用于evm
跟踪,并以比原始json更友好的方式导航数据。
通过例如python opviewer.py -f example2.json
运行它
最简单的方法是使用Docker图像。
docker build . -t evmlab && docker run -it evmlab
Docker图像也可以在hub.docker.com上自动生成:
docker pull holiman/evmlab && docker run -it holiman/evmlab
EVM
EVM格式
如果你想在evmlab中添加一个evm
,下面是要考虑的问题。
输入
evm
应该接受以下输入:
--code <code>
-要执行的代码。--codeFile <file>
-包含要执行的代码的文件。有时真正大的输入块不能通过bash传递。--gas <int>
--price <int>
--sender <address>
-地址ORIGIN
--receiver <address
-地址ADDRESS
--input <code>
:CALLDATA
--value <int>
--json
-布尔标志,是否为每个操作码输出json输出(基准测试时禁用json很有用)--nomemory
-禁用显示每个操作的完整内存输出--create
-如果指定,它将作为initcode执行--prestate
-链式规范,与客户机通常使用的规范相同。
基本上,evm
应该能够非常简单地运行一些事情,比如:
$evm --code 6040 --json run {"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"}{"pc":2,"op":0,"gas":"0x2540be3fd","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0x40"],"depth":1,"error":null,"opName":"STOP"}{"output":"","gasUsed":"0x3","time":141485}
但它也应该能够重构实际的链上事务,使用复杂的选项包括prestate,其中不传递code
,因为它已经显示在prestate
:
$evm --prestate /home/martin/workspace/evmlab/output//0xd6d519-genesis-geth_wq38zsy5.json --gas 150000 --sender 0x69ea6b31ef305d6b99bb2d4c9d99456fa108b02a --receiver 0xb97048628db6b661d4c2aa833e95dbe1a905b280 --input a9059cbb0000000000000000000000008eef795fd9150f118bddeca556a5a2a2438ab865000000000000000000000000000000000000000000000081ebd8ffd6b2a58000 --json run
输出
evm
应该为每个操作输出一个json
对象。示例:
{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"}
必需:pc
,op
,gas
,stack
,depth
可选:opName
,gasCost
,error
stack
、memory
和memSize
是操作执行之前的值。
在执行结束时,一些摘要信息是好的,例如
{"output":"","gasUsed":"0x3","time":141485}
当错误发生时,geth和parity以不同的方式处理它们。
对工作方式的细微改变是可以的,我们可以处理格式上的差异和细微的怪癖。