Kava 5主网回滚事后剖析

作者:Kevin Davis,Kava技术开发主管

Kava 5主网回滚事后剖析

北京时间3月4日晚,Kava 5主网成功上线,但在启动几分钟后,Kava核心开发团队在HARD Protocol发现了一个bug,于是决定回滚。在这篇事后剖析中,Kava Labs技术开发主管Kevin Davis将公布事件发生的原委和根本原因,并从技术角度阐述Kava作为一个项目和社区,为避免未来再度发生类似事件所正在采取的措施。

事件发生时间表

注:事件发生时间为北京时间2021年3月4日-3月5日。

21:00

Kava-4主链按计划停止运行,开始向Kava-5主链迁移。

23:05 

Kava-5主链启动时,2/3的Staking验证者上线。

23:40

在对新启动的主链进行QA测试时,Kava工程师观察到部分用户HARD奖励申领出现了意外的数值。

00:00

在寻找根本原因时,Kava工程师观察到部分用户的HARD奖励申领对象出现异常。

00:05

在查看可用方案,确认所有用户资金安全后,团队决定报告安全委员会申请关闭主链。

00:20

安全委员会提出软件升级方案,Kava-5主链停用。

1:00

确定Bug的根本原因。团队决定回滚到Kava-4功能集,工程师开始正式制定计划,以恢复主链运行。

2:30

公布推荐的回滚计划。团队正式发布带有回滚指令的新版本Kava链。

14:30

Kava 6主网上线(搭载原Kava 4功能集但以新的链ID命名)

事件根源

Kava开发团队已对HARD Protocol进行部分内部审计,这篇审计报告说明了本次事件是为了修复HARD Protocol清算的核算逻辑中的一个bug。

HARD审计链接:https://github.com/Kava-Labs/kava/pull/823

在代码审核过程中,技术团队曾指出应该使用安全差集来避免代币数量为负数,进而导致cosmos-sdk sdk.Coins对象的panic。这个问题的修复是不正确的。

Kava 5主网回滚事后剖析

代码链接:https://gist.githubusercontent.com/karzak/aeee0e02831d912398e0470aeb15d233/raw/c7a4f0c6ac32befdf6f6b736652358f82c90c041/DecrementBorrwedCoins.go

这种对代币集结果进行差集处理导致了借出的代币的不相交元素被完全从计算中剔除。然后,这种对借币和供币总量的计算错误就产生了下游效应,即产生了HARD Protocol申领对象的奖励计算不准确,这个问题在Kava 5推出后立即被发现。

Bug 奖金

所有在Kava 5上线期间曾申领HARD奖励的地址,无论领取成功与否,都将分配到250个HARD作为Bug奖金。

技术分析

由于Kava拥有独特的流动性激励架构,所以我们值得分析一下”HARD申领”的定义以及代表含义。在HARD Protocol中,用户会根据自己提供的流动性按比例获得HARD代币的申领资格。待申领奖励表示用户选择最长锁定期(1年)申领时有权获得的HARD代币余额。

在任何时候,用户都可以使用MsgClaimReward交易申领他们的HARD奖励。申领时,用户声明HARD代币的锁仓时间,可以是1个月,也可以是1年,代币会从HARD模块账户转到用户的vesting锁定账户。因为所有申领的HARD申领都是锁定的,所以用户不能立即将代币从MsgClaimRewards中转移出去。

以下为一些技术意见:

该bug并没有导致通胀的HARD代币被铸造或可能被铸造。用户如果在HARD模块账户余额上出现了异常的申领,但由于HARD模块账户余额是锁定的,所以没有任何错误的申领奖励被转移出去。

用户如成功申领了异常HARD代币,也无法消耗。从设计上看,奖励锁仓机制可以防止奖励计算出现bug时用户立刻提现奖励的情况。

Kava安全委员会的职能如期运行。安全委员会的目标是为Kava提供一个”安全门”,用于处理非常严重、主动攻击型、以及可能会威胁用户资金及主链安全的bug。安全委员会几乎只有在升级过程或观察到漏洞后才会启用。最重要的是,虽然安全委员会提供了一种方法来暂停主链运行,但并不具备重新上线主链的功能。Kava主链的运行取决于验证者,并与所有Kava治理参与者协调完成。Kava Labs以及更强大的Kava治理将在决策过程中始终保持透明,并随时欢迎社区及用户对完善平台管理的意见和反馈。

改进方向

在审计过程中如果一个简单的算术错误逃过了代码审查,我们首先想到的是审计过程很仓促。鉴于这是我们第一次将外部团队成员的审计过程(与交付给外部审计公司形成对比)纳入我们的发布周期,看来我们很可能在审计过程中对审计代码修复的预估时间不足,今后我们将通过前期分配更多的时间来缓解这一问题,同时也将审计完成检查纳入到我们的审计排期过程中。在这种情况下,我认为我们过于严格地遵守我们的时间表,应该多花一周时间来处理审计检查和PR。

第二点也是我们从以往开发过程中吸取的经验是,保证代码冻结期限非常关键,以及如果核心状态机代码因为任何原因而被”解冻”,那么发布排期的更新也至为重要。在这种情况下,我们有一个激励性的测试网与审计同时进行。在审计和修复合并后,额外的激励测试网大概率会发现这个错误,这也是我们将在未来的开发过程中加入的部分。

此外,这次发布凸显了事先沟通、精心规划的发布重启程序的重要性。虽然在故障期间的沟通也是有效的,但如果有一个更好的预先规划过程,就可以避免在规划重启的确切顺序时产生的一些额外的故障时间。今后,我们将为每一次发布制定一个”回滚”手册并进行内部沟通,以便参与节点在发布回滚的情况下有一个例行程序可循。

反思

构建去中心化的金融应用会带来许多开发上的挑战,我们将不断地从错误中学习,不断地发展最佳实践,并研究行业领先应用的经验,思考有无改进空间。Kava是一个不断成长的团队,也在根据产品及开发需求不断发展新的技术运营力量。

虽然这次发布最终没有成功,但我们在产品开发和发布过程上做了很多改进,我们将对此保持始终学习的态度,也非常感谢社区和验证者们的理解和支持。失败并不会让我们退缩:我们将从错误中吸取教训,并一如既往地继续打造DeFi的未来。

点击阅读原文,查看原报告。

来源:KAVA