@@ -3056,12 +3056,27 @@ async fn revert_minority_fork_on_resume() {
30563056// version is correct. This is the easiest schema test to write without historic versions of
30573057// Lighthouse on-hand, but has the disadvantage that the min version needs to be adjusted manually
30583058// as old downgrades are deprecated.
3059- #[ tokio:: test]
3060- async fn schema_downgrade_to_min_version ( ) {
3059+ async fn schema_downgrade_to_min_version (
3060+ store_config : StoreConfig ,
3061+ reconstruct_historic_states : bool ,
3062+ ) {
30613063 let num_blocks_produced = E :: slots_per_epoch ( ) * 4 ;
30623064 let db_path = tempdir ( ) . unwrap ( ) ;
3063- let store = get_store ( & db_path) ;
3064- let harness = get_harness ( store. clone ( ) , LOW_VALIDATOR_COUNT ) ;
3065+ let spec = test_spec :: < E > ( ) ;
3066+
3067+ let chain_config = ChainConfig {
3068+ reconstruct_historic_states,
3069+ ..ChainConfig :: default ( )
3070+ } ;
3071+ let import_all_data_columns = false ;
3072+
3073+ let store = get_store_generic ( & db_path, store_config. clone ( ) , spec. clone ( ) ) ;
3074+ let harness = get_harness_generic (
3075+ store. clone ( ) ,
3076+ LOW_VALIDATOR_COUNT ,
3077+ chain_config. clone ( ) ,
3078+ import_all_data_columns,
3079+ ) ;
30653080
30663081 harness
30673082 . extend_chain (
@@ -3082,7 +3097,7 @@ async fn schema_downgrade_to_min_version() {
30823097 drop ( harness) ;
30833098
30843099 // Re-open the store.
3085- let store = get_store ( & db_path) ;
3100+ let store = get_store_generic ( & db_path, store_config , spec ) ;
30863101
30873102 // Downgrade.
30883103 migrate_schema :: < DiskHarnessType < E > > (
@@ -3105,16 +3120,28 @@ async fn schema_downgrade_to_min_version() {
31053120 // Recreate the harness.
31063121 let harness = BeaconChainHarness :: builder ( MinimalEthSpec )
31073122 . default_spec ( )
3123+ . chain_config ( chain_config)
31083124 . keypairs ( KEYPAIRS [ 0 ..LOW_VALIDATOR_COUNT ] . to_vec ( ) )
31093125 . testing_slot_clock ( slot_clock)
31103126 . resumed_disk_store ( store. clone ( ) )
31113127 . mock_execution_layer ( )
31123128 . build ( ) ;
31133129
3130+ // Check chain dump for appropriate range depending on whether this is an archive node.
3131+ let chain_dump_start_slot = if reconstruct_historic_states {
3132+ Slot :: new ( 0 )
3133+ } else {
3134+ store. get_split_slot ( )
3135+ } ;
3136+
31143137 check_finalization ( & harness, num_blocks_produced) ;
31153138 check_split_slot ( & harness, store. clone ( ) ) ;
3116- check_chain_dump ( & harness, num_blocks_produced + 1 ) ;
3117- check_iterators ( & harness) ;
3139+ check_chain_dump_from_slot (
3140+ & harness,
3141+ chain_dump_start_slot,
3142+ num_blocks_produced + 1 - chain_dump_start_slot. as_u64 ( ) ,
3143+ ) ;
3144+ check_iterators_from_slot ( & harness, chain_dump_start_slot) ;
31183145
31193146 // Check that downgrading beyond the minimum version fails (bound is *tight*).
31203147 let min_version_sub_1 = SchemaVersion ( min_version. as_u64 ( ) . checked_sub ( 1 ) . unwrap ( ) ) ;
@@ -3127,6 +3154,67 @@ async fn schema_downgrade_to_min_version() {
31273154 . expect_err ( "should not downgrade below minimum version" ) ;
31283155}
31293156
3157+ // Schema upgrade/downgrade on an archive node where the optimised migration does apply due
3158+ // to the split state being aligned to a diff layer.
3159+ #[ tokio:: test]
3160+ async fn schema_downgrade_to_min_version_archive_node_grid_aligned ( ) {
3161+ // Need to use 3 as the hierarchy exponent to get diffs on every epoch boundary with minimal
3162+ // spec.
3163+ schema_downgrade_to_min_version (
3164+ StoreConfig {
3165+ hierarchy_config : HierarchyConfig :: from_str ( "3,4,5" ) . unwrap ( ) ,
3166+ prune_payloads : false ,
3167+ ..StoreConfig :: default ( )
3168+ } ,
3169+ true ,
3170+ )
3171+ . await
3172+ }
3173+
3174+ // Schema upgrade/downgrade on an archive node where the optimised migration DOES NOT apply
3175+ // due to the split state NOT being aligned to a diff layer.
3176+ #[ tokio:: test]
3177+ async fn schema_downgrade_to_min_version_archive_node_grid_unaligned ( ) {
3178+ schema_downgrade_to_min_version (
3179+ StoreConfig {
3180+ hierarchy_config : HierarchyConfig :: from_str ( "7" ) . unwrap ( ) ,
3181+ prune_payloads : false ,
3182+ ..StoreConfig :: default ( )
3183+ } ,
3184+ true ,
3185+ )
3186+ . await
3187+ }
3188+
3189+ // Schema upgrade/downgrade on a full node with a fairly normal per-epoch diff config.
3190+ #[ tokio:: test]
3191+ async fn schema_downgrade_to_min_version_full_node_per_epoch_diffs ( ) {
3192+ schema_downgrade_to_min_version (
3193+ StoreConfig {
3194+ hierarchy_config : HierarchyConfig :: from_str ( "3,4,5" ) . unwrap ( ) ,
3195+ prune_payloads : false ,
3196+ ..StoreConfig :: default ( )
3197+ } ,
3198+ false ,
3199+ )
3200+ . await
3201+ }
3202+
3203+ // Schema upgrade/downgrade on a full node with dense per-slot diffs.
3204+ // FIXME(tree-states): this will panic
3205+ #[ tokio:: test]
3206+ async fn schema_downgrade_to_min_version_full_node_dense_diffs ( ) {
3207+ schema_downgrade_to_min_version (
3208+ StoreConfig {
3209+ hierarchy_config : HierarchyConfig :: from_str ( "0,3,4,5" ) . unwrap ( ) ,
3210+ prune_payloads : false ,
3211+ ..StoreConfig :: default ( )
3212+ } ,
3213+ true ,
3214+ )
3215+ . await
3216+ }
3217+
31303218/// Check that blob pruning prunes blobs older than the data availability boundary.
31313219#[ tokio:: test]
31323220async fn deneb_prune_blobs_happy_case ( ) {
@@ -3700,7 +3788,11 @@ fn check_split_slot(
37003788
37013789/// Check that all the states in a chain dump have the correct tree hash.
37023790fn check_chain_dump ( harness : & TestHarness , expected_len : u64 ) {
3703- let mut chain_dump = harness. chain . chain_dump ( ) . unwrap ( ) ;
3791+ check_chain_dump_from_slot ( harness, Slot :: new ( 0 ) , expected_len)
3792+ }
3793+
3794+ fn check_chain_dump_from_slot ( harness : & TestHarness , from_slot : Slot , expected_len : u64 ) {
3795+ let mut chain_dump = harness. chain . chain_dump_from_slot ( from_slot) . unwrap ( ) ;
37043796
37053797 assert_eq ! ( chain_dump. len( ) as u64 , expected_len) ;
37063798
@@ -3748,7 +3840,7 @@ fn check_chain_dump(harness: &TestHarness, expected_len: u64) {
37483840
37493841 let mut forward_block_roots = harness
37503842 . chain
3751- . forwards_iter_block_roots ( Slot :: new ( 0 ) )
3843+ . forwards_iter_block_roots ( from_slot )
37523844 . expect ( "should get iter" )
37533845 . map ( Result :: unwrap)
37543846 . collect :: < Vec < _ > > ( ) ;
@@ -3769,10 +3861,14 @@ fn check_chain_dump(harness: &TestHarness, expected_len: u64) {
37693861/// Check that every state from the canonical chain is in the database, and that the
37703862/// reverse state and block root iterators reach genesis.
37713863fn check_iterators ( harness : & TestHarness ) {
3864+ check_iterators_from_slot ( harness, Slot :: new ( 0 ) )
3865+ }
3866+
3867+ fn check_iterators_from_slot ( harness : & TestHarness , slot : Slot ) {
37723868 let mut max_slot = None ;
37733869 for ( state_root, slot) in harness
37743870 . chain
3775- . forwards_iter_state_roots ( Slot :: new ( 0 ) )
3871+ . forwards_iter_state_roots ( slot )
37763872 . expect ( "should get iter" )
37773873 . map ( Result :: unwrap)
37783874 {
@@ -3794,7 +3890,7 @@ fn check_iterators(harness: &TestHarness) {
37943890 assert_eq ! (
37953891 harness
37963892 . chain
3797- . forwards_iter_block_roots( Slot :: new ( 0 ) )
3893+ . forwards_iter_block_roots( slot )
37983894 . expect( "should get iter" )
37993895 . last( )
38003896 . map( Result :: unwrap)
0 commit comments