通过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的相关情况在下一篇中介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,但是PHP并不是用来编写智能合约的语言。智能合约通常使用Solidity语言编写,然后在以太坊平台上部署和执行。如果你想了解如何使用PHP与智能合约进行交互,我可以为你提供一些相关信息。 在与智能合约进行交互时,你可以使用以太坊的Web3.js库。Web3.js是一个JavaScript库,它允许你与以太坊网络进行交互,并与智能合约进行通信。 以下是一个使用PHP与Web3.js库进行智能合约交互的示例: ```php <?php require_once 'vendor/autoload.php'; use Web3\Web3; use Web3\Contract; use Web3\Utils; $web3 = new Web3('http://localhost:8545'); // 这里的URL是你以太坊节点的RPC地址 $contractAddress = '0x1234567890abcdef'; // 智能合约地址 $contractABI = '[{"constant":true,"inputs":[],"name":"getCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"setCount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]'; // 智能合约ABI $contract = new Contract($web3->provider, $contractABI); $contract->at($contractAddress); // 调用智能合约的方法 $result = $contract->call('getCount'); $count = Utils::toDec($result); echo "当前计数:$count"; // 发送交易调用智能合约的方法 $account = '0xabcdef1234567890'; // 发送交易的账户地址 $privateKey = '0xabcdef1234567890'; // 发送交易的账户私钥 $web3->personal->unlockAccount($account, 'password', 60); // 解锁账户 $transaction = $contract->send('setCount', [42], $account, [ 'gas' => 300000, 'gasPrice' => 20e9, 'nonce' => $web3->eth->getTransactionCount($account), 'from' => $account, 'value' => 0, 'chainId' => 1, 'privateKey' => $privateKey, ]); echo "交易哈希:{$transaction->hash}"; ?> ``` 请注意,上述示例中的代码是使用PHP的Web3.php库与智能合约进行交互的基本示例。你需要根据你的具体情况进行适当的修改和配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值