diff --git a/fendermint/actors/build.rs b/fendermint/actors/build.rs index 8cc64a14b..97f78e063 100644 --- a/fendermint/actors/build.rs +++ b/fendermint/actors/build.rs @@ -81,6 +81,11 @@ fn main() -> Result<(), Box> { if !result.success() { return Err("actor build failed".into()); } + + // make sure the output dir exists + std::fs::create_dir_all("output") + .expect("failed to create output dir for the actors_bundle.car file"); + let dst = Path::new("output/actors_bundle.car"); let mut bundler = Bundler::new(dst); for (&pkg, id) in ACTORS.iter().zip(1u32..) { diff --git a/fendermint/actors/chainmetadata/src/actor.rs b/fendermint/actors/chainmetadata/src/actor.rs index baf46f23c..ecbf999bd 100644 --- a/fendermint/actors/chainmetadata/src/actor.rs +++ b/fendermint/actors/chainmetadata/src/actor.rs @@ -11,10 +11,11 @@ use fil_actors_runtime::runtime::{ActorCode, Runtime}; use fil_actors_runtime::ActorDowncast; use fil_actors_runtime::ActorError; use fil_actors_runtime::Array; +use fvm_shared::clock::ChainEpoch; use fvm_shared::error::ExitCode; use crate::shared::BLOCKHASHES_AMT_BITWIDTH; -use crate::{ConstructorParams, Method, State}; +use crate::{ConstructorParams, Method, PushBlockParams, State}; #[cfg(feature = "fil-actor")] fil_actors_runtime::wasm_trampoline!(Actor); @@ -42,7 +43,7 @@ impl Actor { Ok(()) } - fn push_block(rt: &impl Runtime, block: Cid) -> Result<(), ActorError> { + fn push_block(rt: &impl Runtime, params: PushBlockParams) -> Result<(), ActorError> { rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; rt.transaction(|st: &mut State, rt| { @@ -56,7 +57,7 @@ impl Actor { // push the block to the AMT blockhashes - .set(rt.curr_epoch().try_into().unwrap(), block.to_string()) + .set(params.epoch as u64, params.block.to_string()) .unwrap(); // remove the oldest block if the AMT is full @@ -87,7 +88,7 @@ impl Actor { Ok(state.lookback_len) } - fn block_cid(rt: &impl Runtime, rewind: u64) -> Result { + fn block_cid(rt: &impl Runtime, epoch: ChainEpoch) -> Result, ActorError> { let st: State = rt.state()?; // load the blockhashes AMT @@ -98,20 +99,25 @@ impl Actor { ) })?; - let blockhash: &String = blockhashes - .get(blockhashes.count() - rewind - 1) - .unwrap() - .unwrap(); + // get the block cid from the AMT, if it does not exist return None + let blockhash: &String = match blockhashes.get(epoch as u64).unwrap() { + Some(v) => v, + None => { + return Ok(None); + } + }; - Cid::from_str(blockhash.as_str()).map_err(|_| { - ActorError::unchecked( + // return the blockhash as a cid, or an error if the cid is invalid + match Cid::from_str(blockhash.as_str()) { + Ok(cid) => Ok(Some(cid)), + Err(_) => Err(ActorError::unchecked( ExitCode::USR_ILLEGAL_STATE, format!( - "failed to parse cid, hash: {}, rewind: {}", - blockhash, rewind + "failed to parse cid, blockhash: {}, epoch: {}", + blockhash, epoch ), - ) - }) + )), + } } } diff --git a/fendermint/actors/chainmetadata/src/shared.rs b/fendermint/actors/chainmetadata/src/shared.rs index a930a7c5a..4daf88f49 100644 --- a/fendermint/actors/chainmetadata/src/shared.rs +++ b/fendermint/actors/chainmetadata/src/shared.rs @@ -3,7 +3,7 @@ use cid::Cid; use fvm_ipld_encoding::tuple::{Deserialize_tuple, Serialize_tuple}; -use fvm_shared::METHOD_CONSTRUCTOR; +use fvm_shared::{clock::ChainEpoch, METHOD_CONSTRUCTOR}; use num_derive::FromPrimitive; // The state is a stores `blockhashes` in an AMT containing the blockhashes of the @@ -28,6 +28,12 @@ pub struct ConstructorParams { pub lookback_len: u64, } +#[derive(Default, Debug, Serialize_tuple, Deserialize_tuple)] +pub struct PushBlockParams { + pub epoch: ChainEpoch, + pub block: Cid, +} + #[derive(FromPrimitive)] #[repr(u64)] pub enum Method { diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 1b32497a8..79d91aa1d 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -85,8 +85,12 @@ where // Push the current block hash to the chainmetadata actor // - let block_cid = fendermint_vm_message::cid(&state.block_hash().unwrap()).unwrap(); - let params = fvm_ipld_encoding::RawBytes::serialize(block_cid)?; + let params = fvm_ipld_encoding::RawBytes::serialize( + fendermint_actor_chainmetadata::PushBlockParams { + epoch: height, + block: fendermint_vm_message::cid(&state.block_hash().unwrap()).unwrap(), + }, + )?; let msg = FvmMessage { from: system::SYSTEM_ACTOR_ADDR, to: fvm_shared::address::Address::new_id(fendermint_actors::CHAINMETADATA_ACTOR_ID),