use anyhow::Context;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::CborStore;
use fvm_ipld_encoding::tuple::*;
use fvm_ipld_hamt::Hamt;
use fvm_shared::address::{Address, Payload};
use fvm_shared::{ActorID, HAMT_BIT_WIDTH};
use crate::state_tree::{ActorState, StateTree};
pub const INIT_ACTOR_ID: ActorID = 1;
use crate::kernel::{ClassifyResult, Result};
#[derive(Serialize_tuple, Deserialize_tuple, Debug)]
pub struct State {
pub address_map: Cid,
pub next_id: ActorID,
pub network_name: String,
#[cfg(feature = "m2-native")]
pub installed_actors: Cid,
}
impl State {
#[allow(unused)]
pub fn new_test<B: Blockstore>(store: &B) -> Self {
#[cfg(feature = "m2-native")]
use multihash_codetable::Code::Blake2b256;
let e_cid = Hamt::<_, String>::new_with_bit_width(&store, 5)
.flush()
.unwrap();
#[cfg(feature = "m2-native")]
let el_cid = store.put_cbor(&Vec::<Cid>::new(), Blake2b256).unwrap();
State {
address_map: e_cid,
next_id: 100,
network_name: "test".to_owned(),
#[cfg(feature = "m2-native")]
installed_actors: el_cid,
}
}
pub fn load<B>(state_tree: &StateTree<B>) -> Result<(Self, ActorState)>
where
B: Blockstore,
{
let init_act = state_tree
.get_actor(INIT_ACTOR_ID)?
.context("init actor address could not be resolved")
.or_fatal()?;
let state = state_tree
.store()
.get_cbor(&init_act.state)
.or_fatal()?
.context("init actor state not found")
.or_fatal()?;
Ok((state, init_act))
}
pub fn map_address_to_new_id<B>(&mut self, store: B, addr: &Address) -> Result<ActorID>
where
B: Blockstore,
{
let id = self.next_id;
self.next_id += 1;
let mut map = Hamt::<B, _>::load_with_bit_width(&self.address_map, store, HAMT_BIT_WIDTH)
.or_fatal()?;
map.set(addr.to_bytes().into(), id).or_fatal()?;
self.address_map = map.flush().or_fatal()?;
Ok(id)
}
pub fn resolve_address<B>(&self, store: B, addr: &Address) -> Result<Option<u64>>
where
B: Blockstore,
{
if let &Payload::ID(id) = addr.payload() {
return Ok(Some(id));
}
let map = Hamt::<B, _>::load_with_bit_width(&self.address_map, store, HAMT_BIT_WIDTH)
.context("failed to load init actor address map")
.or_fatal()?;
Ok(map
.get(&addr.to_bytes())
.context("failed to read init actor address map")
.or_fatal()?
.copied())
}
}