forest/state_migration/nv21fix/
migration.rs1use super::{SystemStateOld, system, verifier::Verifier};
5use crate::networks::{ChainConfig, Height};
6use crate::prelude::*;
7use crate::shim::{
8 address::Address,
9 clock::ChainEpoch,
10 machine::{BuiltinActor, BuiltinActorManifest},
11 state_tree::{StateTree, StateTreeVersion},
12};
13use crate::state_migration::common::PostMigrationCheck;
14use crate::state_migration::common::{StateMigration, migrators::nil_migrator};
15use crate::utils::db::CborStoreExt as _;
16use anyhow::bail;
17
18impl<BS: Blockstore + ShallowClone> StateMigration<BS> {
19 pub fn add_nv21fix_migrations(
20 &mut self,
21 store: &BS,
22 state: &Cid,
23 new_manifest: &BuiltinActorManifest,
24 ) -> anyhow::Result<()> {
25 let state_tree = StateTree::new_from_root(store, state)?;
26 let system_actor = state_tree.get_required_actor(&Address::new_id(0))?;
27
28 let system_actor_state = store.get_cbor_required::<SystemStateOld>(&system_actor.state)?;
29
30 let current_manifest_data = system_actor_state.builtin_actors;
31
32 let current_manifest =
33 BuiltinActorManifest::load_v1_actor_list(store, ¤t_manifest_data)?;
34
35 for (name, code) in current_manifest.builtin_actors() {
36 let new_code = new_manifest.get(name)?;
37 self.add_migrator(code, nil_migrator(new_code))
38 }
39
40 self.add_migrator(
41 current_manifest.get_system(),
42 system::system_migrator(new_manifest),
43 );
44
45 Ok(())
46 }
47}
48
49struct PostMigrationVerifier {
50 state_pre: Cid,
51}
52
53impl<BS: Blockstore + ShallowClone> PostMigrationCheck<BS> for PostMigrationVerifier {
54 fn post_migrate_check(&self, store: &BS, actors_out: &StateTree<BS>) -> anyhow::Result<()> {
55 let actors_in = StateTree::new_from_root(store, &self.state_pre)?;
56 let system_actor = actors_in.get_required_actor(&Address::new_id(0))?;
57
58 let system_actor_state = store.get_cbor_required::<SystemStateOld>(&system_actor.state)?;
59
60 let current_manifest_data = system_actor_state.builtin_actors;
61
62 let current_manifest =
63 BuiltinActorManifest::load_v1_actor_list(store, ¤t_manifest_data)?;
64
65 actors_in.for_each(|address, actor_in| {
66 let actor_out = actors_out.get_required_actor(&address)?;
67
68 if actor_in.sequence != actor_out.sequence {
69 bail!(
70 "actor {address} sequence mismatch: pre-migration: {}, post-migration: {}",
71 actor_in.sequence,
72 actor_out.sequence
73 );
74 }
75
76 if actor_in.balance != actor_out.balance {
77 bail!(
78 "actor {address} balance mismatch: pre-migration: {}, post-migration: {}",
79 actor_in.balance,
80 actor_out.balance
81 );
82 }
83
84 if actor_in.state != actor_out.state && actor_in.code != current_manifest.get_system() {
85 bail!(
86 "actor {address} state mismatch: pre-migration: {}, post-migration: {}",
87 actor_in.state,
88 actor_out.state
89 );
90 }
91
92 if actor_in.code != current_manifest.get(BuiltinActor::Miner)?
93 && actor_in.code != actor_out.code
94 {
95 bail!(
96 "actor {address} code mismatch: pre-migration: {}, post-migration: {}",
97 actor_in.code,
98 actor_out.code
99 );
100 }
101
102 Ok(())
103 })?;
104
105 Ok(())
106 }
107}
108
109pub fn run_migration<DB>(
111 chain_config: &ChainConfig,
112 blockstore: &DB,
113 state: &Cid,
114 epoch: ChainEpoch,
115) -> anyhow::Result<Cid>
116where
117 DB: Blockstore + ShallowClone + Send + Sync,
118{
119 assert!(
120 chain_config.network.is_testnet(),
121 "NV21 fix only applies to test network"
122 );
123
124 let new_manifest_cid = chain_config
125 .height_infos
126 .get(&Height::WatermelonFix)
127 .context("no height info for calibration network version NV21 (fixed)")?
128 .bundle
129 .as_ref()
130 .context("no bundle for calibration network version NV21 (fixed)")?;
131
132 blockstore.get(new_manifest_cid)?.with_context(|| {
133 format!(
134 "manifest for network version NV21 (fixed) not found in blockstore: {new_manifest_cid}"
135 )
136 })?;
137
138 let verifier = Arc::new(Verifier::default());
140
141 let new_manifest = BuiltinActorManifest::load_manifest(blockstore, new_manifest_cid)?;
142 let mut migration = StateMigration::<DB>::new(Some(verifier));
143 migration.add_nv21fix_migrations(blockstore, state, &new_manifest)?;
144 migration.add_post_migration_check(Arc::new(PostMigrationVerifier { state_pre: *state }));
145
146 let actors_in = StateTree::new_from_root(blockstore, state)?;
147 let actors_out = StateTree::new(blockstore, StateTreeVersion::V5)?;
148 let new_state = migration.migrate_state_tree(blockstore, epoch, actors_in, actors_out)?;
149
150 Ok(new_state)
151}