Renaissance Labs

Posted on Mar 11, 2022Read on Mirror.xyz

Evmos 升级失败分析及解决方案

Evmos Dev https://evmos.dev/quickstart/run_node.html#reset-data

3 月 7 日上午,Cosmos EVM 兼容中心 Evmos 在 Discord 官方群表示,网络升级失败,并将暂停 24-48 小时。3 月 8 日下午,Cosmos EVM 兼容中心 Evmos 在推特发文称,「鉴于社区反馈,Evmos 至少在接下来的几天内都不会上线」。

今日 15:27(GMT+8)时,Evmos 团队在 Github 上发表了升级失败报告,对网络升级失败的核心问题进行了解读。

为什么链停止运行了?

・核心团队在主网上发布了部分测试的升级程序代码

・发生共识错误之后协调失误,团队安排的时间太紧凑,只有几个小时可用于进行升级部署

・升级的复杂性达到了一个极端 —— 需要彻底重启整个网络并完成同步

・5 个验证者双签,导致它们被 tombstoned(Foresight News 注:tombstone 指验证节点如果验证错误就会被惩罚。)

1)当验证者被 tombstone 后,他们将不能再次成为验证节点。

2)这是一个严重的错误。tombstone 本质上是永久封禁,所有的委托都需要手动解除绑定,这对委托人来说也是一个可怕的场景。

・考虑到受影响的验证节点和用户(比例非常大),暂停这条链是可以接受的。

・在尝试恢复网络数小时后,我们目睹了多个验证节点被 tombstone。验证者社区和核心团队认为这是不对的,于是决定停止网络,直到新版本测试达到可用于生产的状况后再重启。

为什么会出现 5 个验证者双签?

・他们在共识停止期间运行 unsafe-reset-all ,导致他们破坏了 priv_validator_state.json 文件。此外,一些节点在迁移到其他机器的过程中,并忘记拷贝迁移 priv_validator_state.json 文件

・他们不知道必须备份并迁移 priv_validator_state.json,因为当链正常运行时这通常都不是问题,大多数块将在一轮内达成共识,并且在说明手册中没有明确说明一定要这样做。

为什么有这么多验证者运行 unsafe-reset-all 而不保留他们的 priv_validator_state.json ?

・验证者必须从快照中恢复,因为如果他们在升级期间重新启动节点,他们将不再参与共识,所以在这样做时,它们要么完全删除 $EVMOSD _ home/data,要么运行 unsafe-reset-all。在共识停止期间执行此操作时,它是不安全的(正如在其标题中指出的命令那样),并且如果没有备份 priv_validator_state.json,则不完全了解如何恢复。

・关于 priv_validator_state.json 有很多误解

rm $HOME/.evmosd/config/addrbook.json $HOME/.evmosd/config/genesis.json evmosd unsafe-reset-all

・关于这个文件在重新同步时的影响,没有明确的答案(验证节点对共识的运行机制缺乏理解,同一区块每一轮共识的达成都意味着提议者的变更,如果提议者回来并重新运行此轮共识流程,就像 5 位双重签名者所做的那样,他们将抛出两个区块。)

为什么验证者必须从快照中恢复?

・当链停止运行并且人们在停止期间重新启动他们的验证节点时,验证节点不会自动恢复参与共识流程。(当验证者开始使用 v2.0.1 版本时,许多人认为 peer 存在问题,因为这在 Cosmos 生态系统中很常见。在停止其节点修改 peer 列表和 / 或增加连接的 peer 数量之后,它们重新启动其节点。我们认为这导致了 Tendermint 的不确定状态。正如我们所说的,这种不确定状态是指 Tendermint 不知道它应该处于块同步模式还是共识模式,从而导致节点无法继续运行。)

・因此,解决方案是使用快照重新启动一个新的数据库。

・在这段时间里,许多人超量访问 Polkachu 端点,但是在从头开始下载或同步节点之后,操作人员设法启动了 Polkachu 快照的镜像。

・双签的人和该区块提交者有很强的关联性。

以下是在区块高度 58701 的共识流程中违反拜占庭规则的行为:

BF5FC06E32A4168817A16D69692F36C8F7A5DA37, proposed round 0, and double signed round 0.

FF9F24A7DB626386EBA92D1E8D058474CEC40C26, proposed round 2, and double signed round 2.

4F8EDD442959D0BB78F8CE0012BAD23AFEE6E08C, proposed round 4, and double signed round 4.

76692115F93AE444FA857C7BA963F125D8C2E6C6, proposed round 8, and double signed round 8.

