智能合约 Event 恢复
其实数据库被误删这种事情不是 Dapp 专属的一种事故,而应该在所有具有数据库应用的防范列表中。这一次只是结合智能合约的数据库的一种特例和它特殊的「修复」方式。
成本核算
- 显性成本:50USD + 275USD (Infura Team Plan + Archive Node Access Permission)
- 隐形成本:用户信任度降低,项目的打击
- 健康成本:团队所有人两天精神紧绷
Dapp 架构
sequenceDiagram
autonumber
par 用户注册流程
用户->>前端: 钱包签名
前端->>智能合约: 调用只能合约注册账户
智能合约->>后端: 通过 Event(emit Register(用户ID, 用户以太坊地址)) 数据同步
end
par 登陆到后端
用户->>前端: 钱包签名
前端->>后端: 签名信息传递给后端
后端->>前端: 验签取到用户以太坊地址,返回用户ID
end
在本案例中 Dapp 的架构如上所示,有三个端,前端用户界面,业务全在智能合约中,后端收集一些信息做统计、分析的工作。
在这个架构下,event 的 subscribe 和 持久化显得十分重要,所有的数据都是由 event 生成。
发生原因
工程师在重置已使用的测试环境时,误删了线上环境数据库,由于用户的所有信息都是从 API 读取的,数据库删除后所有用户进入前端都是空空一片,只能保证基本的业务流程的使用,所有的统计信息都没了。
团队成员马上进入战斗状态,
- 首先询问删除了什么表:
delete from table
的方式删除了用户表、event 原始数据表 - 其次判断恢复方式
- MySQL 层面:备份文件、binlog,这两个都没有!
- Event 层面:重新拉取一下从项目开始到现在只能合约发到后端的
event
,重新组织数据。
因为并没有做备份,没有开 binlog,没有使用云服务,现在从 MySQL 层面无法下手。因为后端只是收到 event 然后转换为结构化数据,持久化到数据库中,所以决定使用从头处理一遍 Event 的方式去恢复被删除的数据。
然后经过实际试用后选择了 Infura 这家的 Archive 节点的服务,当时我们找到了三种方式:
- 自建以太坊全节点,以太坊轻节点我们搭建过一次,但是有足足 10 个区块的延迟,是无法接受的,现在需要搭建全节点来拉取 event 的话,从同步需要的时间和前期积累的经验来看,不考虑这种方式
- QuikNode 的服务,他们的 rpc 节点我们试用过,Dashboard 做的十分简陋,节点使用起来速度也比较慢,并且区块同步有延迟,不考虑
- Infura 的服务,Infura 的服务是非常不错的,已经经过了 MetaMask 及各种钱包的验证。经过我们本次事故恢复的体验来说,Infura 做的以太坊服务是非常值得推荐的(除了他们的 billing 系统,操作的时候一定要慎重,订单、优惠券管理一塌糊涂,重复扣费蒙眼扣费)。
然后我们从 Infura Archive 节点拉取了从合约部署到当前区块的所有 event 重新持久化后替换了线上数据库,完成事件处理。
吃一堑长一智
- MySQL(持久化数据) 一定要定期备份、开启 binlog