如果Fabric的智能合约函数陷入死循环会怎么样
大家好,我是powervip!今天和大家一起探讨一下:如果Fabric的智能合约函数陷入死循环会怎么样
func (t *SimpleChaincode) Test(stub shim.ChaincodeStubInterface, args []string) pb.Response {
// 选择商品价格在1元到100元之间的商品名称和数量
s := "{\"fields\": [\"GoodsName\", \"GoodsCount\"], \"selector\":{ \"$and\": [{\"GoodPrice\":{\"$gte\": 1}}, {\"GoodPrice\":{\"$lte\": 100}}] }}"
resultsIterator, err := stub.GetQueryResult(q)
defer resultsIterator.Close()
if err != nil {
return shim.Error(err.Error())
}
var count uint64
for resultsIterator.HasNext() {
count++
// resultsIterator.Next() // 注释掉该语句,函数将陷入死循环
fmt.Println("count=", count)
}
msg := fmt.Sprintf("count: %d", count)
return shim.Success([]byte(msg))
}
上面的代码由于把 resultsIterator.Next() 这行代码注释掉,返回的数据集如果包含有1条记录或以上,游标就会一直停留在第一条数据记录上,导致 resultsIterator.HasNext() 永远为true,从而陷入死循环。
合约函数陷入死循环后,由于Fabric一般默认的智能合约函数调用时长最长为30秒,超过30秒后,Fabric会返回类似于下面的超时提示:
Error: endorsement failure during invoke. response: status:500 message:"failed to execute transaction 81f3c7715ae5f6678c711238571bb1c778c274bc505287da3f857465835832d6: error sending: timeout expired while executing transaction"
你以为合约函数调用就这样结束了?No!如果你attach上peer节点(具体命令是:docker attach c5841e55155a,c5841e55155a为该节点的CONTAINER ID),你会发现,peer节点的log会不断地打印出类似下面的信息:
count= 10000 count= 10001 count= 10002 count= 10003 count= 10004 count= 10005 count= 10006 count= 10007 count= 10008 count= 10009 ...
表明合约函数还在不断地执行死循环代码。
如果这时候,你想在客户端执行其它的合约函数,得到的结果都是超时,因为智能合约在上次调用中陷入死循环后,没办法执行新的函数调用了。后果真的很严重,需要认真注意合约函数会引起死循环的代码!
要如何结束死循环,目前来看只有重启peer节点了。如果你有更好的方法,欢迎提出来讨论。
我是powervip 我的公众号:区块链战斗机 我的知乎:https://www.zhihu.com/people/powervip 我的学习笔记:www.study.win
原创作品,版权所有,侵权必究!商业转载请联系作者获得授权;非商业转载需保留作者署名信息,注明出处并保留原文链接。
如果你觉得这篇文章写得还可以,请帮忙点个赞,谢谢! 你的鼓励,我的动力!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!