Fix how the wallet network is handled

Now that the wallet network is stored in `keys.txt`, it is invalid to
pass around network parameters alongside the wallet directory. They
are now parsed at the place where the wallet directory is used (often at
the same time as parsing the rest of `keys.txt`), and then passed around
with other variables derived from it.

This also fixes a bug with the `init` command, where a new wallet could
not be created unless an existing wallet at that path existed (to parse
the network parameters from), but if that path existed then `init`
(correctly) refused to overwrite it. The network parameters for this
command are now correctly constructed from the config option.
This commit is contained in:
Jack Grigg 2023-11-18 00:37:19 +00:00
parent f54e31c7f5
commit 15dffd83eb
10 changed files with 65 additions and 77 deletions

View File

@ -3,20 +3,23 @@ use gumdrop::Options;
use zcash_client_backend::data_api::WalletRead;
use zcash_client_sqlite::WalletDb;
use zcash_primitives::{consensus::Parameters, zip32::AccountId};
use zcash_primitives::zip32::AccountId;
use crate::{data::get_db_paths, error, ui::format_zec, MIN_CONFIRMATIONS};
use crate::{
data::{get_db_paths, get_wallet_network},
error,
ui::format_zec,
MIN_CONFIRMATIONS,
};
// Options accepted for the `balance` command
#[derive(Debug, Options)]
pub(crate) struct Command {}
impl Command {
pub(crate) fn run(
self,
params: impl Parameters + Copy + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir);
let db_data = WalletDb::for_path(db_data, params)?;

View File

@ -10,7 +10,7 @@ use zcash_client_sqlite::{
chain::init::init_blockmeta_db, wallet::init::init_wallet_db, FsBlockDb, WalletDb,
};
use zcash_primitives::{
consensus::Parameters,
consensus::{self, Parameters},
zip32::AccountId,
zip339::{Count, Mnemonic},
};
@ -18,7 +18,7 @@ use zcash_primitives::{
use crate::{
data::{get_db_paths, init_wallet_keys, Network},
error,
remote::{connect_to_lightwalletd, Lightwalletd},
remote::connect_to_lightwalletd,
};
// Options accepted for the `init` command
@ -38,12 +38,9 @@ pub(crate) struct Command {
}
impl Command {
pub(crate) async fn run(
self,
params: impl Parameters + Lightwalletd + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let opts = self;
let params = consensus::Network::from(opts.network);
// Get the current chain height (for the wallet's birthday).
let mut client = connect_to_lightwalletd(&params).await?;

View File

@ -4,7 +4,6 @@ use gumdrop::Options;
use zcash_client_backend::data_api::{SaplingInputSource, WalletRead};
use zcash_client_sqlite::WalletDb;
use zcash_primitives::{
consensus::Parameters,
transaction::components::{
amount::{Amount, MAX_MONEY},
sapling::fees::InputView,
@ -12,18 +11,20 @@ use zcash_primitives::{
zip32::AccountId,
};
use crate::{data::get_db_paths, error, ui::format_zec};
use crate::{
data::{get_db_paths, get_wallet_network},
error,
ui::format_zec,
};
// Options accepted for the `balance` command
#[derive(Debug, Options)]
pub(crate) struct Command {}
impl Command {
pub(crate) fn run(
self,
params: impl Parameters + Copy + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir);
let db_data = WalletDb::for_path(db_data, params)?;

View File

@ -8,12 +8,14 @@ use zcash_client_backend::{
};
use zcash_client_sqlite::WalletDb;
use zcash_primitives::{
consensus::Parameters,
transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule},
zip32::AccountId,
};
use crate::{data::get_db_paths, error, MIN_CONFIRMATIONS};
use crate::{
data::{get_db_paths, get_wallet_network},
error, MIN_CONFIRMATIONS,
};
#[derive(Clone, Copy, Debug)]
pub(crate) enum FeeRule {
@ -66,11 +68,9 @@ pub(crate) struct Command {
}
impl Command {
pub(crate) async fn run(
self,
params: impl Parameters + Copy + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let mut db_data = WalletDb::for_path(db_data, params)?;

View File

@ -1,10 +1,8 @@
use gumdrop::Options;
use zcash_primitives::consensus::Parameters;
use crate::{
data::{erase_wallet_state, read_keys},
remote::{connect_to_lightwalletd, Lightwalletd},
remote::connect_to_lightwalletd,
};
// Options accepted for the `reset` command
@ -12,17 +10,14 @@ use crate::{
pub(crate) struct Command {}
impl Command {
pub(crate) async fn run(
self,
params: impl Parameters + Lightwalletd + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
// Load the wallet network, seed, and birthday from disk.
let keys = read_keys(wallet_dir.as_ref())?;
let params = keys.network();
// Connect to the client (for re-initializing the wallet).
let client = connect_to_lightwalletd(&params).await?;
// Load the wallet seed and birthday from disk.
let keys = read_keys(wallet_dir.as_ref())?;
// Erase the wallet state (excluding key material).
erase_wallet_state(wallet_dir.as_ref()).await;

View File

@ -14,16 +14,14 @@ use zcash_client_backend::{
zip321::{Payment, TransactionRequest},
};
use zcash_client_sqlite::WalletDb;
use zcash_primitives::{
consensus::Parameters, transaction::components::amount::NonNegativeAmount, zip32::AccountId,
};
use zcash_primitives::{transaction::components::amount::NonNegativeAmount, zip32::AccountId};
use zcash_proofs::prover::LocalTxProver;
use crate::{
commands::propose::{parse_fee_rule, FeeRule},
data::{get_db_paths, get_wallet_seed},
data::{get_db_paths, read_keys},
error,
remote::{connect_to_lightwalletd, Lightwalletd},
remote::connect_to_lightwalletd,
MIN_CONFIRMATIONS,
};
@ -45,17 +43,15 @@ pub(crate) struct Command {
}
impl Command {
pub(crate) async fn run(
self,
params: impl Parameters + Lightwalletd + Copy + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let keys = read_keys(wallet_dir.as_ref())?;
let params = keys.network();
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let (_, db_data) = get_db_paths(wallet_dir);
let mut db_data = WalletDb::for_path(db_data, params)?;
let seed = get_wallet_seed(wallet_dir)?;
let usk = UnifiedSpendingKey::from_seed(&params, seed.expose_secret(), account)
let usk = UnifiedSpendingKey::from_seed(&params, keys.seed().expose_secret(), account)
.map_err(error::Error::from)?;
let mut client = connect_to_lightwalletd(&params).await?;

View File

@ -24,9 +24,9 @@ use zcash_primitives::{
};
use crate::{
data::{get_block_path, get_db_paths},
data::{get_block_path, get_db_paths, get_wallet_network},
error,
remote::{connect_to_lightwalletd, Lightwalletd},
remote::connect_to_lightwalletd,
};
const BATCH_SIZE: u32 = 10_000;
@ -36,11 +36,9 @@ const BATCH_SIZE: u32 = 10_000;
pub(crate) struct Command {}
impl Command {
pub(crate) async fn run(
self,
params: impl Parameters + Lightwalletd + Copy + Send + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) async fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let params = get_wallet_network(wallet_dir.as_ref())?;
let (fsblockdb_root, db_data) = get_db_paths(wallet_dir.as_ref());
let fsblockdb_root = fsblockdb_root.as_path();
let mut db_cache = FsBlockDb::for_path(fsblockdb_root).map_err(error::Error::from)?;

View File

@ -5,10 +5,9 @@ use zcash_client_sqlite::{
wallet::init::{init_wallet_db, WalletMigrationError},
FsBlockDb, WalletDb,
};
use zcash_primitives::consensus::Parameters;
use crate::{
data::{get_db_paths, get_wallet_seed},
data::{get_db_paths, get_wallet_network, get_wallet_seed},
error,
};
@ -17,11 +16,9 @@ use crate::{
pub(crate) struct Command {}
impl Command {
pub(crate) fn run(
self,
params: impl Parameters + 'static,
wallet_dir: Option<String>,
) -> Result<(), anyhow::Error> {
pub(crate) fn run(self, wallet_dir: Option<String>) -> Result<(), anyhow::Error> {
let params = get_wallet_network(wallet_dir.as_ref())?;
let (fsblockdb_root, db_data) = get_db_paths(wallet_dir.as_ref());
let mut db_cache = FsBlockDb::for_path(fsblockdb_root).map_err(error::Error::from)?;
let mut db_data = WalletDb::for_path(db_data, params)?;

View File

@ -105,6 +105,10 @@ pub(crate) struct WalletKeys {
}
impl WalletKeys {
pub(crate) fn network(&self) -> consensus::Network {
self.network
}
pub(crate) fn seed(&self) -> &SecretVec<u8> {
&self.seed
}

View File

@ -7,7 +7,6 @@ use std::env;
use std::num::NonZeroU32;
use std::sync::atomic::{AtomicUsize, Ordering};
use data::get_wallet_network;
use gumdrop::Options;
mod commands;
@ -80,19 +79,17 @@ fn main() -> Result<(), anyhow::Error> {
})
.build()?;
let params = get_wallet_network(opts.wallet_dir.as_ref())?;
runtime.block_on(async {
match opts.command {
Some(Command::Init(command)) => command.run(params, opts.wallet_dir).await,
Some(Command::Reset(command)) => command.run(params, opts.wallet_dir).await,
Some(Command::Upgrade(command)) => command.run(params, opts.wallet_dir),
Some(Command::Sync(command)) => command.run(params, opts.wallet_dir).await,
Some(Command::Balance(command)) => command.run(params, opts.wallet_dir),
Some(Command::Init(command)) => command.run(opts.wallet_dir).await,
Some(Command::Reset(command)) => command.run(opts.wallet_dir).await,
Some(Command::Upgrade(command)) => command.run(opts.wallet_dir),
Some(Command::Sync(command)) => command.run(opts.wallet_dir).await,
Some(Command::Balance(command)) => command.run(opts.wallet_dir),
Some(Command::ListTx(command)) => command.run(opts.wallet_dir),
Some(Command::ListUnspent(command)) => command.run(params, opts.wallet_dir),
Some(Command::Propose(command)) => command.run(params, opts.wallet_dir).await,
Some(Command::Send(command)) => command.run(params, opts.wallet_dir).await,
Some(Command::ListUnspent(command)) => command.run(opts.wallet_dir),
Some(Command::Propose(command)) => command.run(opts.wallet_dir).await,
Some(Command::Send(command)) => command.run(opts.wallet_dir).await,
_ => Ok(()),
}
})