@@ -61,14 +61,14 @@ use crate::utils::get_size::{
6161 GetSize , vec_heap_size_helper, vec_with_stack_only_item_heap_size_helper,
6262} ;
6363use ahash:: { HashMap , HashMapExt } ;
64- use anyhow:: { Context as _, bail} ;
64+ use anyhow:: { Context as _, bail, ensure } ;
6565use bls_signatures:: { PublicKey as BlsPublicKey , Serialize as _} ;
6666use chain_rand:: ChainRand ;
6767use cid:: Cid ;
6868pub use circulating_supply:: GenesisInfo ;
6969use fil_actor_verifreg_state:: v12:: DataCap ;
7070use fil_actor_verifreg_state:: v13:: ClaimID ;
71- use fil_actors_shared:: fvm_ipld_amt:: Amtv0 as Amt ;
71+ use fil_actors_shared:: fvm_ipld_amt:: { Amt , Amtv0 } ;
7272use fil_actors_shared:: fvm_ipld_bitfield:: BitField ;
7373use fil_actors_shared:: v12:: runtime:: DomainSeparationTag ;
7474use fil_actors_shared:: v13:: runtime:: Policy ;
@@ -91,6 +91,7 @@ use tracing::{error, info, instrument, trace, warn};
9191pub use utils:: is_valid_for_sending;
9292
9393const DEFAULT_TIPSET_CACHE_SIZE : NonZeroUsize = nonzero ! ( 1024usize ) ;
94+ const EVENTS_AMT_BITWIDTH : u32 = 5 ;
9495
9596/// Intermediary for retrieving state objects and updating actor states.
9697type CidPair = ( Cid , Cid ) ;
@@ -560,11 +561,24 @@ where
560561 let ts = tipset. clone ( ) ;
561562 let this = Arc :: clone ( self ) ;
562563 let cids = tipset. cids ( ) ;
564+ let events_root = events_root. cloned ( ) ;
563565 self . receipt_event_cache_handler
564566 . get_events_or_else (
565567 key,
566568 Box :: new ( move || {
567569 Box :: pin ( async move {
570+ // If the events are not in the cache, try to load them from the blockstore
571+ if let Some ( events_root) = events_root
572+ && let Ok ( stamped_events) =
573+ StampedEvent :: get_events ( this. blockstore ( ) , & events_root)
574+ {
575+ return Ok ( StateEvents {
576+ events : vec ! [ stamped_events] ,
577+ roots : vec ! [ Some ( events_root) ] ,
578+ } ) ;
579+ }
580+
581+ // If the events are neither in the cache nor in the blockstore, compute them.
568582 let state_out = this
569583 . compute_tipset_state ( ts, NO_CALLBACK , VMTrace :: NotTraced )
570584 . await ?;
@@ -1986,8 +2000,28 @@ where
19862000 let ( receipts, events, events_roots) =
19872001 vm. apply_block_messages ( & block_messages, epoch, callback) ?;
19882002
1989- // step 5: construct receipt root from receipts and flush the state-tree
1990- let receipt_root = Amt :: new_from_iter ( chain_index. db ( ) , receipts) ?;
2003+ // step 5: construct receipt root from receipts
2004+ let receipt_root = Amtv0 :: new_from_iter ( chain_index. db ( ) , receipts) ?;
2005+
2006+ // step 6: store events AMTs in the blockstore
2007+ for ( msg_events, events_root) in events. iter ( ) . zip ( events_roots. iter ( ) ) {
2008+ if let Some ( event_root) = events_root {
2009+ // Store the events AMT - the root CID should match the one computed by FVM
2010+ let derived_event_root = Amt :: new_from_iter_with_bit_width (
2011+ chain_index. db ( ) ,
2012+ EVENTS_AMT_BITWIDTH ,
2013+ msg_events. iter ( ) ,
2014+ )
2015+ . map_err ( |e| Error :: Other ( format ! ( "failed to store events AMT: {e}" ) ) ) ?;
2016+
2017+ // Verify the stored root matches the FVM-computed root
2018+ ensure ! (
2019+ derived_event_root. eq( event_root) ,
2020+ "Events AMT root mismatch: derived={derived_event_root}, actual={event_root}."
2021+ ) ;
2022+ }
2023+ }
2024+
19912025 let state_root = vm. flush ( ) ?;
19922026
19932027 Ok ( StateOutput {
0 commit comments