iuna-e2e-checkpoint.rs (2135B)
1 use std::{env, path::PathBuf}; 2 3 use anyhow::{Context, Result, bail}; 4 use iuna::adapters::{chain_store::SqliteChainStore, ui_data_store::SqliteUiDataStore}; 5 6 fn main() -> Result<()> { 7 let mut args = env::args_os().skip(1); 8 let source = PathBuf::from(args.next().context("missing source chain database")?); 9 let chain_destination = 10 PathBuf::from(args.next().context("missing destination chain database")?); 11 let ui_destination = PathBuf::from(args.next().context("missing destination UI database")?); 12 let height = args 13 .next() 14 .context("missing checkpoint height")? 15 .into_string() 16 .map_err(|_| anyhow::anyhow!("checkpoint height is not valid UTF-8"))? 17 .parse::<u64>() 18 .context("checkpoint height is not an unsigned integer")?; 19 if args.next().is_some() { 20 bail!("usage: iuna-e2e-checkpoint SOURCE_DB CHAIN_DB UI_DB HEIGHT"); 21 } 22 for destination in [&chain_destination, &ui_destination] { 23 if destination.exists() { 24 bail!("destination already exists: {}", destination.display()); 25 } 26 } 27 28 let source_store = SqliteChainStore::open(&source)?; 29 let mut snapshot = source_store 30 .load()? 31 .with_context(|| format!("source has no chain snapshot: {}", source.display()))?; 32 let source_height = snapshot 33 .blocks 34 .last() 35 .context("source chain snapshot is empty")? 36 .height; 37 if source_height < height { 38 bail!("source height {source_height} is below checkpoint height {height}"); 39 } 40 41 snapshot.blocks.truncate( 42 usize::try_from(height) 43 .context("checkpoint height does not fit in memory")? 44 .checked_add(1) 45 .context("checkpoint height overflow")?, 46 ); 47 SqliteChainStore::open(&chain_destination)?.save(&snapshot)?; 48 SqliteUiDataStore::open(&ui_destination)?.project_snapshot(&snapshot, false)?; 49 50 let tip = snapshot.blocks.last().context("checkpoint is empty")?; 51 println!( 52 "materialized height {} ({}) from source height {}", 53 tip.height, tip.hash, source_height 54 ); 55 Ok(()) 56 }