简介
本文档介绍激活 MIP-8 的运维方面:将节点的数据库从 slot 编码迁移到 page 编码,实时进行且无需从创世块重新同步。每个节点在双写两种编码,直到分叉将网络切换到 page 编码数据库,然后删除旧的 slot 编码数据库。背景
MIP-8
MIP-8 重新组织了 EVM 状态 trie 使其页感知:存储 slot 被分组到 4 KB 的页中,而不是通过哈希独立分散在磁盘上。对于节点运营者来说,重要的是这改变了磁盘上的 trie 布局 — 这就是为什么需要迁移。TrieDB 时间线
时间线是磁盘上 trie 状态的完整副本,通过将每个已提交的区块以给定编码写入其中构建而成。节点可以一次运行一个或两个时间线,每个都有自己的编码:- Slot 编码时间线使用当前的 trie 布局,每个存储 slot 的磁盘位置由哈希独立确定。这是 MIP-8 之前的格式。
- Page 编码时间线使用 MIP-8 布局,slot 被打包到 128 个连续 slot 的页中。这是 MIP-8 之后的格式。
状态机类型
节点的数据库工具(monad-mpt、monad-cli)将 slot 和 page 编码称为状态机类型:
对于执行而言,重要的是哪个时间线是规范的还是影子的。规范时间线是其
state_root 用于规范链上区块的时间线;影子时间线在另一种编码上并行计算相同的区块,但其 state_root 不会在任何地方使用。
MIP-8 激活正是这两者之间的翻转:
- 激活前,
ethereum(slot)是规范的,monad(page)是影子 - 在硬分叉时交换,
monad(page)成为规范的,ethereum(slot)成为影子。
迁移计划
迁移分三个阶段进行:两个运营者操作和一个硬分叉。阶段 A 在每个节点上激活 page 时间线。阶段 B 是 MIP-8 硬分叉:在固定时间戳,规范链从 slot 时间线切换到 page 时间线。阶段 C 停用现在已成为遗留的 slot 时间线。1
初始状态
DB 模式是 Legacy/Slot — 单个 slot 时间线。执行为 MIP-8 激活前状态。
2
阶段 A — Page 激活
运营者激活 page 次时间线,将 DB 模式变为 Dual。执行仍处于 MIP-8 激活前状态 — 在执行层面尚未发生变化。
3
阶段 B — 硬分叉
在分叉时间戳,MIP-8 在全网激活:page 时间线成为规范,slot 时间线成为其影子。节点保持在 Dual 模式。
4
阶段 C — Slot 停用(最终)
运营者将 page 时间线提升为主时间线,并停用现在成为次时间线的 slot 时间线。DB 模式翻转到 Page — 单个 page 时间线。节点现在已完全迁移。
运维
网络状态
获取当前状态
直接使用monad-mpt 检查节点当前的磁盘状态:
Prometheus 指标
您可以通过 Prometheus 指标monad_triedb_migration_phase 监控双 DB 迁移阶段:
0:slot 编码(初始阶段的预期值)1:双模式(阶段 A 和阶段 B 的预期值)2:page 编码(阶段 C 的预期值)
Monad 状态
monad-status 脚本已更新以反映 TrieDB 模式,例如:
硬重置节点
硬重置流程本身没有改变 — 仍然遵循硬重置说明。下面的 DB 模式逻辑在同一个restore-from-snapshot 步骤中自动发生;无需学习新的手动操作。
硬重置不会迁移您现有的数据库 — 它会清除数据库并从快照中重建。这意味着重置工具无法查看节点先前的磁盘状态来决定要重建什么(重置会在其他操作运行之前截断 DB),因此它会使用以下逻辑选择目标 DB 模式:
- 如果 MIP-8 硬分叉已经通过,它会仅创建 page 时间线,并将快照导入其中。
- 如果分叉尚未通过且它也可以创建 page 时间线,则结果为 Dual 模式,快照会导入两个时间线。
- 如果分叉尚未通过且无法创建 page 时间线,则结果为 Legacy/Slot,快照仅导入 slot 时间线。
第一行是有意为之的:一旦 MIP-8 在网络上激活,就没有理由建立一个 slot 时间线,只是为了在下一阶段再次停用它 — 重置的节点直接进入 page-only 模式。
迁移任务
这适用于全节点和验证者。 迁移分三个阶段进行。阶段 A 和 C 是您在每个节点上执行的操作;阶段 B 是按计划发生的全网硬分叉。阶段 A - Page 激活
此过程从0.15.2 开始支持。
此步骤使用从该版本开始的新 monad-mpt 和 monad-cli 二进制文件。
停止 monad 服务:
Activated secondary timeline; stamped state-machine kind to monad.
转储当前主时间线的快照:
snapshot dump success=true。大约需要 5 分钟。
将快照加载到 page 次时间线中:
load_to_secondary=true。大约需要 3 分钟。
清理快照:
latest 值接近(此示例中为 47536183):
- Primary:
latest is 47536183 - Secondary:
latest is 47536183
active (running)。确认节点重新加入并推进区块。
完成后,节点处于双写模式 — 下次启动时它将把每个新区块提交到两个时间线。
monad-execution 日志会打印 state_root primary=<slot root> secondary=<page root>,两个时间线都应出现在每个区块中。
在每个节点上运行此操作以将节点带入双模式。
每个节点必须在 MIP-8 硬分叉时间戳之前完成此阶段。
阶段 B - MIP-8 硬分叉
MIP-8 激活 阶段 B 是计划中的协议升级,而不是运营者的操作。其时间戳编码在全链范围的版本中,对每个节点都相同 — 只有当整个网络完成阶段 A 后才会发布。 在该时间戳,MIP-8 在执行层激活,规范的state_root 从 slot 时间线翻转到 page 时间线,全网范围内,在同一个区块中:
- 分叉之前 — slot 时间线是规范的;page 时间线跟随它。
- 分叉时及之后 — page 时间线是规范的;slot 时间线跟随它。
阶段 C - Slot 停用
此阶段将停用 TrieDB 中的 slot 时间线。此操作只能在 MIP-8 激活硬分叉时间戳之后进行。 另请注意,在 MIP-8 激活时间戳后进行硬重置的节点将仅恢复为 Page 时间线,无需停用任何时间线。 验证节点是否需要此阶段:ethereum(slot)且次时间线是 monad(page)时才继续。任何其他组合都意味着节点不应运行此阶段。
停止 monad 服务:
monad 的主时间线 — slot 时间线现在已消失。
启动 Monad 服务:
active (running)。确认节点重新加入并推进区块。现在它是一个单一的 page 时间线。
Monad 未来的版本将强制要求 slot 编码时间线被停用。
状态归档节点
状态归档节点(也称为历史全节点)在其本地 TrieDB 数据库中存储自创世以来的每个区块,而不是对旧状态进行剪枝。这使其在 MIP-8 迁移中成为特殊情况:- 阶段 A — 无差异。状态归档节点像其他任何节点一样升级并运行 Dual-DB 迁移。
- 阶段 B — 在硬分叉时间戳时,在状态归档节点上重新运行阶段 A 程序。这会在主时间线当前位置重新播种辅助时间线 — 这是仅适用于状态归档节点的特殊情况。
- 阶段 C — 状态归档节点不运行 slot 停用。 跳过此阶段:
slot-encoded时间线永久保持活动状态,以便节点保留其完整历史。
延伸阅读
- 工程运行手册 — 完整的运营者程序,包括故障处理、回滚和护栏
- 网络信息 — 当前网络状态和分叉时间戳
- MIP-8 — 页感知存储背后的提案
- Mipland — MIP-8 跟踪和讨论
- MIP-8: page-ified storage state — 论坛讨论

