From 48d305c406a46d4d7ff1f023d8239c1cc2683662 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 6 Sep 2019 14:09:12 -0700 Subject: [PATCH] Automatically load and save wallet --- rust-lightclient/src/commands.rs | 37 +++++++++++++++++++++-------- rust-lightclient/src/lightclient.rs | 7 ++++++ rust-lightclient/src/lightwallet.rs | 29 ++++++++++------------ rust-lightclient/src/main.rs | 16 ++++++++++--- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/rust-lightclient/src/commands.rs b/rust-lightclient/src/commands.rs index e809e65..8979990 100644 --- a/rust-lightclient/src/commands.rs +++ b/rust-lightclient/src/commands.rs @@ -7,7 +7,7 @@ pub trait Command { fn short_help(&self) -> String; - fn exec(&self, args: &[String], lightclient: &mut LightClient); + fn exec(&self, _args: &[String], lightclient: &mut LightClient); } struct SyncCommand {} @@ -21,7 +21,7 @@ impl Command for SyncCommand { "Download CompactBlocks and sync to the server".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_sync(); } } @@ -37,7 +37,7 @@ impl Command for HelpCommand { "Lists all available commands".to_string() } - fn exec(&self, args: &[String], _: &mut LightClient) { + fn exec(&self, _args: &[String], _: &mut LightClient) { // Print a list of all commands get_commands().iter().for_each(| (cmd, obj) | { println!("{} - {}", cmd, obj.short_help()); @@ -55,7 +55,7 @@ impl Command for InfoCommand { "Get the lightwalletd server's info".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_info(); } } @@ -70,7 +70,7 @@ impl Command for AddressCommand { "List all current addresses".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_address(); } } @@ -85,7 +85,7 @@ impl Command for SendCommand { "Send ZEC to the given address".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_send( "ztestsapling1x65nq4dgp0qfywgxcwk9n0fvm4fysmapgr2q00p85ju252h6l7mmxu2jg9cqqhtvzd69jwhgv8d".to_string(), 1500000, @@ -103,7 +103,7 @@ impl Command for SaveCommand { "Save wallet file to disk".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_save(); } } @@ -118,11 +118,27 @@ impl Command for ReadCommand { "Read wallet file from disk".to_string() } - fn exec(&self, args: &[String], lightclient: &mut LightClient) { + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { lightclient.do_read(); } } +struct QuitCommand {} +impl Command for QuitCommand { + fn help(&self) { + println!("Quit"); + } + + fn short_help(&self) -> String { + "Quit the lightwallet, saving state to disk".to_string() + } + + fn exec(&self, _args: &[String], lightclient: &mut LightClient) { + lightclient.do_save(); + } +} + + pub fn get_commands() -> Box>> { let mut map: HashMap> = HashMap::new(); @@ -133,12 +149,13 @@ pub fn get_commands() -> Box>> { map.insert("send".to_string(), Box::new(SendCommand{})); map.insert("save".to_string(), Box::new(SaveCommand{})); map.insert("read".to_string(), Box::new(ReadCommand{})); + map.insert("quit".to_string(), Box::new(QuitCommand{})); Box::new(map) } -pub fn do_user_command(cmd: String, lightclient: &mut LightClient) { - match get_commands().get(&cmd) { +pub fn do_user_command(cmd: &String, lightclient: &mut LightClient) { + match get_commands().get(cmd) { Some(cmd) => cmd.exec(&[], lightclient), None => { println!("Unknown command : {}. Type 'help' for a list of commands", cmd); diff --git a/rust-lightclient/src/lightclient.rs b/rust-lightclient/src/lightclient.rs index faa2e3a..c5e61e4 100644 --- a/rust-lightclient/src/lightclient.rs +++ b/rust-lightclient/src/lightclient.rs @@ -1,6 +1,7 @@ use crate::lightwallet::LightWallet; use std::fs::File; +use std::io; use std::io::prelude::*; use std::sync::Arc; @@ -62,16 +63,22 @@ impl LightClient { } pub fn do_read(&mut self) { + print!("Reading wallet..."); + io::stdout().flush().ok().expect("Could not flush stdout"); let mut file_buffer = File::open("wallet.dat").unwrap(); let lw = LightWallet::read(&mut file_buffer).unwrap(); self.wallet = Arc::new(lw); + println!("[OK]"); } pub fn do_save(&self) { + print!("Saving wallet..."); + io::stdout().flush().ok().expect("Could not flush stdout"); let mut file_buffer = File::create("wallet.dat").unwrap(); self.wallet.write(&mut file_buffer).unwrap(); + println!("[OK]"); } diff --git a/rust-lightclient/src/lightwallet.rs b/rust-lightclient/src/lightwallet.rs index e5b6162..2f9811c 100644 --- a/rust-lightclient/src/lightwallet.rs +++ b/rust-lightclient/src/lightwallet.rs @@ -1,22 +1,22 @@ pub extern crate ff; use std::time::SystemTime; - use std::io::{self, Read, Write}; - - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use pairing::bls12_381::{Bls12}; -use zcash_primitives::primitives::{Diversifier, Note, PaymentAddress, /*read_note */ }; use std::cmp; use std::collections::HashMap; use std::sync::{Arc, RwLock}; + use protobuf::*; + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use pairing::bls12_381::{Bls12}; +use ff::{PrimeField, PrimeFieldRepr}; + use zcash_client_backend::{ constants::testnet::HRP_SAPLING_PAYMENT_ADDRESS, encoding::encode_payment_address, proto::compact_formats::CompactBlock, welding_rig::scan_block, }; -use ff::{PrimeField, PrimeFieldRepr}; + use zcash_primitives::{ block::BlockHash, merkle_tree::{CommitmentTree, IncrementalWitness}, @@ -30,21 +30,16 @@ use zcash_primitives::{ note_encryption::{Memo, try_sapling_note_decryption}, zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}, JUBJUB, -}; -use zcash_primitives::jubjub::{ - JubjubEngine, - fs::{Fs, FsRepr}, + primitives::{Diversifier, Note, PaymentAddress}, + jubjub::{ + JubjubEngine, + fs::{Fs, FsRepr}, + } }; use crate::address; use crate::prover; -// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global -// allocator. -#[cfg(feature = "wee_alloc")] -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; - const ANCHOR_OFFSET: u32 = 10; const SAPLING_ACTIVATION_HEIGHT: i32 = 280_000; diff --git a/rust-lightclient/src/main.rs b/rust-lightclient/src/main.rs index d541cf8..a68e0a5 100644 --- a/rust-lightclient/src/main.rs +++ b/rust-lightclient/src/main.rs @@ -16,7 +16,10 @@ pub mod grpc_client { pub fn main() { - let mut light_client = LightClient::new(); + let mut lightclient = LightClient::new(); + + // At startup, read the wallet.dat + commands::do_user_command(&"read".to_string(), &mut lightclient); // `()` can be used when no completer is required let mut rl = Editor::<()>::new(); @@ -24,18 +27,25 @@ pub fn main() { println!("No previous history."); } loop { - let readline = rl.readline(&format!("Block:{} (h for help) >> ", light_client.last_scanned_height())); + let readline = rl.readline(&format!("Block:{} (h for help) >> ", lightclient.last_scanned_height())); match readline { Ok(line) => { rl.add_history_entry(line.as_str()); - commands::do_user_command(line, &mut light_client); + commands::do_user_command(&line, &mut lightclient); + + // Special check for Quit command. + if line == "quit" { + break; + } }, Err(ReadlineError::Interrupted) => { println!("CTRL-C"); + lightclient.do_save(); break }, Err(ReadlineError::Eof) => { println!("CTRL-D"); + lightclient.do_save(); break }, Err(err) => {