Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency updates #54

Merged
merged 2 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
493 changes: 253 additions & 240 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anyhow = "1"
bip0039 = { version = "0.12", features = ["std", "all-languages"] }
futures-util = "0.3"
gumdrop = "0.8"
hex = "0.4"
prost = "0.13"
rayon = "1.7"
rusqlite = { version = "0.32", features = ["time"] }
Expand All @@ -23,6 +24,7 @@ toml = "0.8"
tonic = { version = "0.12", features = ["gzip", "tls-webpki-roots"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
uuid = "1"

orchard = { version = "0.10", default-features = false }
sapling = { package = "sapling-crypto", version = "0.3" }
Expand All @@ -33,6 +35,7 @@ zcash_keys = { version = "0.5", features = ["unstable", "orchard"] }
zcash_primitives = "0.20"
zcash_proofs = "0.20"
zcash_protocol = "0.4"
zip32 = "0.1"
zip321 = "0.2"

# Seed encryption
Expand Down Expand Up @@ -61,3 +64,13 @@ tui = [
"dep:tokio-util",
"dep:tui-logger",
]

[patch.crates-io]
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_keys = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
zip321 = { git = "https://github.com/zcash/librustzcash.git", rev = "e0f04e6c7749751e7f590b2c25275f1fa3421d50" }
8 changes: 4 additions & 4 deletions src/commands/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ impl Command {
}
println!(" Balance: {}", printer.format(balance.total()));
println!(
" Sapling Spendable: {}",
" Sapling Spendable: {}",
printer.format(balance.sapling_balance().spendable_value()),
);
println!(
" Orchard Spendable: {}",
" Orchard Spendable: {}",
printer.format(balance.orchard_balance().spendable_value()),
);
#[cfg(feature = "transparent-inputs")]
println!(
" Unshielded: {}",
printer.format(balance.unshielded()),
" Unshielded Spendable: {}",
printer.format(balance.unshielded_balance().spendable_value()),
);
} else {
println!("Insufficient information to build a wallet summary.");
Expand Down
42 changes: 30 additions & 12 deletions src/commands/import_ufvk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ use gumdrop::Options;

use zcash_address::unified::{self, Encoding};
use zcash_client_backend::{
data_api::{AccountBirthday, AccountPurpose, WalletWrite},
data_api::{AccountBirthday, AccountPurpose, WalletWrite, Zip32Derivation},
proto::service,
};
use zcash_client_sqlite::WalletDb;
use zcash_keys::keys::UnifiedFullViewingKey;
use zcash_primitives::consensus;
use zip32::fingerprint::SeedFingerprint;

use crate::{
data::get_db_paths,
Expand All @@ -19,14 +20,23 @@ use crate::{
// Options accepted for the `import-ufvk` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(help = "a name for the account")]
name: String,

#[options(free, required, help = "The Unified Full Viewing Key to import")]
ufvk: String,

#[options(free, required, help = "the UFVK's birthday")]
birthday: u32,

#[options(help = "can the wallet omit information needed to spend funds (default is false)")]
view_only: bool,
#[options(
help = "hex encoding of the ZIP 32 fingerprint for the seed from which the UFVK was derived",
parse(try_from_str = "hex::decode")
)]
seed_fingerprint: Option<Vec<u8>>,

#[options(help = "ZIP 32 account index corresponding to the UFVK")]
hd_account_index: Option<u32>,

#[options(
help = "the server to initialize with (default is \"ecc\")",
Expand Down Expand Up @@ -84,16 +94,24 @@ impl Command {
.map_err(error::Error::from)?
};

let purpose = match (self.seed_fingerprint, self.hd_account_index) {
(Some(seed_fingerprint), Some(hd_account_index)) => Ok(AccountPurpose::Spending {
derivation: Some(Zip32Derivation::new(
SeedFingerprint::from_bytes(
seed_fingerprint
.as_slice()
.try_into()
.map_err(|_| anyhow!("Incorrect seed_fingerprint length"))?,
),
zip32::AccountId::try_from(hd_account_index)?,
)),
}),
(None, None) => Ok(AccountPurpose::ViewOnly),
_ => Err(anyhow!("Need either both (for spending) or neither (for view-only) of seed_fingerprint and hd_account_index")),
}?;

// Import the UFVK.
db_data.import_account_ufvk(
&ufvk,
&birthday,
if self.view_only {
AccountPurpose::ViewOnly
} else {
AccountPurpose::Spending
},
)?;
db_data.import_account_ufvk(&self.name, &ufvk, &birthday, purpose, None)?;

Ok(())
}
Expand Down
18 changes: 9 additions & 9 deletions src/commands/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use crate::{
// Options accepted for the `init` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(help = "a name for the account")]
name: String,

#[options(help = "age identity file to encrypt the mnemonic phrase to")]
identity: String,

Expand All @@ -29,9 +32,6 @@ pub(crate) struct Command {
#[options(help = "the wallet's birthday (default is current chain height)")]
birthday: Option<u32>,

#[options(help = "the number of accounts to initialise the wallet with (default is 1)")]
accounts: Option<usize>,

#[options(
help = "the network the wallet will be used with: \"test\" or \"main\" (default is \"test\")",
parse(try_from_str = "Network::parse")
Expand Down Expand Up @@ -110,9 +110,10 @@ impl Command {
Self::init_dbs(
params,
wallet_dir.as_ref(),
&opts.name,
&seed,
birthday,
opts.accounts.unwrap_or(1),
None,
)
}

Expand All @@ -137,17 +138,16 @@ impl Command {
pub(crate) fn init_dbs(
params: impl Parameters + 'static,
wallet_dir: Option<&String>,
account_name: &str,
seed: &SecretVec<u8>,
birthday: AccountBirthday,
accounts: usize,
key_source: Option<&str>,
) -> Result<(), anyhow::Error> {
// Initialise the block and wallet DBs.
let mut db_data = init_dbs(params, wallet_dir)?;

// Add accounts.
for _ in 0..accounts {
db_data.create_account(seed, &birthday)?;
}
// Add account.
db_data.create_account(account_name, seed, &birthday, key_source)?;

Ok(())
}
Expand Down
65 changes: 31 additions & 34 deletions src/commands/init_fvk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,26 @@ use gumdrop::Options;

use zcash_address::unified::{Encoding, Ufvk};
use zcash_client_backend::{
data_api::{AccountPurpose, WalletWrite},
data_api::{AccountPurpose, WalletWrite, Zip32Derivation},
proto::service,
};
use zcash_keys::{encoding::decode_extfvk_with_network, keys::UnifiedFullViewingKey};
use zcash_primitives::consensus::NetworkType;
use zcash_protocol::consensus;
use zip32::fingerprint::SeedFingerprint;

use crate::{
config::WalletConfig,
data::init_dbs,
remote::{tor_client, Servers},
};

#[derive(Clone, Copy, Debug, Default)]
pub(crate) enum Purpose {
#[default]
Viewing,
Spending,
}

impl Purpose {
pub(crate) fn parse(name: &str) -> Result<Purpose, String> {
match name {
"viewing" => Ok(Purpose::Viewing),
"spending" => Ok(Purpose::Spending),
other => Err(format!("Unsupported purpose: {}", other)),
}
}
}

impl From<Purpose> for AccountPurpose {
fn from(value: Purpose) -> Self {
match value {
Purpose::Viewing => AccountPurpose::ViewOnly,
Purpose::Spending => AccountPurpose::Spending,
}
}
}

// Options accepted for the `init` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(help = "a name for the account")]
name: String,

#[options(
help = "serialized full viewing key (Unified or Sapling) to initialize the wallet with"
)]
Expand All @@ -53,19 +31,22 @@ pub(crate) struct Command {
#[options(help = "the wallet's birthday (default is current chain height)")]
birthday: Option<u32>,

#[options(
help = "hex encoding of the ZIP 32 fingerprint for the seed from which the UFVK was derived",
parse(try_from_str = "hex::decode")
)]
seed_fingerprint: Option<Vec<u8>>,

#[options(help = "ZIP 32 account index corresponding to the UFVK")]
hd_account_index: Option<u32>,

#[options(
help = "the server to initialize with (default is \"ecc\")",
default = "ecc",
parse(try_from_str = "Servers::parse")
)]
server: Servers,

