forest/state_migration/common/
migration_job.rs

1// Copyright 2019-2025 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use std::sync::Arc;
5
6use crate::shim::{address::Address, clock::ChainEpoch, state_tree::ActorState};
7use fvm_ipld_blockstore::Blockstore;
8
9use super::{ActorMigration, ActorMigrationInput, MigrationCache};
10
11/// Defines migration result for a single actor migration.
12#[derive(Debug)]
13pub(in crate::state_migration) struct MigrationJobOutput {
14    pub address: Address,
15    pub actor_state: ActorState,
16}
17
18/// Defines migration job for a single actor migration.
19pub(in crate::state_migration) struct MigrationJob<BS: Blockstore> {
20    pub address: Address,
21    pub actor_state: ActorState,
22    pub actor_migration: Arc<dyn ActorMigration<BS>>,
23}
24
25impl<BS: Blockstore> MigrationJob<BS> {
26    pub(in crate::state_migration) fn run(
27        &self,
28        store: &BS,
29        prior_epoch: ChainEpoch,
30        cache: MigrationCache,
31    ) -> anyhow::Result<Option<MigrationJobOutput>> {
32        if let Some(result) = self
33            .actor_migration
34            .migrate_state(
35                store,
36                ActorMigrationInput {
37                    address: self.address,
38                    balance: self.actor_state.balance.clone().into(),
39                    head: self.actor_state.state,
40                    prior_epoch,
41                    cache,
42                },
43            )
44            .map_err(|e| {
45                anyhow::anyhow!(
46                    "state migration failed for {} actor, addr {}:{}",
47                    self.actor_state.code,
48                    self.address,
49                    e
50                )
51            })?
52        {
53            Ok(Some(MigrationJobOutput {
54                address: self.address,
55                actor_state: ActorState::new(
56                    result.new_code_cid,
57                    result.new_head,
58                    self.actor_state.balance.clone().into(),
59                    self.actor_state.sequence,
60                    self.actor_state.delegated_address.map(Address::from),
61                ),
62            }))
63        } else {
64            Ok(None)
65        }
66    }
67}