From edf0794dc49d8d704656b4085181c360409b5607 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 16 Sep 2019 21:13:54 -0700 Subject: [PATCH] Add logging --- Cargo.toml | 1 + src/lightclient.rs | 70 +++++++++++++++++++++++++++++++++------------- src/main.rs | 32 ++++++++++++++++++--- 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 220c092..60ecca8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ futures = "0.1" bytes = "0.4" base58 = "0.1.0" log = "0.4" +log4rs = { version = "0.8.3", default-features = false, features = ["file", "file_appender"]} dirs = "2.0.2" http = "0.1" prost = "0.5" diff --git a/src/lightclient.rs b/src/lightclient.rs index fab0c8f..9f1a903 100644 --- a/src/lightclient.rs +++ b/src/lightclient.rs @@ -1,5 +1,7 @@ use crate::lightwallet::LightWallet; +use log::info; + use std::path::Path; use std::fs::File; use std::io; @@ -32,7 +34,8 @@ use crate::grpc_client::client::CompactTxStreamer; type Client = crate::grpc_client::client::CompactTxStreamer, tower_grpc::BoxBody>>; pub const DEFAULT_SERVER: &str = "http://127.0.0.1:9067"; -pub const WALLET_NAME: &str = "zeclite.wallet.dat"; +pub const WALLET_NAME: &str = "zeclite.wallet.dat"; +pub const LOGFILE_NAME: &str = "zeclite.debug.log"; pub struct LightClient { pub wallet : Arc, @@ -53,37 +56,49 @@ impl LightClient { } pub fn get_params_path(name: &str) -> Box { - let mut params_location; + let mut params_location; - if cfg!(target_os="macos") || cfg!(target_os="windows") { - params_location = dirs::data_dir() - .expect("Couldn't determine app data directory!"); - params_location.push("ZcashParams"); - } else { - params_location = dirs::home_dir() - .expect("Couldn't determine home directory!"); - params_location.push(".zcash-params"); - }; + if cfg!(target_os="macos") || cfg!(target_os="windows") { + params_location = dirs::data_dir() + .expect("Couldn't determine app data directory!"); + params_location.push("ZcashParams"); + } else { + params_location = dirs::home_dir() + .expect("Couldn't determine home directory!"); + params_location.push(".zcash-params"); + }; params_location.push(name); params_location.into_boxed_path() } - pub fn get_wallet_path() -> Box { - let mut wallet_location; + pub fn get_zcash_data_path() -> Box { + let mut zcash_data_location; if cfg!(target_os="macos") || cfg!(target_os="windows") { - wallet_location = dirs::data_dir().expect("Couldn't determine app data directory!"); - wallet_location.push("Zcash/testnet3"); + zcash_data_location = dirs::data_dir().expect("Couldn't determine app data directory!"); + zcash_data_location.push("Zcash/testnet3"); } else { - wallet_location = dirs::home_dir().expect("Couldn't determine home directory!"); - wallet_location.push(".zcash/testnet3"); + zcash_data_location = dirs::home_dir().expect("Couldn't determine home directory!"); + zcash_data_location.push(".zcash/testnet3"); }; + zcash_data_location.into_boxed_path() + } + + pub fn get_wallet_path() -> Box { + let mut wallet_location = LightClient::get_zcash_data_path().into_path_buf(); wallet_location.push(WALLET_NAME); wallet_location.into_boxed_path() } + pub fn get_log_path() -> Box { + let mut log_path = LightClient::get_zcash_data_path().into_path_buf(); + log_path.push(LOGFILE_NAME); + + log_path.into_boxed_path() + } + pub fn new(seed_phrase: Option, server: Option) -> io::Result { let server = match server { Some(s) => if s.starts_with("http://") {s} else { "http://".to_string() + &s} @@ -118,6 +133,7 @@ impl LightClient { l }; + // Read Sapling Params let mut f = match File::open(LightClient::get_params_path("sapling-output.params")) { @@ -134,6 +150,7 @@ impl LightClient { }; f.read_to_end(&mut lc.sapling_spend)?; + info!("Created LightClient to {}", &server); println!("Lightclient connecting to {}", server); Ok(lc) @@ -182,6 +199,8 @@ impl LightClient { File::create(LightClient::get_wallet_path()).unwrap()); self.wallet.write(&mut file_buffer).unwrap(); + info!("Saved wallet"); + format!("Saved Wallet") } @@ -403,14 +422,18 @@ impl LightClient { } pub fn do_rescan(&self) -> String { + info!("Rescan starting"); // First, clear the state from the wallet self.wallet.clear_blocks(); // Then set the inital block self.set_wallet_initial_state(); - + // Then, do a sync, which will force a full rescan from the initial state - self.do_sync() + let response = self.do_sync(); + info!("Rescan finished"); + + response } pub fn do_sync(&self) -> String { @@ -429,6 +452,8 @@ impl LightClient { }); let last_block = latest_block_height.load(Ordering::SeqCst); + info!("Latest block is {}", last_block); + // Get the end height to scan to. let mut end_height = std::cmp::min(last_scanned_height + 1000, last_block); @@ -446,6 +471,7 @@ impl LightClient { } // Fetch compact blocks + info!("Fetching blocks {}-{}", last_scanned_height, end_height); self.fetch_blocks(last_scanned_height, end_height, move |encoded_block: &[u8]| { local_light_wallet.scan_block(encoded_block); @@ -477,8 +503,9 @@ impl LightClient { println!(); // Print a new line, to finalize the syncing updates let mut responses = vec![]; - responses.push(format!("Synced to {}, Downloaded {} kB", last_block, bytes_downloaded.load(Ordering::SeqCst) / 1024)); + info!("Synced to {}, Downloaded {} kB", last_block, bytes_downloaded.load(Ordering::SeqCst) / 1024); + responses.push(format!("Synced to {}, Downloaded {} kB", last_block, bytes_downloaded.load(Ordering::SeqCst) / 1024)); // Get the Raw transaction for all the wallet transactions @@ -509,11 +536,13 @@ impl LightClient { .map( | (txid, _, h) | (txid.clone(), *h) ) // We're only interested in the txids, so drop the Memo, which is None anyway .collect::>(); // and convert into Vec } + info!("Fetching {} new txids", txids_to_fetch.len()); // And go and fetch the txids, getting the full transaction, so we can // read the memos for (txid, height) in txids_to_fetch { let light_wallet_clone = self.wallet.clone(); + info!("Fetching full Tx: {}", txid); responses.push(format!("Fetching full Tx: {}", txid)); self.fetch_full_tx(txid, move |tx_bytes: &[u8] | { @@ -541,6 +570,7 @@ impl LightClient { } pub fn do_send(&self, addr: &str, value: u64, memo: Option) -> String { + info!("Creating transaction"); let rawtx = self.wallet.send_to_address( u32::from_str_radix("2bb40e60", 16).unwrap(), // Blossom ID &self.sapling_spend, &self.sapling_output, diff --git a/src/main.rs b/src/main.rs index f782a72..bca3b8b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,21 +6,41 @@ mod commands; use std::sync::Arc; use std::time::Duration; + use lightclient::LightClient; +use log::{info, LevelFilter}; +use log4rs::append::file::FileAppender; +use log4rs::encode::pattern::PatternEncoder; +use log4rs::config::{Appender, Config, Root}; + use rustyline::error::ReadlineError; use rustyline::Editor; +use clap::{Arg, App}; + pub mod grpc_client { include!(concat!(env!("OUT_DIR"), "/cash.z.wallet.sdk.rpc.rs")); } - - pub fn main() { - use clap::{Arg, App}; + // Configure logging first. + let logfile = FileAppender::builder() + .encoder(Box::new(PatternEncoder::new("{l} - {m}\n"))) + .build(LightClient::get_log_path()).unwrap(); - let matches = App::new("Light Client") + let config = Config::builder() + .appender(Appender::builder().build("logfile", Box::new(logfile))) + .build(Root::builder() + .appender("logfile") + .build(LevelFilter::Info)).unwrap(); + + log4rs::init_config(config).unwrap(); + + info!("Starting ZecLite CLI"); + + // Get command line arguments + let matches = App::new("ZecLite CLI") .version("1.0") .arg(Arg::with_name("seed") .short("s") @@ -46,6 +66,9 @@ pub fn main() { Err(e) => { eprintln!("Failed to start wallet. Error was:\n{}", e); return; } }; + // After getting the lightclient, ask server for info + info!("{}", lightclient.do_info()); + // At startup, run a sync let sync_update = lightclient.do_sync(); println!("{}", sync_update); @@ -63,6 +86,7 @@ pub fn main() { resp_tx.send(cmd_response).unwrap(); if cmd == "quit" { + info!("Quit"); break; } },