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
70
71
72
73
74
75
76
77
78
79
80
// Copyright 2019-2026 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT
// ported from commit hash b622af
// The FVM crates only support state tree versions 3,4 and 5. This module
// contains read-only support for state tree version 0. This version is required
// to parse genesis states. Ideally, we would have a library that supports _all_
// state tree versions.
use cid::Cid;
use fil_actors_shared::fvm_ipld_hamt::Hamtv0 as Hamt;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::CborStore;
use super::state_tree::StateRoot;
use super::state_tree::StateTreeVersion;
use crate::shim::address::Address;
pub use fvm2::state_tree::ActorState as ActorStateV2;
const HAMTV0_BIT_WIDTH: u32 = 5;
// This is a read-only version of the earliest state trees.
/// State tree implementation using HAMT. This structure is not thread safe and should only be used
/// in sync contexts.
pub struct StateTreeV0<S> {
hamt: Hamt<S, ActorStateV2>,
}
impl<S> StateTreeV0<S>
where
S: Blockstore,
{
/// Constructor for a HAMT state tree given an IPLD store
pub fn new_from_root(store: S, c: &Cid) -> anyhow::Result<Self> {
// Try to load state root, if versioned
let (version, actors) = if let Ok(Some(StateRoot {
version, actors, ..
})) = store.get_cbor(c)
{
(StateTreeVersion::from(version), actors)
} else {
// Fallback to v0 state tree if retrieval fails
(StateTreeVersion::V0, *c)
};
match version {
StateTreeVersion::V0 => {
let hamt = Hamt::load_with_bit_width(&actors, store, HAMTV0_BIT_WIDTH)?;
Ok(Self { hamt })
}
_ => anyhow::bail!("unsupported state tree version: {version:?}"),
}
}
/// Retrieve store reference to modify db.
pub fn store(&self) -> &S {
self.hamt.store()
}
/// Get actor state from an address. Will be resolved to ID address.
pub fn get_actor(&self, addr: &Address) -> anyhow::Result<Option<ActorStateV2>> {
let addr = match self.lookup_id(addr)? {
Some(addr) => addr,
None => return Ok(None),
};
// if state doesn't exist, find using hamt
let act = self.hamt.get(&addr.to_bytes())?.cloned();
Ok(act)
}
/// Get an ID address from any Address
pub fn lookup_id(&self, addr: &Address) -> anyhow::Result<Option<Address>> {
if addr.protocol() == fvm_shared4::address::Protocol::ID {
return Ok(Some(*addr));
}
anyhow::bail!("StateTreeV0::lookup_id is only defined for ID addresses")
}
}