之前我们说过NEO智能合约的调试问题,过去了一段时间,有很多东西都发生了比较大的变化。让我们重新再来探讨一下这个话题。

先说日期,2018年4月27日,马上迎来劳动节。

 

以后可能还会再次谈论这个话题。

 

然后明确几个问题,把一些经常纠结的地方先说清楚

  1. 如果你连neo同步区块还没搞明白,先不要凑智能合约开发这个热闹。
  2. 我们只讨论C#开发智能合约的调试问题,其它的暂无工具开发计划。
  3. NEO官方没有智能合约调试工具,所以我们的工具是有很多定制的成分。
    1. 为什么要调试

一次编码,按下f5,一切正常,挥一挥衣袖就潇洒的离开,那是传说。

当代码执行不符合预期时,我们需要深入分析问题,需要更精细的观测手段。

 

而NEO官方并没有提供这样的工具,于是我们开发了一揽子工具用于解决调试问题

他们是:

  1. NeonDebug 替换的c#智能合约编译器
  2. NeoGUI-NEL 定制版NeoGUI 或者 NeoCli-NEl 定制版的NeoCli
  3. NeonDebugGUI,智能合约执行情况观测工具

 

为了3的正常运行,1 2 都是必须的,如果你想知道为什么,源码可以告诉你答案

 

https://github.com/NewEconoLab/neondebug

https://github.com/NewEconoLab/neo-gui-nel

 

  1. 合约的编译

你可曾听过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的那个了,他记录字节码地址和源代码地址的映射关系

 

生成在这个路径也是有意义的,调试查看工具会直接来这个路径找合约,以前需要用调试查看工具再打开一次合约,现在不用了,直接用同一个路径。

 

  1. 合约的调用

A,用neogui 测试执行合约

    用neogui-nel,测试执行一个合约,只有nel定制版支持。

    

试运行固定产生一个0x00 的log文件,看这个log就可以调试了,这个下一节再说,我们这里之说产生log文件的办法。

 

产生这个log是调试的唯一办法。

 

B 、用NEOCLI 测试执行合约

调用NEOCLI -NEL的 rpc invokescript 接口,会在返回值多返回一个fulllog字段,将其保存为文件,就是这个llvmhex文件,可以用来调试。

只有nel定制版支持

C、用NEOGUI发交易

用NEL定制版NEOGUI发起交易,只有nel定制版支持

 

 

发起交易,

会得到交易id同名的llvm文件

Id[0]

Id[1]

这种为鉴权合约的log

只有通过neogui nel定制版发起交易 或者 neocli nel定制版的 rpc接口 sendraw发起交易

才会产生鉴权合约的log,才可以调试鉴权合约,其他只调试应用合约

D、通过NEOCLI的sendraw RPC 发起交易

只有nel定制版支持

会得到交易id同名的llvm文件

Id[0]

Id[1]

这种为鉴权合约的log

E、通过其他方式产生的交易

由于交易会同步给每一个节点,定制的neo-gui-nel,和neo-gui-cli

可以得到所有的交易,无论是谁产生的。

但是做智能合约的调试的LOG是很耗时的,所以他并不总是打开的,有一个开关去控制他

这个开关在config.json里面

NEOGUI-nel的设置为true,表示只生成这个GUI自己发起的交易的LOG

打开这个同步就会变得非常慢,调试的时候再用。

 

NEOGUI-nel不修改这个config 也可以打开生成任何人发起的交易的开关

这里按一下让他显示为=false,然后之后同步的每一笔交易都会生成调试LOG了

这个只在内存修改,每次打开neo-gui都要看一眼。

 

  1. 合约的调试

编译,启动NeonDebugGUI

略,他也在NeonDebug仓库中

 

使用Load 打开对应的llvmhex.txt文件即可调试

这两个load,一个是打开一个对话框,一个是输入txid自己去找,结果都一样。

 

功能介绍

打开调试LOG以后

图中红黄蓝部分先注意一下

红色部分最重要,首先观察合约执行状态 halt break 为vm正常停机,程序正常走到结束。

Fault break为vm异常停机,你可以直接反着从最下边看看到底怎么了。

 

红色部分为整个VM内Dump下来的执行流程,也就是整个智能合约的过程到底干了什么,从红色部分选择最上面一项,然后用键盘的方向键下,往下挪,先完整的看几个合约,可以建立一些基本的感觉。

 

黄色部分为智能合约源码,当红色部分选中条目变化时,如果能找到对应的源码,黄色部分就会跳转高亮。

 

通常最主要的调试观测方法就是选红色、看黄色。

 

然后蓝色部分收集了所有syscall,因为neoVM的虚拟机自身是纯计算,所有对链产生影响或者和链互访的功能都是通过syscall进行的,看一个合约有哪些syscall就能快速了解这个合约的行为,当然这需要建立在熟悉的基础上,只要多看,就能熟悉。

调试小提示

  1. 红色部分最重要
  2. 选中条目时,执行栈显示的这条指令执行之后的状态。

比如

Equal指令是==表达式,他显示的false只能告诉你是不想等,要看是谁和谁比较,往前倒退一条指令

