From 4b0f57bab40a517d9c0627acb62ee91fb0c902a5 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 31 Oct 2024 19:30:49 +0100 Subject: [PATCH 01/19] Implement OrchardBundle enum --- Cargo.toml | 2 +- zcash_primitives/src/transaction/builder.rs | 55 +++--- .../src/transaction/components/orchard.rs | 115 ++++++++++--- zcash_primitives/src/transaction/mod.rs | 162 +++++++++--------- zcash_primitives/src/transaction/tests.rs | 32 ++-- zcash_primitives/src/transaction/txid.rs | 44 +++-- 6 files changed, 238 insertions(+), 172 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 348c250f46..cd411d53e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ sapling = { package = "sapling-crypto", version = "0.1.3" } # - Orchard nonempty = "0.7" -orchard = { version = "0.8.0", default-features = false } +orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "spendauth_clone" } pasta_curves = "0.5" # - Transparent diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index d85ea3d643..4881bb209f 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -41,16 +41,7 @@ use crate::transaction::components::transparent::builder::TransparentInputInfo; #[cfg(not(feature = "transparent-inputs"))] use std::convert::Infallible; -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use orchard::{ - issuance, - issuance::{IssueBundle, IssueInfo}, - keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}, - orchard_flavor::OrchardZSA, -}; -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use rand_core::OsRng; - +use crate::transaction::OrchardBundle; #[cfg(zcash_unstable = "zfuture")] use crate::{ extensions::transparent::{ExtensionTxBuilder, ToPayload}, @@ -62,6 +53,15 @@ use crate::{ fees::FutureFeeRule, }, }; +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +use orchard::{ + issuance, + issuance::{IssueBundle, IssueInfo}, + keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}, + orchard_flavor::OrchardZSA, +}; +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +use rand_core::OsRng; /// Since Blossom activation, the default transaction expiry delta should be 40 blocks. /// @@ -868,8 +868,6 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< }; let mut unproven_orchard_bundle = None; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - let mut unproven_orchard_zsa_bundle = None; let mut orchard_meta = orchard::builder::BundleMetadata::empty(); if let Some(builder) = self.orchard_builder { @@ -879,12 +877,12 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_zsa_bundle = Some(bundle); + unproven_orchard_bundle = Some(OrchardBundle::OrchardZSA(bundle)); orchard_meta = meta; } } else { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_bundle = Some(bundle); + unproven_orchard_bundle = Some(OrchardBundle::OrchardVanilla(bundle)); orchard_meta = meta; } }; @@ -902,8 +900,6 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< sapling_bundle, orchard_bundle: unproven_orchard_bundle, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: unproven_orchard_zsa_bundle, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: self.issuance_builder, #[cfg(zcash_unstable = "zfuture")] tze_bundle, @@ -949,9 +945,8 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< .transpose() .map_err(Error::SaplingBuild)?; - let orchard_bundle = unauthed_tx - .orchard_bundle - .map(|b| { + let orchard_bundle: Option> = match unauthed_tx.orchard_bundle { + Some(OrchardBundle::OrchardVanilla(b)) => Some(OrchardBundle::OrchardVanilla( b.create_proof( &orchard::circuit::ProvingKey::build::(), &mut rng, @@ -963,14 +958,11 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< &self.orchard_saks, ) }) - }) - .transpose() - .map_err(Error::OrchardBuild)?; + .unwrap(), + )), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - let orchard_zsa_bundle = unauthed_tx - .orchard_zsa_bundle - .map(|b| { + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA( b.create_proof( &orchard::circuit::ProvingKey::build::(), &mut rng, @@ -982,9 +974,12 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< &self.orchard_saks, ) }) - }) - .transpose() - .map_err(Error::OrchardBuild)?; + .unwrap(), + )), + + None => None, + Some(_) => unreachable!(), + }; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] let issue_bundle = unauthed_tx @@ -1003,8 +998,6 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< sapling_bundle, orchard_bundle, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle, diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index f8eee9e8cd..6285eb8de1 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -16,9 +16,9 @@ use orchard::{ }; use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; - +use zcash_protocol::value::ZatBalance; use super::Amount; -use crate::transaction::Transaction; +use crate::transaction::{OrchardBundle, Transaction}; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use byteorder::LittleEndian; @@ -51,6 +51,58 @@ impl MapAuth for () { } } +pub trait BuildBundle { + fn build_bundle( + actions: NonEmpty>, + flags: Flags, + value_balance: Amount, + burn: Vec<(AssetBase, NoteValue)>, + anchor: Anchor, + authorization: A, + ) -> OrchardBundle; +} + +impl BuildBundle for OrchardVanilla { + fn build_bundle( + actions: NonEmpty>, + flags: Flags, + value_balance: Amount, + burn: Vec<(AssetBase, NoteValue)>, + anchor: Anchor, + authorization: A, + ) -> OrchardBundle { + OrchardBundle::OrchardVanilla(Bundle::from_parts( + actions, + flags, + value_balance, + burn, + anchor, + authorization, + )) + } +} + +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +impl BuildBundle for OrchardZSA { + fn build_bundle( + actions: NonEmpty>, + flags: Flags, + value_balance: Amount, + burn: Vec<(AssetBase, NoteValue)>, + anchor: Anchor, + authorization: A, + ) -> OrchardBundle { + OrchardBundle::OrchardZSA(orchard::Bundle::from_parts( + actions, + flags, + value_balance, + burn, + anchor, + authorization, + )) + } +} + pub trait ReadBurn { fn read_burn(reader: &mut R) -> io::Result>; } @@ -63,6 +115,7 @@ impl ReadBurn for OrchardVanilla { } // Read burn for OrchardZSA +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] impl ReadBurn for OrchardZSA { fn read_burn(reader: &mut R) -> io::Result> { Vector::read(reader, |r| read_burn(r)) @@ -310,6 +363,26 @@ impl WriteBurn for OrchardZSA { /// Writes an [`orchard::Bundle`] in the appropriate transaction format. pub fn write_orchard_bundle( + mut writer: W, + bundle: Option<&OrchardBundle>, +) -> io::Result<()> { + if let Some(bundle) = &bundle { + match bundle { + OrchardBundle::OrchardVanilla(b) => { write_orchard_vanilla_bundle(b, writer)? } + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(b) => { write_orchard_zsa_bundle(b, writer)? }, + _ => unreachable!(), + } + } else { + CompactSize::write(&mut writer, 0)?; + } + + Ok(()) +} + + +/// Writes an [`orchard::Bundle`] in the appropriate transaction format. +pub fn write_orchard_vanilla_bundle( mut writer: W, bundle: Option<&orchard::Bundle>, ) -> io::Result<()> { @@ -432,35 +505,22 @@ pub fn write_action_without_auth( #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { + use orchard::Bundle; use proptest::prelude::*; use crate::transaction::components::amount::testing::arb_amount; - use crate::transaction::components::Amount; - use crate::transaction::TxVersion; - use orchard::bundle::{ - testing::{self as t_orch}, - Authorized, Bundle, - }; - use orchard::orchard_flavor::{OrchardVanilla, OrchardZSA}; + use crate::transaction::{OrchardBundle, TxVersion}; + use orchard::bundle::{testing::{self as t_orch}, Authorized}; + use orchard::orchard_flavor::OrchardZSA; prop_compose! { pub fn arb_bundle(n_actions: usize)( orchard_value_balance in arb_amount(), bundle in t_orch::BundleArb::arb_bundle(n_actions) - ) -> Bundle { + ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap() - } - } - - pub fn arb_bundle_for_version( - v: TxVersion, - ) -> impl Strategy>> { - if v.has_orchard() { - Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_bundle(n)))) - } else { - Strategy::boxed(Just(None)) + OrchardBundle::OrchardVanilla(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap()) } } @@ -468,18 +528,23 @@ pub mod testing { pub fn arb_zsa_bundle(n_actions: usize)( orchard_value_balance in arb_amount(), bundle in t_orch::BundleArb::arb_bundle(n_actions) - ) -> Bundle { + ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap() + let bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + return OrchardBundle::OrchardZSA(bundle); + panic!("ZSA is not supported in this version"); } } - pub fn arb_zsa_bundle_for_version( + pub fn arb_bundle_for_version( v: TxVersion, - ) -> impl Strategy>> { + ) -> impl Strategy>> { if v.has_orchard_zsa() { Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_zsa_bundle(n)))) + } else if v.has_orchard() { + Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_bundle(n)))) } else { Strategy::boxed(Just(None)) } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 2b974fe108..41891b2542 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -14,11 +14,14 @@ mod tests; use blake2b_simd::Hash as Blake2bHash; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use memuse::DynamicUsage; -use orchard::{builder::Unproven, orchard_flavor::OrchardVanilla}; +use orchard::{ + builder::Unproven, orchard_flavor::OrchardVanilla, orchard_flavor::OrchardZSA, Bundle, +}; use std::convert::TryFrom; use std::fmt; use std::fmt::Debug; use std::io::{self, Read, Write}; +use std::marker::PhantomData; use std::ops::Deref; use zcash_encoding::{CompactSize, Vector}; @@ -39,13 +42,13 @@ use self::{ util::sha256d::{HashReader, HashWriter}, }; +#[cfg(zcash_unstable = "zfuture")] +use self::components::tze::{self, TzeIn, TzeOut}; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use crate::transaction::components::issuance; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use orchard::{issuance::IssueBundle, orchard_flavor::OrchardZSA}; - -#[cfg(zcash_unstable = "zfuture")] -use self::components::tze::{self, TzeIn, TzeOut}; +use orchard::issuance::IssueBundle; +use zcash_protocol::value::ZatBalance; const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C48270; const OVERWINTER_TX_VERSION: u32 = 3; @@ -299,7 +302,6 @@ pub trait Authorization { type SaplingAuth: sapling::bundle::Authorization; type OrchardAuth: orchard::bundle::Authorization; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type OrchardZsaAuth: orchard::bundle::Authorization; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -310,7 +312,7 @@ pub trait Authorization { } /// [`Authorization`] marker type for fully-authorized transactions. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Authorized; impl Authorization for Authorized { @@ -318,7 +320,6 @@ impl Authorization for Authorized { type SaplingAuth = sapling::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type OrchardZsaAuth = orchard::bundle::Authorized; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -371,6 +372,65 @@ impl PartialEq for Transaction { } } +#[derive(Debug, Clone)] +pub enum OrchardBundle { + OrchardVanilla(Bundle), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardZSA(Bundle), + #[doc(hidden)] + _Phantom(PhantomData), +} + +/// Errors that can occur during transaction construction. +#[derive(Debug)] +pub enum BundleError { + WrongBundleType, +} + +impl OrchardBundle { + pub fn value_balance(&self) -> &Amount { + match self { + OrchardBundle::OrchardVanilla(b) => b.value_balance(), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(b) => b.value_balance(), + _ => unreachable!(), + } + } + + pub fn map_authorization< + R, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] R2, + NV: orchard::bundle::Authorization, + NZ: orchard::bundle::Authorization, + >( + self, + context: &mut R, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] context_zsa: &mut R2, + spend_auth: impl FnMut(&mut R, &V, V::SpendAuth) -> NV::SpendAuth, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] spend_auth_zsa: impl FnMut( + &mut R2, + &Z, + Z::SpendAuth, + ) + -> NZ::SpendAuth, + step: impl FnOnce(&mut R, V) -> NV, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] step_zsa: impl FnOnce(&mut R2, Z) -> NZ, + ) -> OrchardBundle { + match self { + OrchardBundle::OrchardVanilla(b) => { + OrchardBundle::OrchardVanilla(b.map_authorization(context, spend_auth, step)) + } + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(b) => OrchardBundle::OrchardZSA(b.map_authorization( + context_zsa, + spend_auth_zsa, + step_zsa, + )), + _ => unreachable!(), + } + } +} + /// The information contained in a Zcash transaction. #[derive(Debug)] pub struct TransactionData { @@ -381,9 +441,7 @@ pub struct TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: Option>, + orchard_bundle: Option>, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: Option>, #[cfg(zcash_unstable = "zfuture")] @@ -401,10 +459,7 @@ impl TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, - #[rustfmt::skip] - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: Option>, + orchard_bundle: Option>, #[rustfmt::skip] #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: Option>, @@ -419,8 +474,6 @@ impl TransactionData { sapling_bundle, orchard_bundle, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle: None, @@ -439,7 +492,7 @@ impl TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, + orchard_bundle: Option>, tze_bundle: Option>, ) -> Self { TransactionData { @@ -485,19 +538,10 @@ impl TransactionData { self.sapling_bundle.as_ref() } - pub fn orchard_bundle( - &self, - ) -> Option<&orchard::Bundle> { + pub fn orchard_bundle(&self) -> Option<&OrchardBundle> { self.orchard_bundle.as_ref() } - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - pub fn orchard_zsa_bundle( - &self, - ) -> Option<&orchard::Bundle> { - self.orchard_zsa_bundle.as_ref() - } - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] pub fn issue_bundle(&self) -> Option<&IssueBundle> { self.issue_bundle.as_ref() @@ -556,20 +600,10 @@ impl TransactionData { ) } - #[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */ ))] fn digest_orchard>(&self, digester: &D) -> D::OrchardDigest { digester.digest_orchard(self.orchard_bundle.as_ref()) } - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - fn digest_orchard>(&self, digester: &D) -> D::OrchardDigest { - if self.version.has_orchard_zsa() { - digester.digest_orchard_zsa(self.orchard_zsa_bundle.as_ref()) - } else { - digester.digest_orchard(self.orchard_bundle.as_ref()) - } - } - /// Maps the bundles from one type to another. /// /// This shouldn't be necessary for most use cases; it is provided for handling the @@ -583,17 +617,8 @@ impl TransactionData { Option>, ) -> Option>, f_orchard: impl FnOnce( - Option>, - ) -> Option< - orchard::bundle::Bundle, - >, - #[rustfmt::skip] - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - f_zsa_orchard: impl FnOnce( - Option>, - ) -> Option< - orchard::bundle::Bundle, - >, + Option>, + ) -> Option>, #[rustfmt::skip] #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] f_issue: impl FnOnce( @@ -614,8 +639,6 @@ impl TransactionData { sapling_bundle: f_sapling(self.sapling_bundle), orchard_bundle: f_orchard(self.orchard_bundle), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: f_zsa_orchard(self.orchard_zsa_bundle), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: f_issue(self.issue_bundle), #[cfg(zcash_unstable = "zfuture")] tze_bundle: f_tze(self.tze_bundle), @@ -658,15 +681,13 @@ impl TransactionData { orchard_bundle: self.orchard_bundle.map(|b| { b.map_authorization( &mut f_orchard, - |f, _, s| f.map_spend_auth(s), - |f, a| f.map_authorization(a), - ) - }), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: self.orchard_zsa_bundle.map(|b| { - b.map_authorization( + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] &mut f_orchard_zsa, |f, _, s| f.map_spend_auth(s), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + |f, _, s| f.map_spend_auth(s), + |f, a| f.map_authorization(a), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] |f, a| f.map_authorization(a), ) }), @@ -831,8 +852,6 @@ impl Transaction { }), orchard_bundle: None, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: None, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: None, #[cfg(zcash_unstable = "zfuture")] tze_bundle: None, @@ -868,7 +887,8 @@ impl Transaction { Self::read_v5_header_fragment(&mut reader)?; let transparent_bundle = Self::read_transparent(&mut reader)?; let sapling_bundle = sapling_serialization::read_v5_bundle(&mut reader)?; - let orchard_bundle = orchard_serialization::read_orchard_bundle(&mut reader)?; + let orchard_bundle: Option> = + orchard_serialization::read_orchard_bundle(&mut reader)?; #[cfg(zcash_unstable = "zfuture")] let tze_bundle = if version.has_tze() { @@ -885,9 +905,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: None, + orchard_bundle: orchard_bundle.map(OrchardBundle::OrchardVanilla), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: None, #[cfg(zcash_unstable = "zfuture")] @@ -942,8 +960,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: None, - orchard_zsa_bundle, + orchard_bundle: orchard_bundle.map(OrchardBundle::OrchardZSA), issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle, @@ -1082,7 +1099,7 @@ impl Transaction { self.write_sapling(&mut writer)?; orchard_serialization::write_orchard_zsa_bundle( &mut writer, - self.orchard_zsa_bundle.as_ref(), + self.orchard_bundle.as_ref(), )?; issuance::write_v6_bundle(self.issue_bundle.as_ref(), &mut writer)?; #[cfg(zcash_unstable = "zfuture")] @@ -1169,13 +1186,7 @@ pub trait TransactionDigest { fn digest_orchard( &self, - orchard_bundle: Option<&orchard::Bundle>, - ) -> Self::OrchardDigest; - - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - fn digest_orchard_zsa( - &self, - orchard_bundle: Option<&orchard::Bundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -1250,7 +1261,6 @@ pub mod testing { transparent_bundle in transparent_testing::arb_bundle(), sapling_bundle in sapling_testing::arb_bundle_for_version(version), orchard_bundle in orchard_testing::arb_bundle_for_version(version), - _orchard_zsa_bundle in orchard_testing::arb_zsa_bundle_for_version(version), _issue_bundle in issuance::testing::arb_bundle_for_version(version), version in Just(version) ) -> TransactionData { @@ -1264,8 +1274,6 @@ pub mod testing { sapling_bundle, orchard_bundle, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - orchard_zsa_bundle: _orchard_zsa_bundle, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: _issue_bundle, } } diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index 14fd491b94..e6c6171951 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -3,10 +3,6 @@ use std::ops::Deref; use proptest::prelude::*; -use crate::{ - consensus::BranchId, legacy::Script, transaction::components::amount::NonNegativeAmount, -}; - use super::{ sapling, sighash::{ @@ -20,6 +16,12 @@ use super::{ txid::TxIdDigester, Authorization, Transaction, TransactionData, TxDigests, TxIn, }; +use crate::transaction::OrchardBundle::OrchardVanilla; +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +use crate::transaction::OrchardBundle::OrchardZSA; +use crate::{ + consensus::BranchId, legacy::Script, transaction::components::amount::NonNegativeAmount, +}; #[cfg(zcash_unstable = "zfuture")] use super::components::tze; @@ -53,13 +55,18 @@ fn check_roundtrip(tx: Transaction) -> Result<(), TestCaseError> { ); prop_assert_eq!(tx.sapling_value_balance(), txo.sapling_value_balance()); prop_assert_eq!( - tx.orchard_bundle.as_ref().map(|v| *v.value_balance()), - txo.orchard_bundle.as_ref().map(|v| *v.value_balance()) - ); - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - prop_assert_eq!( - tx.orchard_zsa_bundle.as_ref().map(|v| *v.value_balance()), - txo.orchard_zsa_bundle.as_ref().map(|v| *v.value_balance()) + tx.orchard_bundle.as_ref().map(|v| match v { + OrchardVanilla(b) => *b.value_balance(), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardZSA(b) => *b.value_balance(), + _ => unreachable!(), + }), + txo.orchard_bundle.as_ref().map(|v| match v { + OrchardVanilla(b) => *b.value_balance(), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardZSA(b) => *b.value_balance(), + _ => unreachable!(), + }) ); #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] if tx.issue_bundle.is_some() { @@ -221,7 +228,6 @@ impl Authorization for TestUnauthorized { type SaplingAuth = sapling::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type OrchardZsaAuth = orchard::bundle::Authorized; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -296,8 +302,6 @@ fn zip_0244() { txdata.sapling_bundle().cloned(), txdata.orchard_bundle().cloned(), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - txdata.orchard_zsa_bundle().cloned(), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] txdata.issue_bundle().cloned(), ); #[cfg(zcash_unstable = "zfuture")] diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index a89537c1fd..09af65c49c 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -6,7 +6,6 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; use byteorder::{LittleEndian, WriteBytesExt}; use ff::PrimeField; use orchard::bundle; -use orchard::orchard_flavor::OrchardVanilla; use crate::{ consensus::{BlockHeight, BranchId}, @@ -21,7 +20,8 @@ use super::{ amount::Amount, transparent::{self, TxIn, TxOut}, }, - Authorization, Authorized, TransactionDigest, TransparentDigests, TxDigests, TxId, TxVersion, + Authorization, Authorized, OrchardBundle, TransactionDigest, TransparentDigests, TxDigests, + TxId, TxVersion, }; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -347,17 +347,16 @@ impl TransactionDigest for TxIdDigester { fn digest_orchard( &self, - orchard_bundle: Option<&bundle::Bundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest { - orchard_bundle.map(|b| b.commitment().0) - } - - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - fn digest_orchard_zsa( - &self, - orchard_bundle: Option<&bundle::Bundle>, - ) -> Self::OrchardDigest { - orchard_bundle.map(|b| b.commitment().0) + orchard_bundle.map(|b| { + match b { + OrchardBundle::OrchardVanilla(vanilla_bundle) => vanilla_bundle.commitment().0, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.commitment().0, + _ => unreachable!(), + } + }) } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -541,20 +540,17 @@ impl TransactionDigest for BlockTxCommitmentDigester { fn digest_orchard( &self, - orchard_bundle: Option<&bundle::Bundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest { orchard_bundle.map_or_else(bundle::commitments::hash_bundle_auth_empty, |b| { - b.authorizing_commitment().0 - }) - } - - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - fn digest_orchard_zsa( - &self, - orchard_bundle: Option<&bundle::Bundle>, - ) -> Self::OrchardDigest { - orchard_bundle.map_or_else(bundle::commitments::hash_bundle_auth_empty, |b| { - b.authorizing_commitment().0 + match b { + OrchardBundle::OrchardVanilla(vanilla_bundle) => { + vanilla_bundle.authorizing_commitment().0 + } + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.authorizing_commitment().0, + _ => unreachable!(), + } }) } From 58b313810df8ddcdabf0106304d6e34aace206a3 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 31 Oct 2024 19:34:31 +0100 Subject: [PATCH 02/19] Clean up build warnings --- .../src/transaction/components/orchard.rs | 17 ++++++++++++----- zcash_primitives/src/transaction/txid.rs | 1 - 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 6285eb8de1..0b6dd6ad1b 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -2,7 +2,10 @@ use std::convert::TryFrom; use std::io::{self, Read, Write}; +use super::Amount; +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use crate::transaction::components::issuance::read_asset; +use crate::transaction::{OrchardBundle, Transaction}; use byteorder::{ReadBytesExt, WriteBytesExt}; use nonempty::NonEmpty; use orchard::{ @@ -17,8 +20,6 @@ use orchard::{ use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; use zcash_protocol::value::ZatBalance; -use super::Amount; -use crate::transaction::{OrchardBundle, Transaction}; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use byteorder::LittleEndian; @@ -218,6 +219,7 @@ pub fn read_orchard_zsa_bundle( ))) } +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] fn read_burn(reader: &mut R) -> io::Result<(AssetBase, NoteValue)> { Ok((read_asset(reader)?, read_note_value(reader)?)) } @@ -339,6 +341,7 @@ pub fn read_signature(mut reader: R) -> io::Result(mut reader: R) -> io::Result { let mut bytes = [0; 8]; reader.read_exact(&mut bytes)?; @@ -510,7 +513,10 @@ pub mod testing { use crate::transaction::components::amount::testing::arb_amount; use crate::transaction::{OrchardBundle, TxVersion}; - use orchard::bundle::{testing::{self as t_orch}, Authorized}; + use orchard::bundle::{ + testing::{self as t_orch}, + Authorized, + }; use orchard::orchard_flavor::OrchardZSA; prop_compose! { @@ -525,15 +531,16 @@ pub mod testing { } prop_compose! { + #[allow(unreachable_code)] pub fn arb_zsa_bundle(n_actions: usize)( orchard_value_balance in arb_amount(), bundle in t_orch::BundleArb::arb_bundle(n_actions) ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - let bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); + let _bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - return OrchardBundle::OrchardZSA(bundle); + return OrchardBundle::OrchardZSA(_bundle); panic!("ZSA is not supported in this version"); } } diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 09af65c49c..0a288be5b2 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -27,7 +27,6 @@ use super::{ #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use orchard::{ issuance::{IssueBundle, Signed}, - orchard_flavor::OrchardZSA, }; #[cfg(zcash_unstable = "zfuture")] From 4fd1fd9d38e2aefa3f87e2f1de15d92c88bb2d3e Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 31 Oct 2024 19:47:35 +0100 Subject: [PATCH 03/19] Fix clippy warnings --- zcash_primitives/src/transaction/builder.rs | 32 ++++++++++--------- .../src/transaction/components/orchard.rs | 12 +++---- zcash_primitives/src/transaction/mod.rs | 18 +++++------ zcash_primitives/src/transaction/txid.rs | 4 +-- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 4881bb209f..2b67a1e227 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -877,7 +877,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_bundle = Some(OrchardBundle::OrchardZSA(bundle)); + unproven_orchard_bundle = Some(OrchardBundle::OrchardZSA(Box::new(bundle))); orchard_meta = meta; } } else { @@ -946,24 +946,26 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< .map_err(Error::SaplingBuild)?; let orchard_bundle: Option> = match unauthed_tx.orchard_bundle { - Some(OrchardBundle::OrchardVanilla(b)) => Some(OrchardBundle::OrchardVanilla( - b.create_proof( - &orchard::circuit::ProvingKey::build::(), - &mut rng, - ) - .and_then(|b| { - b.apply_signatures( + Some(OrchardBundle::OrchardVanilla(b)) => { + Some(OrchardBundle::OrchardVanilla(Box::new( + b.create_proof( + &orchard::circuit::ProvingKey::build::(), &mut rng, - *shielded_sig_commitment.as_ref(), - &self.orchard_saks, ) - }) - .unwrap(), - )), + .and_then(|b| { + b.apply_signatures( + &mut rng, + *shielded_sig_commitment.as_ref(), + &self.orchard_saks, + ) + }) + .unwrap(), + ))) + } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA( - b.create_proof( + Box::new(b.create_proof( &orchard::circuit::ProvingKey::build::(), &mut rng, ) @@ -975,7 +977,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< ) }) .unwrap(), - )), + ))), None => None, Some(_) => unreachable!(), diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 0b6dd6ad1b..f3f5111604 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -72,14 +72,14 @@ impl BuildBundle for OrchardVanilla { anchor: Anchor, authorization: A, ) -> OrchardBundle { - OrchardBundle::OrchardVanilla(Bundle::from_parts( + OrchardBundle::OrchardVanilla(Box::new(Bundle::from_parts( actions, flags, value_balance, burn, anchor, authorization, - )) + ))) } } @@ -93,14 +93,14 @@ impl BuildBundle for OrchardZSA { anchor: Anchor, authorization: A, ) -> OrchardBundle { - OrchardBundle::OrchardZSA(orchard::Bundle::from_parts( + OrchardBundle::OrchardZSA(Box::new(orchard::Bundle::from_parts( actions, flags, value_balance, burn, anchor, authorization, - )) + ))) } } @@ -526,7 +526,7 @@ pub mod testing { ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - OrchardBundle::OrchardVanilla(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap()) + OrchardBundle::OrchardVanilla(Box::new(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap())) } } @@ -540,7 +540,7 @@ pub mod testing { // value doesn't exceed the MAX_MONEY bounds. let _bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - return OrchardBundle::OrchardZSA(_bundle); + return OrchardBundle::OrchardZSA(Box::new(_bundle)); panic!("ZSA is not supported in this version"); } } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 41891b2542..2659821aa0 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -374,9 +374,9 @@ impl PartialEq for Transaction { #[derive(Debug, Clone)] pub enum OrchardBundle { - OrchardVanilla(Bundle), + OrchardVanilla(Box>), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardZSA(Bundle), + OrchardZSA(Box>), #[doc(hidden)] _Phantom(PhantomData), } @@ -417,15 +417,15 @@ impl Orcha #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] step_zsa: impl FnOnce(&mut R2, Z) -> NZ, ) -> OrchardBundle { match self { - OrchardBundle::OrchardVanilla(b) => { - OrchardBundle::OrchardVanilla(b.map_authorization(context, spend_auth, step)) - } + OrchardBundle::OrchardVanilla(b) => OrchardBundle::OrchardVanilla(Box::new( + b.map_authorization(context, spend_auth, step), + )), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(b) => OrchardBundle::OrchardZSA(b.map_authorization( + OrchardBundle::OrchardZSA(b) => OrchardBundle::OrchardZSA(Box::new(b.map_authorization( context_zsa, spend_auth_zsa, step_zsa, - )), + ))), _ => unreachable!(), } } @@ -905,7 +905,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: orchard_bundle.map(OrchardBundle::OrchardVanilla), + orchard_bundle: orchard_bundle.map(|b| OrchardBundle::OrchardVanilla(Box::new(b))), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: None, #[cfg(zcash_unstable = "zfuture")] @@ -960,7 +960,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: orchard_bundle.map(OrchardBundle::OrchardZSA), + orchard_bundle: orchard_bundle.map(|b| OrchardBundle::OrchardZSA(Box::new(b))), issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle, diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 0a288be5b2..e730ad8781 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -25,9 +25,7 @@ use super::{ }; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use orchard::{ - issuance::{IssueBundle, Signed}, -}; +use orchard::issuance::{IssueBundle, Signed}; #[cfg(zcash_unstable = "zfuture")] use super::{ From 509268446f2d474e1c5fabdeec2f7aa0221aa3ca Mon Sep 17 00:00:00 2001 From: alexey <2365507+alexeykoren@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:27:20 +0100 Subject: [PATCH 04/19] Remove OrchardZsaAuth --- Cargo.toml | 2 +- rust-toolchain.toml | 2 +- zcash_primitives/src/transaction/builder.rs | 7 +- .../src/transaction/components/orchard.rs | 18 ++--- zcash_primitives/src/transaction/mod.rs | 78 +++++-------------- zcash_primitives/src/transaction/tests.rs | 4 - zcash_primitives/src/transaction/txid.rs | 6 +- 7 files changed, 35 insertions(+), 82 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cd411d53e6..fd6eebc92c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ sapling = { package = "sapling-crypto", version = "0.1.3" } # - Orchard nonempty = "0.7" -orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "spendauth_clone" } +orchard = "0.8.0" pasta_curves = "0.5" # - Transparent diff --git a/rust-toolchain.toml b/rust-toolchain.toml index cad9254a9c..6ea608282d 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.70.0" +channel = "1.71.0" components = [ "clippy", "rustfmt" ] diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 2b67a1e227..aba6438c19 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -945,7 +945,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< .transpose() .map_err(Error::SaplingBuild)?; - let orchard_bundle: Option> = match unauthed_tx.orchard_bundle { + let orchard_bundle: Option> = match unauthed_tx.orchard_bundle { Some(OrchardBundle::OrchardVanilla(b)) => { Some(OrchardBundle::OrchardVanilla(Box::new( b.create_proof( @@ -964,8 +964,8 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA( - Box::new(b.create_proof( + Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA(Box::new( + b.create_proof( &orchard::circuit::ProvingKey::build::(), &mut rng, ) @@ -980,7 +980,6 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< ))), None => None, - Some(_) => unreachable!(), }; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index f3f5111604..514f37a647 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -60,7 +60,7 @@ pub trait BuildBundle { burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, authorization: A, - ) -> OrchardBundle; + ) -> OrchardBundle; } impl BuildBundle for OrchardVanilla { @@ -71,7 +71,7 @@ impl BuildBundle for OrchardVanilla { burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, authorization: A, - ) -> OrchardBundle { + ) -> OrchardBundle { OrchardBundle::OrchardVanilla(Box::new(Bundle::from_parts( actions, flags, @@ -92,7 +92,7 @@ impl BuildBundle for OrchardZSA { burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, authorization: A, - ) -> OrchardBundle { + ) -> OrchardBundle { OrchardBundle::OrchardZSA(Box::new(orchard::Bundle::from_parts( actions, flags, @@ -367,13 +367,13 @@ impl WriteBurn for OrchardZSA { /// Writes an [`orchard::Bundle`] in the appropriate transaction format. pub fn write_orchard_bundle( mut writer: W, - bundle: Option<&OrchardBundle>, + bundle: Option<&OrchardBundle>, ) -> io::Result<()> { if let Some(bundle) = &bundle { match bundle { - OrchardBundle::OrchardVanilla(b) => { write_orchard_vanilla_bundle(b, writer)? } + OrchardBundle::OrchardVanilla(b) => write_orchard_vanilla_bundle(b, writer)?, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(b) => { write_orchard_zsa_bundle(b, writer)? }, + OrchardBundle::OrchardZSA(b) => write_orchard_bundle_contents(b, writer)?, _ => unreachable!(), } } else { @@ -523,7 +523,7 @@ pub mod testing { pub fn arb_bundle(n_actions: usize)( orchard_value_balance in arb_amount(), bundle in t_orch::BundleArb::arb_bundle(n_actions) - ) -> OrchardBundle { + ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. OrchardBundle::OrchardVanilla(Box::new(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap())) @@ -535,7 +535,7 @@ pub mod testing { pub fn arb_zsa_bundle(n_actions: usize)( orchard_value_balance in arb_amount(), bundle in t_orch::BundleArb::arb_bundle(n_actions) - ) -> OrchardBundle { + ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. let _bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); @@ -547,7 +547,7 @@ pub mod testing { pub fn arb_bundle_for_version( v: TxVersion, - ) -> impl Strategy>> { + ) -> impl Strategy>> { if v.has_orchard_zsa() { Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_zsa_bundle(n)))) } else if v.has_orchard() { diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 2659821aa0..7449bcc4a2 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -14,14 +14,11 @@ mod tests; use blake2b_simd::Hash as Blake2bHash; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use memuse::DynamicUsage; -use orchard::{ - builder::Unproven, orchard_flavor::OrchardVanilla, orchard_flavor::OrchardZSA, Bundle, -}; +use orchard::{builder::Unproven, orchard_flavor::OrchardVanilla, Bundle}; use std::convert::TryFrom; use std::fmt; use std::fmt::Debug; use std::io::{self, Read, Write}; -use std::marker::PhantomData; use std::ops::Deref; use zcash_encoding::{CompactSize, Vector}; @@ -47,7 +44,7 @@ use self::components::tze::{self, TzeIn, TzeOut}; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use crate::transaction::components::issuance; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use orchard::issuance::IssueBundle; +use orchard::{issuance::IssueBundle, orchard_flavor::OrchardZSA}; use zcash_protocol::value::ZatBalance; const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C48270; @@ -302,8 +299,6 @@ pub trait Authorization { type SaplingAuth: sapling::bundle::Authorization; type OrchardAuth: orchard::bundle::Authorization; - type OrchardZsaAuth: orchard::bundle::Authorization; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth: orchard::issuance::IssueAuth; @@ -320,8 +315,6 @@ impl Authorization for Authorized { type SaplingAuth = sapling::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - type OrchardZsaAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; @@ -341,9 +334,6 @@ impl Authorization for Unauthorized { sapling_builder::InProgress; type OrchardAuth = orchard::builder::InProgress; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - type OrchardZsaAuth = orchard::builder::InProgress; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Unauthorized; @@ -373,12 +363,10 @@ impl PartialEq for Transaction { } #[derive(Debug, Clone)] -pub enum OrchardBundle { - OrchardVanilla(Box>), +pub enum OrchardBundle { + OrchardVanilla(Box>), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardZSA(Box>), - #[doc(hidden)] - _Phantom(PhantomData), + OrchardZSA(Box>), } /// Errors that can occur during transaction construction. @@ -387,46 +375,29 @@ pub enum BundleError { WrongBundleType, } -impl OrchardBundle { +impl OrchardBundle { pub fn value_balance(&self) -> &Amount { match self { OrchardBundle::OrchardVanilla(b) => b.value_balance(), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardBundle::OrchardZSA(b) => b.value_balance(), - _ => unreachable!(), } } - pub fn map_authorization< - R, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] R2, - NV: orchard::bundle::Authorization, - NZ: orchard::bundle::Authorization, - >( + pub fn map_authorization( self, context: &mut R, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] context_zsa: &mut R2, - spend_auth: impl FnMut(&mut R, &V, V::SpendAuth) -> NV::SpendAuth, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] spend_auth_zsa: impl FnMut( - &mut R2, - &Z, - Z::SpendAuth, - ) - -> NZ::SpendAuth, - step: impl FnOnce(&mut R, V) -> NV, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] step_zsa: impl FnOnce(&mut R2, Z) -> NZ, - ) -> OrchardBundle { + spend_auth: impl FnMut(&mut R, &A, A::SpendAuth) -> B::SpendAuth, + step: impl FnOnce(&mut R, A) -> B, + ) -> OrchardBundle { match self { OrchardBundle::OrchardVanilla(b) => OrchardBundle::OrchardVanilla(Box::new( b.map_authorization(context, spend_auth, step), )), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(b) => OrchardBundle::OrchardZSA(Box::new(b.map_authorization( - context_zsa, - spend_auth_zsa, - step_zsa, - ))), - _ => unreachable!(), + OrchardBundle::OrchardZSA(b) => { + OrchardBundle::OrchardZSA(Box::new(b.map_authorization(context, spend_auth, step))) + } } } } @@ -441,7 +412,7 @@ pub struct TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, + orchard_bundle: Option>, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: Option>, #[cfg(zcash_unstable = "zfuture")] @@ -459,7 +430,7 @@ impl TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, + orchard_bundle: Option>, #[rustfmt::skip] #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: Option>, @@ -538,7 +509,7 @@ impl TransactionData { self.sapling_bundle.as_ref() } - pub fn orchard_bundle(&self) -> Option<&OrchardBundle> { + pub fn orchard_bundle(&self) -> Option<&OrchardBundle> { self.orchard_bundle.as_ref() } @@ -617,8 +588,8 @@ impl TransactionData { Option>, ) -> Option>, f_orchard: impl FnOnce( - Option>, - ) -> Option>, + Option>, + ) -> Option>, #[rustfmt::skip] #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] f_issue: impl FnOnce( @@ -650,11 +621,6 @@ impl TransactionData { f_transparent: impl transparent::MapAuth, mut f_sapling: impl sapling_serialization::MapAuth, mut f_orchard: impl orchard_serialization::MapAuth, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - mut f_orchard_zsa: impl orchard_serialization::MapAuth< - A::OrchardZsaAuth, - B::OrchardZsaAuth, - >, #[rustfmt::skip] #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] f_issue: impl issuance::MapIssueAuth, @@ -681,13 +647,7 @@ impl TransactionData { orchard_bundle: self.orchard_bundle.map(|b| { b.map_authorization( &mut f_orchard, - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - &mut f_orchard_zsa, |f, _, s| f.map_spend_auth(s), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - |f, _, s| f.map_spend_auth(s), - |f, a| f.map_authorization(a), - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] |f, a| f.map_authorization(a), ) }), @@ -1186,7 +1146,7 @@ pub trait TransactionDigest { fn digest_orchard( &self, - orchard_bundle: Option<&OrchardBundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] diff --git a/zcash_primitives/src/transaction/tests.rs b/zcash_primitives/src/transaction/tests.rs index e6c6171951..8a737f5c43 100644 --- a/zcash_primitives/src/transaction/tests.rs +++ b/zcash_primitives/src/transaction/tests.rs @@ -59,13 +59,11 @@ fn check_roundtrip(tx: Transaction) -> Result<(), TestCaseError> { OrchardVanilla(b) => *b.value_balance(), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardZSA(b) => *b.value_balance(), - _ => unreachable!(), }), txo.orchard_bundle.as_ref().map(|v| match v { OrchardVanilla(b) => *b.value_balance(), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardZSA(b) => *b.value_balance(), - _ => unreachable!(), }) ); #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] @@ -228,8 +226,6 @@ impl Authorization for TestUnauthorized { type SaplingAuth = sapling::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - type OrchardZsaAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index e730ad8781..6337fb98a7 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -344,14 +344,13 @@ impl TransactionDigest for TxIdDigester { fn digest_orchard( &self, - orchard_bundle: Option<&OrchardBundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest { orchard_bundle.map(|b| { match b { OrchardBundle::OrchardVanilla(vanilla_bundle) => vanilla_bundle.commitment().0, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.commitment().0, - _ => unreachable!(), } }) } @@ -537,7 +536,7 @@ impl TransactionDigest for BlockTxCommitmentDigester { fn digest_orchard( &self, - orchard_bundle: Option<&OrchardBundle>, + orchard_bundle: Option<&OrchardBundle>, ) -> Self::OrchardDigest { orchard_bundle.map_or_else(bundle::commitments::hash_bundle_auth_empty, |b| { match b { @@ -546,7 +545,6 @@ impl TransactionDigest for BlockTxCommitmentDigester { } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.authorizing_commitment().0, - _ => unreachable!(), } }) } From 7fbc632346d2a5d10aa9bc7c572968ed045e50bb Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:49:34 +0100 Subject: [PATCH 05/19] Fix zfuture --- zcash_primitives/src/transaction/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index 7449bcc4a2..eb4aa9de85 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -463,7 +463,7 @@ impl TransactionData { transparent_bundle: Option>, sprout_bundle: Option, sapling_bundle: Option>, - orchard_bundle: Option>, + orchard_bundle: Option>, tze_bundle: Option>, ) -> Self { TransactionData { From b6b6c02f8373f33fd5e602fc244a334240d1f827 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:27:49 +0100 Subject: [PATCH 06/19] Fix client_backend --- zcash_client_backend/src/data_api/wallet.rs | 1 + zcash_client_backend/src/decrypt.rs | 5 ++--- zcash_primitives/src/transaction/mod.rs | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index 4ea35f4b40..fe8027487f 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -1123,6 +1123,7 @@ where .orchard_bundle() .and_then(|bundle| { bundle + .vanilla_bundle() .decrypt_output_with_key(output_index, &orchard_internal_ivk) .map(|(note, _, _)| Note::Orchard(note)) }) diff --git a/zcash_client_backend/src/decrypt.rs b/zcash_client_backend/src/decrypt.rs index f95d7efb80..ca944ab415 100644 --- a/zcash_client_backend/src/decrypt.rs +++ b/zcash_client_backend/src/decrypt.rs @@ -1,6 +1,5 @@ -use std::collections::HashMap; - use sapling::note_encryption::{PreparedIncomingViewingKey, SaplingDomain}; +use std::collections::HashMap; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; use zcash_primitives::{ consensus::{self, BlockHeight}, @@ -159,7 +158,7 @@ pub fn decrypt_transaction<'a, P: consensus::Parameters, AccountId: Copy>( .collect(); #[cfg(feature = "orchard")] - let orchard_bundle = tx.orchard_bundle(); + let orchard_bundle = tx.orchard_bundle().map(|bundle| bundle.vanilla_bundle()); #[cfg(feature = "orchard")] let orchard_outputs = orchard_bundle .iter() diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index eb4aa9de85..e0a0345bf1 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -400,6 +400,14 @@ impl OrchardBundle { } } } + + pub fn vanilla_bundle(&self) -> &Bundle { + match self { + OrchardBundle::OrchardVanilla(b) => b, + #[allow(unreachable_patterns)] + _ => panic!("Wrong bundle type"), + } + } } /// The information contained in a Zcash transaction. From a5500ee9f659907a582068e642934b2c782c9a8d Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:25:45 +0100 Subject: [PATCH 07/19] Disable wasm CI target --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ccb6bd343a..b16787b5b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,13 +168,13 @@ jobs: - name: Verify working directory is clean (excluding lockfile) run: git diff --exit-code ':!Cargo.lock' - build-nodefault: - name: Build target ${{ matrix.target }} - runs-on: ubuntu-latest - strategy: - matrix: - target: - - wasm32-wasi +# build-nodefault: +# name: Build target ${{ matrix.target }} +# runs-on: ubuntu-latest +# strategy: +# matrix: +# target: +# - wasm32-wasi steps: - uses: actions/checkout@v4 From 3f6578ec170c61faa31c64ec73d36a8664c488c3 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:19:12 +0100 Subject: [PATCH 08/19] Better handle errors --- zcash_primitives/src/transaction/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index aba6438c19..426158ef3b 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -959,7 +959,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< &self.orchard_saks, ) }) - .unwrap(), + .map_err(Error::OrchardBuild)?, ))) } @@ -976,7 +976,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< &self.orchard_saks, ) }) - .unwrap(), + .map_err(Error::OrchardBuild)?, ))), None => None, From 02c237937df24037890af58a46399bbbe38bbc1e Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 12 Dec 2024 18:19:35 +0100 Subject: [PATCH 09/19] Re-enable CI wasm check --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b16787b5b7..ccb6bd343a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,13 +168,13 @@ jobs: - name: Verify working directory is clean (excluding lockfile) run: git diff --exit-code ':!Cargo.lock' -# build-nodefault: -# name: Build target ${{ matrix.target }} -# runs-on: ubuntu-latest -# strategy: -# matrix: -# target: -# - wasm32-wasi + build-nodefault: + name: Build target ${{ matrix.target }} + runs-on: ubuntu-latest + strategy: + matrix: + target: + - wasm32-wasi steps: - uses: actions/checkout@v4 From 4ec88dd8bfee794333fc654026a27abfc150dfe3 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:47:04 +0100 Subject: [PATCH 10/19] Switch to zsa1 --- zcash_primitives/src/transaction/components/orchard.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 514f37a647..c25ee136f6 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -17,6 +17,7 @@ use orchard::{ value::{NoteValue, ValueCommitment}, Action, Anchor, }; +use orchard::domain::OrchardDomainCommon; use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; use zcash_protocol::value::ZatBalance; From b47ff6e7b3f121807be6614f7182c1535ac03c9b Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:41:43 +0100 Subject: [PATCH 11/19] Revert "Use correct Nu7 branch_id" This reverts commit f33189f1b29bbdcd792383934d32edd744b9c897. --- components/zcash_protocol/src/consensus.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/zcash_protocol/src/consensus.rs b/components/zcash_protocol/src/consensus.rs index 7bda504089..793cf70680 100644 --- a/components/zcash_protocol/src/consensus.rs +++ b/components/zcash_protocol/src/consensus.rs @@ -626,7 +626,7 @@ impl TryFrom for BranchId { #[cfg(zcash_unstable = "nu6")] 0xc8e7_1055 => Ok(BranchId::Nu6), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - 0x7719_0ad8 => Ok(BranchId::Nu7), + 0x7777_7777 => Ok(BranchId::Nu7), #[cfg(zcash_unstable = "zfuture")] 0xffff_ffff => Ok(BranchId::ZFuture), _ => Err("Unknown consensus branch ID"), @@ -647,7 +647,7 @@ impl From for u32 { #[cfg(zcash_unstable = "nu6")] BranchId::Nu6 => 0xc8e7_1055, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - BranchId::Nu7 => 0x7719_0ad8, + BranchId::Nu7 => 0x7777_7777, #[cfg(zcash_unstable = "zfuture")] BranchId::ZFuture => 0xffff_ffff, } From c08d67374edac76dd12a5ed85bd5a44b45f7e160 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:53:47 +0100 Subject: [PATCH 12/19] Fmt --- zcash_primitives/src/transaction/components/orchard.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index c25ee136f6..e2902836fe 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -8,6 +8,7 @@ use crate::transaction::components::issuance::read_asset; use crate::transaction::{OrchardBundle, Transaction}; use byteorder::{ReadBytesExt, WriteBytesExt}; use nonempty::NonEmpty; +use orchard::domain::OrchardDomainCommon; use orchard::{ bundle::{Authorization, Authorized, Flags}, domain::OrchardDomainCommon, @@ -17,7 +18,6 @@ use orchard::{ value::{NoteValue, ValueCommitment}, Action, Anchor, }; -use orchard::domain::OrchardDomainCommon; use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; use zcash_protocol::value::ZatBalance; From 15f19a7930a5abe3c68471a4abf0c9bcf41c7ed4 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:17:29 +0100 Subject: [PATCH 13/19] Downgrade Rust version --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6ea608282d..cad9254a9c 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.71.0" +channel = "1.70.0" components = [ "clippy", "rustfmt" ] From 9f947f812775224055659f49efbec0f731da8ba2 Mon Sep 17 00:00:00 2001 From: alexey <2365507+alexeykoren@users.noreply.github.com> Date: Sun, 26 Jan 2025 17:10:38 +0100 Subject: [PATCH 14/19] Rebase to latest zsa1 --- components/zcash_protocol/src/consensus.rs | 8 ++- zcash_primitives/src/transaction/builder.rs | 2 +- .../src/transaction/components/orchard.rs | 67 +++++++------------ zcash_primitives/src/transaction/mod.rs | 7 +- 4 files changed, 34 insertions(+), 50 deletions(-) diff --git a/components/zcash_protocol/src/consensus.rs b/components/zcash_protocol/src/consensus.rs index 793cf70680..6487719608 100644 --- a/components/zcash_protocol/src/consensus.rs +++ b/components/zcash_protocol/src/consensus.rs @@ -626,10 +626,12 @@ impl TryFrom for BranchId { #[cfg(zcash_unstable = "nu6")] 0xc8e7_1055 => Ok(BranchId::Nu6), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - 0x7777_7777 => Ok(BranchId::Nu7), + 0x7719_0ad8 => Ok(BranchId::Nu7), #[cfg(zcash_unstable = "zfuture")] 0xffff_ffff => Ok(BranchId::ZFuture), - _ => Err("Unknown consensus branch ID"), + _ => Err(Box::leak( + format!("Unknown consensus branch ID: {:08x}", value).into_boxed_str(), + )), } } } @@ -647,7 +649,7 @@ impl From for u32 { #[cfg(zcash_unstable = "nu6")] BranchId::Nu6 => 0xc8e7_1055, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - BranchId::Nu7 => 0x7777_7777, + BranchId::Nu7 => 0x7719_0ad8, #[cfg(zcash_unstable = "zfuture")] BranchId::ZFuture => 0xffff_ffff, } diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 426158ef3b..4422830488 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -882,7 +882,7 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< } } else { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_bundle = Some(OrchardBundle::OrchardVanilla(bundle)); + unproven_orchard_bundle = Some(OrchardBundle::OrchardVanilla(Box::new(bundle))); orchard_meta = meta; } }; diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index e2902836fe..0a7c99f320 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -8,7 +8,6 @@ use crate::transaction::components::issuance::read_asset; use crate::transaction::{OrchardBundle, Transaction}; use byteorder::{ReadBytesExt, WriteBytesExt}; use nonempty::NonEmpty; -use orchard::domain::OrchardDomainCommon; use orchard::{ bundle::{Authorization, Authorized, Flags}, domain::OrchardDomainCommon, @@ -16,11 +15,10 @@ use orchard::{ orchard_flavor::{OrchardVanilla, OrchardZSA}, primitives::redpallas::{self, SigType, Signature, SpendAuth, VerificationKey}, value::{NoteValue, ValueCommitment}, - Action, Anchor, + Action, Anchor, Bundle, }; use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; -use zcash_protocol::value::ZatBalance; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use byteorder::LittleEndian; @@ -372,10 +370,9 @@ pub fn write_orchard_bundle( ) -> io::Result<()> { if let Some(bundle) = &bundle { match bundle { - OrchardBundle::OrchardVanilla(b) => write_orchard_vanilla_bundle(b, writer)?, + OrchardBundle::OrchardVanilla(b) => write_orchard_vanilla_bundle(writer, b)?, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(b) => write_orchard_bundle_contents(b, writer)?, - _ => unreachable!(), + OrchardBundle::OrchardZSA(b) => write_orchard_zsa_bundle(writer, b)?, } } else { CompactSize::write(&mut writer, 0)?; @@ -384,37 +381,32 @@ pub fn write_orchard_bundle( Ok(()) } - -/// Writes an [`orchard::Bundle`] in the appropriate transaction format. +/// Writes an [`Bundle`] in the appropriate transaction format. pub fn write_orchard_vanilla_bundle( mut writer: W, - bundle: Option<&orchard::Bundle>, + bundle: &Bundle, ) -> io::Result<()> { - if let Some(bundle) = &bundle { - Vector::write_nonempty(&mut writer, bundle.actions(), |w, a| { - write_action_without_auth(w, a) - })?; + Vector::write_nonempty(&mut writer, bundle.actions(), |w, a| { + write_action_without_auth(w, a) + })?; - 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( - &mut writer, - bundle.authorization().proof().as_ref(), - |w, b| w.write_u8(*b), - )?; - Array::write( - &mut writer, - bundle.actions().iter().map(|a| a.authorization()), - |w, auth| w.write_all(&<[u8; 64]>::from(*auth)), - )?; - - writer.write_all(&<[u8; 64]>::from( - bundle.authorization().binding_signature(), - ))?; - } else { - CompactSize::write(&mut writer, 0)?; - } + 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( + &mut writer, + bundle.authorization().proof().as_ref(), + |w, b| w.write_u8(*b), + )?; + Array::write( + &mut writer, + bundle.actions().iter().map(|a| a.authorization()), + |w, auth| w.write_all(&<[u8; 64]>::from(*auth)), + )?; + + writer.write_all(&<[u8; 64]>::from( + bundle.authorization().binding_signature(), + ))?; Ok(()) } @@ -423,15 +415,8 @@ pub fn write_orchard_vanilla_bundle( #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] pub fn write_orchard_zsa_bundle( mut writer: W, - bundle: Option<&orchard::Bundle>, + bundle: &orchard::Bundle, ) -> io::Result<()> { - if bundle.is_none() { - CompactSize::write(&mut writer, 0)?; - return Ok(()); - } - - let bundle = bundle.unwrap(); - // Exactly one action group for NU7 CompactSize::write(&mut writer, 1)?; diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index e0a0345bf1..b6d2b091f5 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -928,7 +928,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: orchard_bundle.map(|b| OrchardBundle::OrchardZSA(Box::new(b))), + orchard_bundle: orchard_zsa_bundle.map(|b| OrchardBundle::OrchardZSA(Box::new(b))), issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle, @@ -1065,10 +1065,7 @@ impl Transaction { self.write_header(&mut writer)?; self.write_transparent(&mut writer)?; self.write_sapling(&mut writer)?; - orchard_serialization::write_orchard_zsa_bundle( - &mut writer, - self.orchard_bundle.as_ref(), - )?; + orchard_serialization::write_orchard_bundle(&mut writer, self.orchard_bundle.as_ref())?; issuance::write_v6_bundle(self.issue_bundle.as_ref(), &mut writer)?; #[cfg(zcash_unstable = "zfuture")] self.write_tze(&mut writer)?; From 19e3a487df362fe9c9c87414c933dbdb226963c8 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 27 Jan 2025 13:25:33 +0100 Subject: [PATCH 15/19] Disable default features for Orchard --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fd6eebc92c..63d21cbf60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ sapling = { package = "sapling-crypto", version = "0.1.3" } # - Orchard nonempty = "0.7" -orchard = "0.8.0" +orchard = { version = "0.8.0", default-features = false } pasta_curves = "0.5" # - Transparent From 5c7f75b0e159bab17fe0958bebb4b69df795f7db Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:24:16 +0100 Subject: [PATCH 16/19] Remove redundant traits --- .../src/transaction/components/orchard.rs | 73 +------------------ 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 0a7c99f320..80a001f0b2 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -51,77 +51,6 @@ impl MapAuth for () { } } -pub trait BuildBundle { - fn build_bundle( - actions: NonEmpty>, - flags: Flags, - value_balance: Amount, - burn: Vec<(AssetBase, NoteValue)>, - anchor: Anchor, - authorization: A, - ) -> OrchardBundle; -} - -impl BuildBundle for OrchardVanilla { - fn build_bundle( - actions: NonEmpty>, - flags: Flags, - value_balance: Amount, - burn: Vec<(AssetBase, NoteValue)>, - anchor: Anchor, - authorization: A, - ) -> OrchardBundle { - OrchardBundle::OrchardVanilla(Box::new(Bundle::from_parts( - actions, - flags, - value_balance, - burn, - anchor, - authorization, - ))) - } -} - -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -impl BuildBundle for OrchardZSA { - fn build_bundle( - actions: NonEmpty>, - flags: Flags, - value_balance: Amount, - burn: Vec<(AssetBase, NoteValue)>, - anchor: Anchor, - authorization: A, - ) -> OrchardBundle { - OrchardBundle::OrchardZSA(Box::new(orchard::Bundle::from_parts( - actions, - flags, - value_balance, - burn, - anchor, - authorization, - ))) - } -} - -pub trait ReadBurn { - fn read_burn(reader: &mut R) -> io::Result>; -} - -// OrchardVanilla has no burn to read -impl ReadBurn for OrchardVanilla { - fn read_burn(_reader: &mut R) -> io::Result> { - Ok(Vec::new()) - } -} - -// Read burn for OrchardZSA -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -impl ReadBurn for OrchardZSA { - fn read_burn(reader: &mut R) -> io::Result> { - Vector::read(reader, |r| read_burn(r)) - } -} - /// Reads an [`orchard::Bundle`] from a v5 transaction format. pub fn read_orchard_bundle( mut reader: R, @@ -202,7 +131,7 @@ pub fn read_orchard_zsa_bundle( let value_balance = Transaction::read_amount(&mut reader)?; - let burn = OrchardZSA::read_burn(&mut reader)?; + let burn = Vector::read(&mut reader, |r| read_burn(r))?; let binding_signature = read_signature::<_, redpallas::Binding>(&mut reader)?; From 3c1ad6bd77c1db34cbca86f6c1b6f791713d3d85 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:35:08 +0100 Subject: [PATCH 17/19] Address PR comments --- components/zcash_protocol/src/consensus.rs | 4 +- zcash_client_backend/src/data_api/wallet.rs | 2 +- zcash_client_backend/src/decrypt.rs | 2 +- zcash_primitives/src/transaction/builder.rs | 67 ++++++++++--------- .../src/transaction/components/orchard.rs | 28 ++++---- zcash_primitives/src/transaction/mod.rs | 40 +++++------ 6 files changed, 71 insertions(+), 72 deletions(-) diff --git a/components/zcash_protocol/src/consensus.rs b/components/zcash_protocol/src/consensus.rs index 6487719608..7bda504089 100644 --- a/components/zcash_protocol/src/consensus.rs +++ b/components/zcash_protocol/src/consensus.rs @@ -629,9 +629,7 @@ impl TryFrom for BranchId { 0x7719_0ad8 => Ok(BranchId::Nu7), #[cfg(zcash_unstable = "zfuture")] 0xffff_ffff => Ok(BranchId::ZFuture), - _ => Err(Box::leak( - format!("Unknown consensus branch ID: {:08x}", value).into_boxed_str(), - )), + _ => Err("Unknown consensus branch ID"), } } } diff --git a/zcash_client_backend/src/data_api/wallet.rs b/zcash_client_backend/src/data_api/wallet.rs index fe8027487f..d9a44b70c5 100644 --- a/zcash_client_backend/src/data_api/wallet.rs +++ b/zcash_client_backend/src/data_api/wallet.rs @@ -1123,7 +1123,7 @@ where .orchard_bundle() .and_then(|bundle| { bundle - .vanilla_bundle() + .as_vanilla_bundle() .decrypt_output_with_key(output_index, &orchard_internal_ivk) .map(|(note, _, _)| Note::Orchard(note)) }) diff --git a/zcash_client_backend/src/decrypt.rs b/zcash_client_backend/src/decrypt.rs index ca944ab415..c9b6d78a85 100644 --- a/zcash_client_backend/src/decrypt.rs +++ b/zcash_client_backend/src/decrypt.rs @@ -158,7 +158,7 @@ pub fn decrypt_transaction<'a, P: consensus::Parameters, AccountId: Copy>( .collect(); #[cfg(feature = "orchard")] - let orchard_bundle = tx.orchard_bundle().map(|bundle| bundle.vanilla_bundle()); + let orchard_bundle = tx.orchard_bundle().map(|bundle| bundle.as_vanilla_bundle()); #[cfg(feature = "orchard")] let orchard_outputs = orchard_bundle .iter() diff --git a/zcash_primitives/src/transaction/builder.rs b/zcash_primitives/src/transaction/builder.rs index 4422830488..1ca71ebaa6 100644 --- a/zcash_primitives/src/transaction/builder.rs +++ b/zcash_primitives/src/transaction/builder.rs @@ -30,9 +30,9 @@ use crate::{ }, }; -use orchard::builder::BundleType; +use orchard::builder::{BundleType, InProgress, Unproven}; use orchard::note::AssetBase; -use orchard::orchard_flavor::OrchardVanilla; +use orchard::orchard_flavor::{OrchardFlavor, OrchardVanilla}; use orchard::Address; #[cfg(feature = "transparent-inputs")] @@ -53,6 +53,7 @@ use crate::{ fees::FutureFeeRule, }, }; +use orchard::bundle::Authorized; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use orchard::{ issuance, @@ -877,12 +878,12 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_bundle = Some(OrchardBundle::OrchardZSA(Box::new(bundle))); + unproven_orchard_bundle = Some(OrchardBundle::OrchardZSA(bundle)); orchard_meta = meta; } } else { let (bundle, meta) = builder.build(&mut rng).map_err(Error::OrchardBuild)?; - unproven_orchard_bundle = Some(OrchardBundle::OrchardVanilla(Box::new(bundle))); + unproven_orchard_bundle = Some(OrchardBundle::OrchardVanilla(bundle)); orchard_meta = meta; } }; @@ -947,37 +948,23 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< let orchard_bundle: Option> = match unauthed_tx.orchard_bundle { Some(OrchardBundle::OrchardVanilla(b)) => { - Some(OrchardBundle::OrchardVanilla(Box::new( - b.create_proof( - &orchard::circuit::ProvingKey::build::(), - &mut rng, - ) - .and_then(|b| { - b.apply_signatures( - &mut rng, - *shielded_sig_commitment.as_ref(), - &self.orchard_saks, - ) - }) - .map_err(Error::OrchardBuild)?, - ))) + Some(OrchardBundle::OrchardVanilla(prove_and_sign( + b, + &mut rng, + &orchard::circuit::ProvingKey::build::(), + shielded_sig_commitment.as_ref(), + &self.orchard_saks, + )?)) } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA(Box::new( - b.create_proof( - &orchard::circuit::ProvingKey::build::(), - &mut rng, - ) - .and_then(|b| { - b.apply_signatures( - &mut rng, - *shielded_sig_commitment.as_ref(), - &self.orchard_saks, - ) - }) - .map_err(Error::OrchardBuild)?, - ))), + Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA(prove_and_sign( + b, + &mut rng, + &orchard::circuit::ProvingKey::build::(), + shielded_sig_commitment.as_ref(), + &self.orchard_saks, + )?)), None => None, }; @@ -1014,6 +1001,22 @@ impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> Builder< } } +fn prove_and_sign( + bundle: orchard::Bundle, V, D>, + mut rng: &mut (impl RngCore + CryptoRng), + proving_key: &orchard::circuit::ProvingKey, + shielded_sig_commitment: &[u8; 32], + orchard_saks: &[orchard::keys::SpendAuthorizingKey], +) -> Result, Error> +where + D: OrchardFlavor, +{ + bundle + .create_proof(proving_key, &mut rng) + .and_then(|b| b.apply_signatures(&mut rng, *shielded_sig_commitment, orchard_saks)) + .map_err(Error::OrchardBuild) +} + #[cfg(zcash_unstable = "zfuture")] impl<'a, P: consensus::Parameters, U: sapling::builder::ProverProgress> ExtensionTxBuilder<'a> for Builder<'a, P, U> diff --git a/zcash_primitives/src/transaction/components/orchard.rs b/zcash_primitives/src/transaction/components/orchard.rs index 80a001f0b2..6bdedcf298 100644 --- a/zcash_primitives/src/transaction/components/orchard.rs +++ b/zcash_primitives/src/transaction/components/orchard.rs @@ -6,7 +6,7 @@ use super::Amount; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use crate::transaction::components::issuance::read_asset; use crate::transaction::{OrchardBundle, Transaction}; -use byteorder::{ReadBytesExt, WriteBytesExt}; +use byteorder::ReadBytesExt; use nonempty::NonEmpty; use orchard::{ bundle::{Authorization, Authorized, Flags}, @@ -20,8 +20,9 @@ use orchard::{ use zcash_encoding::{Array, CompactSize, Vector}; use zcash_note_encryption::note_bytes::NoteBytes; +use zcash_protocol::value::ZatBalance; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use byteorder::LittleEndian; +use {byteorder::LittleEndian, byteorder::WriteBytesExt}; pub const FLAG_SPENDS_ENABLED: u8 = 0b0000_0001; pub const FLAG_OUTPUTS_ENABLED: u8 = 0b0000_0010; @@ -297,9 +298,9 @@ pub fn write_orchard_bundle( mut writer: W, bundle: Option<&OrchardBundle>, ) -> io::Result<()> { - if let Some(bundle) = &bundle { + if let Some(bundle) = bundle { match bundle { - OrchardBundle::OrchardVanilla(b) => write_orchard_vanilla_bundle(writer, b)?, + OrchardBundle::OrchardVanilla(b) => write_v5_bundle(b, writer)?, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardBundle::OrchardZSA(b) => write_orchard_zsa_bundle(writer, b)?, } @@ -310,10 +311,10 @@ pub fn write_orchard_bundle( Ok(()) } -/// Writes an [`Bundle`] in the appropriate transaction format. -pub fn write_orchard_vanilla_bundle( +/// Writes an [`orchard::Bundle`] in the v5 transaction format. +pub fn write_v5_bundle( + bundle: &Bundle, mut writer: W, - bundle: &Bundle, ) -> io::Result<()> { Vector::write_nonempty(&mut writer, bundle.actions(), |w, a| { write_action_without_auth(w, a) @@ -325,14 +326,13 @@ pub fn write_orchard_vanilla_bundle( Vector::write( &mut writer, bundle.authorization().proof().as_ref(), - |w, b| w.write_u8(*b), + |w, b| w.write_all(&[*b]), )?; Array::write( &mut writer, bundle.actions().iter().map(|a| a.authorization()), |w, auth| w.write_all(&<[u8; 64]>::from(*auth)), )?; - writer.write_all(&<[u8; 64]>::from( bundle.authorization().binding_signature(), ))?; @@ -423,7 +423,6 @@ pub fn write_action_without_auth( #[cfg(any(test, feature = "test-dependencies"))] pub mod testing { - use orchard::Bundle; use proptest::prelude::*; use crate::transaction::components::amount::testing::arb_amount; @@ -441,21 +440,20 @@ pub mod testing { ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - OrchardBundle::OrchardVanilla(Box::new(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap())) + OrchardBundle::OrchardVanilla(bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap()) } } prop_compose! { #[allow(unreachable_code)] pub fn arb_zsa_bundle(n_actions: usize)( - orchard_value_balance in arb_amount(), - bundle in t_orch::BundleArb::arb_bundle(n_actions) + _orchard_value_balance in arb_amount(), + _bundle in t_orch::BundleArb::::arb_bundle(n_actions) ) -> OrchardBundle { // overwrite the value balance, as we can't guarantee that the // value doesn't exceed the MAX_MONEY bounds. - let _bundle: Bundle<_, _, OrchardZSA> = bundle.try_map_value_balance::<_, (), _>(|_| Ok(orchard_value_balance)).unwrap(); #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - return OrchardBundle::OrchardZSA(Box::new(_bundle)); + return OrchardBundle::OrchardZSA(_bundle.try_map_value_balance::<_, (), _>(|_| Ok(_orchard_value_balance)).unwrap()); panic!("ZSA is not supported in this version"); } } diff --git a/zcash_primitives/src/transaction/mod.rs b/zcash_primitives/src/transaction/mod.rs index b6d2b091f5..a1a43a0593 100644 --- a/zcash_primitives/src/transaction/mod.rs +++ b/zcash_primitives/src/transaction/mod.rs @@ -45,7 +45,6 @@ use self::components::tze::{self, TzeIn, TzeOut}; use crate::transaction::components::issuance; #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] use orchard::{issuance::IssueBundle, orchard_flavor::OrchardZSA}; -use zcash_protocol::value::ZatBalance; const OVERWINTER_VERSION_GROUP_ID: u32 = 0x03C48270; const OVERWINTER_TX_VERSION: u32 = 3; @@ -364,15 +363,9 @@ impl PartialEq for Transaction { #[derive(Debug, Clone)] pub enum OrchardBundle { - OrchardVanilla(Box>), + OrchardVanilla(Bundle), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardZSA(Box>), -} - -/// Errors that can occur during transaction construction. -#[derive(Debug)] -pub enum BundleError { - WrongBundleType, + OrchardZSA(Bundle), } impl OrchardBundle { @@ -391,21 +384,29 @@ impl OrchardBundle { step: impl FnOnce(&mut R, A) -> B, ) -> OrchardBundle { match self { - OrchardBundle::OrchardVanilla(b) => OrchardBundle::OrchardVanilla(Box::new( - b.map_authorization(context, spend_auth, step), - )), + OrchardBundle::OrchardVanilla(b) => { + OrchardBundle::OrchardVanilla(b.map_authorization(context, spend_auth, step)) + } #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] OrchardBundle::OrchardZSA(b) => { - OrchardBundle::OrchardZSA(Box::new(b.map_authorization(context, spend_auth, step))) + OrchardBundle::OrchardZSA(b.map_authorization(context, spend_auth, step)) } } } - pub fn vanilla_bundle(&self) -> &Bundle { + pub fn as_vanilla_bundle(&self) -> &Bundle { match self { OrchardBundle::OrchardVanilla(b) => b, - #[allow(unreachable_patterns)] - _ => panic!("Wrong bundle type"), + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + OrchardBundle::OrchardZSA(_) => panic!("Wrong bundle type"), + } + } + + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + pub fn as_zsa_bundle(&self) -> &Bundle { + match self { + OrchardBundle::OrchardVanilla(_) => panic!("Wrong bundle type"), + OrchardBundle::OrchardZSA(b) => b, } } } @@ -855,8 +856,7 @@ impl Transaction { Self::read_v5_header_fragment(&mut reader)?; let transparent_bundle = Self::read_transparent(&mut reader)?; let sapling_bundle = sapling_serialization::read_v5_bundle(&mut reader)?; - let orchard_bundle: Option> = - orchard_serialization::read_orchard_bundle(&mut reader)?; + let orchard_bundle = orchard_serialization::read_orchard_bundle(&mut reader)?; #[cfg(zcash_unstable = "zfuture")] let tze_bundle = if version.has_tze() { @@ -873,7 +873,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: orchard_bundle.map(|b| OrchardBundle::OrchardVanilla(Box::new(b))), + orchard_bundle: orchard_bundle.map(OrchardBundle::OrchardVanilla), #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] issue_bundle: None, #[cfg(zcash_unstable = "zfuture")] @@ -928,7 +928,7 @@ impl Transaction { transparent_bundle, sprout_bundle: None, sapling_bundle, - orchard_bundle: orchard_zsa_bundle.map(|b| OrchardBundle::OrchardZSA(Box::new(b))), + orchard_bundle: orchard_zsa_bundle.map(OrchardBundle::OrchardZSA), issue_bundle, #[cfg(zcash_unstable = "zfuture")] tze_bundle, From e540eca18af7399f9a32b723aac043c7ce22c12b Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:26:16 +0100 Subject: [PATCH 18/19] Address PR comments --- zcash_primitives/src/transaction/txid.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 6337fb98a7..0240b351ec 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -24,14 +24,17 @@ use super::{ TxId, TxVersion, }; -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -use orchard::issuance::{IssueBundle, Signed}; - #[cfg(zcash_unstable = "zfuture")] use super::{ components::tze::{self, TzeIn, TzeOut}, TzeDigests, }; +use crate::transaction::OrchardBundle::OrchardVanilla; +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +use { + crate::transaction::OrchardBundle::OrchardZSA, + orchard::issuance::{IssueBundle, Signed}, +}; /// TxId tree root personalization const ZCASH_TX_PERSONALIZATION_PREFIX: &[u8; 12] = b"ZcashTxHash_"; @@ -540,11 +543,9 @@ impl TransactionDigest for BlockTxCommitmentDigester { ) -> Self::OrchardDigest { orchard_bundle.map_or_else(bundle::commitments::hash_bundle_auth_empty, |b| { match b { - OrchardBundle::OrchardVanilla(vanilla_bundle) => { - vanilla_bundle.authorizing_commitment().0 - } + OrchardVanilla(bundle) => bundle.authorizing_commitment().0, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.authorizing_commitment().0, + OrchardZSA(bundle) => bundle.authorizing_commitment().0, } }) } From 35ca3f26a088c10acb502ffb01d49eff7876a2c1 Mon Sep 17 00:00:00 2001 From: alexeykoren <2365507+alexeykoren@users.noreply.github.com> Date: Wed, 12 Feb 2025 21:24:05 +0100 Subject: [PATCH 19/19] Address PR comments --- zcash_primitives/src/transaction/txid.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zcash_primitives/src/transaction/txid.rs b/zcash_primitives/src/transaction/txid.rs index 0240b351ec..86364f0c9b 100644 --- a/zcash_primitives/src/transaction/txid.rs +++ b/zcash_primitives/src/transaction/txid.rs @@ -351,9 +351,9 @@ impl TransactionDigest for TxIdDigester { ) -> Self::OrchardDigest { orchard_bundle.map(|b| { match b { - OrchardBundle::OrchardVanilla(vanilla_bundle) => vanilla_bundle.commitment().0, + OrchardVanilla(v) => v.commitment().0, #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - OrchardBundle::OrchardZSA(zsa_bundle) => zsa_bundle.commitment().0, + OrchardZSA(z) => z.commitment().0, } }) }