forest/state_migration/common/
mod.rs1use std::num::NonZeroUsize;
8
9use crate::{
10 prelude::*,
11 shim::{address::Address, clock::ChainEpoch, econ::TokenAmount, state_tree::StateTree},
12 utils::cache::SizeTrackingCache,
13};
14
15mod macros;
16mod migration_job;
17pub(in crate::state_migration) mod migrators;
18mod state_migration;
19pub(in crate::state_migration) mod verifier;
20
21pub(in crate::state_migration) use state_migration::StateMigration;
22pub(in crate::state_migration) type Migrator<BS> = Arc<dyn ActorMigration<BS> + Send + Sync>;
23
24#[derive(derive_more::Deref)]
26pub(in crate::state_migration) struct MigrationCache(SizeTrackingCache<String, CidWrapper>);
27
28impl MigrationCache {
29 pub fn new(size: NonZeroUsize) -> Self {
30 Self(SizeTrackingCache::new_with_metrics("migration", size))
31 }
32
33 pub fn get_or_insert_with<F>(&self, key: &str, f: F) -> anyhow::Result<Cid>
34 where
35 F: FnOnce() -> anyhow::Result<Cid>,
36 {
37 self.deref()
38 .get_or_insert_with(key, || {
39 let cid = f()?;
40 Ok(cid.into())
41 })
42 .map(From::from)
43 }
44}
45
46impl ShallowClone for MigrationCache {
47 fn shallow_clone(&self) -> Self {
48 Self(self.deref().shallow_clone())
49 }
50}
51
52#[allow(dead_code)] pub(in crate::state_migration) struct ActorMigrationInput {
54 pub address: Address,
56 pub balance: TokenAmount,
58 pub head: Cid,
60 pub prior_epoch: ChainEpoch,
62 pub cache: MigrationCache,
64}
65
66pub(in crate::state_migration) struct ActorMigrationOutput {
68 pub new_code_cid: Cid,
70 pub new_head: Cid,
72}
73
74pub(in crate::state_migration) trait ActorMigration<BS: Blockstore> {
76 fn migrate_state(
77 &self,
78 store: &BS,
79 input: ActorMigrationInput,
80 ) -> anyhow::Result<Option<ActorMigrationOutput>>;
81
82 fn is_deferred(&self) -> bool {
85 false
86 }
87}
88
89pub(in crate::state_migration) trait PostMigrator<BS: Blockstore>:
91 Send + Sync
92{
93 fn post_migrate_state(&self, store: &BS, actors_out: &mut StateTree<BS>) -> anyhow::Result<()>;
94}
95
96pub(in crate::state_migration) trait PostMigrationCheck<BS: Blockstore>:
98 Send + Sync
99{
100 fn post_migrate_check(&self, store: &BS, actors_out: &StateTree<BS>) -> anyhow::Result<()>;
101}
102
103pub(in crate::state_migration) type PostMigratorArc<BS> = Arc<dyn PostMigrator<BS>>;
105
106pub(in crate::state_migration) type PostMigrationCheckArc<BS> = Arc<dyn PostMigrationCheck<BS>>;
108
109pub(in crate::state_migration) trait TypeMigration<From, To> {
112 fn migrate_type(from: From, store: &impl Blockstore) -> anyhow::Result<To>;
113}
114
115pub(in crate::state_migration) struct TypeMigrator;
119
120#[cfg(test)]
121mod tests {
122 use super::MigrationCache;
123 use crate::utils::cid::CidCborExt;
124 use cid::Cid;
125 use nonzero_ext::nonzero;
126
127 #[test]
128 fn test_migration_cache() {
129 let cache = MigrationCache::new(nonzero!(10usize));
130 let cid = Cid::from_cbor_blake2b256(&42).unwrap();
131
132 let value = cache.get_or_insert_with("Azathoth", || Ok(cid)).unwrap();
133 assert_eq!(value, cid);
134 let value = cache
136 .get_or_insert_with("Azathoth", || panic!("value should be cached"))
137 .unwrap();
138 assert_eq!(value, cid);
139
140 let value = cache
143 .get_or_insert_with("Dagon", || cache.get_or_insert_with("Azathoth", || Ok(cid)))
144 .unwrap();
145 assert_eq!(value, cid);
146 }
147}