Update to librustzcash c45d3aed8a

This commit is contained in:
Kris Nuttycombe 2024-03-22 16:54:40 -06:00
parent 159ec41a71
commit 14d6fe18de
10 changed files with 344 additions and 101 deletions

173
Cargo.lock generated
View File

@ -520,6 +520,15 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "document-features"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95"
dependencies = [
"litrs",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
@ -529,7 +538,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]] [[package]]
name = "equihash" name = "equihash"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
"byteorder", "byteorder",
@ -554,7 +563,7 @@ dependencies = [
[[package]] [[package]]
name = "f4jumble" name = "f4jumble"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"blake2b_simd", "blake2b_simd",
] ]
@ -934,8 +943,7 @@ dependencies = [
[[package]] [[package]]
name = "incrementalmerkletree" name = "incrementalmerkletree"
version = "0.5.0" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zcash/incrementalmerkletree?rev=e1a7a80212c22e5a8912d05860f7eb6899c56a7c#e1a7a80212c22e5a8912d05860f7eb6899c56a7c"
checksum = "361c467824d4d9d4f284be4b2608800839419dccc4d4608f28345237fe354623"
dependencies = [ dependencies = [
"either", "either",
] ]
@ -1045,6 +1053,12 @@ version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.20" version = "0.4.20"
@ -1227,9 +1241,8 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "orchard" name = "orchard"
version = "0.6.0" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zcash/orchard?rev=33474bdbfd7268e1f84718078d47f63d01a879d5#33474bdbfd7268e1f84718078d47f63d01a879d5"
checksum = "5d31e68534df32024dcc89a8390ec6d7bef65edd87d91b45cfb481a2eb2d77c5"
dependencies = [ dependencies = [
"aes", "aes",
"bitvec", "bitvec",
@ -1251,6 +1264,8 @@ dependencies = [
"subtle", "subtle",
"tracing", "tracing",
"zcash_note_encryption", "zcash_note_encryption",
"zcash_spec",
"zip32",
] ]
[[package]] [[package]]
@ -1709,6 +1724,37 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "sapling-crypto"
version = "0.1.2"
source = "git+https://github.com/zcash/sapling-crypto?rev=22412ae07644813253feb064d1692b0823242853#22412ae07644813253feb064d1692b0823242853"
dependencies = [
"aes",
"bellman",
"bitvec",
"blake2b_simd",
"blake2s_simd",
"bls12_381",
"byteorder",
"document-features",
"ff",
"fpe",
"group",
"hex",
"incrementalmerkletree",
"jubjub",
"lazy_static",
"memuse",
"rand",
"rand_core",
"redjubjub",
"subtle",
"tracing",
"zcash_note_encryption",
"zcash_spec",
"zip32",
]
[[package]] [[package]]
name = "schemer" name = "schemer"
version = "0.2.1" version = "0.2.1"
@ -1841,8 +1887,7 @@ dependencies = [
[[package]] [[package]]
name = "shardtree" name = "shardtree"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/zcash/incrementalmerkletree?rev=e1a7a80212c22e5a8912d05860f7eb6899c56a7c#e1a7a80212c22e5a8912d05860f7eb6899c56a7c"
checksum = "dbf20c7a2747d9083092e3a3eeb9a7ed75577ae364896bebbc5e0bdcd4e97735"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"either", "either",
@ -2608,19 +2653,20 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
[[package]] [[package]]
name = "zcash_address" name = "zcash_address"
version = "0.3.0" version = "0.3.2"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"bech32", "bech32",
"bs58", "bs58",
"f4jumble", "f4jumble",
"zcash_encoding", "zcash_encoding",
"zcash_protocol",
] ]
[[package]] [[package]]
name = "zcash_client_backend" name = "zcash_client_backend"
version = "0.10.0" version = "0.11.1"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"base64", "base64",
"bech32", "bech32",
@ -2628,6 +2674,7 @@ dependencies = [
"bs58", "bs58",
"byteorder", "byteorder",
"crossbeam-channel", "crossbeam-channel",
"document-features",
"group", "group",
"hex", "hex",
"incrementalmerkletree", "incrementalmerkletree",
@ -2637,7 +2684,9 @@ dependencies = [
"orchard", "orchard",
"percent-encoding", "percent-encoding",
"prost", "prost",
"rand_core",
"rayon", "rayon",
"sapling-crypto",
"secrecy", "secrecy",
"shardtree", "shardtree",
"subtle", "subtle",
@ -2648,44 +2697,83 @@ dependencies = [
"which", "which",
"zcash_address", "zcash_address",
"zcash_encoding", "zcash_encoding",
"zcash_keys",
"zcash_note_encryption", "zcash_note_encryption",
"zcash_primitives", "zcash_primitives",
"zcash_protocol",
"zip32",
] ]
[[package]] [[package]]
name = "zcash_client_sqlite" name = "zcash_client_sqlite"
version = "0.8.1" version = "0.9.1"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"bs58", "bs58",
"byteorder", "byteorder",
"document-features",
"group", "group",
"incrementalmerkletree", "incrementalmerkletree",
"jubjub", "jubjub",
"maybe-rayon", "maybe-rayon",
"nonempty",
"orchard",
"prost", "prost",
"rusqlite", "rusqlite",
"sapling-crypto",
"schemer", "schemer",
"schemer-rusqlite", "schemer-rusqlite",
"secrecy", "secrecy",
"shardtree", "shardtree",
"subtle",
"time 0.3.30", "time 0.3.30",
"tracing", "tracing",
"uuid", "uuid",
"zcash_address",
"zcash_client_backend", "zcash_client_backend",
"zcash_encoding", "zcash_encoding",
"zcash_keys",
"zcash_primitives", "zcash_primitives",
"zcash_protocol",
"zip32",
] ]
[[package]] [[package]]
name = "zcash_encoding" name = "zcash_encoding"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"nonempty", "nonempty",
] ]
[[package]]
name = "zcash_keys"
version = "0.1.1"
source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [
"bech32",
"blake2b_simd",
"bls12_381",
"bs58",
"byteorder",
"document-features",
"group",
"memuse",
"nonempty",
"orchard",
"rand_core",
"sapling-crypto",
"secrecy",
"subtle",
"tracing",
"zcash_address",
"zcash_encoding",
"zcash_primitives",
"zcash_protocol",
"zip32",
]
[[package]] [[package]]
name = "zcash_note_encryption" name = "zcash_note_encryption"
version = "0.4.0" version = "0.4.0"
@ -2701,17 +2789,14 @@ dependencies = [
[[package]] [[package]]
name = "zcash_primitives" name = "zcash_primitives"
version = "0.13.0" version = "0.14.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"aes", "aes",
"bellman",
"bip0039", "bip0039",
"bitvec",
"blake2b_simd", "blake2b_simd",
"blake2s_simd",
"bls12_381",
"byteorder", "byteorder",
"document-features",
"equihash", "equihash",
"ff", "ff",
"fpe", "fpe",
@ -2719,29 +2804,33 @@ dependencies = [
"hex", "hex",
"incrementalmerkletree", "incrementalmerkletree",
"jubjub", "jubjub",
"lazy_static",
"memuse", "memuse",
"nonempty", "nonempty",
"orchard", "orchard",
"rand", "rand",
"rand_core", "rand_core",
"redjubjub", "redjubjub",
"sapling-crypto",
"sha2", "sha2",
"subtle", "subtle",
"tracing", "tracing",
"zcash_address", "zcash_address",
"zcash_encoding", "zcash_encoding",
"zcash_note_encryption", "zcash_note_encryption",
"zcash_protocol",
"zcash_spec",
"zip32",
] ]
[[package]] [[package]]
name = "zcash_proofs" name = "zcash_proofs"
version = "0.13.0" version = "0.14.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=236cd569ee4a824d98920d1a61b8cc2b90ceba1d#236cd569ee4a824d98920d1a61b8cc2b90ceba1d" source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [ dependencies = [
"bellman", "bellman",
"blake2b_simd", "blake2b_simd",
"bls12_381", "bls12_381",
"document-features",
"group", "group",
"home", "home",
"jubjub", "jubjub",
@ -2749,11 +2838,30 @@ dependencies = [
"lazy_static", "lazy_static",
"rand_core", "rand_core",
"redjubjub", "redjubjub",
"sapling-crypto",
"tracing", "tracing",
"xdg", "xdg",
"zcash_primitives", "zcash_primitives",
] ]
[[package]]
name = "zcash_protocol"
version = "0.1.0"
source = "git+https://github.com/zcash/librustzcash.git?rev=c45d3aed8ae2ac5ab41878df864eb4889793ac1b#c45d3aed8ae2ac5ab41878df864eb4889793ac1b"
dependencies = [
"document-features",
"memuse",
]
[[package]]
name = "zcash_spec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7a3bf58b673cb3dacd8ae09ba345998923a197ab0da70d6239d8e8838949e9b"
dependencies = [
"blake2b_simd",
]
[[package]] [[package]]
name = "zec-sqlite-cli" name = "zec-sqlite-cli"
version = "0.1.0" version = "0.1.0"
@ -2761,9 +2869,11 @@ dependencies = [
"anyhow", "anyhow",
"futures-util", "futures-util",
"gumdrop", "gumdrop",
"orchard",
"prost", "prost",
"rayon", "rayon",
"rusqlite", "rusqlite",
"sapling-crypto",
"schemer", "schemer",
"secrecy", "secrecy",
"time 0.2.27", "time 0.2.27",
@ -2773,8 +2883,10 @@ dependencies = [
"tracing-subscriber", "tracing-subscriber",
"zcash_client_backend", "zcash_client_backend",
"zcash_client_sqlite", "zcash_client_sqlite",
"zcash_keys",
"zcash_primitives", "zcash_primitives",
"zcash_proofs", "zcash_proofs",
"zcash_protocol",
] ]
[[package]] [[package]]
@ -2816,3 +2928,14 @@ dependencies = [
"quote", "quote",
"syn 2.0.38", "syn 2.0.38",
] ]
[[package]]
name = "zip32"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e"
dependencies = [
"blake2b_simd",
"memuse",
"subtle",
]

