From 7d2811f13630955a4bbfa8afbe584222e1971993 Mon Sep 17 00:00:00 2001 From: skoupidi Date: Tue, 10 Dec 2024 19:30:51 +0200 Subject: [PATCH] drk: added sub command to list scanned blocks --- bin/drk/src/cli_util.rs | 10 +++++-- bin/drk/src/main.rs | 56 +++++++++++++++++++++++++++++++++++ bin/drk/src/scanned_blocks.rs | 53 ++++++++++++++++++--------------- 3 files changed, 93 insertions(+), 26 deletions(-) diff --git a/bin/drk/src/cli_util.rs b/bin/drk/src/cli_util.rs index 7bdc1a861..d7b904c71 100644 --- a/bin/drk/src/cli_util.rs +++ b/bin/drk/src/cli_util.rs @@ -382,7 +382,7 @@ pub fn generate_completions(shell: &str) -> Result<()> { let simulate_tx = SubCommand::with_name("simulate-tx").about("Read a transaction from stdin and simulate it"); - let tx_hash = Arg::with_name("tx-hash").help("Transaction hash"); + let tx_hash = Arg::with_name("tx-hash").help("Fetch specific history record (optional)"); let encode = Arg::with_name("encode") .long("encode") @@ -392,9 +392,15 @@ pub fn generate_completions(shell: &str) -> Result<()> { .about("Fetch broadcasted transactions history") .args(&vec![tx_hash, encode]); + let height = Arg::with_name("height").help("Fetch specific height record (optional)"); + + let scanned_blocks = SubCommand::with_name("scanned-blocks") + .about("Fetch scanned blocks records") + .args(&vec![height]); + let explorer = SubCommand::with_name("explorer") .about("Explorer related subcommands") - .subcommands(vec![fetch_tx, simulate_tx, txs_history]); + .subcommands(vec![fetch_tx, simulate_tx, txs_history, scanned_blocks]); // Alias let alias = Arg::with_name("alias").help("Token alias"); diff --git a/bin/drk/src/main.rs b/bin/drk/src/main.rs index 307abac34..140e009e9 100644 --- a/bin/drk/src/main.rs +++ b/bin/drk/src/main.rs @@ -410,6 +410,12 @@ enum ExplorerSubcmd { /// Encode specific history record transaction to base58 encode: bool, }, + + /// Fetch scanned blocks records + ScannedBlocks { + /// Fetch specific height record (optional) + height: Option, + }, } #[derive(Clone, Debug, Deserialize, StructOpt)] @@ -1960,6 +1966,56 @@ async fn realmain(args: Args, ex: Arc>) -> Result<()> { Ok(()) } + + ExplorerSubcmd::ScannedBlocks { height } => { + let drk = new_wallet( + blockchain_config.wallet_path, + blockchain_config.wallet_pass, + None, + ex, + args.fun, + ) + .await; + + if let Some(h) = height { + let (height, hash, _) = match drk.get_scanned_block_record(h) { + Ok(ret) => ret, + Err(e) => { + eprintln!("Failed to retrieve scanned block record: {e:?}"); + exit(2); + } + }; + + println!("Height: {height}"); + println!("Hash: {hash}"); + + return Ok(()) + } + + let map = match drk.get_scanned_block_records() { + Ok(m) => m, + Err(e) => { + eprintln!("Failed to retrieve scanned blocks records: {e:?}"); + exit(2); + } + }; + + // Create a prettytable with the new data: + let mut table = Table::new(); + table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + table.set_titles(row!["Height", "Hash"]); + for (height, hash, _) in map.iter() { + table.add_row(row![height, hash]); + } + + if table.is_empty() { + println!("No scanned blocks records found"); + } else { + println!("{table}"); + } + + Ok(()) + } }, Subcmd::Alias { command } => match command { diff --git a/bin/drk/src/scanned_blocks.rs b/bin/drk/src/scanned_blocks.rs index 6bd8b9518..c9e254a4a 100644 --- a/bin/drk/src/scanned_blocks.rs +++ b/bin/drk/src/scanned_blocks.rs @@ -49,14 +49,8 @@ impl Drk { self.wallet.exec_sql(&query, rusqlite::params![height, hash, rollback_query]) } - /// Get a scanned block information record. - pub fn get_scanned_block_record(&self, height: u32) -> WalletDbResult<(u32, String, String)> { - let row = self.wallet.query_single( - WALLET_SCANNED_BLOCKS_TABLE, - &[], - convert_named_params! {(WALLET_SCANNED_BLOCKS_COL_HEIGH, height)}, - )?; - + /// Auxiliary function to parse a `WALLET_SCANNED_BLOCKS_TABLE` records. + fn parse_scanned_block_record(&self, row: &[Value]) -> WalletDbResult<(u32, String, String)> { let Value::Integer(height) = row[0] else { return Err(WalletDbError::ParseColumnValueError); }; @@ -75,15 +69,35 @@ impl Drk { Ok((height, hash.clone(), rollback_query.clone())) } + /// Get a scanned block information record. + pub fn get_scanned_block_record(&self, height: u32) -> WalletDbResult<(u32, String, String)> { + let row = self.wallet.query_single( + WALLET_SCANNED_BLOCKS_TABLE, + &[], + convert_named_params! {(WALLET_SCANNED_BLOCKS_COL_HEIGH, height)}, + )?; + + self.parse_scanned_block_record(&row) + } + + /// Fetch all scanned block information record. + pub fn get_scanned_block_records(&self) -> WalletDbResult> { + let rows = self.wallet.query_multiple(WALLET_SCANNED_BLOCKS_TABLE, &[], &[])?; + + let mut ret = Vec::with_capacity(rows.len()); + for row in rows { + ret.push(self.parse_scanned_block_record(&row)?); + } + + Ok(ret) + } + /// Get the last scanned block height and hash from the wallet. /// If database is empty default (0, '-') is returned. pub fn get_last_scanned_block(&self) -> WalletDbResult<(u32, String)> { let query = format!( - "SELECT {}, {} FROM {} ORDER BY {} DESC LIMIT 1;", - WALLET_SCANNED_BLOCKS_COL_HEIGH, - WALLET_SCANNED_BLOCKS_COL_HASH, - WALLET_SCANNED_BLOCKS_TABLE, - WALLET_SCANNED_BLOCKS_COL_HEIGH, + "SELECT * FROM {} ORDER BY {} DESC LIMIT 1;", + WALLET_SCANNED_BLOCKS_TABLE, WALLET_SCANNED_BLOCKS_COL_HEIGH, ); let ret = self.wallet.query_custom(&query, &[])?; @@ -91,18 +105,9 @@ impl Drk { return Ok((0, String::from("-"))) } - let Value::Integer(height) = ret[0][0] else { - return Err(WalletDbError::ParseColumnValueError); - }; - let Ok(height) = u32::try_from(height) else { - return Err(WalletDbError::ParseColumnValueError); - }; + let (height, hash, _) = self.parse_scanned_block_record(&ret[0])?; - let Value::Text(ref hash) = ret[0][1] else { - return Err(WalletDbError::ParseColumnValueError); - }; - - Ok((height, hash.clone())) + Ok((height, hash)) } /// Reset the scanned blocks information records in the wallet.