From 4623f98d9a87b8f71ce383866f823bff92461745 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 4 Jun 2021 11:05:56 -0600 Subject: [PATCH] Fix bugs in construction of Sapling txid hashes. --- zcash_primitives/src/transaction/mod.rs | 6 +++++- zcash_primitives/src/transaction/tests.rs | 2 +- zcash_primitives/src/transaction/txid.rs | 26 +++++++++++++---------- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 31b0c95bd..9dfa3d56f 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -640,7 +640,11 @@ impl Transaction { let orchard_bundle = Self::read_v5_orchard(&mut reader)?; #[cfg(feature = "zfuture")] - let tze_bundle = Self::read_tze(&mut reader)?; + let tze_bundle = if version.has_tze() { + Self::read_tze(&mut reader)? + } else { + None + }; let data = TransactionData { version, diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 5c3e48150..75029138f 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -162,9 +162,9 @@ fn zip_0243() { fn zip_0244() { for tv in self::data::zip_0244::make_test_vectors() { let tx = Transaction::read(&tv.tx[..], BranchId::Nu5).unwrap(); - let txid_parts = tx.deref().digest(TxIdDigester); assert_eq!(tx.txid.as_ref(), &tv.txid); + let txid_parts = tx.deref().digest(TxIdDigester); match tv.transparent_input { Some(n) => { let script = Script(tv.script_code.unwrap()); diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 0f532ad45..4195bb6f9 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -157,8 +157,12 @@ pub(crate) fn hash_sapling_spends( } let mut h = hasher(ZCASH_SAPLING_SPENDS_HASH_PERSONALIZATION); - h.write_all(&ch.finalize().as_bytes()).unwrap(); - h.write_all(&nh.finalize().as_bytes()).unwrap(); + if !shielded_spends.is_empty() { + let compact_digest = ch.finalize(); + h.write_all(&compact_digest.as_bytes()).unwrap(); + let noncompact_digest = nh.finalize(); + h.write_all(&noncompact_digest.as_bytes()).unwrap(); + } h.finalize() } @@ -185,9 +189,11 @@ pub(crate) fn hash_sapling_outputs(shielded_outputs: &[OutputDescription]) } let mut h = hasher(ZCASH_SAPLING_OUTPUTS_HASH_PERSONALIZATION); - h.write_all(&ch.finalize().as_bytes()).unwrap(); - h.write_all(&mh.finalize().as_bytes()).unwrap(); - h.write_all(&nh.finalize().as_bytes()).unwrap(); + if !shielded_outputs.is_empty() { + h.write_all(&ch.finalize().as_bytes()).unwrap(); + h.write_all(&mh.finalize().as_bytes()).unwrap(); + h.write_all(&nh.finalize().as_bytes()).unwrap(); + } h.finalize() } @@ -258,18 +264,16 @@ fn hash_sapling_txid_data( ) -> Blake2bHash { let mut h = hasher(ZCASH_SAPLING_HASH_PERSONALIZATION); if let Some(bundle) = sapling_bundle { - if !bundle.shielded_spends.is_empty() { + if !(bundle.shielded_spends.is_empty() && bundle.shielded_outputs.is_empty()) { h.write_all(hash_sapling_spends(&bundle.shielded_spends).as_bytes()) .unwrap(); - } - if !bundle.shielded_outputs.is_empty() { h.write_all(hash_sapling_outputs(&bundle.shielded_outputs).as_bytes()) .unwrap(); - } - h.write_all(&bundle.value_balance.to_i64_le_bytes()) - .unwrap(); + h.write_all(&bundle.value_balance.to_i64_le_bytes()) + .unwrap(); + } } h.finalize() }