39 lines
1.2 KiB
Rust
39 lines
1.2 KiB
Rust
use clap::ArgMatches;
|
|
use storage::BlockRef;
|
|
use config::Config;
|
|
use primitives::hash::H256;
|
|
use util::init_db;
|
|
|
|
pub fn rollback(cfg: Config, matches: &ArgMatches) -> Result<(), String> {
|
|
try!(init_db(&cfg));
|
|
|
|
let block_ref = matches.value_of("BLOCK").expect("BLOCK is required in cli.yml; qed");
|
|
let block_ref = if block_ref.len() == 64 {
|
|
BlockRef::Hash({
|
|
let hash: H256 = block_ref.parse().map_err(|e| format!("Invalid block number: {}", e))?;
|
|
hash.reversed()
|
|
})
|
|
} else {
|
|
BlockRef::Number(block_ref.parse().map_err(|e| format!("Invalid block hash: {}", e))?)
|
|
};
|
|
|
|
let required_block_hash = cfg.db.block_header(block_ref.clone()).ok_or(format!("Block {:?} is unknown", block_ref))?.hash();
|
|
let genesis_hash = cfg.network.genesis_block().hash();
|
|
|
|
let mut best_block_hash = cfg.db.best_block().hash;
|
|
debug_assert!(best_block_hash != H256::default()); // genesis inserted in init_db
|
|
|
|
loop {
|
|
if best_block_hash == required_block_hash {
|
|
info!("Reverted to block {:?}", block_ref);
|
|
return Ok(());
|
|
}
|
|
|
|
if best_block_hash == genesis_hash {
|
|
return Err(format!("Failed to revert to block {:?}. Reverted to genesis", block_ref));
|
|
}
|
|
|
|
best_block_hash = cfg.db.rollback_best().map_err(|e| format!("{:?}", e))?;
|
|
}
|
|
}
|