倒退后观测计算栈,valuetool 会帮助你显示这个数据可能是什么

  1. 是多条虚拟机指令对应一条cs源码,并且有些是对应不到的。

记住这一点,而不能只盯着源码,左边最重要,左边要选到关键的代码。

你要搞清楚那些最关键的指令,比如syscall appcall equal

这并不会有多复杂,知道找关键指令就会快很多。

  1. 一定要熟悉syscall

最重要的storage.put 就是一个syscall

五一劳动节,讲讲NEO智能合约的调试的更多相关文章

  1. NEO智能合约开发(二)再续不可能的任务

      NEO智能合约开发中,应用合约比较简单,是的你没看错,应用合约比较简单. 应用合约三部曲,发布.调用.看结果.除了看结果工具比较缺乏,发布调用neogui最起码可以支撑你测试.   鉴权合约比较麻 ...

  2. NEO智能合约开发(一)不可能完成的任务

    悬赏任务 兹有如下合约 public static object Main(string method, object[] args) { if (Runtime.Trigger == Trigger ...

  3. 用 C# 编写 NEO 智能合约

    工具 -> 扩展和更新安装 NeoContractPlugin 插件 打开 Visual Studio 2017,打开 工具, 扩展和更新 ,在左侧点击 联机 ,搜索 Neo,安装 NeoCon ...

  4. neo智能合约的生命周期

  5. 通过METAMASK调试和发布智能合约指南(转载)

    2017-12-07 芯链团队 小明微思考 原文地址:https://mp.weixin.qq.com/s?__biz=MzA4Mzk2MzUzNg==&mid=2651223347& ...

  6. NEO从入门到开窗(2) - 智能合约的面相

    一.啰嗦两句 昨天讲了智能合约的一生,那丫长啥样啊?今儿我就跟各位唠叨唠叨. 二.一个简单的智能合约 下面这段就是NEO实例源码里的一个,干撒用的?聪明的你一眼儿就看出来了吧,就是一个所谓域名合约的增 ...

  7. NEO从入门到开窗(1) - 一个智能合约的诞生

    一.啰嗦两句 最近一直都在研究区块链,BitCoin,Etherenum, Hyper Ledger Fabric还有今天的主角小蚂蚁,当然出名以后改了一个艺名叫NEO.区块链大部分都是用Golang ...

  8. EOS智能合约开发(四):智能合约部署及调试(附编程示例)

    EOS智能合约开发(一):EOS环境搭建和创建节点 EOS智能合约开发(二):EOS创建和管理钱包 EOS智能合约开发(三):EOS创建和管理账号 部署智能合约的示例代码如下: $ cleos set ...

  9. 【精解】EOS智能合约演练

    EOS,智能合约,abi,wasm,cleos,eosiocpp,开发调试,钱包,账户,签名权限 热身 本文旨在针对EOS智能合约进行一个完整的实操演练,过程中深入熟悉掌握整个EOS智能合约的流程,过 ...

随机推荐

  1. Docker容器进入的4种方式

    Docker容器进入的4种方式 $ sudo docker ps $ sudo docker exec -it 775c7c9ee1e1 /bin/bash 在使用Docker创建了容器之后,大家比较 ...

  2. log4j 初体验

    1.Log4j简介      在应用程序中添加日志记录目的基于三个: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作 跟踪代码运行时轨迹,作为日后审计的依据 担当集成开发环境 ...

  3. (二叉树 DFS 递归) leetcode 112. Path Sum

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  4. function Language

    什么是函数式语言: 函数式语言(functional language)一类程序设计语言.是一种非冯·诺伊曼式的程序设计语言.函数式语言主要成分是原始函数.定义函数和函数型.这种语言具有较强的组织数据 ...

  5. 金融量化分析【day112】:股票数据分析Tushare2

    目录 1.使用tushare包获取某股票的历史行情数据 2.使用pandas包计算该股票历史数据的5日局限和60日均线 3.matplotlib包可视化历史数据的收盘价和历史均线 4.分析输出所有金叉 ...

  6. ACM-ICPC 2018 徐州赛区网络预赛 G Trace(思维+set)

    https://nanti.jisuanke.com/t/31459 题意 n个矩阵,不存在包含,矩阵左下角都在(0,0),给右上角坐标,后来的矩阵会覆盖前面的矩阵,求矩阵周长. 分析 set按照x或 ...

  7. Javaweb学习笔记——(二十四)——————图书商城项目

    图书商城          环境搭建         1.导入原型             *用户模块             *分类模块             *图书模块              ...

  8. Git——如何将本地项目提交至远程仓库(第一次)

    1.(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库. git init 2.把文件添加到版本库中,使用命令 git add .添加到暂存区里面去,不要忘记后面的小数 ...

  9. 【*和&】复习-杂七杂八代码收集

      int main() { ;//整数k,地址为x00CFFCA4 int &c = k;//引用参数c,c及&c的值与k及&k相同 int *w = &k;//指针 ...

  10. Linux-Centos 虚拟机安装

    Centos安装方法 第一步:一般只有第一项和第三项有用 其余的没啥卵用 第二步:提示检查镜像完整性,这里我们不要检查  选 skip 继续(之前尝试选择OK,最后安装失败了,也不想找原因了) 第三步 ...