Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZSA bundle enum #78

Open
wants to merge 18 commits into
base: zsa1
Choose a base branch
from
Open

ZSA bundle enum #78

wants to merge 18 commits into from

Conversation

alexeykoren
Copy link
Collaborator

@alexeykoren alexeykoren commented Nov 3, 2024

User description

Replace 2 separate Orchard bundle with a single enum


PR Type

enhancement


Description

  • Introduced OrchardBundle enum to consolidate the handling of Orchard bundles, replacing separate variables for different bundle types.
  • Implemented the BuildBundle trait for constructing OrchardVanilla and OrchardZSA bundles.
  • Updated transaction data structures and logic to use the new OrchardBundle enum, simplifying the code and removing redundancy.
  • Adjusted tests to align with the new unified bundle handling approach.
  • Updated the orchard dependency branch in Cargo.toml to spendauth_clone.

Changes walkthrough 📝

Relevant files
Enhancement
builder.rs
Consolidate Orchard bundle handling with `OrchardBundle` enum

zcash_primitives/src/transaction/builder.rs

  • Replaced separate Orchard bundle variables with a single OrchardBundle
    enum.
  • Updated logic to handle OrchardBundle enum types.
  • Removed redundant unproven_orchard_zsa_bundle variable.
  • +36/-41 
    orchard.rs
    Implement `BuildBundle` trait and update bundle handling 

    zcash_primitives/src/transaction/components/orchard.rs

  • Introduced BuildBundle trait for constructing bundles.
  • Implemented BuildBundle for OrchardVanilla and OrchardZSA.
  • Updated bundle reading and writing functions to use OrchardBundle.
  • +120/-51
    mod.rs
    Unify Orchard bundle handling with `OrchardBundle` enum   

    zcash_primitives/src/transaction/mod.rs

  • Defined OrchardBundle enum to unify bundle handling.
  • Updated transaction data structures to use OrchardBundle.
  • Removed separate handling for OrchardZSA bundles.
  • +87/-79 
    txid.rs
    Update transaction digest logic for `OrchardBundle`           

    zcash_primitives/src/transaction/txid.rs

  • Updated transaction digest logic to use OrchardBundle.
  • Removed separate digest handling for OrchardZSA.
  • +21/-28 
    Tests
    tests.rs
    Update tests for unified `OrchardBundle` handling               

    zcash_primitives/src/transaction/tests.rs

  • Updated tests to reflect changes in OrchardBundle handling.
  • Removed separate assertions for OrchardZSA.
  • +18/-14 
    Dependencies
    Cargo.toml
    Update `orchard` dependency branch                                             

    Cargo.toml

    • Updated orchard dependency branch to spendauth_clone.
    +1/-1     

    💡 PR-Agent usage: Comment /help "your question" on any pull request to receive relevant information

    Copy link

    qodo-merge-pro bot commented Nov 3, 2024

    PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here.

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Code Complexity
    The introduction of the OrchardBundle enum and its implementations adds significant complexity to the codebase. Ensure that this new structure doesn't introduce any unexpected behavior or edge cases.

    Potential Performance Impact
    The new BuildBundle trait and its implementations might affect performance. Verify that these changes don't introduce any significant overhead, especially in frequently called methods.

    Correctness of Digest Logic
    The changes to the transaction digest logic, particularly in the TxIdDigester and BlockTxCommitmentDigester implementations, need careful review to ensure they correctly handle both OrchardVanilla and OrchardZSA bundles.

    Copy link

    qodo-merge-pro bot commented Nov 3, 2024

    PR-Agent was enabled for this repository. To continue using it, please link your git user with your CodiumAI identity here.

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Score
    Security
    Implement a custom Debug trait to protect sensitive information

    Consider adding a custom Debug implementation for OrchardBundle to avoid exposing
    sensitive information when debugging.

    zcash_primitives/src/transaction/mod.rs [376-383]

    -#[derive(Debug, Clone)]
    +#[derive(Clone)]
     pub enum OrchardBundle<V: orchard::bundle::Authorization, Z: orchard::bundle::Authorization> {
         OrchardVanilla(Box<Bundle<V, Amount, OrchardVanilla>>),
         #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )]
         OrchardZSA(Box<Bundle<Z, Amount, OrchardZSA>>),
         #[doc(hidden)]
         _Phantom(PhantomData<Z>),
     }
     
    +impl<V: orchard::bundle::Authorization, Z: orchard::bundle::Authorization> std::fmt::Debug for OrchardBundle<V, Z> {
    +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    +        match self {
    +            OrchardBundle::OrchardVanilla(_) => write!(f, "OrchardBundle::OrchardVanilla(...)"),
    +            OrchardBundle::OrchardZSA(_) => write!(f, "OrchardBundle::OrchardZSA(...)"),
    +            OrchardBundle::_Phantom(_) => write!(f, "OrchardBundle::_Phantom(...)"),
    +        }
    +    }
    +}
    +
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: Implementing a custom Debug trait to avoid exposing sensitive information is a significant security improvement, as it prevents potentially sensitive data from being inadvertently logged or displayed during debugging.

    8
    Maintainability
    Extract repeated match expression into a separate function to reduce code duplication

    Consider extracting the repeated match expression into a separate function to reduce
    code duplication and improve maintainability.

    zcash_primitives/src/transaction/tests.rs [58-69]

    -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!(),
    -})
    +fn get_orchard_value_balance(bundle: &OrchardBundle<bundle::Authorized, bundle::Authorized>) -> Amount {
    +    match bundle {
    +        OrchardVanilla(b) => *b.value_balance(),
    +        #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )]
    +        OrchardZSA(b) => *b.value_balance(),
    +        _ => unreachable!(),
    +    }
    +}
     
    +// In the test function:
    +tx.orchard_bundle.as_ref().map(get_orchard_value_balance),
    +txo.orchard_bundle.as_ref().map(get_orchard_value_balance)
    +
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    Why: Extracting the repeated match expression into a separate function reduces code duplication and improves maintainability. This change enhances the code's structure and makes future modifications easier.

    8
    Enhancement
    Refactor the OrchardBundle handling to use a match expression for improved readability and maintainability

    Consider using a match expression instead of if-else for handling different
    OrchardBundle variants. This would make the code more idiomatic and easier to extend
    in the future.

    zcash_primitives/src/transaction/builder.rs [951-986]

    -if let Some(OrchardBundle::OrchardVanilla(b)) => {
    -    Some(OrchardBundle::OrchardVanilla(Box::new(
    -        b.create_proof(
    -            &orchard::circuit::ProvingKey::build::<OrchardVanilla>(),
    +match unauthed_tx.orchard_bundle {
    +    Some(OrchardBundle::OrchardVanilla(b)) => {
    +        Some(OrchardBundle::OrchardVanilla(Box::new(
    +            b.create_proof(
    +                &orchard::circuit::ProvingKey::build::<OrchardVanilla>(),
    +                &mut rng,
    +            )
    +            .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(
    +        Box::new(b.create_proof(
    +            &orchard::circuit::ProvingKey::build::<OrchardZSA>(),
                 &mut rng,
             )
             .and_then(|b| {
                 b.apply_signatures(
                     &mut rng,
                     *shielded_sig_commitment.as_ref(),
                     &self.orchard_saks,
                 )
             })
             .unwrap(),
    -    )))
    +    ))),
    +    None => None,
     }
     
    -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )]
    -Some(OrchardBundle::OrchardZSA(b)) => Some(OrchardBundle::OrchardZSA(
    -    Box::new(b.create_proof(
    -        &orchard::circuit::ProvingKey::build::<OrchardZSA>(),
    -        &mut rng,
    -    )
    -
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    Why: The suggestion to use a match expression instead of if-else for handling OrchardBundle variants improves code readability and maintainability. It aligns with Rust's idiomatic practices and makes the code easier to extend in the future.

    7
    Simplify the BuildBundle trait for improved code clarity and maintainability

    Consider using a more idiomatic Rust pattern for the BuildBundle trait
    implementation, such as the From trait, to improve code clarity and maintainability.

    zcash_primitives/src/transaction/components/orchard.rs [52-102]

     pub trait BuildBundle<A: Authorization, D: OrchardDomainCommon> {
    -    fn build_bundle(
    -        actions: NonEmpty<Action<A::SpendAuth, D>>,
    -        flags: Flags,
    -        value_balance: Amount,
    -        burn: Vec<(AssetBase, NoteValue)>,
    -        anchor: Anchor,
    -        authorization: A,
    -    ) -> OrchardBundle<A, A>;
    +    fn build_bundle(bundle: Bundle<A, Amount, D>) -> OrchardBundle<A, A>;
     }
     
    +impl<A: Authorization> BuildBundle<A, OrchardVanilla> for OrchardVanilla {
    +    fn build_bundle(bundle: Bundle<A, Amount, OrchardVanilla>) -> OrchardBundle<A, A> {
    +        OrchardBundle::OrchardVanilla(Box::new(bundle))
    +    }
    +}
    +
    +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )]
    +impl<A: Authorization> BuildBundle<A, OrchardZSA> for OrchardZSA {
    +    fn build_bundle(bundle: Bundle<A, Amount, OrchardZSA>) -> OrchardBundle<A, A> {
    +        OrchardBundle::OrchardZSA(Box::new(bundle))
    +    }
    +}
    +
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    Why: The suggestion to use a more idiomatic Rust pattern for the BuildBundle trait implementation simplifies the code, making it more maintainable and easier to understand, which is beneficial for long-term code quality.

    6
    Simplify the OrchardBundle handling using map_or_else for improved code conciseness

    Consider using the map_or_else method instead of map followed by a match expression.
    This can simplify the code and make it more concise.

    zcash_primitives/src/transaction/txid.rs [349-356]

    -orchard_bundle.map(|b| {
    -    match b {
    +orchard_bundle.map_or_else(|| None, |b| {
    +    Some(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!(),
    -    }
    +    })
     })
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    Why: Using map_or_else instead of map followed by a match expression simplifies the code, making it more concise and easier to read. This change enhances the code's clarity without altering its functionality.

    6
    Improve enum variant naming for better code clarity

    Consider using a more descriptive name for the _Phantom variant in the OrchardBundle
    enum. For example, Placeholder or Reserved might better convey its purpose.

    zcash_primitives/src/transaction/mod.rs [376-383]

     pub enum OrchardBundle<V: orchard::bundle::Authorization, Z: orchard::bundle::Authorization> {
         OrchardVanilla(Box<Bundle<V, Amount, OrchardVanilla>>),
         #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )]
         OrchardZSA(Box<Bundle<Z, Amount, OrchardZSA>>),
         #[doc(hidden)]
    -    _Phantom(PhantomData<Z>),
    +    Reserved(PhantomData<Z>),
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 5

    Why: The suggestion to rename the _Phantom variant to Reserved improves code clarity by providing a more descriptive name, which can help developers understand the purpose of the variant more easily.

    5
    Improve code readability by using a match expression instead of if-else statements

    Consider using a match expression instead of if-else statements in the
    arb_bundle_for_version function to improve readability and maintainability.

    zcash_primitives/src/transaction/components/orchard.rs [446-455]

     pub fn arb_bundle_for_version(
         v: TxVersion,
     ) -> impl Strategy<Value = Option<OrchardBundle<Authorized, Authorized>>> {
    -    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))
    +    match v {
    +        v if v.has_orchard_zsa() => Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_zsa_bundle(n)))),
    +        v if v.has_orchard() => Strategy::boxed((1usize..100).prop_flat_map(|n| prop::option::of(arb_bundle(n)))),
    +        _ => Strategy::boxed(Just(None)),
         }
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 4

    Why: Using a match expression instead of if-else statements can improve readability and maintainability, but the impact is relatively minor as the original code is already clear and functional.

    4

    💡 Need additional feedback ? start a PR chat

    @alexeykoren alexeykoren requested a review from PaulLaux November 3, 2024 09:59
    @alexeykoren alexeykoren changed the title [DRAFT] ZSA bundle enum ZSA bundle enum Nov 5, 2024
    @QED-it QED-it deleted a comment from what-the-diff bot Nov 20, 2024
    Copy link

    @PaulLaux PaulLaux left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    please update the branches (especially Orchard with regard to QED-it/orchard#119)

    Cargo.toml Outdated
    @@ -58,7 +58,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 = "zsa1" }
    orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "spendauth_clone" }
    Copy link

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    we need the related PR

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Done, there is an open PR in Orchard
    QED-it/orchard#125

    zcash_primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
    zcash_primitives/src/transaction/mod.rs Show resolved Hide resolved
    zcash_primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
    zcash_primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
    # strategy:
    # matrix:
    # target:
    # - wasm32-wasi

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I've brought it back, let's see

    Cargo.toml Outdated
    @@ -127,4 +127,4 @@ codegen-units = 1
    [patch.crates-io]
    zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" }
    sapling = { package = "sapling-crypto", version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" }
    orchard = { version = "0.8.0", git = "https://github.com/QED-it/orchard", branch = "zsa1" }
    orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "spendauth_clone" }

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I don't follow, shouldn't we use the branch from QED-it/orchard#119 ?

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    It is based on the one you mention

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    the one i mentioned is remove_circuit_param. But I prefer zsa1 and a commit hash

    &self.orchard_saks,
    )
    })
    .unwrap(),

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    do not ignore the possibility of error here: (x2)

    let orchard_bundle: Option<OrchardBundle<_>> = match unauthed_tx.orchard_bundle {
                Some(OrchardBundle::OrchardVanilla(b)) => {
                    Some(OrchardBundle::OrchardVanilla(Box::new(
                        b.create_proof(
                            &orchard::circuit::ProvingKey::build::<OrchardVanilla>(),
                            &mut rng,
                        )
                        .and_then(|b| {
                            b.apply_signatures(
                                &mut rng,
                                *shielded_sig_commitment.as_ref(),
                                &self.orchard_saks,
                            )
                        })
                        .map_err(Error::OrchardBuild)?,
                    )))
                }

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Done

    Copy link

    @PaulLaux PaulLaux left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    This looks much better! waiting for the test vectors.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    2 participants