forest/state_migration/nv19/
power.rs

1// Copyright 2019-2025 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4//! This module contains the migration logic for the `NV19` upgrade for the
5//! Power actor.
6
7use crate::shim::sector::convert_window_post_proof_v1_to_v1p1;
8use crate::state_migration::common::{ActorMigration, ActorMigrationInput, ActorMigrationOutput};
9use crate::utils::db::CborStoreExt as _;
10use cid::Cid;
11use fil_actor_power_state::{
12    v10::{Claim as ClaimV10, State as StateV10},
13    v11::{Claim as ClaimV11, State as StateV11},
14};
15use fil_actors_shared::v11::{
16    builtin::HAMT_BIT_WIDTH, make_empty_map, make_map_with_root_and_bitwidth,
17};
18use fvm_ipld_blockstore::Blockstore;
19use std::sync::Arc;
20
21pub struct PowerMigrator(Cid);
22
23pub(in crate::state_migration) fn power_migrator<BS: Blockstore>(
24    cid: Cid,
25) -> Arc<dyn ActorMigration<BS> + Send + Sync> {
26    Arc::new(PowerMigrator(cid))
27}
28
29// original golang code: https://github.com/filecoin-project/go-state-types/blob/master/builtin/v11/migration/power.go
30impl<BS: Blockstore> ActorMigration<BS> for PowerMigrator {
31    fn migrate_state(
32        &self,
33        store: &BS,
34        input: ActorMigrationInput,
35    ) -> anyhow::Result<Option<ActorMigrationOutput>> {
36        let in_state: StateV10 = store.get_cbor_required(&input.head)?;
37
38        let in_claims = make_map_with_root_and_bitwidth(&in_state.claims, &store, HAMT_BIT_WIDTH)?;
39
40        let empty_claims = make_empty_map::<BS, ()>(store, HAMT_BIT_WIDTH).flush()?;
41
42        let mut out_claims = make_map_with_root_and_bitwidth(&empty_claims, store, HAMT_BIT_WIDTH)?;
43
44        in_claims.for_each(|key, claim: &ClaimV10| {
45            let new_proof_type = convert_window_post_proof_v1_to_v1p1(claim.window_post_proof_type)
46                .map_err(|e| anyhow::anyhow!("{e}"))?;
47            let out_claim = ClaimV11 {
48                window_post_proof_type: new_proof_type,
49                raw_byte_power: claim.raw_byte_power.clone(),
50                quality_adj_power: claim.quality_adj_power.clone(),
51            };
52            out_claims.set(key.to_owned(), out_claim)?;
53            Ok(())
54        })?;
55
56        let out_claims_root = out_claims.flush()?;
57
58        let out_state = StateV11 {
59            total_raw_byte_power: in_state.total_raw_byte_power,
60            total_bytes_committed: in_state.total_bytes_committed,
61            total_quality_adj_power: in_state.total_quality_adj_power,
62            total_qa_bytes_committed: in_state.total_qa_bytes_committed,
63            total_pledge_collateral: in_state.total_pledge_collateral,
64            this_epoch_raw_byte_power: in_state.this_epoch_raw_byte_power,
65            this_epoch_quality_adj_power: in_state.this_epoch_quality_adj_power,
66            this_epoch_pledge_collateral: in_state.this_epoch_pledge_collateral,
67            this_epoch_qa_power_smoothed: in_state.this_epoch_qa_power_smoothed,
68            miner_count: in_state.miner_count,
69            miner_above_min_power_count: in_state.miner_above_min_power_count,
70            cron_event_queue: in_state.cron_event_queue,
71            first_cron_epoch: in_state.first_cron_epoch,
72            claims: out_claims_root,
73            proof_validation_batch: in_state.proof_validation_batch,
74        };
75
76        let new_head = store.put_cbor_default(&out_state)?;
77
78        Ok(Some(ActorMigrationOutput {
79            new_code_cid: self.0,
80            new_head,
81        }))
82    }
83}