@@ -2848,6 +2848,35 @@ impl SortitionDB {
2848
2848
Ok ( ( ) )
2849
2849
}
2850
2850
2851
+ /// Validates given StacksEpochs (will runtime panic if there is any invalid StacksEpoch structuring) and
2852
+ /// replaces them into the SortitionDB's epochs table
2853
+ fn validate_and_replace_epochs (
2854
+ db_tx : & Transaction ,
2855
+ epochs : & [ StacksEpoch ] ,
2856
+ ) -> Result < ( ) , db_error > {
2857
+ let epochs = StacksEpoch :: validate_epochs ( epochs) ;
2858
+ let existing_epochs = Self :: get_stacks_epochs ( db_tx) ?;
2859
+ if existing_epochs == epochs {
2860
+ return Ok ( ( ) ) ;
2861
+ }
2862
+ info ! ( "Replace existing epochs with new epochs" ) ;
2863
+ db_tx. execute ( "DELETE FROM epochs;" , NO_PARAMS ) ?;
2864
+ for epoch in epochs. into_iter ( ) {
2865
+ let args: & [ & dyn ToSql ] = & [
2866
+ & ( epoch. epoch_id as u32 ) ,
2867
+ & u64_to_sql ( epoch. start_height ) ?,
2868
+ & u64_to_sql ( epoch. end_height ) ?,
2869
+ & epoch. block_limit ,
2870
+ & epoch. network_epoch ,
2871
+ ] ;
2872
+ db_tx. execute (
2873
+ "INSERT INTO epochs (epoch_id,start_block_height,end_block_height,block_limit,network_epoch) VALUES (?1,?2,?3,?4,?5)" ,
2874
+ args
2875
+ ) ?;
2876
+ }
2877
+ Ok ( ( ) )
2878
+ }
2879
+
2851
2880
/// Get a block commit by its content-addressed location in a specific sortition.
2852
2881
pub fn get_block_commit (
2853
2882
conn : & Connection ,
@@ -3322,6 +3351,10 @@ impl SortitionDB {
3322
3351
3323
3352
self . apply_schema_8_migration ( migrator. take ( ) ) ?;
3324
3353
} else if version == expected_version {
3354
+ let tx = self . tx_begin ( ) ?;
3355
+ SortitionDB :: validate_and_replace_epochs ( & tx, epochs) ?;
3356
+ tx. commit ( ) ?;
3357
+
3325
3358
return Ok ( ( ) ) ;
3326
3359
} else {
3327
3360
panic ! ( "The schema version of the sortition DB is invalid." )
@@ -10629,4 +10662,51 @@ pub mod tests {
10629
10662
good_ops_2[ 3 ]
10630
10663
) ;
10631
10664
}
10665
+
10666
+ #[ test]
10667
+ fn test_validate_and_replace_epochs ( ) {
10668
+ use crate :: core:: STACKS_EPOCHS_MAINNET ;
10669
+
10670
+ let path_root = "/tmp/test_validate_and_replace_epochs" ;
10671
+ if fs:: metadata ( path_root) . is_ok ( ) {
10672
+ fs:: remove_dir_all ( path_root) . unwrap ( ) ;
10673
+ }
10674
+
10675
+ fs:: create_dir_all ( path_root) . unwrap ( ) ;
10676
+
10677
+ let mut bad_epochs = STACKS_EPOCHS_MAINNET . to_vec ( ) ;
10678
+ let idx = bad_epochs. len ( ) - 2 ;
10679
+ bad_epochs[ idx] . end_height += 1 ;
10680
+ bad_epochs[ idx + 1 ] . start_height += 1 ;
10681
+
10682
+ let sortdb = SortitionDB :: connect (
10683
+ & format ! ( "{}/sortdb.sqlite" , & path_root) ,
10684
+ 0 ,
10685
+ & BurnchainHeaderHash ( [ 0x00 ; 32 ] ) ,
10686
+ 0 ,
10687
+ & bad_epochs,
10688
+ PoxConstants :: mainnet_default ( ) ,
10689
+ None ,
10690
+ true ,
10691
+ )
10692
+ . unwrap ( ) ;
10693
+
10694
+ let db_epochs = SortitionDB :: get_stacks_epochs ( sortdb. conn ( ) ) . unwrap ( ) ;
10695
+ assert_eq ! ( db_epochs, bad_epochs) ;
10696
+
10697
+ let fixed_sortdb = SortitionDB :: connect (
10698
+ & format ! ( "{}/sortdb.sqlite" , & path_root) ,
10699
+ 0 ,
10700
+ & BurnchainHeaderHash ( [ 0x00 ; 32 ] ) ,
10701
+ 0 ,
10702
+ & STACKS_EPOCHS_MAINNET . to_vec ( ) ,
10703
+ PoxConstants :: mainnet_default ( ) ,
10704
+ None ,
10705
+ true ,
10706
+ )
10707
+ . unwrap ( ) ;
10708
+
10709
+ let db_epochs = SortitionDB :: get_stacks_epochs ( sortdb. conn ( ) ) . unwrap ( ) ;
10710
+ assert_eq ! ( db_epochs, STACKS_EPOCHS_MAINNET . to_vec( ) ) ;
10711
+ }
10632
10712
}
0 commit comments