@@ -78,7 +78,8 @@ pub struct ChainStore {
7878 /// Tracks blocks for the purpose of forming tipsets.
7979 tipset_tracker : TipsetTracker < DbImpl > ,
8080
81- genesis_block_header : Arc < CachingBlockHeader > ,
81+ /// Genesis tipset.
82+ genesis : Tipset ,
8283
8384 /// validated blocks
8485 pub ( crate ) validated_blocks : SizeTrackingCache < CidWrapper , ( ) > ,
@@ -99,7 +100,7 @@ impl ShallowClone for ChainStore {
99100 ec_calculator_finalized_epoch : self . ec_calculator_finalized_epoch . shallow_clone ( ) ,
100101 chain_index : self . chain_index . shallow_clone ( ) ,
101102 tipset_tracker : self . tipset_tracker . shallow_clone ( ) ,
102- genesis_block_header : self . genesis_block_header . shallow_clone ( ) ,
103+ genesis : self . genesis . shallow_clone ( ) ,
103104 validated_blocks : self . validated_blocks . shallow_clone ( ) ,
104105 chain_config : self . chain_config . shallow_clone ( ) ,
105106 messages_in_tipset_cache : self . messages_in_tipset_cache . shallow_clone ( ) ,
@@ -111,9 +112,11 @@ impl ChainStore {
111112 pub fn new (
112113 db : impl Into < DbImpl > ,
113114 chain_config : Arc < ChainConfig > ,
114- genesis_block_header : CachingBlockHeader ,
115+ genesis : impl Into < Tipset > ,
115116 ) -> anyhow:: Result < Self > {
116117 let db = db. into ( ) ;
118+ let genesis = genesis. into ( ) ;
119+ anyhow:: ensure!( genesis. epoch( ) == 0 , "genesis tipset must be at epoch 0" ) ;
117120 let ( publisher, _) = broadcast:: channel ( SINK_CAP ) ;
118121 let head = if let Some ( head_tsk) = db
119122 . heaviest_tipset_key ( )
@@ -122,11 +125,11 @@ impl ChainStore {
122125 Tipset :: load_required ( & db, & head_tsk)
123126 . with_context ( || format ! ( "failed to load head tipset with key {head_tsk}" ) ) ?
124127 } else {
125- Tipset :: from ( & genesis_block_header )
128+ genesis . shallow_clone ( )
126129 } ;
127130 let heaviest_tipset = Arc :: new ( ArcSwap :: from_pointee ( head. shallow_clone ( ) ) ) ;
128131 let f3_finalized_tipset: Arc < ArcSwapOption < Tipset > > = Default :: default ( ) ;
129- let chain_index = ChainIndex :: new ( db. shallow_clone ( ) ) ;
132+ let chain_index = ChainIndex :: new ( db. shallow_clone ( ) , genesis . shallow_clone ( ) ) ;
130133 let ec_calculator_finalized_epoch = Arc :: new ( AtomicI64 :: new (
131134 ChainGetTipSetFinalityStatus :: get_ec_finality_epoch ( & chain_index, & chain_config, & head) ,
132135 ) ) ;
@@ -150,7 +153,7 @@ impl ChainStore {
150153 heaviest_tipset,
151154 f3_finalized_tipset,
152155 ec_calculator_finalized_epoch,
153- genesis_block_header : genesis_block_header . into ( ) ,
156+ genesis ,
154157 validated_blocks : SizeTrackingCache :: new_with_metrics (
155158 "validated_blocks" ,
156159 VALIDATED_BLOCKS_CACHE_SIZE ,
@@ -259,20 +262,21 @@ impl ChainStore {
259262 self . tipset_tracker . expand ( header)
260263 }
261264
265+ /// Returns the genesis block header.
262266 pub fn genesis_block_header ( & self ) -> & CachingBlockHeader {
263- & self . genesis_block_header
267+ self . genesis . min_ticket_block ( )
268+ }
269+
270+ /// Returns the genesis tipset.
271+ pub fn genesis_tipset ( & self ) -> Tipset {
272+ self . genesis . shallow_clone ( )
264273 }
265274
266275 /// Returns the currently tracked heaviest tipset.
267276 pub fn heaviest_tipset ( & self ) -> Tipset {
268277 self . heaviest_tipset . load ( ) . as_ref ( ) . shallow_clone ( )
269278 }
270279
271- /// Returns the genesis tipset.
272- pub fn genesis_tipset ( & self ) -> Tipset {
273- Tipset :: from ( self . genesis_block_header ( ) )
274- }
275-
276280 /// Subscribes head changes.
277281 pub fn subscribe_head_changes ( & self ) -> broadcast:: Receiver < HeadChanges > {
278282 self . head_changes_tx . subscribe ( )
@@ -407,13 +411,10 @@ impl ChainStore {
407411
408412 // More null blocks than lookback
409413 if lbr >= heaviest_tipset. epoch ( ) {
410- // This situation is extremely rare so it's fine to compute the
411- // state-root without caching.
412- let genesis_timestamp = heaviest_tipset. genesis ( chain_index. db ( ) ) ?. timestamp ;
414+ let genesis_timestamp = chain_index. genesis ( ) . min_ticket_block ( ) . timestamp ;
413415 let beacon = Arc :: new ( chain_config. get_beacon_schedule ( genesis_timestamp) ) ;
414416 let ExecutedTipset { state_root, .. } =
415417 crate :: state_manager:: apply_block_messages_blocking (
416- genesis_timestamp,
417418 chain_index. shallow_clone ( ) ,
418419 chain_config. shallow_clone ( ) ,
419420 beacon,
@@ -726,14 +727,16 @@ mod tests {
726727 let gen_block = CachingBlockHeader :: new ( RawBlockHeader {
727728 miner_address : Address :: new_id ( 0 ) ,
728729 state_root : Cid :: new_v1 ( DAG_CBOR , MultihashCode :: Identity . digest ( & [ ] ) ) ,
729- epoch : 1 ,
730+ epoch : 0 ,
730731 weight : 2u32 . into ( ) ,
731732 messages : Cid :: new_v1 ( DAG_CBOR , MultihashCode :: Identity . digest ( & [ ] ) ) ,
732733 message_receipts : Cid :: new_v1 ( DAG_CBOR , MultihashCode :: Identity . digest ( & [ ] ) ) ,
733734 ..Default :: default ( )
734735 } ) ;
735- let cs = ChainStore :: new ( db, chain_config, gen_block. clone ( ) ) . unwrap ( ) ;
736+ let gen_ts = Tipset :: from ( & gen_block) ;
737+ let cs = ChainStore :: new ( db, chain_config, gen_ts. shallow_clone ( ) ) . unwrap ( ) ;
736738
739+ assert_eq ! ( cs. genesis_tipset( ) , gen_ts) ;
737740 assert_eq ! ( cs. genesis_block_header( ) , & gen_block) ;
738741 }
739742
0 commit comments