Skip to main content

forest/state_migration/nv18/
migration.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use std::sync::Arc;
5
6use crate::networks::{ChainConfig, Height};
7use crate::shim::machine::BuiltinActorManifest;
8use crate::shim::{
9    address::Address,
10    clock::ChainEpoch,
11    state_tree::{StateTree, StateTreeVersion},
12};
13use anyhow::anyhow;
14use cid::Cid;
15use fvm_ipld_blockstore::Blockstore;
16use fvm_ipld_encoding::CborStore as _;
17
18use super::{
19    SystemStateOld, eam::EamPostMigrator, eth_account::EthAccountPostMigrator, init, system,
20    verifier::Verifier,
21};
22use crate::state_migration::common::{StateMigration, migrators::nil_migrator};
23impl<BS: Blockstore> StateMigration<BS> {
24    pub fn add_nv18_migrations(
25        &mut self,
26        store: Arc<BS>,
27        state: &Cid,
28        new_manifest: &Cid,
29    ) -> anyhow::Result<()> {
30        let state_tree = StateTree::new_from_root(store.clone(), state)?;
31        let system_actor = state_tree
32            .get_actor(&Address::new_id(0))?
33            .ok_or_else(|| anyhow!("system actor not found"))?;
34
35        let system_actor_state = store
36            .get_cbor::<SystemStateOld>(&system_actor.state)?
37            .ok_or_else(|| anyhow!("system actor state not found"))?;
38        let current_manifest =
39            BuiltinActorManifest::load_v1_actor_list(&store, &system_actor_state.builtin_actors)?;
40
41        let new_manifest = BuiltinActorManifest::load_manifest(&store, new_manifest)?;
42
43        for (actor, cid) in current_manifest.builtin_actors() {
44            let new_cid = new_manifest.get(actor)?;
45            self.add_migrator(cid, nil_migrator(new_cid));
46        }
47
48        self.add_migrator(
49            current_manifest.get_init(),
50            init::init_migrator(new_manifest.get_init()),
51        );
52
53        self.add_migrator(
54            current_manifest.get_system(),
55            system::system_migrator(&new_manifest),
56        );
57
58        // Add post-migration steps
59        self.add_post_migrator(Arc::new(EamPostMigrator));
60
61        self.add_post_migrator(Arc::new(EthAccountPostMigrator));
62
63        Ok(())
64    }
65}
66
67/// Runs the migration for `NV18`. Returns the new state root.
68pub fn run_migration<DB>(
69    chain_config: &ChainConfig,
70    blockstore: &Arc<DB>,
71    state: &Cid,
72    epoch: ChainEpoch,
73) -> anyhow::Result<Cid>
74where
75    DB: Blockstore + Send + Sync,
76{
77    let new_manifest_cid = chain_config
78        .height_infos
79        .get(&Height::Hygge)
80        .ok_or_else(|| anyhow!("no height info for network version NV18"))?
81        .bundle
82        .as_ref()
83        .ok_or_else(|| anyhow!("no bundle info for network version NV18"))?;
84
85    blockstore.get(new_manifest_cid)?.ok_or_else(|| {
86        anyhow!(
87            "manifest for network version NV18 not found in blockstore: {}",
88            new_manifest_cid
89        )
90    })?;
91
92    // Add migration specification verification
93    let verifier = Arc::new(Verifier::default());
94
95    let mut migration = StateMigration::<DB>::new(Some(verifier));
96    migration.add_nv18_migrations(blockstore.clone(), state, new_manifest_cid)?;
97
98    let actors_in = StateTree::new_from_root(blockstore.clone(), state)?;
99    let actors_out = StateTree::new(blockstore.clone(), StateTreeVersion::V5)?;
100    let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?;
101
102    Ok(new_state)
103}