From 3b8f0214eb18f4f2910297fcc316e32bde141608 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 1 Jul 2021 10:27:30 -0600 Subject: [PATCH 1/2] Move Orchard bundle commitments to the `orchard` crate. --- Cargo.toml | 4 +- .../src/transaction/components/amount.rs | 6 ++ .../src/transaction/components/orchard.rs | 14 ++-- zcash_primitives/src/transaction/mod.rs | 2 +- zcash_primitives/src/transaction/txid.rs | 78 ++----------------- 5 files changed, 23 insertions(+), 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 51e8569e2..ad09e8ee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,6 @@ codegen-units = 1 nom = { git = "https://github.com/myrrlyn/nom.git", rev = "d6b81f5303b0a347726e1f3f428751f376e7b771" } # In development. -halo2 = { git = "https://github.com/zcash/halo2.git", rev = "236115917df9db45282fec24d1e1e36f275f71ab" } -orchard = { git = "https://github.com/zcash/orchard.git", rev = "21b77d6ec56fc7e37aab9da68e88bc5dd754fe10" } +halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" } +orchard = { git = "https://github.com/zcash/orchard.git", rev = "8454f86d423edbf0b53a1d5d32df1c691f8b7188" } zcash_note_encryption = { path = "components/zcash_note_encryption" } diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs index 560badf9c..601d29132 100644 --- a/zcash_primitives/src/transaction/components/amount.rs +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -118,6 +118,12 @@ impl From for i64 { } } +impl From<&Amount> for i64 { + fn from(amount: &Amount) -> i64 { + amount.0 + } +} + impl From for u64 { fn from(amount: Amount) -> u64 { amount.0 as u64 diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 193199132..295e60509 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -20,6 +20,14 @@ pub const FLAG_SPENDS_ENABLED: u8 = 0b0000_0001; pub const FLAG_OUTPUTS_ENABLED: u8 = 0b0000_0010; pub const FLAGS_EXPECTED_UNSET: u8 = !(FLAG_SPENDS_ENABLED | FLAG_OUTPUTS_ENABLED); +/// Marker for a bundle with no proofs or signatures. +#[derive(Debug)] +pub struct Unauthorized; + +impl Authorization for Unauthorized { + type SpendAuth = (); +} + /// Reads an [`orchard::Bundle`] from a v5 transaction format. pub fn read_v5_bundle( mut reader: R, @@ -185,7 +193,7 @@ pub fn write_v5_bundle( write_flags(&mut writer, &bundle.flags())?; writer.write_all(&bundle.value_balance().to_i64_le_bytes())?; - write_anchor(&mut writer, bundle.anchor())?; + writer.write_all(&bundle.anchor().to_bytes())?; Vector::write( &mut writer, bundle.authorization().proof().as_ref(), @@ -257,10 +265,6 @@ pub fn write_flags(mut writer: W, flags: &Flags) -> io::Result<()> { writer.write_all(&[byte]) } -pub fn write_anchor(mut writer: W, anchor: &Anchor) -> io::Result<()> { - writer.write_all(&anchor.to_bytes()) -} - #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { use proptest::prelude::*; diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 3904c747c..28a25e919 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -255,7 +255,7 @@ pub struct Unauthorized; impl Authorization for Unauthorized { type TransparentAuth = transparent::builder::Unauthorized; type SaplingAuth = sapling::builder::Unauthorized; - type OrchardAuth = orchard::builder::Unauthorized; + type OrchardAuth = orchard_serialization::Unauthorized; #[cfg(feature = "zfuture")] type TzeAuth = tze::builder::Unauthorized; diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 9b31ce2a4..0b5fdcc4f 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -13,7 +13,6 @@ use crate::consensus::{BlockHeight, BranchId}; use super::{ components::{ amount::Amount, - orchard as ser_orch, sapling::{self, OutputDescription, SpendDescription}, transparent::{self, TxIn, TxOut}, }, @@ -33,7 +32,6 @@ const ZCASH_TX_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZcashTxHash_"; const ZCASH_HEADERS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdHeadersHash"; const ZCASH_TRANSPARENT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdTranspaHash"; const ZCASH_SAPLING_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdSaplingHash"; -const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; #[cfg(feature = "zfuture")] const ZCASH_TZE_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdTZE____Hash"; @@ -58,14 +56,9 @@ const ZCASH_SAPLING_OUTPUTS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdSOu const ZCASH_SAPLING_OUTPUTS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdSOutM__Hash"; const ZCASH_SAPLING_OUTPUTS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdSOutN__Hash"; -const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash"; -const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; -const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; - const ZCASH_AUTH_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZTxAuthHash_"; const ZCASH_TRANSPARENT_SCRIPTS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthTransHash"; const ZCASH_SAPLING_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthSapliHash"; -const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; #[cfg(feature = "zfuture")] const ZCASH_TZE_WITNESSES_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthTZE__Hash"; @@ -272,56 +265,6 @@ fn hash_sapling_txid_empty() -> Blake2bHash { hasher(ZCASH_SAPLING_HASH_PERSONALIZATION).finalize() } -/// Write disjoint parts of each Orchard shielded action as 3 separate hashes: -/// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION -/// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized -/// with ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION -/// * \[(cv, rk, enc_ciphertext\[564..\], out_ciphertext)*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION -/// -/// Then, hash these together along with (flags, value_balance_orchard, anchor_orchard), -/// personalized with ZCASH_ORCHARD_ACTIONS_HASH_PERSONALIZATION -fn hash_orchard_txid_data( - bundle: &orchard::Bundle, -) -> Blake2bHash { - 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); - - for action in bundle.actions().iter() { - ch.write_all(&action.nullifier().to_bytes()).unwrap(); - ch.write_all(&action.cmx().to_bytes()).unwrap(); - ch.write_all(&action.encrypted_note().epk_bytes).unwrap(); - ch.write_all(&action.encrypted_note().enc_ciphertext[..52]) - .unwrap(); - - mh.write_all(&action.encrypted_note().enc_ciphertext[52..564]) - .unwrap(); - - nh.write_all(&action.cv_net().to_bytes()).unwrap(); - nh.write_all(&<[u8; 32]>::from(action.rk())).unwrap(); - nh.write_all(&action.encrypted_note().enc_ciphertext[564..]) - .unwrap(); - nh.write_all(&action.encrypted_note().out_ciphertext) - .unwrap(); - } - - h.write_all(&ch.finalize().as_bytes()).unwrap(); - h.write_all(&mh.finalize().as_bytes()).unwrap(); - h.write_all(&nh.finalize().as_bytes()).unwrap(); - ser_orch::write_flags(&mut h, bundle.flags()).unwrap(); - h.write_all(&bundle.value_balance().to_i64_le_bytes()) - .unwrap(); - ser_orch::write_anchor(&mut h, bundle.anchor()).unwrap(); - h.finalize() -} - -fn hash_orchard_txid_empty() -> Blake2bHash { - hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION).finalize() -} - #[cfg(feature = "zfuture")] fn hash_tze_txid_data(tze_digests: Option<&TzeDigests>) -> Blake2bHash { let mut h = hasher(ZCASH_TZE_HASH_PERSONALIZATION); @@ -381,7 +324,7 @@ impl TransactionDigest for TxIdDigester { &self, orchard_bundle: Option<&orchard::Bundle>, ) -> Self::OrchardDigest { - orchard_bundle.map(hash_orchard_txid_data) + orchard_bundle.map(|b| b.commitment().0) } #[cfg(feature = "zfuture")] @@ -435,7 +378,7 @@ pub(crate) fn to_hash( .unwrap(); h.write_all( orchard_digest - .unwrap_or_else(hash_orchard_txid_empty) + .unwrap_or_else(orchard::commitments::hash_bundle_txid_empty) .as_bytes(), ) .unwrap(); @@ -537,20 +480,9 @@ impl TransactionDigest for BlockTxCommitmentDigester { &self, orchard_bundle: Option<&orchard::Bundle>, ) -> Self::OrchardDigest { - let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); - if let Some(bundle) = orchard_bundle { - h.write_all(bundle.authorization().proof().as_ref()) - .unwrap(); - for action in bundle.actions().iter() { - h.write_all(&<[u8; 64]>::from(action.authorization())) - .unwrap(); - } - h.write_all(&<[u8; 64]>::from( - bundle.authorization().binding_signature(), - )) - .unwrap(); - } - h.finalize() + orchard_bundle.map_or_else(orchard::commitments::hash_bundle_auth_empty, |b| { + b.authorizing_commitment().0 + }) } #[cfg(feature = "zfuture")] From 232feb71be6dbf8e318e8f73db613dd7da0e7e86 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 29 Jul 2021 10:37:23 -0600 Subject: [PATCH 2/2] Use orchard::Flags::to_byte/from_byte --- .../src/transaction/components/orchard.rs | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 295e60509..565ed187f 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -151,17 +151,7 @@ pub fn read_action_without_auth(mut reader: R) -> io::Result pub fn read_flags(mut reader: R) -> io::Result { let mut byte = [0u8; 1]; reader.read_exact(&mut byte)?; - if byte[0] & FLAGS_EXPECTED_UNSET == 0 { - Ok(Flags::from_parts( - byte[0] & FLAG_SPENDS_ENABLED != 0, - byte[0] & FLAG_OUTPUTS_ENABLED != 0, - )) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Unexpected bits set in Orchard flags value.", - )) - } + Flags::from_byte(byte[0]) } pub fn read_anchor(mut reader: R) -> io::Result { @@ -191,7 +181,7 @@ pub fn write_v5_bundle( write_action_without_auth(w, a) })?; - write_flags(&mut writer, &bundle.flags())?; + writer.write_all(&[bundle.flags().to_byte()])?; writer.write_all(&bundle.value_balance().to_i64_le_bytes())?; writer.write_all(&bundle.anchor().to_bytes())?; Vector::write( @@ -254,17 +244,6 @@ pub fn write_action_without_auth( Ok(()) } -pub fn write_flags(mut writer: W, flags: &Flags) -> io::Result<()> { - let mut byte = 0u8; - if flags.spends_enabled() { - byte |= FLAG_SPENDS_ENABLED; - } - if flags.outputs_enabled() { - byte |= FLAG_OUTPUTS_ENABLED; - } - writer.write_all(&[byte]) -} - #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { use proptest::prelude::*;