View File

@ -13,6 +13,8 @@ gumdrop = "0.8"
prost = "0.12" prost = "0.12"
rayon = "1.7" rayon = "1.7"
rusqlite = { version = "0.29", features = ["time"] } rusqlite = { version = "0.29", features = ["time"] }
orchard = { version = "0.7.1", default-features = false }
sapling = { package = "sapling-crypto", version = "0.1.2" }
schemer = "0.2" schemer = "0.2"
secrecy = "0.8" secrecy = "0.8"
time = "0.2" time = "0.2"
@ -20,13 +22,21 @@ tokio = { version = "1.21.0", features = ["fs", "macros", "rt-multi-thread"] }
tonic = { version = "0.10", features = ["gzip", "tls-webpki-roots"] } tonic = { version = "0.10", features = ["gzip", "tls-webpki-roots"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
zcash_client_backend = { version = "0.10", features = ["lightwalletd-tonic"] } zcash_client_backend = { version = "0.11", features = ["lightwalletd-tonic", "orchard"] }
zcash_client_sqlite = { version = "0.8", features = ["unstable"] } zcash_client_sqlite = { version = "0.9", features = ["unstable", "orchard"] }
zcash_primitives = "0.13" zcash_keys = { version = "0.1", features = ["unstable", "orchard"] }
zcash_proofs = "0.13" zcash_primitives = "0.14"
zcash_proofs = "0.14"
zcash_protocol = "0.1"
[patch.crates-io] [patch.crates-io]
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" } zcash_keys = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" } zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" } zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "236cd569ee4a824d98920d1a61b8cc2b90ceba1d" } zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "c45d3aed8ae2ac5ab41878df864eb4889793ac1b" }
orchard = { git = "https://github.com/zcash/orchard", rev = "33474bdbfd7268e1f84718078d47f63d01a879d5" }
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "e1a7a80212c22e5a8912d05860f7eb6899c56a7c" }
sapling = { git = "https://github.com/zcash/sapling-crypto", package = "sapling-crypto", rev = "22412ae07644813253feb064d1692b0823242853" }
shardtree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "e1a7a80212c22e5a8912d05860f7eb6899c56a7c" }

