超级账本Fabric智能合约开发需要注意的一个巨坑

超级账本Fabric智能合约开发需要注意的一个巨坑,第1张

下面是一个简单的合约函数:

func SetKey (stub shim.ChaincodeStubInterface, key,value string) pb.Response {

stub.PutState(key, []byte(value))

msg := fmt.Sprintf("Set key: %s, value: %s", key,m value)



// 发送事件

SendEvent(stub, “SetKey”, msg)

}

假设快速地提交2个交易,这2个交易都是调用SetKey()合约函数,只是value参数不同,分别是“123”和“456”

交易1:-c '{"Args": ["SetKey","key1", "123"]}'

交易2:-c '{"Args": ["SetKey","key1", "456"]}'

如果这2个都刚好打包在同一个区块,并且刚好是按先交易1,后交易2的顺序来提交。你会发现这2个交易都能成功写入区块里,并同时产生了2个事件。但如果你使用GetState()去取key1的值时,你会发现key1的值是"123",而不是"456"。如果查看交易的状态,你会发现交易1的交易状态是:VALID。交易2的交易状态是: MVCC_READ_CONFLICT。也就是说,虽然这2个交易都能成功写入区块里,但交易2却是非法交易,没有执行修改世界状态的 *** 作。

其中的原因是:超级账本的每个键值都有版本管理,在同一个区块里,只允许有一笔交易更改同一个键对应的键值。例如:在上面的例子里,在交易1前,"key1"的版本号是1,当写入交易1时,当"key1"的版本号变为2。当写入交易2时,仍然认为"key1"的版本号是1,并即将变为2,从而发生冲突。根本的原因是,在提交区块之前,不会提交区块里的交易。同一个区块里的如果有2笔交易更改同一个键的值时,在提交区块之前,键的版本不会因为第1笔交易而更改。这是从以太坊开发转到超级账本开发特别需要注意的地方,这是由于以太坊和超级账本的运作机制不同而产生的差别。对于以太坊,同一个区块里的如果有2笔交易更改同一个键的值时是允许的,因为区块里的交易已经是排好序的,通过nounce值来标识交易的先后顺序。但超级账本不一样,提议(交易)响应由客户端从背书节点采集,然后发送给排序节点并最终由排序节点将其分发给提交节点。也就是,只有交易送到排序节点才真正排序。

同样地,如果在一个合约函数里,先调用PutState()修改了某个键值,然后想马上调用GetState()读取该键来获取修改后的键值,读出来的结果还是修改前的键值,不能得到本次修改后的键值,这是以太坊开发者刚转到超级账本开发容易犯的错误。

------------------------------------------------------------------------------

我的公众号:区块链战斗机

我的知乎:powervip - 知乎

我的csdn:powervip的博客_CSDN博客-区块链,以太坊,比特币领域博主

我的github:欢迎来到powervip的博客 | powervip.github.io

我的学习笔记:Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.

如果你觉得这篇文章写得还可以,请帮忙点个赞,谢谢!著作权归作者所有。如需转载,请注明原文出处并保留原文链接。​

你的鼓励,我的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/925765.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存