总结超级账本合约开发过程中遇到的坑

1. 不要尝试获取节点本地的时间作为key或value的值

即使每个节点的本地的时间系统是经过校对一致的,但同一个交易在每个节点上执行的时间点不一定是相同的。如果使用time.now().unix()来取节点本地的时间作为key或value的值,会导致每个节点执行同一个交易的结果不一致,从而造成交易失败。正确的做法是使用函数GetTxTimestamp()来获取交易的时间。每个节点通过函数GetTxTimestamp()来获取到的交易时间是相同的
例子:
t, err := stub.GetTxTimestamp()
t.Seconds // 交易的时间,unix时间戳,精确到秒
t.Nanos// 交易的时间,unix时间戳,精确到纳秒
time.Unix(t.Seconds, int64(t.Nanos)).UnixNano() / 1e6 // 交易的时间,unix时间戳,精确到毫秒



2. 在同一个区块里多笔交易对同一键进行更新

对同一键进行更新的一个或多笔交易打包到同一块中,只有第1笔交易会成功,后面的交易会失败。相关的原因是:在一个区块里的多笔交易,只有在区块被提交后才会真正生效。而每一个键值都有版本号,假设一个键“key_1”在本个区块提交前的版本号为9,然后在本个区块里有2笔交易分别更新键"key_1"的值为"123"和"456"。那么当第1笔交易更新键“key_1”的值时,键"key_1"的版本号在本个区块里将更新为10,但在本区块未提交前,真正生效的版本号还是9。而当执行第2笔交易时,该交易读取到键"key_1"的版本号还是9,这样第2笔交易还是把键"key_1"的版本号更新为10,这样系统会判断为“双花”行为,从而引起冲突,导致只有第1笔交易会执行成功,第2笔交易执行失败。具体可以参考这篇文章 https://learnblockchain.cn/article/620
因此,试图在fabric合约里创建全局的计数器是一件不可靠的事情。



3. 在同一个区块里多笔交易先后对同一个键进行更新和读取

假设在一个区块里有2笔交易,第1笔交易对键"key_1"值更新为"123",第2笔交易尝试读取键"key_1"的值,结果第2笔交易读键"key_1"的值结果为空。原因上面已经提及到,一个区块里的多笔交易,只有在区块被提交后才会真正生效。



4. 在一个方法内对同一个键先写后读

在一个方法内对同一个键先进行写键值(putState()),然后再进行读键值(getState()),会发现前面的putState操作没有生效,原因也是同前面一样的道理



5. 尝试通过合约使用加密算法对信息进行加密

有些加密算法对同样内容的信息进行加密,有可能每次加密的结果是不一样的。例如:RSA公钥对同一数据加密,每次的结果都不一样。这样会导致不同的节点执行加密的结果不一样,从而导致提交的内容不一致,造成交易失败

猜你喜欢

转载自blog.csdn.net/powervip/article/details/111386309
今日推荐