9BA4035E5B58DAB71B6573791FDAA3D9E1C78A00, proposed round 10, and double signed round 10.

为什么验证者要重新启动它们的节点?

・一些节点重新启动,因为它「看起来卡住了」。

・其他节点重新启动,因为没有人能够保持一组可靠的 peer。

・本次升级比大多数验证者所习惯的升级都要复杂。

为什么没有一群稳定同步的 peer 呢?

・我们怀疑许多节点并没有进行升级,导致升级重新启动后的节点连接到一些没有升级的无效节点。许多节点的 addrbook.json 因为没有升级导致他们与新版本无法兼容。

・人们很可能连接到没有升级的 seed,并可能传播他们大量无效的 addrbook.json peer。

・当人们在升级过程中关闭他们的节点,导致 peer 的状况变得更糟。

・有几个关键节点直到后来才升级,这意味着许多关键节点都在运行旧版本。

・我们在解决,并创建了一个稳定的 peer 列表。

为什么我们需要在 v2.0.1 之前紧急发布 v1.1.2 版本?

・在高度 58,700 它需要一个升级处理程序紧急升级链。我们不想通过治理进行升级,因为有一个安全漏洞还没有被修复,否则需要等待至少 5 天的时间,这会导致大量的人利用漏洞窃取他人的资产。

为什么我们没有发现 v2.0.0 早期升级失败的问题?

・没有自动化的测试套件来捕捉错误,因此测试必须从头开始构建测试工具或手动完成。手动测试一直持续到交付的最后时刻,但是并非所有团队成员都能拥有在迁移期间快速手动测试需求的能力。

・因为我们在最后一分钟更改了迁移逻辑以尝试通过模块迁移进行升级(因为这比在升级处理程序中执行的做法更安全),所以我们在升级前测试了这大约 300 个块。我们没有足够的时间在几个小时前召集可用人员并准备好进行测试,因为这是手动测试,需要对升级有深入的了解。

・当我们使用旧的升级处理逻辑(在升级处理程序中设置新参数)时,在指定块高度使用 cosmovisor 进行升级时已经通过测试并可以正常工作,但它不符合最佳实践,因为设置新的参数应该在模块本身的迁移处理程序中完成。在编写迁移处理程序时,我们试图获取现有参数并进行设置,当你在迁移过程中时 GetParam 将返回空字节。所以解决方法是在迁移中设置所有新参数,而不从存储中检索旧参数。

・当我们测试迁移逻辑并发现故障、其他 Evmos 工程师重新上线时,它已经落后了 300 个块。到那时,已经来不及了,Evmos 不得不接受在区块高度 58700 升级的命运。

为什么这个升级对于验证者来说变得如此复杂?

Evmos 团队在协调紧急升级时出现了几个错误:

・没有对 v2.0.0 进行测试导致了第二次更新。如果没有经过测试,则应该推迟升级。

・由于漏洞的严重性,发布时间很紧迫。

1)通知应至少提前 24 小时发出,区块高度有所推迟,但在升级前几个 小时发布的版本被限制了,这意味着验证者必须在线交换二进制文件。

2)升级非常激进。

3)时间线是在修复之前选择的,这不是安全事件的(合理)处理方式。

4)即使用户资金存在风险,也应该在公开之前找到解决方案,即使是更 广泛的验证者组。

・在不可行的时间线上为此使用 cosmovisor,当原始设计使状态机兼容直到分叉高度时,需要手动升级。团队在节点运营商中过度估计了 cosmovisor 的重要性。

为什么要花这么多轮来尝试升级?

・因为升级版本是最后一刻发布的,而且升级失败了,是不能立即恢复的。

・投票权不在我们这里,我们在争取了 66% 的投票权,在 10 轮回合中,也就是说持续了数小时。

为什么人们需要依赖快照和重新同步 v1.1.2 来重新应用升级 v2.0.1?

当验证者开始使用 v2.0.1 版本时,许多人认为 peer 存在问题,因为这在 Cosmos 生态系统中很常见。在停止运行其节点以修改对 peer 列表和 / 或增加 peer 数量之后,他们重新启动了节点。我们认为这导致了 Tendermint 的一种不确定状态。正如我们所说的,这种不确定状态导致 Tendermint 不知道它应该处于块同步模式还是共识模式,从而导致节点处于闲置状态。要从这种不稳定状态中恢复,用户需要删除他们的数据库并从升级前的快照中恢复并同步到升级高度,然后更改到 v2.0.1.

此外,Evmos 团队还在 Github 上发布了补救文件供开发者和验证者参考。

Evmos