Bump Zcash deps to Ironwood revisions + mechanical API migrations
What changed, and why it matters
This commit updates the Zcash-related Rust libraries inside the Keystone 3 firmware to newer versions. It also makes small code changes so the firmware keeps compiling with the new library APIs, removes some old tests that no longer work with the new wire format, and adjusts how transaction hashes are computed. The commit itself is described by its author as not building in isolation; the remaining matching changes are in the next commit. There is no direct evidence in the commit that this fixes or introduces a security vulnerability.
Review this commit together with the following commit that completes the Ironwood parsing/signing changes, because this commit does not build or pass tests in isolation. Verify that the ZIP-244 sighash changes and transparent address handling remain semantically equivalent, and that the removed anti-spoofing and malformed-bundle tests are restored against the new PCZT API. Confirm the Git-pinned Zcash forks match expected upstream revisions and have not introduced unexpected changes.
Security signals we found
Dependency bump to major new revisions of Zcash cryptographic crates
Switch from crates.io releases to Git-pinned forks (valargroup/librustzcash and zcash/orchard)
ZIP-244 sighash digest code changes in pczt_ext.rs
Removal of existing unit tests covering PCZT parsing, signing, and anti-spoofing checks
Commit explicitly does not build in isolation
Evidence from the diff
The change bumps Zcash crate versions (orchard 0.11→0.14, pczt 0.2→0.7, zcash_primitives 0.22→0.28, zcash_transparent 0.2→0.8, zcash_keys 0.8→0.14, zcash_protocol 0.5→0.9, zcash_address 0.7→0.12, zcash_encoding 0.3→0.4) and pins them to specific Git revisions via [patch.crates-io]. It enables the zcash_unstable=”nu6.3” cfg, migrates transparent address extraction to from_script_from_chain/from_script_pubkey, adapts SignableInput::from_parts to the new API, and updates ZIP-244 sighash digest handling in pczt_ext.rs. A large block of tests using the old PCZT builder API is removed, with the commit message stating equivalent tests will be restored in the following commit. The author explicitly notes the commit does not build standalone.
Changed components
rust/.cargo/config.tomlrust/Cargo.lockrust/Cargo.tomlrust/apps/zcash/Cargo.tomlrust/apps/zcash/build.rsrust/apps/zcash/src/lib.rsrust/apps/zcash/src/pczt/check.rsrust/apps/zcash/src/pczt/mod.rsrust/zcash_vendor/Cargo.tomlrust/zcash_vendor/src/pczt_ext.rsInspect captured patch +201 / −437
diff --git a/rust/.cargo/config.toml b/rust/.cargo/config.toml
index 58061e3..4d70cf4 100644
--- a/rust/.cargo/config.toml
+++ b/rust/.cargo/config.toml
@@ -2,3 +2,4 @@
## This path is hardcoded into the Makefiles, so make sure a contributor’s
## config hasn’t overridden it.
target-dir = "target"
+rustflags = ["--cfg", "zcash_unstable=\"nu6.3\""]
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index ed58114..0a50f41 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -482,12 +482,15 @@ dependencies = [
"bitvec",
"blake2b_simd",
"hex",
+ "incrementalmerkletree",
"keystore",
"pczt",
"postcard",
"rand_core 0.6.4",
"rust_tools",
"serde",
+ "serde_with",
+ "shardtree",
"thiserror-core",
"zcash_note_encryption",
"zcash_primitives",
@@ -909,6 +912,15 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "bounded-vec"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09dc0086e469182132244e9b8d313a0742e1132da43a08c24b9dd3c18e0faf3a"
+dependencies = [
+ "thiserror 2.0.12",
+]
+
[[package]]
name = "bs58"
version = "0.5.1"
@@ -1282,6 +1294,12 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "corez"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4df6f98652d30167eaeea34d77b730e07c8caba6df17bd4551842b9b8da01deb"
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -1657,12 +1675,11 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "equihash"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca4f333d4ccc9d23c06593733673026efa71a332e028b00f12cf427b9677dce9"
+version = "0.3.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
"blake2b_simd",
- "core2",
+ "corez",
]
[[package]]
@@ -1783,6 +1800,14 @@ dependencies = [
"blake2b_simd",
]
+[[package]]
+name = "f4jumble"
+version = "0.1.1"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
+dependencies = [
+ "blake2b_simd",
+]
+
[[package]]
name = "fastrand"
version = "2.3.0"
@@ -2051,9 +2076,9 @@ dependencies = [
[[package]]
name = "halo2_gadgets"
-version = "0.3.1"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73a5e510d58a07d8ed238a5a8a436fe6c2c79e1bb2611f62688bc65007b4e6e7"
+checksum = "fb2a697cad929f706b7987fe804ad57d43622cd37463ba7e4d662a926fdcfea3"
dependencies = [
"arrayvec",
"bitvec",
@@ -3014,14 +3039,13 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "orchard"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1ef66fcf99348242a20d582d7434da381a867df8dc155b3a980eca767c56137"
+version = "0.14.0"
+source = "git+https://github.com/zcash/orchard?rev=b2af0a11abe00f59c51258d349c2105fe7a16215#b2af0a11abe00f59c51258d349c2105fe7a16215"
dependencies = [
"aes",
"bitvec",
"blake2b_simd",
- "core2",
+ "corez",
"ff",
"fpe",
"getset",
@@ -3037,6 +3061,7 @@ dependencies = [
"pasta_curves",
"proptest",
"rand",
+ "rand_core 0.6.4",
"reddsa",
"serde",
"sinsemilla",
@@ -3115,10 +3140,10 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pczt"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ecd86f6f9acfadafa3aca948083a5cc6b8c5ff66fd2044416c20269c3953acd"
+version = "0.7.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
+ "blake2b_simd",
"bls12_381",
"ff",
"getset",
@@ -3127,6 +3152,7 @@ dependencies = [
"orchard",
"pasta_curves",
"postcard",
+ "rand_core 0.6.4",
"redjubjub",
"sapling-crypto",
"secp256k1",
@@ -3135,6 +3161,7 @@ dependencies = [
"zcash_note_encryption",
"zcash_primitives",
"zcash_protocol",
+ "zcash_script",
"zcash_transparent",
]
@@ -3961,9 +3988,9 @@ checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "sapling-crypto"
-version = "0.5.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d3c081c83f1dc87403d9d71a06f52301c0aa9ea4c17da2a3435bbf493ffba4"
+checksum = "2d70756ede56b5e4dd417979777bd87ddb83dfcbd0815dbf8175a9920537f8a0"
dependencies = [
"aes",
"bellman",
@@ -3971,7 +3998,7 @@ dependencies = [
"blake2b_simd",
"blake2s_simd",
"bls12_381",
- "core2",
+ "corez",
"document-features",
"ff",
"fpe",
@@ -4293,6 +4320,18 @@ dependencies = [
"keccak",
]
+[[package]]
+name = "shardtree"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "359e552886ae54d1642091645980d83f7db465fd9b5b0248e3680713c1773388"
+dependencies = [
+ "bitflags 2.9.1",
+ "either",
+ "incrementalmerkletree",
+ "tracing",
+]
+
[[package]]
name = "shlex"
version = "1.3.0"
@@ -5370,40 +5409,38 @@ dependencies = [
[[package]]
name = "zcash_address"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71591bb4eb2fd7622e88eed42e7d7d8501cd1e920a0698c7fb08723a8c1d0b4f"
+version = "0.12.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
"bech32 0.11.0",
"bs58",
- "core2",
- "f4jumble",
+ "corez",
+ "f4jumble 0.1.1 (git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed)",
"zcash_encoding",
"zcash_protocol",
]
[[package]]
name = "zcash_encoding"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca38087e6524e5f51a5b0fb3fc18f36d7b84bf67b2056f494ca0c281590953d"
+version = "0.4.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
- "core2",
+ "corez",
+ "hex",
"nonempty",
]
[[package]]
name = "zcash_keys"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f19138db56626babaed67c9f8d8d6094b0413cc34f63b6e5a76071e44d395175"
+version = "0.14.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
"bech32 0.11.0",
"bip32",
"blake2b_simd",
"bls12_381",
"bs58",
- "core2",
+ "corez",
"group",
"memuse",
"nonempty",
@@ -5434,21 +5471,15 @@ dependencies = [
[[package]]
name = "zcash_primitives"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4033e521ce8bc2e37cfa98f3db847495339de15858b349cc8a4078154cdc25dc"
+version = "0.28.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
- "bip32",
"blake2b_simd",
"block-buffer 0.11.0-rc.3",
- "bs58",
- "core2",
+ "corez",
"crypto-common 0.2.0-rc.1",
"equihash",
"ff",
- "fpe",
- "getset",
- "group",
"hex",
"incrementalmerkletree",
"jubjub",
@@ -5456,35 +5487,46 @@ dependencies = [
"nonempty",
"orchard",
"proptest",
- "rand",
"rand_core 0.6.4",
"redjubjub",
- "ripemd 0.1.3",
"sapling-crypto",
"secp256k1",
"sha2 0.10.9",
- "subtle",
- "tracing",
- "zcash_address",
"zcash_encoding",
"zcash_note_encryption",
"zcash_protocol",
- "zcash_spec",
+ "zcash_script",
"zcash_transparent",
- "zip32",
]
[[package]]
name = "zcash_protocol"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0525851dd97796f47537e9b15e504888cd214b2c6d021731fdfa0e7cb941a21e"
+version = "0.9.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
- "core2",
+ "corez",
"hex",
"incrementalmerkletree",
"incrementalmerkletree-testing",
"proptest",
+ "zcash_encoding",
+]
+
+[[package]]
+name = "zcash_script"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "774d808ab619b0f1887d7b90cd815c356101698d16aa681f3d2d9dea063de475"
+dependencies = [
+ "bip32",
+ "bitflags 2.9.1",
+ "bounded-vec",
+ "hex",
+ "ripemd 0.1.3",
+ "secp256k1",
+ "sha1",
+ "sha2 0.10.9",
+ "thiserror 2.0.12",
]
[[package]]
@@ -5498,16 +5540,15 @@ dependencies = [
[[package]]
name = "zcash_transparent"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cd8c2d138ec893d3d384d97304da9ff879424056087c8ac811780a0e8d96a99"
+version = "0.8.0"
+source = "git+https://github.com/valargroup/librustzcash?rev=dc95dcef33a081b925db551eac8bf6533fff22ed#dc95dcef33a081b925db551eac8bf6533fff22ed"
dependencies = [
"bip32",
- "blake2b_simd",
"bs58",
- "core2",
+ "corez",
"getset",
"hex",
+ "nonempty",
"proptest",
"ripemd 0.1.3",
"secp256k1",
@@ -5516,6 +5557,7 @@ dependencies = [
"zcash_address",
"zcash_encoding",
"zcash_protocol",
+ "zcash_script",
"zcash_spec",
"zip32",
]
@@ -5531,7 +5573,7 @@ dependencies = [
"bs58",
"byteorder",
"chacha20poly1305",
- "f4jumble",
+ "f4jumble 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ff",
"fpe",
"getset",
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index c3c8e61..f03bd8a 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -120,3 +120,13 @@ getrandom = "0.2"
minicbor = { version = "0.19", features = ["alloc"] }
zeroize = { version = "1.8.2", default-features = false }
# third party dependencies end
+
+[patch.crates-io]
+orchard = { git = "https://github.com/zcash/orchard", rev = "b2af0a11abe00f59c51258d349c2105fe7a16215" }
+pczt = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_address = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_encoding = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_keys = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_primitives = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_protocol = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
+zcash_transparent = { git = "https://github.com/valargroup/librustzcash", rev = "dc95dcef33a081b925db551eac8bf6533fff22ed" }
diff --git a/rust/apps/zcash/Cargo.toml b/rust/apps/zcash/Cargo.toml
index 66a03e0..59ed83c 100644
--- a/rust/apps/zcash/Cargo.toml
+++ b/rust/apps/zcash/Cargo.toml
@@ -17,16 +17,25 @@ bitvec = { version = "1.0.1", default-features = false, features = ["alloc"] }
blake2b_simd = { workspace = true }
rand_core = { workspace = true, features = ["getrandom"] }
zcash_note_encryption = "0.4.1"
+postcard = { version = "1.0.3", features = ["alloc"] }
+serde = { workspace = true }
+serde_with = { version = "3.11.0", features = [
+ "alloc",
+ "macros",
+], default-features = false }
[dev-dependencies]
keystore = { path = "../../keystore" }
-pczt = { version = "0.2.1", default-features = false, features = ["orchard", "sapling", "transparent", "zcp-builder"] }
-zcash_primitives = { version = "0.22", default-features = false, features = ["circuits", "test-dependencies", "transparent-inputs"] }
-postcard = { version = "1.0.3", features = ["alloc"] }
-serde = { workspace = true }
+pczt = { version = "0.7", default-features = false, features = ["orchard", "sapling", "transparent", "zcp-builder"] }
+zcash_primitives = { version = "0.28", default-features = false, features = ["circuits", "test-dependencies", "transparent-inputs"] }
+incrementalmerkletree = { version = "0.8.2", default-features = false }
+shardtree = "0.6.2"
[lints.rust]
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
+unexpected_cfgs = { level = "warn", check-cfg = [
+ 'cfg(coverage_nightly)',
+ 'cfg(zcash_unstable, values("nu6.3"))',
+] }
[features]
default = ["cypherpunk"]
diff --git a/rust/apps/zcash/build.rs b/rust/apps/zcash/build.rs
index ff0e0b3..e8ca0b2 100644
--- a/rust/apps/zcash/build.rs
+++ b/rust/apps/zcash/build.rs
@@ -23,12 +23,24 @@ fn main() {
let line = line.trim();
if let Some(val) = line.strip_prefix("#define SOFTWARE_VERSION_MAJOR ") {
if !val.starts_with('(') {
- major = Some(val.trim().parse().expect("SOFTWARE_VERSION_MAJOR is not a valid u8"));
+ major = Some(
+ val.trim()
+ .parse()
+ .expect("SOFTWARE_VERSION_MAJOR is not a valid u8"),
+ );
}
} else if let Some(val) = line.strip_prefix("#define SOFTWARE_VERSION_MINOR ") {
- minor = Some(val.trim().parse().expect("SOFTWARE_VERSION_MINOR is not a valid u8"));
+ minor = Some(
+ val.trim()
+ .parse()
+ .expect("SOFTWARE_VERSION_MINOR is not a valid u8"),
+ );
} else if let Some(val) = line.strip_prefix("#define SOFTWARE_VERSION_BUILD ") {
- build = Some(val.trim().parse().expect("SOFTWARE_VERSION_BUILD is not a valid u8"));
+ build = Some(
+ val.trim()
+ .parse()
+ .expect("SOFTWARE_VERSION_BUILD is not a valid u8"),
+ );
}
}
diff --git a/rust/apps/zcash/src/lib.rs b/rust/apps/zcash/src/lib.rs
index f617a77..d7473bb 100644
--- a/rust/apps/zcash/src/lib.rs
+++ b/rust/apps/zcash/src/lib.rs
@@ -18,6 +18,9 @@ use zcash_vendor::{
zip32,
};
+#[cfg(any(test, feature = "multi_coins"))]
+use zcash_vendor::pczt::Pczt;
+
/// Generates a Zcash address from a Unified Full Viewing Key (UFVK).
///
/// # Parameters
@@ -215,312 +218,3 @@ pub fn sign_pczt(pczt: &[u8], seed: &[u8]) -> Result<Vec<u8>> {
let pczt = pczt::parse_pczt(pczt)?;
pczt::sign::sign_pczt(pczt, seed)
}
-
-#[cfg(feature = "cypherpunk")]
-#[cfg(test)]
-mod tests {
- use alloc::vec::Vec;
-
- use ::pczt::roles::creator::Creator;
- use consensus::MainNetwork;
- use keystore::algorithms::zcash::{calculate_seed_fingerprint, derive_ufvk};
- use rand_core::OsRng;
- use serde::{Deserialize, Serialize};
- use zcash_primitives::transaction::{
- builder::{BuildConfig, Builder, PcztResult},
- fees::zip317,
- };
- use zcash_vendor::{
- orchard,
- transparent::{bundle as transparent, keys::IncomingViewingKey},
- zcash_protocol::{
- consensus::{BranchId, NetworkConstants},
- memo::MemoBytes,
- value::Zatoshis,
- },
- zip32,
- };
-
- use super::*;
- extern crate std;
-
- const EMPTY_SAPLING_BUNDLE_ERROR: &str =
- "sapling value_sum must be zero when Sapling bundle is empty";
-
- #[derive(Serialize, Deserialize)]
- struct PcztMirror {
- global: ::pczt::common::Global,
- transparent: ::pczt::transparent::Bundle,
- sapling: SaplingBundleMirror,
- orchard: ::pczt::orchard::Bundle,
- }
-
- #[derive(Serialize, Deserialize)]
- struct SaplingBundleMirror {
- spends: Vec<::pczt::sapling::Spend>,
- outputs: Vec<::pczt::sapling::Output>,
- value_sum: i128,
- anchor: [u8; 32],
- bsk: Option<[u8; 32]>,
- }
-
- fn malformed_pczt_with_empty_sapling_bundle_and_nonzero_value_sum() -> Vec<u8> {
- let mut bytes = Creator::new(
- BranchId::Nu6.into(),
- 10,
- MainNetwork.coin_type(),
- [0; 32],
- [0; 32],
- )
- .build()
- .serialize();
- let mut pczt: PcztMirror = postcard::from_bytes(&bytes[8..]).unwrap();
- assert!(pczt.sapling.spends.is_empty());
- assert!(pczt.sapling.outputs.is_empty());
-
- pczt.sapling.value_sum = 1;
-
- bytes.truncate(8);
- postcard::to_extend(&pczt, bytes).unwrap()
- }
-
- fn assert_empty_sapling_bundle_error<T: core::fmt::Debug>(result: Result<T>) {
- assert_eq!(
- result.unwrap_err(),
- ZcashError::InvalidPczt(EMPTY_SAPLING_BUNDLE_ERROR.to_string())
- );
- }
-
- #[test]
- fn test_get_address() {
- let address = get_address(&MainNetwork, "uview1s2e0495jzhdarezq4h4xsunfk4jrq7gzg22tjjmkzpd28wgse4ejm6k7yfg8weanaghmwsvc69clwxz9f9z2hwaz4gegmna0plqrf05zkeue0nevnxzm557rwdkjzl4pl4hp4q9ywyszyjca8jl54730aymaprt8t0kxj8ays4fs682kf7prj9p24dnlcgqtnd2vnskkm7u8cwz8n0ce7yrwx967cyp6dhkc2wqprt84q0jmwzwnufyxe3j0758a9zgk9ssrrnywzkwfhu6ap6cgx3jkxs3un53n75s3");
- assert_eq!(address.unwrap(), "u1tqdskj32l9udfp0rysmca6gpz73fdqc2rmeenyhh0nfrq4vgak284ehkxefw5cf9495rdur0tparuntevp6nnetzjkyzv08m524e4swwk94asas7hm2ad5w5c64zz00hmr7nux0yhaz");
- }
-
- #[test]
- fn test_pczt_orchard_to_transparent() {
- let pczt_hex = hex::decode("50435a5401000000058ace9cb502d5a09cc70c0100f083ae0185010000000180ade2041976a91467f7aa14f177a7e0058c66c7242e086488bd3d1088ac000001237431544d4c4a376b324e344e6172716b3546643575556f38324e58534d624b5267436300000000fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e010000000000000000000000000000000000000000000000000000000000000000024d2eeb083d7c168f64239c3186d53c72e2b1a3a5140f5250f0963689c08cd61c0999baea13f0be05dc6a2554bb2f8f093f4d20911202567a5ab9fd17bce5142b3f79838a71d14757fcff03ba16486a3efb26c9773ec9596821d1e5f32039fe220001d5d3506f152f62c45198446223abf29e06da700990a779fb60a460712fb666a0ff1fab61e2b2b3566b263d0180b6dc05014b2225d5521d6dbb55ae03d22567ce98b242ba5520bc4e2493ec36fb9211c6350194215c2aa089dfa317c61bab4b9747f4e45abca855e45e00710a3dc5caa40a570186f6f9e818f6674c2df92918a55d20f340944de5c67c1c4a9ee347c2c2d6d71d4753d765f2859a3157f7b05cc3bc7089e3f2c9d5abb3fcb1708e74c790985d3dd90cfe2ed03276dfda527c6e8c08d9a1fdeedcb6aef59d9e5bf0ae5d9477ed030001872727f23f40a96896b66d04de905791bae2bc7ee9dc1f4e4ec5ae493dc2fc1001afb475105f1f5b477c52aa3c32ccf131b0c556b80f55ac555460e6b5148bf85303a0808080088581808008808080800800002585b32c42aa5a12b2763953f09aafed13450eda0c416e32d0978260c4171c375413b91e25fa826399623b6716ae8bbb0b4a1099de22478944627af7e5969aa0c404ffab4d35664c1dafd2d2c0cecf4fb3c8b054179f84b2d35d207077b3d256b429acdee34963c573b55ae20fffce73e0e3e575c8fde9d115e7ffab50b3bee60d2436b72c17677e1d7db141fafa72c7f89002908a7a8de3320e5ad3d1ed0bb545235e136904c5c5e4adfa5a100420ceb2196e5e197e919aeaeefa7cb2a1d98e011539af52d618bfb3ba1dfc2d2c01e9bd67523bb6787eb5a0d28e30ad483c6303efd4796795082cc67ea94ba8548a33da1a5ec7c56174bd6b260f548e83a924b7cdd32980ca489b44e981aa1d81cefe2581eebf3a585fb80542aea4a27862f593203b560a412ba4e737c8f678f239f3d1d07c5a82367435f0a0921c46600eb4f6f7387b3cb5984af98b1337f5148ad6388b62dab7cdc48c66ff81685894c2d1d0fe41716b7cb457fb5bd6ff13e321d2f91c15d431f942d7869955dfeadfff61638266ba38d7ba4db7ffe5ee03550d345715cebd9b378181b5769c22e1b20328165da02eeb5d246c70c008ac0c7f7b1bba2cf8270f013eb99cbc5d534270180f34892fdf08d8c16c518d8b7f62d832d676c65fcae34c640ff30d5bd9d65afeab509117a98374b4b9b016228a65bdd803d6c601d2ad6a654c2fe4487d9c7b088d886c36a6afe63d33f8c474f096500acabbb63968e7408c620cc8139331cf7227e9bdbf4b7bae292e15d310e66186b730f28d0515ac5bb71fcc5de09995fe89d005cc2c7afd0fb8f01b315815d38366ebeb6de9ed565b5d1f2ce14b7795b9ad784851f357beacc454be41aaec506f0148461ba5907043ab8618114bbbede979d7f0e0e0af914750df648079e3625e4f309d13ff74d4ada783203bb3652137abd8327cdd06b9332591c9abdcc0cc16f7fec2e0afd849bef8927b3b0ceeca2b90af7611875b78cf525852ee83e10c8f4cb2c80045cbf33c0801a55eeb15c9dca6e53b3dde8a12daf820f1f76624ee48e3128aaa0ef6f6fb32a0303d89e88be288be1b92a301e893790179ec07711e275f48de2f5f8e0ee7b000091c9d96159746d46f353e67463d7052000000000118c5796d39cd2bc56b0a062c20ebd32feb0b57cc231c262d6703520f8de603211edcf51f6084e3288cbdb02957a02cd68fb84973a6a98260fb60f30951dedb2e1240275687c0bd82a2653a2c212bd3c0ea75cd294f5a4d31dcf507c15461402760282899f6b560858c0b6bd95c708f62d1e856480a52401d0d7d6a642fa1c2a10176072c6147735b785ea4ad9276378885704a44c6246f4630ef1df59438562e055bba6c1411a790727ab27421e6c418df8b65cb636d6786ce9e5b632659f5d32401caffe6271e2d77d8634e67a116926d7566b5eb2f2aadba6498d7a1e120f27f52379bb3f8781090ae47e30b0100011a78b2abbab21b29d79141fdff8a389c2eacde5be75c69ae4c4fabc175aec10a0142b202630def2df1f7cd23fcf362c68194829282c57b0c4d5f0ca023b51a571f01bd466676b53cfc27ba4a94bb4ab3ed19d8db336042e09e1e756b560b5ce7fc05d5dc3269236828f541662db5bfd4ab6e07c4dac2682906ee85eca2d12b6522013dd286fc499141cfebfb53175ea4321e08e8a504604bbc2e9d3e59706a1fa439000130febcd5d0c57c6e3780d6fe1f6c07f01a9d5d7a053ac5562f29304418d33a20000000f7fa16a612e422c34d61c44ae692b255c921239547172fcd26519928a3abb10d22548d840b466f1fed5ccb4c442d97b4b59d1a728455ee1598bae8e316f819bac404c9112693c57e0733d550ddc984d82ecc9047721e7e7bc6f283ba00852e49a4d3cda4dad343a366650b1d75b26025eadc5200113ebcc2a4a7db9ac2291083d76e7a8c04831764caf35e4c18bfc58e58699b4a651ca3686a95a6db7133611b5ce80a14225cdac643311869ea0c4a6d760379f285fa9c396c435361044da7e077f236d589a3eb962129988ea6ccde694cb72fa986748fc106981320f478a1c5402fe75a26dee31ec9fad4240aa19932fa8361c43798aa381c63b0c0b17657ccf37792a28456cfe6562e15d9e4aa26ed2660b6c8fc8a92cd352a6025dabcbed5eba82d88b9df3ba73270ff2f9c44fca8b0c1df8ed4cbfa2a4ebe7d0bcc6e5ce73e43b51e054860d7939ca13d77813b372070fd24cdd9c0e2fad7567471c0279bba19a76f0cdbd3107220821dd676c1df6524c15b87c1318eda418d65f8c66d2a77a65f6894199d44611e60c0291c330d1692bd521aef0e316e2b3f8c377b0d6873b3b645196ba74a79c6e0509869ac66276c3e2dfefd54a12365b5945406e7b673321ed36e89a14a194ae8b864e9ac4684655bae7fcd3123a226f282ac6ac82ca88d6a383d8be90f87f4cb85225f697932abfb4c05cda3b6dadb003621fee663f3fcb8f1c96320a3f148bc106ec231961a8f5142dd614317eef16b81492668a8b8795b85d7b0f737fa8d79e9dc3d78840d158a73dc6d1700ce3a8de2a9f93ff1bc8108703b94fd5bd230a19dd0fd821b832d3508b335e07bac28e95c3ab0eb637334bf166fa2a440ea35c0372bb5a745ee86c727a80f0d0d080fef6642ae7aae1407d6a25c3050c498a52ae300105bded1f19829b10df00e7ba301a9aef2c99ad7c5338b0e259ab97ea852630606b8d59709ca067d32698c8761e0f7d5b76ac07d4860b0fe2992010ba88827bb37cf4e3436488580e79101b366d454f29aa2bdf76725130baa08b38af3a71c251521809c84fe3d086943f39f01d760884b6342fac60c010001c54930d4f4f9946dfe91ac3e94cf5b513871c4a5c0c21137959482da796d2d280000000001c4666732084baff2e402ed7d3e457303c73b77dbd4aa5bc943ac7ca96f3779070398a2e304004aed48232c44dbd0b0b5404063ecc4679436f28c6251cbba91e29388fcd98d0e0001dc2be19f4118dbb7500df3a95e304733b247cea7f8c681f6aaafceb8fc1d7d28").unwrap();
- let seed = hex::decode("d561f5aba9db8b100a9a84197322e522f952171a388ad74eaab1ab9db815be3335c3099a0a2bb0fee57e630db5ed7251412b6bd4b905cf518627411fee3f32dd").unwrap();
- let ufvk = derive_ufvk(&MainNetwork, &seed, "m/32'/133'/0'").unwrap();
- let seed_fingerprint = calculate_seed_fingerprint(&seed).unwrap();
- let parsed_pczt = parse_pczt_cypherpunk(
- &MainNetwork,
- &pczt_hex,
- &ufvk.to_string(),
- &seed_fingerprint,
- )
- .unwrap();
- assert!(parsed_pczt.get_transparent().is_some());
- assert!(parsed_pczt.get_orchard().is_some());
- let transparent = parsed_pczt.get_transparent().unwrap();
- let orchard = parsed_pczt.get_orchard().unwrap();
- assert_eq!(transparent.get_from().len(), 0);
- assert_eq!(transparent.get_to().len(), 1);
- assert_eq!(orchard.get_from().len(), 1);
- assert_eq!(orchard.get_to().len(), 1);
- assert_eq!(
- transparent.get_to().first().unwrap().get_address(),
- "t1TMLJ7k2N4Narqk5Fd5uUo82NXSMbKRgCc"
- );
- assert_eq!(transparent.get_to().first().unwrap().get_value(), "0.1 ZEC");
- assert!(!transparent.get_to().first().unwrap().get_is_change());
- assert_eq!(orchard.get_from().first().unwrap().get_address(), None);
- assert_eq!(orchard.get_from().first().unwrap().get_value(), "0.12 ZEC");
- assert!(orchard.get_from().first().unwrap().get_is_mine());
- assert_eq!(
- orchard.get_to().first().unwrap().get_address(),
- "<internal-address>"
- );
- assert_eq!(orchard.get_to().first().unwrap().get_value(), "0.01985 ZEC");
- assert!(orchard.get_to().first().unwrap().get_is_change());
- assert_eq!(parsed_pczt.get_fee_value(), "0.00015 ZEC");
- }
-
- #[test]
- fn test_parse_pczt_rejects_orchard_internal_ovk_change_spoofing() {
- let params = MainNetwork;
- let rng = OsRng;
-
- let victim_seed = [7u8; 32];
- let ufvk_text = derive_ufvk(¶ms, &victim_seed, "m/32'/133'/0'").unwrap();
- let ufvk = UnifiedFullViewingKey::decode(¶ms, &ufvk_text).unwrap();
- let victim_fvk = ufvk.orchard().unwrap().clone();
- let victim_account = zcash_vendor::transparent::keys::AccountPrivKey::from_seed(
- ¶ms,
- &victim_seed,
- zip32::AccountId::ZERO,
- )
- .unwrap();
- let (victim_addr, address_index) = victim_account
- .to_account_pubkey()
- .derive_external_ivk()
- .unwrap()
- .default_address();
- let victim_sk = victim_account
- .derive_external_secret_key(address_index)
- .unwrap();
- let secp = bitcoin::secp256k1::Secp256k1::signing_only();
- let victim_pubkey = victim_sk.public_key(&secp);
-
- let attacker_orchard_sk = orchard::keys::SpendingKey::from_bytes([2; 32]).unwrap();
- let attacker_fvk = orchard::keys::FullViewingKey::from(&attacker_orchard_sk);
- let attacker_recipient = attacker_fvk.address_at(0u32, orchard::keys::Scope::External);
- let victim_change = victim_fvk.address_at(0u32, orchard::keys::Scope::Internal);
-
- let utxo = transparent::OutPoint::fake();
- let coin = transparent::TxOut {
- value: Zatoshis::const_from_u64(1_000_000),
- script_pubkey: victim_addr.script(),
- };
-
- let mut builder = Builder::new(
- ¶ms,
- 10_000_000.into(),
- BuildConfig::Standard {
- sapling_anchor: None,
- orchard_anchor: Some(orchard::Anchor::empty_tree()),
- },
- );
- builder
- .add_transparent_input(victim_pubkey, utxo, coin)
- .unwrap();
- builder
- .add_orchard_output::<zip317::FeeRule>(
- Some(victim_fvk.to_ovk(orchard::keys::Scope::Internal)),
- attacker_recipient,
- 100_000,
- MemoBytes::empty(),
- )
- .unwrap();
- builder
- .add_orchard_output::<zip317::FeeRule>(
- Some(victim_fvk.to_ovk(orchard::keys::Scope::Internal)),
- victim_change,
- 885_000,
- MemoBytes::empty(),
- )
- .unwrap();
-
- let PcztResult { pczt_parts, .. } = builder
- .build_for_pczt(rng, &zip317::FeeRule::standard())
- .unwrap();
- let pczt = Creator::build_from_parts(pczt_parts).unwrap();
- let pczt_bytes = pczt.serialize();
- let seed_fingerprint = calculate_seed_fingerprint(&victim_seed).unwrap();
-
- let result = parse_pczt_cypherpunk(¶ms, &pczt_bytes, &ufvk_text, &seed_fingerprint);
- match result {
- Err(ZcashError::InvalidPczt(_)) => {}
- Err(ZcashError::InvalidDataError(msg))
- if msg.contains("Orchard output was recoverable with an internal OVK but does not belong to this wallet") => {}
- Err(e) => panic!("unexpected error: {e:?}"),
- Ok(parsed) => {
- let orchard = parsed.get_orchard();
- panic!("unexpected success: orchard={orchard:?}");
- }
- }
-
- let check_result =
- check_pczt_cypherpunk(¶ms, &pczt_bytes, &ufvk_text, &seed_fingerprint, 0);
- match check_result {
- Err(ZcashError::InvalidPczt(_)) => {}
- Err(ZcashError::InvalidDataError(msg))
- if msg.contains("Orchard output was recoverable with an internal OVK but does not belong to this wallet") => {}
- Err(e) => panic!("unexpected check error: {e:?}"),
- Ok(()) => panic!("unexpected check success"),
- }
- }
-
- #[test]
- fn test_check_pczt_rejects_empty_sapling_bundle_with_nonzero_value_sum() {
- let seed = [9u8; 32];
- let malformed_pczt = malformed_pczt_with_empty_sapling_bundle_and_nonzero_value_sum();
- let ufvk = derive_ufvk(&MainNetwork, &seed, "m/32'/133'/0'").unwrap();
- let seed_fingerprint = calculate_seed_fingerprint(&seed).unwrap();
-
- let result = check_pczt_cypherpunk(
- &MainNetwork,
- &malformed_pczt,
- &ufvk.to_string(),
- &seed_fingerprint,
- 0,
- );
-
- assert_empty_sapling_bundle_error(result);
- }
-
- #[test]
- fn test_get_address_invalid_ufvk() {
- let invalid_ufvk = "invalid_ufvk_string";
- let result = get_address(&MainNetwork, invalid_ufvk);
- assert!(result.is_err());
- assert!(matches!(
- result.unwrap_err(),
- ZcashError::GenerateAddressError(_)
- ));
- }
-
- #[test]
- fn test_check_pczt_invalid_data() {
- let invalid_pczt = b"invalid_pczt_data";
- let seed = hex::decode("d561f5aba9db8b100a9a84197322e522f952171a388ad74eaab1ab9db815be3335c3099a0a2bb0fee57e630db5ed7251412b6bd4b905cf518627411fee3f32dd").unwrap();
- let ufvk = derive_ufvk(&MainNetwork, &seed, "m/32'/133'/0'").unwrap();
- let seed_fingerprint = calculate_seed_fingerprint(&seed).unwrap();
-
- let result = check_pczt_cypherpunk(
- &MainNetwork,
- invalid_pczt,
- &ufvk.to_string(),
- &seed_fingerprint,
- 0,
- );
- assert!(result.is_err());
- assert!(matches!(result.unwrap_err(), ZcashError::InvalidPczt(_)));
- }
-
- #[test]
- fn test_check_pczt_invalid_ufvk() {
- let pczt_hex = hex::decode("50435a5401000000058ace9cb502d5a09cc70c0100f083ae0185010000000180ade2041976a91467f7aa14f177a7e0058c66c7242e086488bd3d1088ac000001237431544d4c4a376b324e344e6172716b3546643575556f38324e58534d624b5267436300000000fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e010000000000000000000000000000000000000000000000000000000000000000024d2eeb083d7c168f64239c3186d53c72e2b1a3a5140f5250f0963689c08cd61c0999baea13f0be05dc6a2554bb2f8f093f4d20911202567a5ab9fd17bce5142b3f79838a71d14757fcff03ba16486a3efb26c9773ec9596821d1e5f32039fe220001d5d3506f152f62c45198446223abf29e06da700990a779fb60a460712fb666a0ff1fab61e2b2b3566b263d0180b6dc05014b2225d5521d6dbb55ae03d22567ce98b242ba5520bc4e2493ec36fb9211c6350194215c2aa089dfa317c61bab4b9747f4e45abca855e45e00710a3dc5caa40a570186f6f9e818f6674c2df92918a55d20f340944de5c67c1c4a9ee347c2c2d6d71d4753d765f2859a3157f7b05cc3bc7089e3f2c9d5abb3fcb1708e74c790985d3dd90cfe2ed03276dfda527c6e8c08d9a1fdeedcb6aef59d9e5bf0ae5d9477ed030001872727f23f40a96896b66d04de905791bae2bc7ee9dc1f4e4ec5ae493dc2fc1001afb475105f1f5b477c52aa3c32ccf131b0c556b80f55ac555460e6b5148bf85303a0808080088581808008808080800800002585b32c42aa5a12b2763953f09aafed13450eda0c416e32d0978260c4171c375413b91e25fa826399623b6716ae8bbb0b4a1099de22478944627af7e5969aa0c404ffab4d35664c1dafd2d2c0cecf4fb3c8b054179f84b2d35d207077b3d256b429acdee34963c573b55ae20fffce73e0e3e575c8fde9d115e7ffab50b3bee60d2436b72c17677e1d7db141fafa72c7f89002908a7a8de3320e5ad3d1ed0bb545235e136904c5c5e4adfa5a100420ceb2196e5e197e919aeaeefa7cb2a1d98e011539af52d618bfb3ba1dfc2d2c01e9bd67523bb6787eb5a0d28e30ad483c6303efd4796795082cc67ea94ba8548a33da1a5ec7c56174bd6b260f548e83a924b7cdd32980ca489b44e981aa1d81cefe2581eebf3a585fb80542aea4a27862f593203b560a412ba4e737c8f678f239f3d1d07c5a82367435f0a0921c46600eb4f6f7387b3cb5984af98b1337f5148ad6388b62dab7cdc48c66ff81685894c2d1d0fe41716b7cb457fb5bd6ff13e321d2f91c15d431f942d7869955dfeadfff61638266ba38d7ba4db7ffe5ee03550d345715cebd9b378181b5769c22e1b20328165da02eeb5d246c70c008ac0c7f7b1bba2cf8270f013eb99cbc5d534270180f34892fdf08d8c16c518d8b7f62d832d676c65fcae34c640ff30d5bd9d65afeab509117a98374b4b9b016228a65bdd803d6c601d2ad6a654c2fe4487d9c7b088d886c36a6afe63d33f8c474f096500acabbb63968e7408c620cc8139331cf7227e9bdbf4b7bae292e15d310e66186b730f28d0515ac5bb71fcc5de09995fe89d005cc2c7afd0fb8f01b315815d38366ebeb6de9ed565b5d1f2ce14b7795b9ad784851f357beacc454be41aaec506f0148461ba5907043ab8618114bbbede979d7f0e0e0af914750df648079e3625e4f309d13ff74d4ada783203bb3652137abd8327cdd06b9332591c9abdcc0cc16f7fec2e0afd849bef8927b3b0ceeca2b90af7611875b78cf525852ee83e10c8f4cb2c80045cbf33c0801a55eeb15c9dca6e53b3dde8a12daf820f1f76624ee48e3128aaa0ef6f6fb32a0303d89e88be288be1b92a301e893790179ec07711e275f48de2f5f8e0ee7b000091c9d96159746d46f353e67463d7052000000000118c5796d39cd2bc56b0a062c20ebd32feb0b57cc231c262d6703520f8de603211edcf51f6084e3288cbdb02957a02cd68fb84973a6a98260fb60f30951dedb2e1240275687c0bd82a2653a2c212bd3c0ea75cd294f5a4d31dcf507c15461402760282899f6b560858c0b6bd95c708f62d1e856480a52401d0d7d6a642fa1c2a10176072c6147735b785ea4ad9276378885704a44c6246f4630ef1df59438562e055bba6c1411a790727ab27421e6c418df8b65cb636d6786ce9e5b632659f5d32401caffe6271e2d77d8634e67a116926d7566b5eb2f2aadba6498d7a1e120f27f52379bb3f8781090ae47e30b0100011a78b2abbab21b29d79141fdff8a389c2eacde5be75c69ae4c4fabc175aec10a0142b202630def2df1f7cd23fcf362c68194829282c57b0c4d5f0ca023b51a571f01bd466676b53cfc27ba4a94bb4ab3ed19d8db336042e09e1e756b560b5ce7fc05d5dc3269236828f541662db5bfd4ab6e07c4dac2682906ee85eca2d12b6522013dd286fc499141cfebfb53175ea4321e08e8a504604bbc2e9d3e59706a1fa439000130febcd5d0c57c6e3780d6fe1f6c07f01a9d5d7a053ac5562f29304418d33a20000000f7fa16a612e422c34d61c44ae692b255c921239547172fcd26519928a3abb10d22548d840b466f1fed5ccb4c442d97b4b59d1a728455ee1598bae8e316f819bac404c9112693c57e0733d550ddc984d82ecc9047721e7e7bc6f283ba00852e49a4d3cda4dad343a366650b1d75b26025eadc5200113ebcc2a4a7db9ac2291083d76e7a8c04831764caf35e4c18bfc58e58699b4a651ca3686a95a6db7133611b5ce80a14225cdac643311869ea0c4a6d760379f285fa9c396c435361044da7e077f236d589a3eb962129988ea6ccde694cb72fa986748fc106981320f478a1c5402fe75a26dee31ec9fad4240aa19932fa8361c43798aa381c63b0c0b17657ccf37792a28456cfe6562e15d9e4aa26ed2660b6c8fc8a92cd352a6025dabcbed5eba82d88b9df3ba73270ff2f9c44fca8b0c1df8ed4cbfa2a4ebe7d0bcc6e5ce73e43b51e054860d7939ca13d77813b372070fd24cdd9c0e2fad7567471c0279bba19a76f0cdbd3107220821dd676c1df6524c15b87c1318eda418d65f8c66d2a77a65f6894199d44611e60c0291c330d1692bd521aef0e316e2b3f8c377b0d6873b3b645196ba74a79c6e0509869ac66276c3e2dfefd54a12365b5945406e7b673321ed36e89a14a194ae8b864e9ac4684655bae7fcd3123a226f282ac6ac82ca88d6a383d8be90f87f4cb85225f697932abfb4c05cda3b6dadb003621fee663f3fcb8f1c96320a3f148bc106ec231961a8f5142dd614317eef16b81492668a8b8795b85d7b0f737fa8d79e9dc3d78840d158a73dc6d1700ce3a8de2a9f93ff1bc8108703b94fd5bd230a19dd0fd821b832d3508b335e07bac28e95c3ab0eb637334bf166fa2a440ea35c0372bb5a745ee86c727a80f0d0d080fef6642ae7aae1407d6a25c3050c498a52ae300105bded1f19829b10df00e7ba301a9aef2c99ad7c5338b0e259ab97ea852630606b8d59709ca067d32698c8761e0f7d5b76ac07d4860b0fe2992010ba88827bb37cf4e3436488580e79101b366d454f29aa2bdf76725130baa08b38af3a71c251521809c84fe3d086943f39f01d760884b6342fac60c010001c54930d4f4f9946dfe91ac3e94cf5b513871c4a5c0c21137959482da796d2d280000000001c4666732084baff2e402ed7d3e457303c73b77dbd4aa5bc943ac7ca96f3779070398a2e304004aed48232c44dbd0b0b5404063ecc4679436f28c6251cbba91e29388fcd98d0e0001dc2be19f4118dbb7500df3a95e304733b247cea7f8c681f6aaafceb8fc1d7d28").unwrap();
- let seed_fingerprint = [0u8; 32];
-
- let result = check_pczt_cypherpunk(
- &MainNetwork,
- &pczt_hex,
- "invalid_ufvk",
- &seed_fingerprint,
- 0,
- );
- assert!(result.is_err());
- assert!(matches!(
- result.unwrap_err(),
- ZcashError::InvalidDataError(_)
- ));
- }
-
- #[test]
- fn test_parse_pczt_invalid_data() {
- let invalid_pczt = b"invalid_pczt_data";
- let seed = hex::decode("d561f5aba9db8b100a9a84197322e522f952171a388ad74eaab1ab9db815be3335c3099a0a2bb0fee57e630db5ed7251412b6bd4b905cf518627411fee3f32dd").unwrap();
- let ufvk = derive_ufvk(&MainNetwork, &seed, "m/32'/133'/0'").unwrap();
- let seed_fingerprint = calculate_seed_fingerprint(&seed).unwrap();
-
- let result = parse_pczt_cypherpunk(
- &MainNetwork,
- invalid_pczt,
- &ufvk.to_string(),
- &seed_fingerprint,
- );
- assert!(result.is_err());
- assert!(matches!(result.unwrap_err(), ZcashError::InvalidPczt(_)));
- }
-
- #[test]
- fn test_sign_pczt_invalid_data() {
- let invalid_pczt = b"invalid_pczt_data";
- let seed = hex::decode("d561f5aba9db8b100a9a84197322e522f952171a388ad74eaab1ab9db815be3335c3099a0a2bb0fee57e630db5ed7251412b6bd4b905cf518627411fee3f32dd").unwrap();
-
- let result = sign_pczt(invalid_pczt, &seed);
- assert!(result.is_err());
- assert!(matches!(result.unwrap_err(), ZcashError::InvalidPczt(_)));
- }
-}
diff --git a/rust/apps/zcash/src/pczt/check.rs b/rust/apps/zcash/src/pczt/check.rs
index 02f4291..20f6656 100644
--- a/rust/apps/zcash/src/pczt/check.rs
+++ b/rust/apps/zcash/src/pczt/check.rs
@@ -124,7 +124,7 @@ fn check_transparent_input<P: consensus::Parameters>(
) -> Result<bool, ZcashError> {
let script = input.script_pubkey().clone();
//p2sh transparent input is not supported yet
- match script.address() {
+ match TransparentAddress::from_script_from_chain(&script) {
Some(TransparentAddress::PublicKeyHash(hash)) => {
// 1: find my derivation
let my_derivation = input
@@ -172,7 +172,7 @@ fn check_transparent_output<P: consensus::Parameters>(
output: &transparent::pczt::Output,
) -> Result<(), ZcashError> {
let script = output.script_pubkey().clone();
- match script.address() {
+ match TransparentAddress::from_script_pubkey(&script) {
Some(TransparentAddress::PublicKeyHash(hash)) => {
//check user_address and script_pubkey
match output.user_address() {
@@ -403,7 +403,7 @@ fn is_wallet_orchard_address(fvk: &FullViewingKey, address: &Address) -> bool {
#[cfg(feature = "cypherpunk")]
// check output cmx and internal-ovk output ownership constraints
fn check_action_output<P: consensus::Parameters>(
- _params: &P,
+ params: &P,
ufvk: &UnifiedFullViewingKey,
action: &orchard::pczt::Action,
pool_label: &str,
@@ -444,40 +444,3 @@ fn check_action_output<P: consensus::Parameters>(
Ok(())
}
-
-#[cfg(feature = "cypherpunk")]
-#[cfg(test)]
-mod tests {
- use super::*;
- use zcash_vendor::{pczt::Pczt, zcash_protocol::consensus::MAIN_NETWORK};
-
- #[test]
- fn test_check_pczt_to_transparent_output() {
- {
- let fingerprint =
- hex::decode("2fac20755b7bb7c99d302b782ea36f62a1b0cfe8d7d4d09a58e8ba5da26f4578")
- .unwrap();
-
- let ufvk = "uview10zf3gnxd08cne6g7ryh6lln79duzsayg0qxktvyc3l6uutfk0agmyclm5g82h5z0lqv4c2gzp0eu0qc0nxzurxhj4ympwn3gj5c3dc9g7ca4eh3q09fw9kka7qplzq0wnauekf45w9vs4g22khtq57sc8k6j6s70kz0rtqlyat6zsjkcqfrlm9quje8vzszs8y9mjvduf7j2vx329hk2v956g6svnhqswxfp3n760mw233w7ffgsja2szdhy5954hsfldalf28wvav0tctxwkmkgrk43tq2p7sqchzc6";
-
- let unified_fvk = UnifiedFullViewingKey::decode(&MAIN_NETWORK, ufvk).unwrap();
-
- let hex_str = "50435a5401000000058ace9cb502d5a09cc70c0100d989a80185010001227a636173685f636c69656e745f6261636b656e643a70726f706f73616c5f696e666f144951eeff9ccf4eb390ff94a60aa5673db189a8010001a08d061976a9149517c77b7fcc08e66122dccb6ee6713eb7712d2b88ac00000123743158547742385031783459697042744c6850575331334a50445135524d6b4d41364d01207a636173685f636c69656e745f6261636b656e643a6f75747075745f696e666f0100000000fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e010000000000000000000000000000000000000000000000000000000000000000023ad18a78e48f81fe95b3569486ee1db9eed90a319fac6faea1eed4e35b936717236c4a092e80c35e67e0b51b7a41de4013eaffed855b138934b9dcf28ad51f1ea51f60210a8d7f4f6ffb848bbafd4cdfd09df400e53c595861cc0dd8afc32dae010fba942a1bc32f2cc78408be742cd13846bbd50f3869c09d59bffc4e758949b56f422def9eb9d491721b9fc198edf183e9c32920eb30c476f236009a16355d1401b169abb973b87b0fd009693c349a5fdccaa2f1a266ea99f4e7f1fa13d2a8ec96023d73d0573b6fcdbe1b95010001986da568298f3de75fc0bf29de32aec6f2dada30c4e20286eb23667048d21d29017dd8c0825f1f2bc7aac48163e06f44024a657495e7c75fd1d2192336eef159640181679891b0cc1eaf42df83756d69c6833d552e0faa6d3c6af1405f2fcd4fbe0c360dff7f03b6da416da80b533cfb442be30185c9a7f4cba15f7fc836ccbd5d3e88daccb4be13ee8b9f850e542106ecb8107538ea23f4e21882e0c3fa46c0a228018daff38304e9759e20f4bb6f424a1040b554548feaf87e285a0a2ac9de930047e4bdc7042e08965e83fee3c20b18e3a7119457853e42b704f3df3449da1c365804abe0dd16ea51dbe4502e425ef8bb0103a9c314b041a9bf531facdc6ccab8404459261003b77426a46dff084bc2ff8f9a3da8c250bdd0ba8419d086b88fb25285d4fe8d047041cd2be273e8ccfabe154a818f491ea3fb9b9d854f4935480aa253fe35882ddfcc90b2b71eaa44f5299a34a946993fef33bc55c87a5f3427ac646f42eabe190c6856f4c8c1d1f505262b85353de115b061e2a1df24e69ec911e8f1c78b5c0716b8f01d16c560e3b81a07b3030c3beb15613b23e925c9456a9bfee1a25ef51f1ce9bf853c1264f6dd6fa2ea7087a8a78051626518afc8e88a1ed226f0cec1159a4a5ec4131041b3d8cc58ba10c7f676f52805be117a5689fa1a474e3f5bce38349f10e63ba7721a019ced0b63be870cef6f9ef2d228d8a58e695e871f7c4b0e94445d5255708c50298b13c55044f8f5995a258826291eda6f1671681e8f101aad68a17330a3faf4017f87b315aa53bb57fb785953dd9a480c85dd1182fcb235df28c7d3f3d8b79fe72f3b42d63c7ae563f0a4df22de593a488ee514dbda39291a69a0fd09a17ca6786cba733fdadb0f785147676378e7fbdd2a00a45b14460f415578abf268306554e68261022eb4c1e60df1566ac1853d01b2685924329e17963014ba9cd39f6c1c7f7e169574bab623fc15066223196ce0b1ef2251e5dc1f56707910d825c1451bf98115afd2dff4800fcfefc74c237b7bfec5cc2bf20e158f09cbd482b2f17cb0dcef82660ff0f697459e9cb1fdc77a10cffa9b91d88c3791b4a47e11781e0a7e1215315900a40bad41570d70ed6e7598d48eb8956ef90afda546e823446a3cb65a80f1407ea065d196f07524561be836cb5de0b9d5ba3665d2abf29c30bcef800dbeee9e293c59e4c5cee22984e205ebd67147ed3bf8234e654e32053e16bfe2cdeb70f83e1288793284056aac734eb8593feae99c48036b3d852f228febddd3c402bc5ae92d1e1adc313a53eae14213d67afb688efe0c2cdbff9ff826ad0b6cb2d8907949fbacc71fa539a9c60e6c3e2b79ba68b4b73b5b7d6f6e8f08ab80eb53099df60f6bd0c06d9b1e701c7471b9e9453bc78fa00ecaa28a1dbc9b56d2b0750eb5d038d58257a94fc57072f676555b9120536834309db16e168d8dc3f2b8680435853f216b576e39e9ea212f3fb2804c85065d801cf77c2586a76c404023554755ee41cffc358a30d67a26f758979f7f52233a680f0fa64ecdce560dfb206f232ec18450806a8fd8eccf23ea0cbd2dbe3374ccce23449d58aef4512452a329c037f96294f7a97a99fd7721e7bf07e32940b96dbb29e91a6bf267dfecf3e7bccaa657d405d2e7fd76ff8d51203b532a54868089c81d010b3b1b123a1303ec7643dbd09c1f396bc6915f6c4a02cdeba9becd724bb1f42e000000e0ebfc0224e6821685772ac6261127fa8dc097c4ce073ae9e468dbf8edb67a0131399b289425cf7741a1e779f1a089700276df5b193e1822bbf4416c89d4bc94c404b2ca1419e8f7cd98ed4f692efa5f01cc21558245469cfb558da73c13b42074ac966cc41733ffdfcade01c68062a0e0b4a74a3ab15123d62a6e270ea03c2ce88d337034e9537d7f871e8b1363b14096fd4ceb6ba46b2f7308ee1e0824eadd073dbdad58da08aa58b87fa7328710759597fe5a70516299c4a4302888b974da65c259cf8b3b4a1b7207e4d30f4b0f97e48702a25e17d51fa7ea2889d5926d9c66a151d8c713f267f95e0e730d89dbf2140cddcdc2d3508fa7902b1c360244ec407723929891f3990577a7478d4e0e3e374e4fc59e2ee704fca7a51196170e517eb74c339b016eeb3ff49ce10c13b217bbea0f4c234e4fe2766a788cd23000fe8920f973227ef987104d4d458f7754ed14fa2c798d7081d9311e0109c27ad89f362b24818cd803a600b2f21cf36e321c89ac785268e566e850d4c328eefce8062bbad81a854e08fa9a48f110f00072523cb6a670c52891af6e893ac010d4cf540a7ef598437803488d203de92966eb8ca9594d36ccb023d229ac8c391f4b9d50a569890052f27d9271f122c10f78b4c94c256f1e67a9e9c20779d34a0898daedb972ccee455ebb0e48b39d405f74f9074b943c5b5a38612e94bc8c82ec6176b90156289a99f816f64a5cd8cdfd8a9d1de4158e144869e3c535d1928f14d76d6a806b8730b92ada3353ededeb8c2151e876c566121ea2a6cfc93e3da2b1780b827ed7e5420c716b52b7811e650befc972685d153ac68ec9bf7d8b0a09659c5b36bd8226796770ebc05a6b9057a2c82feaae40a281edec65993cd792c980a845d2fbff8189d288500875f768205053e84b399b1a6141f380b7cfc235f26d3ce316cf2afae0404be86ea803a2733c9d32478c822dfa905a4e360c5fef6e05419088fe8921392c4366f976ecfd33332c0273e6ad6770a7a993010bf78b0565a3aa4fbb531de5fbd44a6caa636b2c03f0a38250bf599389154c4a55e4599a13b719551486bf010001587617b07bb6120ac6886c2a4641b8a0b9180ebd3375cf55e1f4066464ad43450000000001e902c227e9c4f4206e1f917c596fe9f4e6d2dca81063093d7065a70ed79674052df49c10eb57f2dda99dee1c1c01e9ed7efd1c9f6f971bf62906a97830b7ad2beec2cfcb30451b6c157fd144041e0429fa1aa2f9f7d0e84e74014205f0a9bd08171a83f92b3493fe29fa0802eefab10ecef3904aa569d82f6e95fdf2dc9cdd28000114b0cac3e14c4e1a4a4fd22c98563b9cbe859c67768a39f67abd5dbe55d3d16ff58e5c45b21d8c573f54b901a8ce920701de6d3d52208c36d6a557c3ed5843cf85a03b029ec491b8ad2541db678ab25a3d0125056d422f2e1393ba7e5295422e9ff38ce8276124ae0fec4bb06e147be83a8f017d6d7535f6e3eade13042662d05eefa91d1f4757fcd0b4b844554e77366f4b36a7068e15c2f06aaa11f6bcfd2e9e36231530069f7fb99a2771050689f24f332b427fdd05d1d5f3219230a1406f0955e3ddc0ef5ce2c7f160d797f3e54ef5782001cfdcac17ee2155c2c8b84c2ddc976891132206e97f7296033a7ef7eaa12ef214c4abf71d1439d50cefd21bedf293df7e11e187c64e13dd9a7905a1e2a26d2647cc1004394bba40a982173a00559da43ccad644d32eb4c4f785264fe3ebd9b12a1d7a6c31aab9e988f717752dbb6d8f555dcf360e25f71a7b1d95ab6b54761c3774882f16455a42d4ee6692b641bd0ccf14d81b56f0503932377bf5fae7d5a9c103c10e2ccd48e8778e0b217e8255746c998108508a6e81e1f1c1992ccd65ee9bfb196e0f7257c5dd5392cc0947e0b77bd30e18165c8a3541e62949e40c88c90fdf827133cbd17ab082f151d390180ca92cf0d8c4bd08e01b2f4f50b18bd589171d96723d00a3716420df0a98200f20a5136f36e955b51946a471eb029951e42268c00c34c53b660d2c636bf39e6f67e8933002c7b64fb410cd5e07cdac9e47d9d21c150a6fac33462496e7df033277558b54ac238f073776cb533551ced42caeba694f31fd8d40ccb9fb2e104aa0357a122141052c9a741c4c2c736b6dd0363ddbf27e2922ae2800cb93abe63b70c172de70362d9830e53800398884a7a64ff68ed99e0b9d2e26bdef115ced7bd36305a54386996133c4e65759f3731637a40eba67da103f98adbe364f148b0cc2042cafc6be1166fae39090ab4b354bfb6217b964453b63f8dbd10df936f1734973e0b3bd25f4ed440566c923085903f696bc6347ec0f6f3f63aab58e63b6449583df5658a91972a20291c6311b5b3e5240aff8d7d00212278dfeae9949f887b70ae81e084f8897a5054627acef3efd01c8b29793d522ca2ced953b7fb95e3ba986333da9e69cd355223c929731094b6c2174c7638d2e60040850b766b126a2b4843fcdfdffa5d5cab3f53bc860a3bef68958b5f066177097b04c2aa045a0deffcaca41c5ac92e694466578f5909e72bb78d33310f705cc2dcaa338b312112db04b435a706d63244dd435238f0aa1e9e1598d354708102dcc4273c8a0ed2337ecf7879380a07e7d427c7f9d82e538002bd1442978402cdaf63debf5b40df902dae98dadc029f281474d190cddecef1b10653248a234151f91982912012669f74d0cfa1030ff37b152324e5b8346b3335a0aaeb63a0a2de2bca6a8d987d668defba89dc082196a922634ed88e065c669e526bb8815ee1be8ae2ad91d463bab75ee941d33cc5817b613c63cda943a4c07f600591b088a25d53fdee371cef596766823f4a518a583b1158243afe89700f0da76da46d0060f15d2444cefe7914c9a61e829c730eceb216288fee825f6b3b6298f6f6b6bd62e4c57a617a0aa10ea7a83aa6b6b0ed685b6a3d9e5b8fd14f56cdc18021b12253f3fd4915c19bd831a7920be55d969b2ac23359e2559da77de2373f06ca014ba2787d063cd07ee4944222b7762840eb94c688bec743fa8bdf7715c8fe29f104c2a014c18207b76f3808351694eae9a99f8d7786e4c3e6b0c3452a518b0375deb0829012fac20755b7bb7c99d302b782ea36f62a1b0cfe8d7d4d09a58e8ba5da26f457803a080808008858180800880808080080000c86d0beb146429ab2ddc5e2b67b68cd0fa540c8a2c1637cde3220874577fd72337afa5c4823cffe1c5c57ba90eb737f081827bbf51437a2c420afa809bb04f3cc4046b05a8223b1b1114958bc0e10ecb6ae0b383ebd22f686f57d2f905acca999ae1e85f85acc5cb5b517b4233d3db94dc05259c76e8a04ae5d84f4331348388387edd327e40ae6b542f5b92cfa0a55f01ba9ba3f0035d64311f55042c1b86a8178f3ce47592cc1cdc3d4dfcbe66b267906a2c38313651863037d5fb3aeb4fcb85cb06e489536fe35784e5a1c0bc9a8083fd43ca2aeb18881caa02e9bde0a29ebb0ed1687299d97ce49bb6545050756fda15ee31c9cd947bf9019d90db96e89e3ee3e63717c34b485530590387b8bd2f57adc2c5b2fea35209ea22b4e2cb5e2d65e1f56cd1f16e5954bfb8425826cd87b75e57262d710bd1d5c9bd3b4a2c99a89926cc32c59e16ceb64698e1bcd82ae21d02ee4cb67e814861cd22810a0adaff558df41125e37179d16adc7cd4e1296bd31f44290e8c218664074158e724aee81a5ee5fb7f16852263b6902521c90dc4380b54aaf700a1ca6bd93a22ec1fd062f14b32f6d2d6ff51e151bfda4ccd569bfb966d294be0ee61dae648877e25b0841a27d5c224d4fd949926d4dfde6d28b7d14e16ae60d2112a79da714bb454a9f6a034a191c659fcd0c20a35d85f18b8700a29c5cb9c386f2afb10e8fafa892c3a1c5fbfee08cd58610339b7222f5945e775cfbe87089f48081b38775541cadeebbd5b51ee981b9558a0d4e01a0fba29d0b50fa9b843db2dbcc25071352041a199d7a85d5bd956d7f61db4a95cc26b1709fa48c0eba34676ee7f855b70ea4f8657f6f00180b43be23c6edd3259a84b873d560f60f5a7d7fd54b0330f835398c4ef2bb3a61d2fae5088b03c542ac58f663ad15cb471e39f6f06d2a47cd696bda59923f64718e81a5438f1711d43e284b9c566e596dc77f1e0809f96d40f76804c265ab9654c1ff8c18a1e8410164d09ae5bc1dd982eceb57c0114b0cac3e14c4e1a4a4fd22c98563b9cbe859c67768a39f67abd5dbe55d3d16ff58e5c45b21d8c573f54b901f0cb8b0701cdf9bded0827a82dc56ad98807f9c96ca814b2651a6b82d22a5c10d5fc80cdbd00000001207a636173685f636c69656e745f6261636b656e643a6f75747075745f696e666f11024951eeff9ccf4eb390ff94a60aa5673d015249a562d4ea0bc08e26f627c4a418d274e930230cab2139e2766d2654f0ed3903b882070039fb66568096852da4cb54410485be43a51a0269351ed32433ed7ddd1b12d43b00013b4c678abdaf00e1fc4587a41d1402c75bbc0dcc1c0e2b7652dc14352b87623f";
- let pczt_hex = hex::decode(hex_str).unwrap();
- let pczt = Pczt::parse(&pczt_hex).unwrap();
-
- let fingerprint = fingerprint.try_into().unwrap();
-
- let result = check_pczt_orchard(
- &MAIN_NETWORK,
- &fingerprint,
- zip32::AccountId::ZERO,
- &unified_fvk,
- &pczt,
- );
-
- assert!(result.is_ok());
- }
- }
- //TODO: add test for happy path
-}
diff --git a/rust/apps/zcash/src/pczt/mod.rs b/rust/apps/zcash/src/pczt/mod.rs
index 6939ba9..0784e3c 100644
--- a/rust/apps/zcash/src/pczt/mod.rs
+++ b/rust/apps/zcash/src/pczt/mod.rs
@@ -3,21 +3,13 @@ pub mod parse;
pub mod sign;
pub mod structs;
-use alloc::{format, string::ToString, vec::Vec};
-// Shared imports consumed by the not-yet-refactored `parse`/`sign` submodules via `use super::*`.
-// These move into those modules when they are refactored in a later commit.
-use keystore::algorithms::secp256k1::get_public_key_by_seed;
-use keystore::algorithms::zcash::calculate_seed_fingerprint;
-#[cfg(feature = "cypherpunk")]
-use keystore::algorithms::zcash::sign_message_orchard;
+use alloc::{format, string::ToString};
use zcash_vendor::{
pczt::Pczt,
transparent,
zcash_protocol::value::ZatBalance,
zip32,
};
-#[cfg(feature = "cypherpunk")]
-use zcash_vendor::orchard;
use crate::errors::ZcashError;
diff --git a/rust/zcash_vendor/Cargo.toml b/rust/zcash_vendor/Cargo.toml
index 499ea1f..65bf26b 100644
--- a/rust/zcash_vendor/Cargo.toml
+++ b/rust/zcash_vendor/Cargo.toml
@@ -41,31 +41,31 @@ chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
] }
postcard = { version = "1.0.3", features = ["alloc"] }
getset = { version = "0.1.3" }
-orchard = { version = "0.11", default-features = false, optional = true }
-pczt = { version = "0.2", default-features = false }
+orchard = { version = "0.14", default-features = false, optional = true }
+pczt = { version = "0.7", default-features = false }
serde = { workspace = true }
serde_with = { version = "3.11.0", features = [
"alloc",
"macros",
], default-features = false }
-transparent = { package = "zcash_transparent", version = "0.2", default-features = false, features = [
+transparent = { package = "zcash_transparent", version = "0.8", default-features = false, features = [
"transparent-inputs",
] }
-zcash_address = { version = "0.7", default-features = false }
-zcash_encoding = { version = "0.3", default-features = false }
-zcash_keys = { version = "0.8", default-features = false }
-zcash_protocol = { version = "0.5", default-features = false }
+zcash_address = { version = "0.12", default-features = false }
+zcash_encoding = { version = "0.4", default-features = false }
+zcash_keys = { version = "0.14", default-features = false }
+zcash_protocol = { version = "0.9", default-features = false }
zip32 = { version = "0.2", default-features = false }
rust_tools = { workspace = true }
#zcash end
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
- 'cfg(zcash_unstable, values("zfuture"))',
+ 'cfg(zcash_unstable, values("nu6.3", "zfuture"))',
] }
[dev-dependencies]
-transparent = { package = "zcash_transparent", version = "0.2", default-features = false, features = [
+transparent = { package = "zcash_transparent", version = "0.8", default-features = false, features = [
"transparent-inputs",
"test-dependencies",
] }
@@ -79,6 +79,7 @@ cypherpunk = ["transparent", "orchard"]
transparent = ["pczt/transparent", "zcash_keys/transparent-inputs"]
orchard = [
"pczt/orchard",
+ "pczt/signer",
"zcash_keys/orchard",
"dep:orchard",
]
diff --git a/rust/zcash_vendor/src/pczt_ext.rs b/rust/zcash_vendor/src/pczt_ext.rs
index 73e84ef..3926043 100644
--- a/rust/zcash_vendor/src/pczt_ext.rs
+++ b/rust/zcash_vendor/src/pczt_ext.rs
@@ -190,6 +190,7 @@ fn hash_transparent_tx_id(t_digests: Option<TransparentDigests>) -> Hash {
fn digest_orchard(pczt: &Pczt) -> Hash {
let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION);
+
let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION);
let mut mh = hasher(ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION);
let mut nh = hasher(ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION);
@@ -221,6 +222,7 @@ fn digest_orchard(pczt: &Pczt) -> Hash {
h.update(&value_balance.to_le_bytes());
h.update(pczt.orchard().anchor());
+
h.finalize()
}
@@ -371,9 +373,10 @@ fn transparent_sig_digest(pczt: &Pczt, input_info: Option<SignableInput>) -> Has
ch.update(input.prevout_txid());
ch.update(&input.prevout_index().to_le_bytes());
ch.update(&signable_input.value().to_i64_le_bytes());
- let len = signable_input.script_pubkey().0.len();
+ let script_pubkey = &signable_input.script_pubkey().0 .0;
+ let len = script_pubkey.len();
ch.update(&[len as u8]);
- ch.update(&signable_input.script_pubkey().0);
+ ch.update(script_pubkey);
ch.update(&input.sequence().unwrap_or(0xffffffff).to_le_bytes());
}
let txin_sig_digest = ch.finalize();
@@ -433,6 +436,7 @@ where
pub fn sign_orchard<T>(llsigner: Signer, signer: &T) -> Result<Signer, T::Error>
where
T: PcztSigner,
+ T::Error: From<pczt::orchard::BundleParseError>,
T::Error: From<orchard::pczt::ParseError>,
T::Error: From<transparent::pczt::ParseError>,
{
@@ -460,12 +464,43 @@ where
#[cfg(feature = "cypherpunk")]
#[cfg(test)]
mod tests {
+ use alloc::vec;
+
use pczt::Pczt;
- use transparent::{address::Script, sighash::SighashType};
+ use transparent::{
+ address::Script,
+ bundle::{Authorized, Bundle, OutPoint, TxIn},
+ sighash::SighashType,
+ };
use zcash_protocol::value::Zatoshis;
use super::*;
+ fn script_from_bytes(script_pubkey: &[u8]) -> Script {
+ let mut encoded = vec![script_pubkey.len() as u8];
+ encoded.extend_from_slice(script_pubkey);
+ Script::read(&encoded[..]).unwrap()
+ }
+
+ fn transparent_bundle_for_signable_inputs(pczt: &Pczt) -> Bundle<Authorized> {
+ Bundle {
+ vin: pczt
+ .transparent()
+ .inputs()
+ .iter()
+ .map(|input| {
+ TxIn::from_parts(
+ OutPoint::new(*input.prevout_txid(), *input.prevout_index()),
+ Script::default(),
+ input.sequence().unwrap_or(0xffffffff),
+ )
+ })
+ .collect(),
+ vout: vec![],
+ authorization: Authorized,
+ }
+ }
+
#[test]
fn test_basic_functions_orchard2orchard() {
//orchard to orchard
@@ -542,27 +577,32 @@ mod tests {
"fea284c0b63a4de21c2f660587b2e04461f7089d6c9f8c2e60a3caed77c037ae"
);
- let script_code = Script(pczt.transparent().inputs()[0].script_pubkey().clone());
+ let transparent_bundle = transparent_bundle_for_signable_inputs(&pczt);
+ let script_code = script_from_bytes(pczt.transparent().inputs()[0].script_pubkey());
let signable_input = SignableInput::from_parts(
+ &transparent_bundle,
SighashType::parse(SIGHASH_ALL).unwrap(),
0,
&script_code,
&script_code,
Zatoshis::from_u64(*pczt.transparent().inputs()[0].value()).unwrap(),
- );
+ )
+ .unwrap();
assert_eq!(
hex::encode(shielded_sig_commitment(&pczt, 0, Some(signable_input)).as_bytes()),
"a2865e1c7f3de700eee25fe233da6bbdab267d524bc788998485359441ad3140"
);
- let script_code = Script(pczt.transparent().inputs()[1].script_pubkey().clone());
+ let script_code = script_from_bytes(pczt.transparent().inputs()[1].script_pubkey());
let signable_input2 = SignableInput::from_parts(
+ &transparent_bundle,
SighashType::parse(SIGHASH_ALL).unwrap(),
1,
&script_code,
&script_code,
Zatoshis::from_u64(*pczt.transparent().inputs()[1].value()).unwrap(),
- );
+ )
+ .unwrap();
assert_eq!(
hex::encode(shielded_sig_commitment(&pczt, 0, Some(signable_input2)).as_bytes()),
"9c10678495dfdb1f29beb6583d652bc66cb4e3d27d24d75fb6922f230e9953e8"
Why this scored 27/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.