通过RPC执行智能合约查询返回0x问题总结

最近遇到一个问题,在区块链上执行智能合约的查询操作,返回结果为0x。
问题环境:
HPB区块链同步节点

这里记录一下排查过程:
1、复现。快速同步节点(无法复现)------>全同步节点(可以复现)
最开始在快速同步节点上查询合约并没有出现问题,后来转到全同步节点上就会出现返回0x的情况。
2、日志。打印合约执行日志。发现合约没有正常终止,而是中断。
第一反应是合约执行出错导致的,因此在合约执行的run函数中加了日志查看是哪里出错了错误。日志显示,合约执行并没有正常终止,而是通过evm.abort中断了。
3、查代码。
从RPC入口排查,并根据合约执行的中断标识evm.abort查代码。在初始化虚拟机的代码附近,发现虚拟机设置了5s超时。
4、修改代码。
调整合约执行时间为20s。发现合约执行仍然超时。猜测应该是有部分合约指令执行太慢导致。
5、日志。
确定合约执行的具体情况(合约执行的指令数,发费较长时间的执行),发现SLOAD指令占用的平均时间最长,该指令对应的数据库的Get操作。

6、查数据库代码。
查看数据库Get操作的相关代码。发现第一次查询数据需要到磁盘数据库文件中排查,之后使用缓存。按照该逻辑,指令的执行第一次慢是因为需要有磁盘IO,那之后应该就快了。多执行几次合约,发现能够返回正确结果了。

7、持续测试。
多执行几次后,合约执行返回结果正确。 持续测试,发现了2个新的问题。

2个新问题:
a、命令卡住。运行合约执行命令后,命令界面卡住了,等待6分钟之后,命令继续执行。
经查,是由于查询区块信息的时候的锁与同步区块写入数据库时候锁是同一个,命令卡住的时候,从日志看,节点正在进行数据库写入操作。但写入时长花费6分钟,是不可理解的。
b、持续测试一段时间后,发现再次出现了返回0x的问题
缓存失效导致。

以上两个问题经过排查,都是由于数据库leveldb进行compaction导致。compaction执行完成前,区块同步进行的数据库写入操作进入阻塞状态,而compaction的时间也较长导致阻塞时间长。同时compaction完成后会删除部分表并清除这部分表的缓存。这就是导致以上两个新问题的原因。

关于compaction的相关情况在下一篇中介绍。

猜你喜欢

转载自blog.csdn.net/adwen2009/article/details/86236065