View File

@ -3,7 +3,6 @@ use gumdrop::Options;
use zcash_client_backend::data_api::WalletRead; use zcash_client_backend::data_api::WalletRead;
use zcash_client_sqlite::WalletDb; use zcash_client_sqlite::WalletDb;
use zcash_primitives::zip32::AccountId;
use crate::{ use crate::{
data::{get_db_paths, get_wallet_network}, data::{get_db_paths, get_wallet_network},
@ -20,18 +19,21 @@ impl Command {
pub(crate) fn run(self, 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 params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir); let (_, db_data) = get_db_paths(wallet_dir);
let db_data = WalletDb::for_path(db_data, params)?; let db_data = WalletDb::for_path(db_data, params)?;
let account_id = *db_data
.get_account_ids()?
.first()
.ok_or(anyhow!("Wallet has no accounts"))?;
let address = db_data let address = db_data
.get_current_address(account)? .get_current_address(account_id)?
.ok_or(error::Error::InvalidRecipient)?; .ok_or(error::Error::InvalidRecipient)?;
if let Some(wallet_summary) = db_data.get_wallet_summary(MIN_CONFIRMATIONS.into())? { if let Some(wallet_summary) = db_data.get_wallet_summary(MIN_CONFIRMATIONS.into())? {
let balance = wallet_summary let balance = wallet_summary
.account_balances() .account_balances()
.get(&account) .get(&account_id)
.ok_or_else(|| anyhow!("Missing account 0"))?; .ok_or_else(|| anyhow!("Missing account 0"))?;
println!("{:#?}", wallet_summary); println!("{:#?}", wallet_summary);
@ -45,8 +47,12 @@ impl Command {
} }
println!(" Balance: {}", format_zec(balance.total())); println!(" Balance: {}", format_zec(balance.total()));
println!( println!(
" Spendable: {}", " Sapling Spendable: {}",
format_zec(balance.sapling_balance.spendable_value) format_zec(balance.sapling_balance().spendable_value())
);
println!(
" Orchard Spendable: {}",
format_zec(balance.orchard_balance().spendable_value())
); );
} else { } else {
println!("Insufficient information to build a wallet summary."); println!("Insufficient information to build a wallet summary.");

View File

@ -11,7 +11,6 @@ use zcash_client_sqlite::{
}; };
use zcash_primitives::{ use zcash_primitives::{
consensus::{self, Parameters}, consensus::{self, Parameters},
zip32::AccountId,
zip339::{Count, Mnemonic}, zip339::{Count, Mnemonic},
}; };
@ -102,8 +101,7 @@ impl Command {
}; };
// Add one account. // Add one account.
let (account, _) = db_data.create_account(seed, birthday)?; db_data.create_account(seed, &birthday)?;
assert_eq!(account, AccountId::from(0));
Ok(()) Ok(())
} }

