1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT
use cid::Cid;
use paste::paste;

use super::version::*;
use fvm_ipld_blockstore::Blockstore;
use serde::de::DeserializeOwned;

fn get_obj<T>(store: &impl Blockstore, cid: &Cid) -> anyhow::Result<Option<T>>
where
    T: DeserializeOwned,
{
    match store.get(cid)? {
        Some(bz) => Ok(Some(fvm_ipld_encoding::from_slice(&bz)?)),
        None => Ok(None),
    }
}

macro_rules! actor_state_load_trait {
    ($($actor:ident),*) => {
        $(
paste! {
    pub trait [< $actor ActorStateLoad >] {
        fn load<BS: fvm_ipld_blockstore::Blockstore>(store: &BS, code: Cid, state: Cid) -> anyhow::Result<fil_actor_interface::[< $actor:lower >]::State>;
    }
}
        )*
        }
}

actor_state_load_trait!(
    System, Init, Cron, Account, Power, Miner, Market, Multisig, Reward, Verifreg, DataCap, EVM
);

// We need to provide both the version and the version identifier to the macro; it is a limitation
// of the `paste` crate.
macro_rules! actor_state_load_impl {
    ($actor:ident, $($version:literal, $version_ident:ident),*) => {
        paste! {
        impl [< $actor ActorStateLoad >] for fil_actor_interface::[< $actor:lower >]::State {
            fn load<BS: fvm_ipld_blockstore::Blockstore>(store: &BS, code: Cid, state: Cid) -> anyhow::Result<fil_actor_interface::[< $actor:lower >]::State> {
                use anyhow::Context as _;
                $(
                    if [< is_ $actor:lower _cid_version >](&code, $version) {
                        return get_obj(store, &state)?
                            .map(fil_actor_interface::[< $actor:lower >]::State::[< $version_ident >])
                            .context("Actor state doesn't exist in store");
                    }
                )*
                anyhow::bail!("Unknown actor code {}", code)
            }
        }
                }
    };
}

actor_state_load_impl!(Account, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Cron, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(DataCap, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(EVM, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Init, 0, V0, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Market, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Miner, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Multisig, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Power, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(System, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Verifreg, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);
actor_state_load_impl!(Reward, 8, V8, 9, V9, 10, V10, 11, V11, 12, V12, 13, V13, 14, V14);