8 个版本 (主要变更)

7.0.0 2024 年 7 月 18 日
6.0.0 2024 年 7 月 12 日
5.0.0 2024 年 6 月 24 日
4.0.0 2024 年 5 月 23 日
0.0.0 2024 年 2 月 28 日

#37#升级

Download history 168/week @ 2024-04-29 25/week @ 2024-05-06 21/week @ 2024-05-13 264/week @ 2024-05-20 22/week @ 2024-05-27 77/week @ 2024-06-03 40/week @ 2024-06-10 14/week @ 2024-06-17 173/week @ 2024-06-24 29/week @ 2024-07-01 107/week @ 2024-07-08 136/week @ 2024-07-15 6/week @ 2024-07-22 38/week @ 2024-07-29 11/week @ 2024-08-12

每月下载 57 次
polkadot-sdk 中使用

GPL-3.0-only

2.5MB
43K SLoC

货架迁移

为 FRAME 运行时提供多区块迁移。

概述

货架负责在多个区块上执行一系列多步迁移。过程从每次运行时升级开始。在迁移进行时,正常的操作交易被暂停。

示例

此示例演示了一个基本成功场景的简单模拟。货架配置了两个迁移:第一个迁移在一步之后成功,第二个迁移在两步之后成功。然后执行运行时升级,并推进区块号,直到所有迁移执行完成。之后,检查记录的历史迁移,并断言事件。

货架 API

有关此货架公开的接口的更多信息,包括其配置特质、可调度项、存储项、事件和错误,请参阅pallet模块。

此模块的另一项引人注目的API是其实现了 MultiStepMigrator 特性。这必须连接到 frame_system::Config::MultiBlockMigrator 以正确运行。

API包含一些紧急管理调用。它们都以前缀 force_ 开头,通常不需要。在使用之前请特别注意。

设计目标

  1. 必须自动执行跨多个块的迁移。
  2. 必须公开迁移是否正在进行的信息。
  3. 必须尊重迁移的悲观权重界限。
  4. 必须按顺序执行迁移。不允许跳过;迁移是在全部或无的基础上运行的。
  5. 必须防止重新执行以前的迁移。
  6. 必须为迁移提供事务性存储语义。
  7. 必须保证进度。

设计

Migrations are provided to the pallet through the associated type Config::Migrations of type SteppedMigrations. This allows multiple migrations to be aggregated through a tuple. It simplifies the trait bounds since all associated types of the trait must be provided by the pallet. The actual progress of the pallet is stored in the Cursor storage item. This can either be MigrationCursor::Active or MigrationCursor::Stuck. In the active case it points to the currently active migration and stores its inner cursor. The inner cursor can then be used by the migration to store its inner state and advance. Each time when the migration returns Some(cursor), it signals the pallet that it is not done yet. The cursor is reset on each runtime upgrade. This ensures that it starts to execute at the first migration in the vector. The pallets cursor is only ever incremented or set to Stuck once it encounters an error (Goal 4). Once in the stuck state, the pallet will stay stuck until it is fixed through manual governance intervention. As soon as the cursor of the pallet becomes Some(_); MultiStepMigrator::ongoing returns true (Goal 2). This can be used by upstream code to possibly pause transactions. In on_initialize the pallet will load the current migration and check whether it was already executed in the past by checking for membership of its ID in the Historic set. Historic migrations are skipped without causing an error. Each successfully executed migration is added to this set (Goal 5). This proceeds until no more migrations remain. At that point, the event UpgradeCompleted is emitted (Goal 1). The execution of each migration happens by calling SteppedMigration::transactional_step. This function wraps the inner step function into a transactional layer to allow rollback in the error case (Goal 6). Weight limits must be checked by the migration itself. The pallet provides a WeightMeter for that purpose. The pallet may return SteppedMigrationError::InsufficientWeight at any point. In that scenario, one of two things will happen: if that migration was exclusively executed in this block, and therefore required more than the maximum amount of weight possible, the process becomes Stuck. Otherwise, one re-attempt is executed with the same logic in the next block (Goal 3). Progress through the migrations is guaranteed by providing a timeout for each migration via SteppedMigration::max_steps. The pallet ONLY guarantees progress if this is set to sensible limits (Goal 7).

场景:治理清理

时不时地,治理可以利用 clear_historic 调用。这确保了不会有旧的迁移堆积在 Historic 集中。这可以很少做,因为存储不应该快速增长,且查找权重不会受到很大影响。另一种可能性是部署一个同步的单块迁移,在MBMs开始之前永久清理它们。

场景:成功的升级

成功的运行时升级的标准程序可能如下所示

  1. 迁移配置在 Migrations 配置项中。所有迁移都公开 max_steps,具有容错性,检查它们的权重界限,并具有唯一标识符。
  2. 运行时升级实施。在 UpgradeStarted 事件之后,会有许多 MigrationAdvancedMigrationCompleted 事件。最后,发出 UpgradeCompleted
  3. 在迁移完成后,执行治理场景中描述的清理操作。

建议:失败的升级

失败的升级无法自动恢复,需要治理干预。设置对 UpgradeFailed 事件的监控,以了解任何失败。应设置 FailedMigrationHandler::failed 钩子,以便治理可以采取行动,但仍阻止其他交易与不一致的存储状态交互。请注意,这是至关重要的,因为不一致的状态可能包含错误的余额或其他可能导致巨大损害的内容,如果用户交易不保持暂停,就会造成损害。实现这一点的其中一种方法是通过使用可以防止大多数用户交互但仍然允许白名单治理调用的 SafeModeTxPause 模块。

备注:失败的迁移

失败的迁移不会添加到 Historic 集中。这意味着必须手动删除并修复错误的迁移。即使在考虑历史集之前,这也适用。

备注:事务处理

您可以将迁移步骤的事务性语义视为基本无用,因为在卡住的情况下状态已经混乱。这只会防止它变得更混乱,但并不能阻止它最初就变得混乱。

依赖关系

~17–32MB
~534K SLoC