View File

@ -112,9 +112,9 @@ impl WalletTx {
txid: TxId::from_bytes(txid.try_into().map_err(|_| anyhow!("Invalid TxId"))?), txid: TxId::from_bytes(txid.try_into().map_err(|_| anyhow!("Invalid TxId"))?),
expiry_height: expiry_height.map(BlockHeight::from_u32), expiry_height: expiry_height.map(BlockHeight::from_u32),
account_balance_delta: Amount::from_i64(account_balance_delta) account_balance_delta: Amount::from_i64(account_balance_delta)
.map_err(|()| anyhow!("Amount out of range"))?, .map_err(|_| anyhow!("Amount out of range"))?,
fee_paid: fee_paid fee_paid: fee_paid
.map(|v| NonNegativeAmount::from_u64(v).map_err(|()| anyhow!("Fee out of range"))) .map(|v| NonNegativeAmount::from_u64(v).map_err(|_| anyhow!("Fee out of range")))
.transpose()?, .transpose()?,
sent_note_count, sent_note_count,
received_note_count, received_note_count,

View File

@ -1,15 +1,12 @@
use anyhow::anyhow; use anyhow::anyhow;
use gumdrop::Options; use gumdrop::Options;
use zcash_client_backend::data_api::{SaplingInputSource, WalletRead}; use zcash_client_backend::{
use zcash_client_sqlite::WalletDb; data_api::{InputSource, WalletRead},
use zcash_primitives::{ ShieldedProtocol,
transaction::components::{
amount::{Amount, MAX_MONEY},
sapling::fees::InputView,
},
zip32::AccountId,
}; };
use zcash_client_sqlite::WalletDb;
use zcash_protocol::value::{Zatoshis, MAX_MONEY};
use crate::{ use crate::{
data::{get_db_paths, get_wallet_network}, data::{get_db_paths, get_wallet_network},
@ -25,9 +22,12 @@ impl Command {
pub(crate) fn run(self, 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 params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir); let (_, db_data) = get_db_paths(wallet_dir);
let db_data = WalletDb::for_path(db_data, params)?; let db_data = WalletDb::for_path(db_data, params)?;
let account = *db_data
.get_account_ids()?
.first()
.ok_or(anyhow!("Wallet has no accounts"))?;
// Use the height of the maximum scanned block as the anchor height, to emulate a // Use the height of the maximum scanned block as the anchor height, to emulate a
// zero-conf transaction in order to select every note in the wallet. // zero-conf transaction in order to select every note in the wallet.
@ -37,15 +37,28 @@ impl Command {
.map_err(|e| anyhow!("{:?}", e))? .map_err(|e| anyhow!("{:?}", e))?
.block_height(); .block_height();
let notes = db_data.select_spendable_sapling_notes( let notes = db_data.select_spendable_notes(
account, account,
Amount::const_from_i64(MAX_MONEY), Zatoshis::const_from_u64(MAX_MONEY),
&[ShieldedProtocol::Sapling, ShieldedProtocol::Orchard],
anchor_height, anchor_height,
&[], &[],
)?; )?;
for note in notes { for note in notes.sapling() {
println!("{}: {}", note.note_id(), format_zec(note.value())); println!(
"Sapling {}: {}",
note.internal_note_id(),
format_zec(note.note_value()?)
);
}
for note in notes.orchard() {
println!(
"Orchard {}: {}",
note.internal_note_id(),
format_zec(note.note_value()?)
);
} }
Ok(()) Ok(())

View File

@ -1,16 +1,18 @@
use anyhow::anyhow;
use gumdrop::Options; use gumdrop::Options;
use zcash_client_backend::{ use zcash_client_backend::{
address::RecipientAddress, data_api::{
data_api::wallet::{input_selection::GreedyInputSelector, propose_transfer}, wallet::{input_selection::GreedyInputSelector, propose_transfer},
WalletRead,
},
fees::standard::SingleOutputChangeStrategy, fees::standard::SingleOutputChangeStrategy,
zip321::{Payment, TransactionRequest}, zip321::{Payment, TransactionRequest},
ShieldedProtocol,
}; };
use zcash_client_sqlite::WalletDb; use zcash_client_sqlite::WalletDb;
use zcash_primitives::{ use zcash_keys::address::Address;
transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule}, use zcash_primitives::transaction::{components::amount::NonNegativeAmount, fees::StandardFeeRule};
zip32::AccountId,
};
use crate::{ use crate::{
data::{get_db_paths, get_wallet_network}, data::{get_db_paths, get_wallet_network},
@ -71,17 +73,20 @@ impl Command {
pub(crate) async fn run(self, 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 params = get_wallet_network(wallet_dir.as_ref())?;
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir.as_ref()); let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let mut db_data = WalletDb::for_path(db_data, params)?; let mut db_data = WalletDb::for_path(db_data, params)?;
let account = *db_data
.get_account_ids()?
.first()
.ok_or_else(|| anyhow!("Wallet has no accounts."))?;
let input_selector = GreedyInputSelector::new( let input_selector = GreedyInputSelector::new(
SingleOutputChangeStrategy::new(self.fee_rule.into(), None), SingleOutputChangeStrategy::new(self.fee_rule.into(), None, ShieldedProtocol::Orchard),
Default::default(), Default::default(),
); );
let request = TransactionRequest::new(vec![Payment { let request = TransactionRequest::new(vec![Payment {
recipient_address: RecipientAddress::decode(&params, &self.address) recipient_address: Address::decode(&params, &self.address)
.ok_or(error::Error::InvalidRecipient)?, .ok_or(error::Error::InvalidRecipient)?,
amount: NonNegativeAmount::from_u64(self.value) amount: NonNegativeAmount::from_u64(self.value)
.map_err(|_| error::Error::InvalidAmount)?, .map_err(|_| error::Error::InvalidAmount)?,

View File

@ -1,21 +1,24 @@
#![allow(deprecated)]
use anyhow::anyhow;
use gumdrop::Options; use gumdrop::Options;
use secrecy::ExposeSecret; use secrecy::ExposeSecret;
use zcash_client_backend::{ use zcash_client_backend::{
address::RecipientAddress,
data_api::{ data_api::{
wallet::{input_selection::GreedyInputSelector, spend}, wallet::{input_selection::GreedyInputSelector, spend},
WalletRead, Account, AccountSource, WalletRead,
}, },
fees::standard::SingleOutputChangeStrategy, fees::standard::SingleOutputChangeStrategy,
keys::UnifiedSpendingKey, keys::UnifiedSpendingKey,
proto::service, proto::service,
wallet::OvkPolicy, wallet::OvkPolicy,
zip321::{Payment, TransactionRequest}, zip321::{Payment, TransactionRequest},
ShieldedProtocol,
}; };
use zcash_client_sqlite::WalletDb; use zcash_client_sqlite::WalletDb;
use zcash_primitives::{transaction::components::amount::NonNegativeAmount, zip32::AccountId}; use zcash_keys::address::Address;
use zcash_proofs::prover::LocalTxProver; use zcash_proofs::prover::LocalTxProver;
use zcash_protocol::value::Zatoshis;
use crate::{ use crate::{
commands::propose::{parse_fee_rule, FeeRule}, commands::propose::{parse_fee_rule, FeeRule},
@ -28,7 +31,10 @@ use crate::{
// Options accepted for the `send` command // Options accepted for the `send` command
#[derive(Debug, Options)] #[derive(Debug, Options)]
pub(crate) struct Command { pub(crate) struct Command {
#[options(required, help = "the recipient's Sapling or transparent address")] #[options(
required,
help = "the recipient's Unified, Sapling or transparent address"
)]
address: String, address: String,
#[options(required, help = "the amount in zatoshis")] #[options(required, help = "the amount in zatoshis")]
@ -47,11 +53,22 @@ impl Command {
let keys = read_keys(wallet_dir.as_ref())?; let keys = read_keys(wallet_dir.as_ref())?;
let params = keys.network(); let params = keys.network();
let account = AccountId::from(0);
let (_, db_data) = get_db_paths(wallet_dir); let (_, db_data) = get_db_paths(wallet_dir);
let mut db_data = WalletDb::for_path(db_data, params)?; let mut db_data = WalletDb::for_path(db_data, params)?;
let account_id = *db_data
.get_account_ids()?
.first()
.ok_or(anyhow!("Wallet has no accounts"))?;
let account = db_data
.get_account(account_id)?
.ok_or(anyhow!("Account missing: {:?}", account_id))?;
let account_index = match account.source() {
AccountSource::Derived { account_index, .. } => account_index,
AccountSource::Imported => unreachable!("Imported accounts are not yet supported."),
};
let usk = UnifiedSpendingKey::from_seed(&params, keys.seed().expose_secret(), account) let usk =
UnifiedSpendingKey::from_seed(&params, keys.seed().expose_secret(), account_index)
.map_err(error::Error::from)?; .map_err(error::Error::from)?;
let mut client = connect_to_lightwalletd(&params).await?; let mut client = connect_to_lightwalletd(&params).await?;
@ -61,15 +78,14 @@ impl Command {
let prover = let prover =
LocalTxProver::with_default_location().ok_or(error::Error::MissingParameters)?; LocalTxProver::with_default_location().ok_or(error::Error::MissingParameters)?;
let input_selector = GreedyInputSelector::new( let input_selector = GreedyInputSelector::new(
SingleOutputChangeStrategy::new(self.fee_rule.into(), None), SingleOutputChangeStrategy::new(self.fee_rule.into(), None, ShieldedProtocol::Orchard),
Default::default(), Default::default(),
); );
let request = TransactionRequest::new(vec![Payment { let request = TransactionRequest::new(vec![Payment {
recipient_address: RecipientAddress::decode(&params, &self.address) recipient_address: Address::decode(&params, &self.address)
.ok_or(error::Error::InvalidRecipient)?, .ok_or(error::Error::InvalidRecipient)?,
amount: NonNegativeAmount::from_u64(self.value) amount: Zatoshis::from_u64(self.value).map_err(|_| error::Error::InvalidAmount)?,
.map_err(|_| error::Error::InvalidAmount)?,
memo: None, memo: None,
label: None, label: None,
message: None, message: None,
@ -77,7 +93,7 @@ impl Command {
}]) }])
.map_err(error::Error::from)?; .map_err(error::Error::from)?;
let id_tx = spend( let txids = spend(
&mut db_data, &mut db_data,
&params, &params,
&prover, &prover,
@ -90,13 +106,24 @@ impl Command {
) )
.map_err(error::Error::from)?; .map_err(error::Error::from)?;
if txids.len() > 1 {
return Err(anyhow!(
"Multi-transaction proposals are not yet supported."
));
}
let txid = *txids.first();
// Send the transaction. // Send the transaction.
println!("Sending transaction..."); println!("Sending transaction...");
let (txid, raw_tx) = db_data.get_transaction(id_tx).map(|tx| { let (txid, raw_tx) = db_data
.get_transaction(txid)?
.map(|tx| {
let mut raw_tx = service::RawTransaction::default(); let mut raw_tx = service::RawTransaction::default();
tx.write(&mut raw_tx.data).unwrap(); tx.write(&mut raw_tx.data).unwrap();
(tx.txid(), raw_tx) (tx.txid(), raw_tx)
})?; })
.ok_or(anyhow!("Transaction not found for id {:?}", txid))?;
let response = client.send_transaction(raw_tx).await?.into_inner(); let response = client.send_transaction(raw_tx).await?.into_inner();
if response.error_code != 0 { if response.error_code != 0 {

View File

@ -3,6 +3,7 @@ use std::path::Path;
use anyhow::anyhow; use anyhow::anyhow;
use futures_util::TryStreamExt; use futures_util::TryStreamExt;
use gumdrop::Options; use gumdrop::Options;
use orchard::tree::MerkleHashOrchard;
use prost::Message; use prost::Message;
use tokio::{fs::File, io::AsyncWriteExt, task::JoinHandle}; use tokio::{fs::File, io::AsyncWriteExt, task::JoinHandle};
@ -10,18 +11,18 @@ use tonic::transport::Channel;
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use zcash_client_backend::{ use zcash_client_backend::{
data_api::{ data_api::{
chain::{error::Error as ChainError, scan_cached_blocks, BlockSource, CommitmentTreeRoot}, chain::{
error::Error as ChainError, scan_cached_blocks, BlockSource, ChainState,
CommitmentTreeRoot,
},
scanning::{ScanPriority, ScanRange}, scanning::{ScanPriority, ScanRange},
WalletCommitmentTrees, WalletRead, WalletWrite, WalletCommitmentTrees, WalletRead, WalletWrite,
}, },
proto::service::{self, compact_tx_streamer_client::CompactTxStreamerClient}, proto::service::{self, compact_tx_streamer_client::CompactTxStreamerClient, BlockId},
}; };
use zcash_client_sqlite::{chain::BlockMeta, FsBlockDb, FsBlockDbError, WalletDb}; use zcash_client_sqlite::{chain::BlockMeta, FsBlockDb, FsBlockDbError, WalletDb};
use zcash_primitives::{ use zcash_primitives::merkle_tree::HashSer;
consensus::{BlockHeight, Parameters}, use zcash_protocol::consensus::{BlockHeight, Parameters};
merkle_tree::HashSer,
sapling,
};
use crate::{ use crate::{
data::{get_block_path, get_db_paths, get_wallet_network}, data::{get_block_path, get_db_paths, get_wallet_network},
@ -79,11 +80,21 @@ impl Command {
let block_meta = let block_meta =
download_blocks(client, fsblockdb_root, db_cache, scan_range).await?; download_blocks(client, fsblockdb_root, db_cache, scan_range).await?;
let chain_state =
download_chain_state(client, scan_range.block_range().start - 1)
.await?;
// Scan the downloaded blocks and check for scanning errors that // Scan the downloaded blocks and check for scanning errors that
// indicate the wallet's chain tip is out of sync with blockchain // indicate the wallet's chain tip is out of sync with blockchain
// history. // history.
let scan_ranges_updated = let scan_ranges_updated = scan_blocks(
scan_blocks(params, fsblockdb_root, db_cache, db_data, scan_range)?; params,
fsblockdb_root,
db_cache,
db_data,
&chain_state,
scan_range,
)?;
// Delete the now-scanned blocks, because keeping the entire chain // Delete the now-scanned blocks, because keeping the entire chain
// in CompactBlock files on disk is horrendous for the filesystem. // in CompactBlock files on disk is horrendous for the filesystem.
@ -134,9 +145,18 @@ impl Command {
let block_meta = let block_meta =
download_blocks(client, fsblockdb_root, db_cache, &scan_range).await?; download_blocks(client, fsblockdb_root, db_cache, &scan_range).await?;
let chain_state =
download_chain_state(client, scan_range.block_range().start - 1).await?;
// Scan the downloaded blocks. // Scan the downloaded blocks.
let scan_ranges_updated = let scan_ranges_updated = scan_blocks(
scan_blocks(params, fsblockdb_root, db_cache, db_data, &scan_range)?; params,
fsblockdb_root,
db_cache,
db_data,
&chain_state,
&scan_range,
)?;
// Delete the now-scanned blocks. // Delete the now-scanned blocks.
block_deletions.push(delete_cached_blocks(fsblockdb_root, block_meta)); block_deletions.push(delete_cached_blocks(fsblockdb_root, block_meta));
@ -181,8 +201,7 @@ async fn update_subtree_roots<P: Parameters>(
request.set_shielded_protocol(service::ShieldedProtocol::Sapling); request.set_shielded_protocol(service::ShieldedProtocol::Sapling);
// Hack to work around a bug in the initial lightwalletd implementation. // Hack to work around a bug in the initial lightwalletd implementation.
request.max_entries = 65536; request.max_entries = 65536;
let sapling_roots: Vec<CommitmentTreeRoot<sapling::Node>> = client
let roots: Vec<CommitmentTreeRoot<sapling::Node>> = client
.get_subtree_roots(request) .get_subtree_roots(request)
.await? .await?
.into_inner() .into_inner()
@ -196,8 +215,29 @@ async fn update_subtree_roots<P: Parameters>(
.try_collect() .try_collect()
.await?; .await?;
info!("Sapling tree has {} subtrees", roots.len()); info!("Sapling tree has {} subtrees", sapling_roots.len());
db_data.put_sapling_subtree_roots(0, &roots)?; db_data.put_sapling_subtree_roots(0, &sapling_roots)?;
let mut request = service::GetSubtreeRootsArg::default();
request.set_shielded_protocol(service::ShieldedProtocol::Orchard);
// Hack to work around a bug in the initial lightwalletd implementation.
request.max_entries = 65536;
let orchard_roots: Vec<CommitmentTreeRoot<MerkleHashOrchard>> = client
.get_subtree_roots(request)
.await?
.into_inner()
.and_then(|root| async move {
let root_hash = MerkleHashOrchard::read(&root.root_hash[..])?;
Ok(CommitmentTreeRoot::from_parts(
BlockHeight::from_u32(root.completing_block_height as u32),
root_hash,
))
})
.try_collect()
.await?;
info!("Orchard tree has {} subtrees", orchard_roots.len());
db_data.put_orchard_subtree_roots(0, &orchard_roots)?;
Ok(()) Ok(())
} }
@ -274,6 +314,20 @@ async fn download_blocks(
Ok(block_meta) Ok(block_meta)
} }
async fn download_chain_state(
client: &mut CompactTxStreamerClient<Channel>,
block_height: BlockHeight,
) -> Result<ChainState, anyhow::Error> {
let tree_state = client
.get_tree_state(BlockId {
height: block_height.into(),
hash: vec![],
})
.await?;
Ok(tree_state.into_inner().to_chain_state()?)
}
fn delete_cached_blocks(fsblockdb_root: &Path, block_meta: Vec<BlockMeta>) -> JoinHandle<()> { fn delete_cached_blocks(fsblockdb_root: &Path, block_meta: Vec<BlockMeta>) -> JoinHandle<()> {
let fsblockdb_root = fsblockdb_root.to_owned(); let fsblockdb_root = fsblockdb_root.to_owned();
tokio::spawn(async move { tokio::spawn(async move {
@ -294,6 +348,7 @@ fn scan_blocks<P: Parameters + Send + 'static>(
fsblockdb_root: &Path, fsblockdb_root: &Path,
db_cache: &mut FsBlockDb, db_cache: &mut FsBlockDb,
db_data: &mut WalletDb<rusqlite::Connection, P>, db_data: &mut WalletDb<rusqlite::Connection, P>,
initial_chain_state: &ChainState,
scan_range: &ScanRange, scan_range: &ScanRange,
) -> Result<bool, anyhow::Error> { ) -> Result<bool, anyhow::Error> {
info!("Scanning {}", scan_range); info!("Scanning {}", scan_range);
@ -302,6 +357,7 @@ fn scan_blocks<P: Parameters + Send + 'static>(
db_cache, db_cache,
db_data, db_data,
scan_range.block_range().start, scan_range.block_range().start,
initial_chain_state,
scan_range.len(), scan_range.len(),
); );

View File

@ -1,9 +1,14 @@
use zcash_primitives::transaction::components::Amount; use zcash_protocol::value::ZatBalance;
const COIN: u64 = 1_0000_0000; const COIN: u64 = 1_0000_0000;
pub(crate) fn format_zec(value: impl Into<Amount>) -> String { pub(crate) fn format_zec(value: impl TryInto<ZatBalance>) -> String {
let value = i64::from(value.into()); let value = i64::from(
value
.try_into()
.map_err(|_| ())
.expect("Values are formattable"),
);
let abs_value = value.unsigned_abs(); let abs_value = value.unsigned_abs();
let abs_zec = abs_value / COIN; let abs_zec = abs_value / COIN;
let frac = abs_value % COIN; let frac = abs_value % COIN;