Skip to main content

forest/state_migration/nv22/
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 `NV22` upgrade. State migration logic
5//! comes from the
6//! [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md#migration).
7
8use std::sync::Arc;
9
10use crate::networks::{ChainConfig, Height};
11use crate::shim::{
12    address::Address,
13    clock::ChainEpoch,
14    machine::{BuiltinActor, BuiltinActorManifest},
15    state_tree::{StateTree, StateTreeVersion},
16};
17use crate::utils::db::CborStoreExt as _;
18use anyhow::Context as _;
19use cid::Cid;
20
21use fvm_ipld_blockstore::Blockstore;
22
23use super::{SystemStateOld, market, miner, system, verifier::Verifier};
24use crate::state_migration::common::{StateMigration, migrators::nil_migrator};
25
26impl<BS: Blockstore> StateMigration<BS> {
27    pub fn add_nv22_migrations(
28        &mut self,
29        store: &Arc<BS>,
30        state: &Cid,
31        new_manifest: &BuiltinActorManifest,
32        chain_config: &ChainConfig,
33    ) -> anyhow::Result<()> {
34        let upgrade_epoch = chain_config
35            .height_infos
36            .get(&Height::Dragon)
37            .context("no height info for network version NV22")?
38            .epoch;
39
40        let state_tree = StateTree::new_from_root(store.clone(), state)?;
41        let system_actor = state_tree.get_required_actor(&Address::new_id(0))?;
42        let system_actor_state = store.get_cbor_required::<SystemStateOld>(&system_actor.state)?;
43
44        let current_manifest_data = system_actor_state.builtin_actors;
45
46        let current_manifest =
47            BuiltinActorManifest::load_v1_actor_list(store, &current_manifest_data)?;
48
49        for (name, code) in current_manifest.builtin_actors() {
50            let new_code = new_manifest.get(name)?;
51            self.add_migrator(code, nil_migrator(new_code))
52        }
53
54        let miner_old_code = current_manifest.get(BuiltinActor::Miner)?;
55        let miner_new_code = new_manifest.get(BuiltinActor::Miner)?;
56
57        let market_old_code = current_manifest.get(BuiltinActor::Market)?;
58        let market_new_code = new_manifest.get(BuiltinActor::Market)?;
59
60        let provider_sectors = Arc::new(miner::ProviderSectors::default());
61
62        self.add_migrator(
63            miner_old_code,
64            miner::miner_migrator(upgrade_epoch, provider_sectors.clone(), miner_new_code)?,
65        );
66
67        self.add_migrator(
68            market_old_code,
69            market::market_migrator(upgrade_epoch, provider_sectors.clone(), market_new_code)?,
70        );
71
72        self.add_migrator(
73            current_manifest.get_system(),
74            system::system_migrator(new_manifest),
75        );
76
77        Ok(())
78    }
79}
80
81/// Runs the migration for `NV22`. Returns the new state root.
82pub fn run_migration<DB>(
83    chain_config: &ChainConfig,
84    blockstore: &Arc<DB>,
85    state: &Cid,
86    epoch: ChainEpoch,
87) -> anyhow::Result<Cid>
88where
89    DB: Blockstore + Send + Sync,
90{
91    let new_manifest_cid = chain_config
92        .height_infos
93        .get(&Height::Dragon)
94        .context("no height info for network version NV22")?
95        .bundle
96        .as_ref()
97        .context("no bundle for network version NV22")?;
98
99    blockstore.get(new_manifest_cid)?.context(format!(
100        "manifest for network version NV22 not found in blockstore: {new_manifest_cid}"
101    ))?;
102
103    // Add migration specification verification
104    let verifier = Arc::new(Verifier::default());
105
106    let new_manifest = BuiltinActorManifest::load_manifest(blockstore, new_manifest_cid)?;
107    let mut migration = StateMigration::<DB>::new(Some(verifier));
108    migration.add_nv22_migrations(blockstore, state, &new_manifest, chain_config)?;
109
110    let actors_in = StateTree::new_from_root(blockstore.clone(), state)?;
111    let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?;
112    let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?;
113
114    Ok(new_state)
115}