forest/state_migration/nv24/
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 `NV24` upgrade for the
5//! Power actor.
6
7use crate::shim::clock::ChainEpoch;
8use crate::state_migration::common::{ActorMigration, ActorMigrationInput, ActorMigrationOutput};
9use crate::utils::db::CborStoreExt as _;
10use cid::Cid;
11use fil_actor_power_state::{v14::State as StateV14, v15::State as StateV15};
12use fil_actors_shared::v15::builtin::reward::smooth::FilterEstimate as FilterEstimateV15;
13use fvm_ipld_blockstore::Blockstore;
14use std::sync::Arc;
15
16pub struct PowerMigrator {
17    new_code_cid: Cid,
18    tuktuk_epoch: ChainEpoch,
19    ramp_duration_epochs: u64,
20}
21
22pub(in crate::state_migration) fn power_migrator<BS: Blockstore>(
23    cid: Cid,
24    tuktuk_epoch: ChainEpoch,
25    ramp_duration_epochs: u64,
26) -> Arc<dyn ActorMigration<BS> + Send + Sync> {
27    Arc::new(PowerMigrator {
28        new_code_cid: cid,
29        tuktuk_epoch,
30        ramp_duration_epochs,
31    })
32}
33
34// The v15 actor is identical to v14, except for the addition of the `ramp_start_epoch`
35// and `ramp_duration_epochs` fields.
36impl<BS: Blockstore> ActorMigration<BS> for PowerMigrator {
37    fn migrate_state(
38        &self,
39        store: &BS,
40        input: ActorMigrationInput,
41    ) -> anyhow::Result<Option<ActorMigrationOutput>> {
42        let in_state: StateV14 = store.get_cbor_required(&input.head)?;
43
44        let out_state = StateV15 {
45            total_raw_byte_power: in_state.total_raw_byte_power,
46            total_bytes_committed: in_state.total_bytes_committed,
47            total_quality_adj_power: in_state.total_quality_adj_power,
48            total_qa_bytes_committed: in_state.total_qa_bytes_committed,
49            total_pledge_collateral: in_state.total_pledge_collateral,
50            this_epoch_raw_byte_power: in_state.this_epoch_raw_byte_power,
51            this_epoch_quality_adj_power: in_state.this_epoch_quality_adj_power,
52            this_epoch_pledge_collateral: in_state.this_epoch_pledge_collateral,
53            this_epoch_qa_power_smoothed: FilterEstimateV15 {
54                position: in_state.this_epoch_qa_power_smoothed.position,
55                velocity: in_state.this_epoch_qa_power_smoothed.velocity,
56            },
57            miner_count: in_state.miner_count,
58            miner_above_min_power_count: in_state.miner_above_min_power_count,
59            ramp_start_epoch: self.tuktuk_epoch,
60            ramp_duration_epochs: self.ramp_duration_epochs,
61            cron_event_queue: in_state.cron_event_queue,
62            first_cron_epoch: in_state.first_cron_epoch,
63            claims: in_state.claims,
64            proof_validation_batch: in_state.proof_validation_batch,
65        };
66
67        let new_head = store.put_cbor_default(&out_state)?;
68
69        Ok(Some(ActorMigrationOutput {
70            new_code_cid: self.new_code_cid,
71            new_head,
72        }))
73    }
74}