use anyhow::Context;
use cid::Cid;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::tuple::*;
use fvm_ipld_encoding::{Cbor, CborStore};
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_ADDR: Address = Address::new_id(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,
}
impl Cbor for State {}
impl State {
pub fn load<B>(state_tree: &StateTree<B>) -> Result<(Self, ActorState)>
where
B: Blockstore,
{
let init_act = state_tree
.get_actor(&INIT_ACTOR_ADDR)?
.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)
.or_fatal()?;
Ok(map.get(&addr.to_bytes()).or_fatal()?.copied())
}
}