#[options(
help = "the purpose of the viewing key (default is \"viewing\")",
parse(try_from_str = "Purpose::parse")
)]
purpose: Purpose,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the spending purpose holds a key derivation, I've changed the FVK import pathways to be view-only. We need to do that init refactor to provide a better way to prepare accounts.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's fine for init_fvk, because init will subsume this command, but import_ufvk should be able to import a AccountPurpose::Spending key; after all, the "standard" workflow for Zashi is to initialize with a seed, but then import the UFVK from the hardware wallet with derivation & key source information.

Along those lines, I think that we should specify ZIP 316 metadata for seed fingerprint and hd account index data.


#[options(help = "disable connections via TOR")]
disable_tor: bool,
}
Expand Down Expand Up @@ -123,11 +104,27 @@ impl Command {
)
.await?;

let purpose = match (opts.seed_fingerprint, opts.hd_account_index) {
(Some(seed_fingerprint), Some(hd_account_index)) => Ok(AccountPurpose::Spending {
derivation: Some(Zip32Derivation::new(
SeedFingerprint::from_bytes(
seed_fingerprint
.as_slice()
.try_into()
.map_err(|_| anyhow!("Incorrect seed_fingerprint length"))?,
),
zip32::AccountId::try_from(hd_account_index)?,
)),
}),
(None, None) => Ok(AccountPurpose::ViewOnly),
_ => Err(anyhow!("Need either both (for spending) or neither (for view-only) of seed_fingerprint and hd_account_index")),
}?;

