Skip to content

Commit fc9a304

Browse files
committed
chore: check epochs when we ::connect() to the sortition DB against the given epochs, and replace them if need be
1 parent 8ef0d61 commit fc9a304

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

stackslib/src/chainstate/burn/db/sortdb.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2848,6 +2848,35 @@ impl SortitionDB {
28482848
Ok(())
28492849
}
28502850

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+
28512880
/// Get a block commit by its content-addressed location in a specific sortition.
28522881
pub fn get_block_commit(
28532882
conn: &Connection,
@@ -3322,6 +3351,10 @@ impl SortitionDB {
33223351

33233352
self.apply_schema_8_migration(migrator.take())?;
33243353
} else if version == expected_version {
3354+
let tx = self.tx_begin()?;
3355+
SortitionDB::validate_and_replace_epochs(&tx, epochs)?;
3356+
tx.commit()?;
3357+
33253358
return Ok(());
33263359
} else {
33273360
panic!("The schema version of the sortition DB is invalid.")
@@ -10629,4 +10662,51 @@ pub mod tests {
1062910662
good_ops_2[3]
1063010663
);
1063110664
}
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+
}
1063210712
}

0 commit comments

Comments
 (0)