From e7fdca7b8f1ecb2ab8cf716e9c5e24dbf2ab5236 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 17 Dec 2024 17:41:20 +0000 Subject: [PATCH] pczt sign: Move derivation path matching into protocol-specific crates --- Cargo.lock | 49 ++++++----------- Cargo.toml | 14 +++++ src/commands/pczt/sign.rs | 111 +++++++++++++++----------------------- 3 files changed, 75 insertions(+), 99 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6cb7247..537e841 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1747,8 +1747,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "blake2b_simd", "byteorder", @@ -1799,8 +1798,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d42773cb15447644d170be20231a3268600e0c4cea8987d013b93ac973d3cf7" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "blake2b_simd", ] @@ -3400,9 +3398,9 @@ dependencies = [ [[package]] name = "nonempty" -version = "0.7.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" +checksum = "549e471b99ccaf2f89101bec68f4d244457d5a95a9c3d0672e9564124397741d" [[package]] name = "noop_proc_macro" @@ -3611,8 +3609,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f7152474406422f572de163e0bc63b2126cdbfe17bc849efbbde36fcfe647e" +source = "git+https://github.com/zcash/orchard.git?rev=4fa6d3b549f8803016a309281404eab095d04de8#4fa6d3b549f8803016a309281404eab095d04de8" dependencies = [ "aes", "bitvec", @@ -3780,8 +3777,7 @@ dependencies = [ [[package]] name = "pczt" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545f95dc3d5295b9ed0360aa3b63e610bd4a73f2f382c616b2fda66c3288e989" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "blake2b_simd", "bls12_381", @@ -4857,8 +4853,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c2acdbbab83d554fc2dceea5f7d6d3da71e57adb18a6c80b8901bd0eee54b0" +source = "git+https://github.com/zcash/sapling-crypto.git?rev=3c2235747553da642fb142d1eeb9b1afa8391987#3c2235747553da642fb142d1eeb9b1afa8391987" dependencies = [ "aes", "bellman", @@ -7420,8 +7415,7 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zcash_address" version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b955fe87f2d9052e3729bdbeb0e94975355f4fe39f7d26aea9457bec6a0bb55" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "bech32 0.11.0", "bs58", @@ -7434,8 +7428,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a187ad05cdfe13707c07e6aedca8026b34921d081decfd0b43aac1efd438a7" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "arti-client", "base64 0.22.1", @@ -7497,8 +7490,7 @@ dependencies = [ [[package]] name = "zcash_client_sqlite" version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b8046e94c3d746cc00e0ceb4ec4263c4fb93271a8681b425365ad600148ab15" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "bip32", "bs58", @@ -7536,8 +7528,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3654116ae23ab67dd1f849b01f8821a8a156f884807ff665eac109bf28306c4d" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "core2", "nonempty", @@ -7546,8 +7537,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad3cf576c6e6094cd03f446fcb83ad241ec315a088593cd50940f135cb03ce1" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "bech32 0.11.0", "bip32", @@ -7589,8 +7579,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b45f3ca3a9df34fcdbf036c2c814417bb417bde742812abc09d744bb3d7ed72" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "aes", "bip32", @@ -7630,8 +7619,7 @@ dependencies = [ [[package]] name = "zcash_proofs" version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5826910c516675eca1f34b3557e159f4e35a4a1711b39fa4f01fb0adb9a9c24" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "bellman", "blake2b_simd", @@ -7653,8 +7641,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cb36b15b5a1be70b30c32ce40372dead6561df8a467e297f96b892873a63a2" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "core2", "document-features", @@ -7677,8 +7664,7 @@ dependencies = [ [[package]] name = "zcash_transparent" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0512e8e02af804e852fbbc4bd5db35a9037bc253d2ce396506293a6e7dd745" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "bip32", "blake2b_simd", @@ -7809,8 +7795,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3e613defb0940acef1f54774b51c7f48f2fa705613dd800870dc69f35cd2ea" +source = "git+https://github.com/zcash/librustzcash.git?rev=2bce3ceea756713b737367326069aa204464d3ee#2bce3ceea756713b737367326069aa204464d3ee" dependencies = [ "base64 0.22.1", "nom", diff --git a/Cargo.toml b/Cargo.toml index 92eeaf3..eaa7d0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,3 +78,17 @@ tui = [ "dep:tokio-util", "dep:tui-logger", ] + +[patch.crates-io] +orchard = { git = "https://github.com/zcash/orchard.git", rev = "4fa6d3b549f8803016a309281404eab095d04de8" } +pczt = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +sapling = { package = "sapling-crypto", git = "https://github.com/zcash/sapling-crypto.git", rev = "3c2235747553da642fb142d1eeb9b1afa8391987" } +transparent = { package = "zcash_transparent", git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_client_backend = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_client_sqlite = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_keys = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zcash_protocol = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } +zip321 = { git = "https://github.com/zcash/librustzcash.git", rev = "2bce3ceea756713b737367326069aa204464d3ee" } diff --git a/src/commands/pczt/sign.rs b/src/commands/pczt/sign.rs index 2d342ad..7646cba 100644 --- a/src/commands/pczt/sign.rs +++ b/src/commands/pczt/sign.rs @@ -1,9 +1,9 @@ -use std::collections::BTreeMap; +use std::{collections::BTreeMap, convert::Infallible}; use anyhow::anyhow; use gumdrop::Options; use pczt::{ - roles::{signer::Signer, updater::Updater}, + roles::{signer::Signer, verifier::Verifier}, Pczt, }; use secrecy::ExposeSecret; @@ -46,8 +46,7 @@ impl Command { let seed_fp = SeedFingerprint::from_seed(seed).ok_or_else(|| anyhow!("Invalid seed length"))?; - // Find all the spends matching our seed. For now as a hack, we use the Updater - // role to access the bundle data we need. + // Find all the spends matching our seed. enum KeyRef { Orchard { index: usize, @@ -62,80 +61,58 @@ impl Command { }, } let mut keys = BTreeMap::>::new(); - let pczt = Updater::new(pczt) - .update_orchard_with(|updater| { - for (index, action) in updater.bundle().actions().iter().enumerate() { - if let Some(derivation) = action.spend().zip32_derivation() { - if derivation.seed_fingerprint() == &seed_fp.to_bytes() - && derivation.derivation_path().len() == 3 - && derivation.derivation_path()[0] == zip32::ChildIndex::hardened(32) - && derivation.derivation_path()[1] - == zip32::ChildIndex::hardened(params.network_type().coin_type()) - { - let account_index = zip32::AccountId::try_from( - derivation.derivation_path()[2].index() - (1 << 31), + let pczt = Verifier::new(pczt) + .with_orchard::(|bundle| { + for (index, action) in bundle.actions().iter().enumerate() { + if let Some(account_index) = action + .spend() + .zip32_derivation() + .as_ref() + .and_then(|derivation| { + derivation.extract_account_index( + &seed_fp, + zip32::ChildIndex::hardened(params.network_type().coin_type()), ) - .expect("valid"); - - keys.entry(account_index) - .or_default() - .push(KeyRef::Orchard { index }); - } + }) + { + keys.entry(account_index) + .or_default() + .push(KeyRef::Orchard { index }); } } Ok(()) }) - .expect("no errors") - .update_sapling_with(|updater| { - for (index, spend) in updater.bundle().spends().iter().enumerate() { - if let Some(derivation) = spend.zip32_derivation() { - if derivation.seed_fingerprint() == &seed_fp.to_bytes() - && derivation.derivation_path().len() == 3 - && derivation.derivation_path()[0] == zip32::ChildIndex::hardened(32) - && derivation.derivation_path()[1] - == zip32::ChildIndex::hardened(params.network_type().coin_type()) - { - let account_index = zip32::AccountId::try_from( - derivation.derivation_path()[2].index() - (1 << 31), + .map_err(|e| anyhow!("Invalid PCZT: {:?}", e))? + .with_sapling::(|bundle| { + for (index, spend) in bundle.spends().iter().enumerate() { + if let Some(account_index) = + spend.zip32_derivation().as_ref().and_then(|derivation| { + derivation.extract_account_index( + &seed_fp, + zip32::ChildIndex::hardened(params.network_type().coin_type()), ) - .expect("valid"); - - keys.entry(account_index) - .or_default() - .push(KeyRef::Sapling { index }); - } + }) + { + keys.entry(account_index) + .or_default() + .push(KeyRef::Sapling { index }); } } Ok(()) }) - .expect("no errors") - .update_transparent_with(|updater| { - for (index, input) in updater.bundle().inputs().iter().enumerate() { + .map_err(|e| anyhow!("Invalid PCZT: {:?}", e))? + .with_transparent::(|bundle| { + for (index, input) in bundle.inputs().iter().enumerate() { for derivation in input.bip32_derivation().values() { - if derivation.seed_fingerprint() == &seed_fp.to_bytes() - && derivation.derivation_path().len() == 5 - && derivation.derivation_path()[0] - == bip32::ChildNumber::new(44, true).expect("valid") - && derivation.derivation_path()[1] - == bip32::ChildNumber::new(params.network_type().coin_type(), true) - .expect("valid") - && derivation.derivation_path()[2].is_hardened() - && !derivation.derivation_path()[3].is_hardened() - && !derivation.derivation_path()[4].is_hardened() + if let Some((account_index, scope, address_index)) = derivation + .extract_bip_44_fields( + &seed_fp, + bip32::ChildNumber( + params.network_type().coin_type() + | bip32::ChildNumber::HARDENED_FLAG, + ), + ) { - let account_index = - zip32::AccountId::try_from(derivation.derivation_path()[2].index()) - .expect("valid"); - - let scope = TransparentKeyScope::custom( - derivation.derivation_path()[3].index(), - ) - .expect("valid"); - let address_index = NonHardenedChildIndex::from_index( - derivation.derivation_path()[4].index(), - ) - .expect("valid"); - keys.entry(account_index) .or_default() .push(KeyRef::Transparent { @@ -148,7 +125,7 @@ impl Command { } Ok(()) }) - .expect("no errors") + .map_err(|e| anyhow!("Invalid PCZT: {:?}", e))? .finish(); let mut signer =