Skip to main content

forest/state_migration/nv26fix/
migration.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3//
4//! This module contains the migration logic for the `nv26fix` upgrade. See the parent module for
5//! details on the fix.
6
7use std::sync::Arc;
8
9use crate::networks::{ChainConfig, Height};
10use crate::shim::{
11    address::Address,
12    clock::ChainEpoch,
13    machine::BuiltinActorManifest,
14    state_tree::{StateTree, StateTreeVersion},
15};
16use crate::utils::db::CborStoreExt as _;
17use anyhow::{Context as _, ensure};
18use cid::Cid;
19
20use fvm_ipld_blockstore::Blockstore;
21
22use super::{SystemStateOld, system, verifier::Verifier};
23use crate::state_migration::common::{StateMigration, migrators::nil_migrator};
24
25impl<BS: Blockstore> StateMigration<BS> {
26    pub fn add_nv26fix_migrations(
27        &mut self,
28        store: &Arc<BS>,
29        state: &Cid,
30        new_manifest: &BuiltinActorManifest,
31    ) -> anyhow::Result<()> {
32        let state_tree = StateTree::new_from_root(store.clone(), state)?;
33        let system_actor = state_tree.get_required_actor(&Address::SYSTEM_ACTOR)?;
34        let system_actor_state = store.get_cbor_required::<SystemStateOld>(&system_actor.state)?;
35
36        let current_manifest_data = system_actor_state.builtin_actors;
37
38        let current_manifest =
39            BuiltinActorManifest::load_v1_actor_list(store, &current_manifest_data)?;
40
41        for (name, code) in current_manifest.builtin_actors() {
42            let new_code = new_manifest.get(name)?;
43            self.add_migrator(code, nil_migrator(new_code))
44        }
45
46        self.add_migrator(
47            current_manifest.get_system(),
48            system::system_migrator(new_manifest),
49        );
50
51        Ok(())
52    }
53}
54
55/// Runs the migration for `nv26fix`. Returns the new state root.
56pub fn run_migration<DB>(
57    chain_config: &ChainConfig,
58    blockstore: &Arc<DB>,
59    state: &Cid,
60    epoch: ChainEpoch,
61) -> anyhow::Result<Cid>
62where
63    DB: Blockstore + Send + Sync,
64{
65    // Technically the manifest for this just won't be there for mainnet, but better safe than
66    // sorry.
67    ensure!(
68        chain_config.network.is_testnet(),
69        "this fix migration is only for testnet"
70    );
71    let new_manifest_cid = chain_config
72        .height_infos
73        .get(&Height::TockFix)
74        .context("no height info for network version nv26fix")?
75        .bundle
76        .as_ref()
77        .context("no bundle for network version nv26fix")?;
78
79    blockstore.get(new_manifest_cid)?.context(format!(
80        "manifest for network version nv26fix not found in blockstore: {new_manifest_cid}"
81    ))?;
82
83    // Add migration specification verification
84    let verifier = Arc::new(Verifier::default());
85
86    let new_manifest = BuiltinActorManifest::load_manifest(blockstore, new_manifest_cid)?;
87    let mut migration = StateMigration::<DB>::new(Some(verifier));
88    migration.add_nv26fix_migrations(blockstore, state, &new_manifest)?;
89
90    let actors_in = StateTree::new_from_root(blockstore.clone(), state)?;
91    let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?;
92    let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?;
93
94    Ok(new_state)
95}