use crate::{
api::eth,
mmr::{helper, MergeHash, H256},
result::Error,
ShadowShared,
};
use cmmr::MMR;
use rocksdb::{
backup::{BackupEngine, BackupEngineOptions, RestoreOptions},
IteratorMode,
};
use std::{env, fs::File};
pub fn exec(path: String, from: i32, to: i32) -> Result<(), Error> {
if path.ends_with("tar") {
backup(path)
} else {
geth(path, from, to)
}
}
fn backup(path: String) -> Result<(), Error> {
let db_dir = dirs::home_dir().unwrap().join(".darwinia/cache/mmr");
let mut wal_dir = env::temp_dir();
wal_dir.push("shadow_mmr");
tar::Archive::new(File::open(&path)?).unpack(&env::temp_dir())?;
let mut engine = BackupEngine::open(&BackupEngineOptions::default(), &wal_dir)?;
engine.restore_from_latest_backup(db_dir, wal_dir, &RestoreOptions::default())?;
Ok(())
}
fn geth(path: String, from: i32, to: i32) -> Result<(), Error> {
std::env::set_var("RUST_LOG", "info,darwinia_shadow");
std::env::set_var("GO_LOG", "ALL");
env_logger::init();
info!("Importing ethereum headers from {}...", &path);
let hashes = eth::import(&path, from, to);
let hashes_vec = hashes.split(',').collect::<Vec<&str>>();
info!("Imported {} hashes", hashes_vec.len());
if hashes_vec[0].is_empty() {
error!("Importing hashes from {} failed", path);
return Ok(());
}
info!("Got {} header hashes", hashes_vec.len());
let shared = ShadowShared::new(None);
let mmr_size = shared.db.iterator(IteratorMode::Start).count() as u64;
let last_leaf = helper::mmr_size_to_last_leaf(mmr_size as i64) as usize;
if last_leaf < from as usize {
error!(
"The last leaf of mmr is {}, can not import mmr from {}",
last_leaf, from
);
}
let rect = last_leaf - from as usize;
info!("mmr_size: {}, last_leaf: {}", mmr_size, last_leaf);
let mut mmr = MMR::<_, MergeHash, _>::new(mmr_size, &shared.store);
if hashes_vec.len() > rect {
let mut ptr = rect;
for i in &hashes_vec[ptr..] {
ptr += 1;
if ptr % 1000 == 0 {
trace!("Calculating {:?}/{}", ptr + from as usize, to);
}
mmr.push(H256::from(i))?;
}
}
mmr.commit()?;
info!("done.");
Ok(())
}