以太坊智能合约mapping delete的坑
2016-07-16 09:42:04
平风
  • 访问次数: 114
  • 注册日期: 2016-05-13
  • 最后登录: 2017-10-17
  • 当前积分: 106

股指竞猜合约中,使用solidity的mapping来存放玩家下注情况,通过合约的betRecords(address)接口可以很方便获取自己下注及输赢情况。


但是在下次开盘的时候,需要将旧数据清除,代码是这样的:

for(uint index = 0; index < playerIndex.length; index++) {
   delete betRecords[playerIndex[index]]; //Delete Old Index
}

这个地方要说明一下为什么这么写 - Solidity的mapping 不支持遍历。与我们常用的Map类型不同,Solidity的mapping类型只提供了key-value关系,但是没有遍历功能。这样你把一个数据放入mapping后,没有办法获key 或者value列表,也没用clear方法。


为了能够删除旧数据,我们另外建立了一个索引数组playerIndex来存放玩家的地址。


言归正传,这段代码貌似没有问题,但是在玩家稍微多一点就出现油费耗尽了。以太坊的Gas Limit最大是4712388(1.5PI),但是在有30个记录的情况,一个对象存储大概花费5000个汽油,从VMTRACE上看,他的实现机制大概是这样地:

  1. 移除一个元素
  2. 交换集合中的顺序
  3. 把整个集合再存储一遍

移除一个会导致剩下的都重新存一遍,也就是理论上30个元素的集合清空大概需要2325000个汽油,我的数据结构是3个长整数,那么就翻3倍,还真的超出了。


坑爹啊?!这根本不可能实际商用啊!


新版本改成不要调用delete, 改成赋值一个全为0的结构体,效果观察中  ...

平风 最后编辑, 2016-11-15 01:36:45
51chain是什么

51chain.net
恒生研究院旗下区块链技术社区

让区块链开发变简单

联系我们
联系人: 平风
电话: 0571-26691754
Email: niezx@hundsun.com
QQ: 251048392