mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-02-01 03:12:15 +00:00
Need birthday while restoring seed
This commit is contained in:
parent
adba18e13b
commit
11bc928f8d
@ -61,6 +61,11 @@ pub fn main() {
|
|||||||
.value_name("seed_phrase")
|
.value_name("seed_phrase")
|
||||||
.help("Create a new wallet with the given 24-word seed phrase. Will fail if wallet already exists")
|
.help("Create a new wallet with the given 24-word seed phrase. Will fail if wallet already exists")
|
||||||
.takes_value(true))
|
.takes_value(true))
|
||||||
|
.arg(Arg::with_name("birthday")
|
||||||
|
.long("birthday")
|
||||||
|
.value_name("birthday")
|
||||||
|
.help("Specify wallet birthday when restoring from seed. This is the earlist block height where the wallet has a transaction.")
|
||||||
|
.takes_value(true))
|
||||||
.arg(Arg::with_name("server")
|
.arg(Arg::with_name("server")
|
||||||
.long("server")
|
.long("server")
|
||||||
.value_name("server")
|
.value_name("server")
|
||||||
@ -112,8 +117,25 @@ pub fn main() {
|
|||||||
let command = matches.value_of("COMMAND");
|
let command = matches.value_of("COMMAND");
|
||||||
let params = matches.values_of("PARAMS").map(|v| v.collect()).or(Some(vec![])).unwrap();
|
let params = matches.values_of("PARAMS").map(|v| v.collect()).or(Some(vec![])).unwrap();
|
||||||
|
|
||||||
let maybe_server = matches.value_of("server").map(|s| s.to_string());
|
let maybe_server = matches.value_of("server").map(|s| s.to_string());
|
||||||
let seed = matches.value_of("seed").map(|s| s.to_string());
|
|
||||||
|
let seed = matches.value_of("seed").map(|s| s.to_string());
|
||||||
|
let maybe_birthday = matches.value_of("birthday");
|
||||||
|
|
||||||
|
if seed.is_some() && maybe_birthday.is_none() {
|
||||||
|
eprintln!("ERROR!");
|
||||||
|
eprintln!("Please specify the wallet birthday (eg. '--birthday 600000') to restore from seed.");
|
||||||
|
eprintln!("This should be the block height where the wallet was created. If you don't remember the block height, you can pass '--birthday 0' to scan from the start of the blockchain.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let birthday = match maybe_birthday.unwrap_or("0").parse::<u64>() {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Couldn't parse birthday. This should be a block number. Error={}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let server = LightClientConfig::get_server_or_default(maybe_server);
|
let server = LightClientConfig::get_server_or_default(maybe_server);
|
||||||
|
|
||||||
@ -125,7 +147,7 @@ pub fn main() {
|
|||||||
|
|
||||||
let dangerous = matches.is_present("dangerous");
|
let dangerous = matches.is_present("dangerous");
|
||||||
let nosync = matches.is_present("nosync");
|
let nosync = matches.is_present("nosync");
|
||||||
let (command_tx, resp_rx) = match startup(server, dangerous, seed, !nosync, command.is_none()) {
|
let (command_tx, resp_rx) = match startup(server, dangerous, seed, birthday, !nosync, command.is_none()) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error during startup: {}", e);
|
eprintln!("Error during startup: {}", e);
|
||||||
@ -163,7 +185,7 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, first_sync: bool, print_updates: bool)
|
fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, birthday: u64, first_sync: bool, print_updates: bool)
|
||||||
-> io::Result<(Sender<(String, Vec<String>)>, Receiver<String>)> {
|
-> io::Result<(Sender<(String, Vec<String>)>, Receiver<String>)> {
|
||||||
// Try to get the configuration
|
// Try to get the configuration
|
||||||
let (config, latest_block_height) = LightClientConfig::create(server.clone(), dangerous)?;
|
let (config, latest_block_height) = LightClientConfig::create(server.clone(), dangerous)?;
|
||||||
@ -175,7 +197,7 @@ fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, first_sync:
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let lightclient = match seed {
|
let lightclient = match seed {
|
||||||
Some(phrase) => Arc::new(LightClient::new_from_phrase(phrase, &config, latest_block_height)?),
|
Some(phrase) => Arc::new(LightClient::new_from_phrase(phrase, &config, birthday)?),
|
||||||
None => {
|
None => {
|
||||||
if config.wallet_exists() {
|
if config.wallet_exists() {
|
||||||
Arc::new(LightClient::read_from_disk(&config)?)
|
Arc::new(LightClient::read_from_disk(&config)?)
|
||||||
@ -195,9 +217,6 @@ fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, first_sync:
|
|||||||
println!("Lightclient connecting to {}", config.server);
|
println!("Lightclient connecting to {}", config.server);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the command loop
|
|
||||||
let (command_tx, resp_rx) = command_loop(lightclient.clone());
|
|
||||||
|
|
||||||
// At startup, run a sync.
|
// At startup, run a sync.
|
||||||
if first_sync {
|
if first_sync {
|
||||||
let update = lightclient.do_sync(true);
|
let update = lightclient.do_sync(true);
|
||||||
@ -206,6 +225,9 @@ fn startup(server: http::Uri, dangerous: bool, seed: Option<String>, first_sync:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the command loop
|
||||||
|
let (command_tx, resp_rx) = command_loop(lightclient.clone());
|
||||||
|
|
||||||
Ok((command_tx, resp_rx))
|
Ok((command_tx, resp_rx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::lightwallet::LightWallet;
|
|||||||
use log::{info, warn, error};
|
use log::{info, warn, error};
|
||||||
use rand::{rngs::OsRng, seq::SliceRandom};
|
use rand::{rngs::OsRng, seq::SliceRandom};
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock, Mutex};
|
||||||
use std::sync::atomic::{AtomicU64, AtomicI32, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicU64, AtomicI32, AtomicUsize, Ordering};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -201,6 +201,8 @@ pub struct LightClient {
|
|||||||
// zcash-params
|
// zcash-params
|
||||||
pub sapling_output : Vec<u8>,
|
pub sapling_output : Vec<u8>,
|
||||||
pub sapling_spend : Vec<u8>,
|
pub sapling_spend : Vec<u8>,
|
||||||
|
|
||||||
|
sync_lock : Mutex<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightClient {
|
impl LightClient {
|
||||||
@ -231,7 +233,8 @@ impl LightClient {
|
|||||||
wallet : Arc::new(RwLock::new(LightWallet::new(Some(seed_phrase), &config, 0)?)),
|
wallet : Arc::new(RwLock::new(LightWallet::new(Some(seed_phrase), &config, 0)?)),
|
||||||
config : config.clone(),
|
config : config.clone(),
|
||||||
sapling_output : vec![],
|
sapling_output : vec![],
|
||||||
sapling_spend : vec![]
|
sapling_spend : vec![],
|
||||||
|
sync_lock : Mutex::new(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
l.set_wallet_initial_state(0);
|
l.set_wallet_initial_state(0);
|
||||||
@ -255,7 +258,8 @@ impl LightClient {
|
|||||||
wallet : Arc::new(RwLock::new(LightWallet::new(None, config, latest_block)?)),
|
wallet : Arc::new(RwLock::new(LightWallet::new(None, config, latest_block)?)),
|
||||||
config : config.clone(),
|
config : config.clone(),
|
||||||
sapling_output : vec![],
|
sapling_output : vec![],
|
||||||
sapling_spend : vec![]
|
sapling_spend : vec![],
|
||||||
|
sync_lock : Mutex::new(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
l.set_wallet_initial_state(latest_block);
|
l.set_wallet_initial_state(latest_block);
|
||||||
@ -267,20 +271,22 @@ impl LightClient {
|
|||||||
Ok(l)
|
Ok(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_phrase(seed_phrase: String, config: &LightClientConfig, latest_block: u64) -> io::Result<Self> {
|
pub fn new_from_phrase(seed_phrase: String, config: &LightClientConfig, birthday: u64) -> io::Result<Self> {
|
||||||
if config.wallet_exists() {
|
if config.wallet_exists() {
|
||||||
return Err(Error::new(ErrorKind::AlreadyExists,
|
return Err(Error::new(ErrorKind::AlreadyExists,
|
||||||
"Cannot create a new wallet from seed, because a wallet already exists"));
|
"Cannot create a new wallet from seed, because a wallet already exists"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut l = LightClient {
|
let mut l = LightClient {
|
||||||
wallet : Arc::new(RwLock::new(LightWallet::new(Some(seed_phrase), config, latest_block)?)),
|
wallet : Arc::new(RwLock::new(LightWallet::new(Some(seed_phrase), config, birthday)?)),
|
||||||
config : config.clone(),
|
config : config.clone(),
|
||||||
sapling_output : vec![],
|
sapling_output : vec![],
|
||||||
sapling_spend : vec![]
|
sapling_spend : vec![],
|
||||||
|
sync_lock : Mutex::new(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
l.set_wallet_initial_state(latest_block);
|
println!("Setting birthday to {}", birthday);
|
||||||
|
l.set_wallet_initial_state(birthday);
|
||||||
l.read_sapling_params();
|
l.read_sapling_params();
|
||||||
|
|
||||||
info!("Created new wallet!");
|
info!("Created new wallet!");
|
||||||
@ -302,7 +308,8 @@ impl LightClient {
|
|||||||
wallet : Arc::new(RwLock::new(wallet)),
|
wallet : Arc::new(RwLock::new(wallet)),
|
||||||
config : config.clone(),
|
config : config.clone(),
|
||||||
sapling_output : vec![],
|
sapling_output : vec![],
|
||||||
sapling_spend : vec![]
|
sapling_spend : vec![],
|
||||||
|
sync_lock : Mutex::new(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
lc.read_sapling_params();
|
lc.read_sapling_params();
|
||||||
@ -729,6 +736,10 @@ impl LightClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_sync(&self, print_updates: bool) -> String {
|
pub fn do_sync(&self, print_updates: bool) -> String {
|
||||||
|
// We can only do one sync at a time because we sync blocks in serial order
|
||||||
|
// If we allow multiple syncs, they'll all get jumbled up.
|
||||||
|
let _lock = self.sync_lock.lock().unwrap();
|
||||||
|
|
||||||
// Sync is 3 parts
|
// Sync is 3 parts
|
||||||
// 1. Get the latest block
|
// 1. Get the latest block
|
||||||
// 2. Get all the blocks that we don't have
|
// 2. Get all the blocks that we don't have
|
||||||
|
@ -358,8 +358,8 @@ impl LightWallet {
|
|||||||
})?;
|
})?;
|
||||||
utils::write_string(&mut writer, &self.config.chain_name)?;
|
utils::write_string(&mut writer, &self.config.chain_name)?;
|
||||||
|
|
||||||
// While writing the birthday, be sure that we're right, and that we don't
|
// While writing the birthday, get it from the fn so we recalculate it properly
|
||||||
// have a tx that is before the current birthday
|
// in case of rescans etc...
|
||||||
writer.write_u64::<LittleEndian>(self.get_birthday())?;
|
writer.write_u64::<LittleEndian>(self.get_birthday())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -373,7 +373,11 @@ impl LightWallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_birthday(&self) -> u64 {
|
pub fn get_birthday(&self) -> u64 {
|
||||||
cmp::min(self.get_first_tx_block(), self.birthday)
|
if self.birthday == 0 {
|
||||||
|
self.get_first_tx_block()
|
||||||
|
} else {
|
||||||
|
cmp::min(self.get_first_tx_block(), self.birthday)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the first block that this wallet has a tx in. This is often used as the wallet's "birthday"
|
// Get the first block that this wallet has a tx in. This is often used as the wallet's "birthday"
|
||||||
@ -386,7 +390,7 @@ impl LightWallet {
|
|||||||
.collect::<Vec<u64>>();
|
.collect::<Vec<u64>>();
|
||||||
blocks.sort();
|
blocks.sort();
|
||||||
|
|
||||||
*blocks.first() // Returns optional
|
*blocks.first() // Returns optional, so if there's no txns, it'll get the activation height
|
||||||
.unwrap_or(&cmp::max(self.birthday, self.config.sapling_activation_height))
|
.unwrap_or(&cmp::max(self.birthday, self.config.sapling_activation_height))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user