以前咱们说过NEO智能合约的调试问题,过去了一段时间,有不少东西都发生了比较大的变化。让咱们从新再来探讨一下这个话题。 git
先说日期,2018年4月27日,立刻迎来劳动节。 github
之后可能还会再次谈论这个话题。 json
而后明确几个问题,把一些常常纠结的地方先说清楚 c#
一次编码,按下f5,一切正常,挥一挥衣袖就潇洒的离开,那是传说。 app
当代码执行不符合预期时,咱们须要深刻分析问题,须要更精细的观测手段。 工具
而NEO官方并无提供这样的工具,因而咱们开发了一揽子工具用于解决调试问题 测试
他们是: ui
为了3的正常运行,1 2 都是必须的,若是你想知道为何,源码能够告诉你答案 编码
https://github.com/NewEconoLab/neondebug spa
https://github.com/NewEconoLab/neo-gui-nel
你可曾听过NeoVM,AVM文件,就是智能合约编译生成的那东西,就是NeoVM的字节码,叫AVM是由于之前叫小蚁,ant的A,这个扩展名没一块儿改。
为了方便不那么了解虚拟机的开发者理解,我和C#的类库机制作一个对比。
这个AVM至关因而DLL,要调试一个c# DLL,你须要DLL PDB cs源码三部份内容。DLL存储字节码,PDB存储字节码地址和源码位置的映射,这样才能在断点时根据字节码执行位置定位到源码位置,而cs源码,就是为了让你调试时对照到代码
那么:
DLL-》AVM
PDB-》?
cs-》cs
标准的c#编译器neon.exe(若是不知道neon.exe,再好好补一下C#智能合约编译的相关资料),只生成了一个AVM和一个ABI文件,这个ABI是接口说明。
PDB对应的角色是空缺的
因此你须要 NEL 的 Neon.exe ,编译neondebug仓库的neondebug项目能够获得这个替换的neon.exe
设置环境变量,保证在任何路径能够执行neon
注意红框部分,有Debug字样
这个替换的编译器,就专门解决那个缺失的PDB问题,这个编译器和官方编译器代码随时同步更新,你直接使用这个替换的编译器就行,任何更新都会同步,不须要切换回官方编译器。
重启VS2017以后,来编译一个智能合约试试
注意红框部分,已经使用了咱们的替换版本编译 有(debug)字样
下一行告诉你,在c:\neo\smartcontracts输出了些什么,让咱们来看看。
首先原来的avm照样输出,这些是另外多输出的
文件名所有替换为了合约hash,avm仍是那个avm
Abi.json仍是那个abi
Cs是把智能合约源码copy 过来的,只支持一个智能合约项目有一个代码文件,因此不要分文件。
Map就是替代PDB的那个了,他记录字节码地址和源代码地址的映射关系
生成在这个路径也是有意义的,调试查看工具会直接来这个路径找合约,之前须要用调试查看工具再打开一次合约,如今不用了,直接用同一个路径。
用neogui-nel,测试执行一个合约,只有nel定制版支持。
试运行固定产生一个0x00 的log文件,看这个log就能够调试了,这个下一节再说,咱们这里之说产生log文件的办法。
产生这个log是调试的惟一办法。
调用NEOCLI -NEL的 rpc invokescript 接口,会在返回值多返回一个fulllog字段,将其保存为文件,就是这个llvmhex文件,能够用来调试。
只有nel定制版支持
用NEL定制版NEOGUI发起交易,只有nel定制版支持
发起交易,
会获得交易id同名的llvm文件
Id[0]
Id[1]
这种为鉴权合约的log
只有经过neogui nel定制版发起交易 或者 neocli nel定制版的 rpc接口 sendraw发起交易
才会产生鉴权合约的log,才能够调试鉴权合约,其余只调试应用合约
只有nel定制版支持
会获得交易id同名的llvm文件
Id[0]
Id[1]
这种为鉴权合约的log
因为交易会同步给每个节点,定制的neo-gui-nel,和neo-gui-cli
能够获得全部的交易,不管是谁产生的。
可是作智能合约的调试的LOG是很耗时的,因此他并不老是打开的,有一个开关去控制他
这个开关在config.json里面
NEOGUI-nel的设置为true,表示只生成这个GUI本身发起的交易的LOG
打开这个同步就会变得很是慢,调试的时候再用。
NEOGUI-nel不修改这个config 也能够打开生成任何人发起的交易的开关
这里按一下让他显示为=false,而后以后同步的每一笔交易都会生成调试LOG了
这个只在内存修改,每次打开neo-gui都要看一眼。
编译,启动NeonDebugGUI
略,他也在NeonDebug仓库中
使用Load 打开对应的llvmhex.txt文件便可调试
这两个load,一个是打开一个对话框,一个是输入txid本身去找,结果都同样。
打开调试LOG之后
图中红黄蓝部分先注意一下
红色部分最重要,首先观察合约执行状态 halt break 为vm正常停机,程序正常走到结束。
Fault break为vm异常停机,你能够直接反着从最下边看看到底怎么了。
红色部分为整个VM内Dump下来的执行流程,也就是整个智能合约的过程到底干了什么,从红色部分选择最上面一项,而后用键盘的方向键下,往下挪,先完整的看几个合约,能够创建一些基本的感受。
黄色部分为智能合约源码,当红色部分选中条目变化时,若是能找到对应的源码,黄色部分就会跳转高亮。
一般最主要的调试观测方法就是选红色、看黄色。
而后蓝色部分收集了全部syscall,由于neoVM的虚拟机自身是纯计算,全部对链产生影响或者和链互访的功能都是经过syscall进行的,看一个合约有哪些syscall就能快速了解这个合约的行为,固然这须要创建在熟悉的基础上,只要多看,就能熟悉。
好比
Equal指令是==表达式,他显示的false只能告诉你是不想等,要看是谁和谁比较,往前倒退一条指令
倒退后观测计算栈,valuetool 会帮助你显示这个数据多是什么
记住这一点,而不能只盯着源码,左边最重要,左边要选到关键的代码。
你要搞清楚那些最关键的指令,好比syscall appcall equal
这并不会有多复杂,知道找关键指令就会快不少。
最重要的storage.put 就是一个syscall