// Save the wallet config to disk.
WalletConfig::init_without_mnemonic(wallet_dir.as_ref(), birthday.height(), network)?;

let mut wallet_db = init_dbs(network, wallet_dir.as_ref())?;
wallet_db.import_account_ufvk(&ufvk, &birthday, opts.purpose.into())?;
wallet_db.import_account_ufvk(&opts.name, &ufvk, &birthday, purpose, None)?;

Ok(())
}
Expand Down
7 changes: 5 additions & 2 deletions src/commands/list_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ impl Command {
let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let db_data = WalletDb::for_path(db_data, params)?;

for (i, account_id) in db_data.get_account_ids()?.iter().enumerate() {
for account_id in db_data.get_account_ids()?.iter() {
let account = db_data.get_account(*account_id)?.unwrap();

println!("Account {}", i);
println!("Account {}", account_id.expose_uuid());
if let Some(name) = account.name() {
println!(" Name: {name}");
}
println!(" UIVK: {}", account.uivk().encode(&params));
println!(
" UFVK: {}",
Expand Down
9 changes: 5 additions & 4 deletions src/commands/list_addresses.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use anyhow::anyhow;
use gumdrop::Options;

use uuid::Uuid;
use zcash_client_backend::data_api::{Account, WalletRead};
use zcash_client_sqlite::{AccountId, WalletDb};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_keys::keys::UnifiedAddressRequest;

use crate::{config::get_wallet_network, data::get_db_paths};

// Options accepted for the `list-accounts` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(free, required, help = "the ID of the account to list addresses for")]
account_id: u32,
#[options(free, required, help = "the UUID of the account to list addresses for")]
account_id: Uuid,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm considering changing this to an account flag that can be either an AccountUuid or a name, but the latter I don't think has any uniqueness constraints (and can also be null).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the name is really needed for zec_sqlite_cli and starting next week we should shift our focus to zallet as much as possible anyway.

}

impl Command {
Expand All @@ -21,7 +22,7 @@ impl Command {
let db_data = WalletDb::for_path(db_data, params)?;

let account = db_data
.get_account(AccountId::from_u32(self.account_id))?
.get_account(AccountUuid::from_uuid(self.account_id))?
.ok_or_else(|| anyhow!("No account exists for account id {}", self.account_id))?;

println!("Account {}", self.account_id);
Expand Down
Loading
Loading