From e59808d6f4070229fa5e936c85caf3e35480935a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 8 Dec 2025 08:36:48 +0100 Subject: [PATCH 01/14] Address the following review comments: r2487851383 r2487857002 r2487858123 r2487968253 r2487968899 r2542305679 r2542313926 r2542359143 r2542360991 r2542333126 r2542371427 (see note) r2542392826 (see note) r2542406328 r2542447228 r2542428312 r2542599948 r2542671834 r2542817988 r2542846302 r2542756837 r2543147318 r2543502871 r2543506591 r2543527521 r2543542313 (see note) r2543565714 (see note) r2549938764 r2542276487 r2542288774 r2550151848 r2550187398 r2550276814 r2550352041 r2550380193 r2550407188 r2550616659 Note: r2542371427 is only partially addressed: issuance-related modules were moved under crate::issuance::*, but the zsa-issuance feature has not been added to Cargo.toml yet, and issuance code is not yet gated behind cfg(feature = "zsa-issuance"). The feature flag gating (and related optional dependency changes) will be handled in a follow-up PR. Note: r2542392826 addressed except orchard_flavor changes. Note: r2543542313 - changed pub to pub(crate) but needs to be discussed. Note: r2543565714 - It's not completely clear from the comment, but the doc comment for rseed_split_note has beed revomed in this commit and it has been updated it for create_split_note - is that correct? Also kept create_split_note pub, not pub(crate) - needs to be discussed. --- .github/workflows/ci.yml | 11 +--- Cargo.toml | 2 +- README.md | 5 +- benches/circuit.rs | 4 +- benches/note_decryption.rs | 4 +- benches/utils.rs | 11 +++- book/src/design/actions.md | 2 - rust-toolchain.toml | 2 +- src/action.rs | 4 +- src/builder.rs | 6 +- src/bundle.rs | 4 +- src/bundle/burn_validation.rs | 7 ++- src/bundle/commitments.rs | 18 +++--- src/circuit.rs | 2 + src/circuit/circuit_vanilla.rs | 2 +- src/circuit/circuit_zsa.rs | 8 +-- src/circuit/gadget/add_chip.rs | 2 +- src/circuit/value_commit_orchard.rs | 2 +- src/constants/reference_keys.rs | 5 +- src/constants/sinsemilla.rs | 5 +- src/issuance.rs | 33 +++++++---- src/{issuance_auth.rs => issuance/auth.rs} | 2 +- .../sighash_versioning.rs} | 2 +- src/keys.rs | 9 ++- src/lib.rs | 10 +--- src/note.rs | 58 ++++++++++++++----- src/note/asset_base.rs | 38 ++++++------ src/note/commitment.rs | 2 +- src/pczt/prover.rs | 5 +- src/pczt/tx_extractor.rs | 3 +- src/pczt/verify.rs | 5 +- src/primitives/orchard_primitives.rs | 2 +- src/primitives/orchard_primitives_vanilla.rs | 2 +- src/primitives/orchard_primitives_zsa.rs | 2 +- src/primitives/redpallas.rs | 2 +- ...sh_versioning.rs => sighash_versioning.rs} | 0 src/value.rs | 9 ++- tests/issuance_global_state.rs | 2 +- tests/zsa.rs | 2 +- 39 files changed, 173 insertions(+), 121 deletions(-) rename src/{issuance_auth.rs => issuance/auth.rs} (99%) rename src/{issuance_sighash_versioning.rs => issuance/sighash_versioning.rs} (93%) rename src/{orchard_sighash_versioning.rs => sighash_versioning.rs} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f172ad334..dd837dc73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,6 @@ name: CI checks -#on: [push, pull_request] -on: - push: - branches: [ main ] # Only runs on push to main - pull_request: # Runs on any PR to any branch +on: [push, pull_request] jobs: test: @@ -12,8 +8,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, windows-latest ] - # os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v4 @@ -120,7 +115,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Generate coverage report - run: timeout --preserve-status 300s cargo tarpaulin --engine llvm --timeout 600 --out xml --skip-clean || true + run: cargo tarpaulin --engine llvm --all-features --release --timeout 600 --out xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v3.1.4 diff --git a/Cargo.toml b/Cargo.toml index 92a1b64eb..69c3510dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Kris Nuttycombe ", ] edition = "2021" -rust-version = "1.71" +rust-version = "1.70" description = "The Orchard shielded transaction protocol" license = "MIT OR Apache-2.0" repository = "https://github.com/zcash/orchard" diff --git a/README.md b/README.md index 004ba10b1..8fdcd2730 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ -# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) [![CI checks](https://github.com/QED-it/orchard/actions/workflows/ci.yml/badge.svg?branch=zsa1)](https://github.com/QED-it/orchard/actions/workflows/ci.yml) -# +# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) # -Requires Rust 1.71+. +Requires Rust 1.70+. ## Documentation diff --git a/benches/circuit.rs b/benches/circuit.rs index 579a34675..6c5ac21c7 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -7,7 +7,7 @@ use criterion::{BenchmarkId, Criterion}; use pprof::criterion::{Output, PProfProfiler}; use orchard::{ - builder::{Builder, BundleType}, + builder::Builder, circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, @@ -32,7 +32,7 @@ fn criterion_benchmark(c: &mut Criterion) { let create_bundle = |num_recipients| { let mut builder = Builder::new( - BundleType::DEFAULT_VANILLA, + FL::DEFAULT_BUNDLE_TYPE, Anchor::from_bytes([0; 32]).unwrap(), ); for _ in 0..num_recipients { diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 8f2ce8373..b4ed3f8d7 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use orchard::{ - builder::{Builder, BundleType}, + builder::Builder, circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetBase, @@ -51,7 +51,7 @@ fn bench_note_decryption(c: &mut Criterion) { let bundle = { let mut builder = Builder::new( - BundleType::DEFAULT_VANILLA, + FL::DEFAULT_BUNDLE_TYPE, Anchor::from_bytes([0; 32]).unwrap(), ); // The builder pads to two actions, and shuffles their order. Add two recipients diff --git a/benches/utils.rs b/benches/utils.rs index d5f639278..05bcfd5eb 100644 --- a/benches/utils.rs +++ b/benches/utils.rs @@ -1,8 +1,13 @@ use criterion::{measurement::Measurement, BenchmarkGroup, Criterion}; -use orchard::orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}; +use orchard::{ + builder::BundleType, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, +}; pub(crate) trait OrchardFlavorBench: OrchardFlavor { + const DEFAULT_BUNDLE_TYPE: BundleType; + fn benchmark_group<'a, M: Measurement>( c: &'a mut Criterion, group_name: &str, @@ -10,6 +15,8 @@ pub(crate) trait OrchardFlavorBench: OrchardFlavor { } impl OrchardFlavorBench for OrchardVanilla { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_VANILLA; + fn benchmark_group<'a, M: Measurement>( c: &'a mut Criterion, group_name: &str, @@ -19,6 +26,8 @@ impl OrchardFlavorBench for OrchardVanilla { } impl OrchardFlavorBench for OrchardZSA { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_ZSA; + fn benchmark_group<'a, M: Measurement>( c: &'a mut Criterion, group_name: &str, diff --git a/book/src/design/actions.md b/book/src/design/actions.md index 73c81a1af..ec3649054 100644 --- a/book/src/design/actions.md +++ b/book/src/design/actions.md @@ -21,7 +21,6 @@ balance the transaction without doubling its size. ## Dummy notes for Orchard For Orchard, a transaction is a bundle of actions. Each action is composed of one spend and one output. -This means we have the same amount of "spends" and "outputs" in one transaction. If we would like to create a transaction with a different number of spends and outputs, we need to add "dummy" spends or outputs to balance their count. A dummy spend or output is a note with a value of zero and a random recipient address. @@ -32,7 +31,6 @@ we do not verify that the corresponding spent note commitment is part of the Mer For OrchardZSA, if the number of inputs exceeds the number of outputs, we use dummy output notes (as in Orchard) to fill all actions. -Conversely, if the number of outputs exceeds the number of inputs, we use split notes to fill the actions. In OrchardZSA, ensuring that the AssetBase is correctly created is crucial. For this reason, split notes are used instead of dummy spent notes. Split notes are essentially duplicates of actual spent notes, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6ea608282..cad9254a9 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" ] diff --git a/src/action.rs b/src/action.rs index e48eae5b8..6b60b0249 100644 --- a/src/action.rs +++ b/src/action.rs @@ -2,9 +2,9 @@ use memuse::DynamicUsage; use crate::{ note::{ExtractedNoteCommitment, Nullifier, Rho, TransmittedNoteCiphertext}, - orchard_sighash_versioning::VerSpendAuthSig, primitives::redpallas::{self, SpendAuth}, primitives::OrchardPrimitives, + sighash_versioning::VerSpendAuthSig, value::ValueCommitment, }; @@ -136,12 +136,12 @@ pub(crate) mod testing { asset_base::testing::arb_asset_base, commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, testing::arb_note, Note, TransmittedNoteCiphertext, }, - orchard_sighash_versioning::VerSpendAuthSig, primitives::redpallas::{ self, testing::{arb_spendauth_signing_key, arb_spendauth_verification_key}, }, primitives::{OrchardDomain, OrchardPrimitives}, + sighash_versioning::VerSpendAuthSig, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, }; diff --git a/src/builder.rs b/src/builder.rs index 850534350..52958e37b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -21,9 +21,9 @@ use crate::{ }, note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, Rho, TransmittedNoteCiphertext}, orchard_flavor::OrchardVanilla, - orchard_sighash_versioning::{VerBindingSig, VerSpendAuthSig}, primitives::redpallas::{self, Binding, SpendAuth}, primitives::{OrchardDomain, OrchardPrimitives}, + sighash_versioning::{VerBindingSig, VerSpendAuthSig}, tree::{Anchor, MerklePath}, value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, Proof, @@ -515,7 +515,7 @@ impl ActionInfo { ); let v_net = self.value_sum(); - let cv_net = ValueCommitment::derive(v_net, self.rcv, self.output.asset); + let cv_net = ValueCommitment::derive(v_net, self.rcv.clone(), self.output.asset); let (nf_old, ak, alpha, rk) = self.spend.build(&mut rng); let (note, cmx, encrypted_note) = self.output.build(&cv_net, nf_old, &mut rng); @@ -543,7 +543,7 @@ impl ActionInfo { "spend and recipient note types must be equal" ); let v_net = self.value_sum(); - let cv_net = ValueCommitment::derive(v_net, self.rcv, self.spend.note.asset()); + let cv_net = ValueCommitment::derive(v_net, self.rcv.clone(), self.spend.note.asset()); let spend = self.spend.into_pczt(&mut rng); let output = self.output.into_pczt(&cv_net, spend.nullifier, &mut rng); diff --git a/src/bundle.rs b/src/bundle.rs index edc19f3e5..1f02dbaac 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -26,9 +26,9 @@ use crate::{ bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, note::{AssetBase, Note}, - orchard_sighash_versioning::{OrchardSighashVersion, VerBindingSig, VerSpendAuthSig}, primitives::redpallas::{self, Binding}, primitives::{OrchardDomain, OrchardPrimitives}, + sighash_versioning::{OrchardSighashVersion, VerBindingSig, VerSpendAuthSig}, tree::Anchor, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, Proof, @@ -632,8 +632,8 @@ pub mod testing { use crate::{ note::{asset_base::testing::arb_zsa_asset_base, AssetBase}, - orchard_sighash_versioning::{VerBindingSig, VerSpendAuthSig}, primitives::{redpallas::testing::arb_binding_signing_key, OrchardPrimitives}, + sighash_versioning::{VerBindingSig, VerSpendAuthSig}, value::{ testing::{arb_note_value, arb_note_value_bounded}, NoteValue, ValueSum, MAX_NOTE_VALUE, diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index 0d94c761e..8c42b37a3 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -66,7 +66,10 @@ impl fmt::Display for BurnError { #[cfg(test)] mod tests { use super::*; - use crate::{issuance::compute_asset_desc_hash, issuance_auth::ZSASchnorr, value::NoteValue}; + use crate::{ + issuance::{auth::ZSASchnorr, compute_asset_desc_hash}, + value::NoteValue, + }; use nonempty::NonEmpty; /// Creates an item of bundle burn list for a given asset description hash and value. @@ -84,7 +87,7 @@ mod tests { /// A tuple `(AssetBase, Amount)` representing the burn list item. /// fn get_burn_tuple(asset_desc_hash: &[u8; 32], value: u64) -> (AssetBase, NoteValue) { - use crate::issuance_auth::{IssueAuthKey, IssueValidatingKey}; + use crate::issuance::auth::{IssueAuthKey, IssueValidatingKey}; let isk = IssueAuthKey::::from_bytes(&[1u8; 32]).unwrap(); diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 2a11a308b..6b2edaf4a 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -5,10 +5,12 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; use crate::{ bundle::{Authorization, Authorized, Bundle}, - issuance::{IssueAuth, IssueBundle, Signed}, - issuance_sighash_versioning::IssueSighashVersion, - orchard_sighash_versioning::OrchardSighashVersion, + issuance::{ + sighash_versioning::IssueSighashVersion, + {IssueAuth, IssueBundle, Signed}, + }, primitives::OrchardPrimitives, + sighash_versioning::OrchardSighashVersion, }; pub(crate) const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; @@ -188,13 +190,15 @@ mod tests { Authorized, Bundle, }, circuit::ProvingKey, - issuance::{compute_asset_desc_hash, AwaitingSighash, IssueBundle, IssueInfo}, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, - issuance_sighash_versioning::IssueSighashVersion, + issuance::{ + auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + sighash_versioning::IssueSighashVersion, + {compute_asset_desc_hash, AwaitingSighash, IssueBundle, IssueInfo}, + }, keys::{FullViewingKey, Scope, SpendingKey}, note::{AssetBase, Nullifier}, orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, - orchard_sighash_versioning::OrchardSighashVersion, + sighash_versioning::OrchardSighashVersion, value::NoteValue, Anchor, }; diff --git a/src/circuit.rs b/src/circuit.rs index f5e0a6677..668391bef 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -267,6 +267,7 @@ impl Witnesses { } /// The verifying key for the Orchard Action circuit. +/// In practice this is constructed for either `OrchardVanilla` or `OrchardZSA`. #[derive(Debug, Clone)] pub struct VerifyingKey { pub(crate) params: halo2_proofs::poly::commitment::Params, @@ -286,6 +287,7 @@ impl VerifyingKey { } /// The proving key for the Orchard Action circuit. +/// In practice this is constructed for either `OrchardVanilla` or `OrchardZSA`. #[derive(Debug, Clone)] pub struct ProvingKey { params: halo2_proofs::poly::commitment::Params, diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs index 767e6d6a2..bcda160e0 100644 --- a/src/circuit/circuit_vanilla.rs +++ b/src/circuit/circuit_vanilla.rs @@ -665,7 +665,7 @@ mod tests { let value = spent_note.value() - output_note.value(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + let cv_net = ValueCommitment::derive(value, rcv.clone(), AssetBase::native()); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index 41e796d6b..e2567128c 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -908,7 +908,7 @@ mod tests { let value = spent_note.value() - output_note.value(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + let cv_net = ValueCommitment::derive(value, rcv.clone(), AssetBase::native()); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); @@ -1224,7 +1224,7 @@ mod tests { let cmx = output_note.commitment().into(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(v_net, rcv, asset_base); + let cv_net = ValueCommitment::derive(v_net, rcv.clone(), asset_base); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); @@ -1337,7 +1337,7 @@ mod tests { v_new: circuit.witnesses.v_new, psi_new: circuit.witnesses.psi_new, rcm_new: circuit.witnesses.rcm_new.clone(), - rcv: circuit.witnesses.rcv, + rcv: circuit.witnesses.rcv.clone(), additional_zsa_witnesses: circuit .witnesses @@ -1399,7 +1399,7 @@ mod tests { v_new: circuit.witnesses.v_new, psi_new: circuit.witnesses.psi_new, rcm_new: circuit.witnesses.rcm_new.clone(), - rcv: circuit.witnesses.rcv, + rcv: circuit.witnesses.rcv.clone(), additional_zsa_witnesses: circuit .witnesses diff --git a/src/circuit/gadget/add_chip.rs b/src/circuit/gadget/add_chip.rs index 41b90b1f1..03d57a0e9 100644 --- a/src/circuit/gadget/add_chip.rs +++ b/src/circuit/gadget/add_chip.rs @@ -1,4 +1,4 @@ -//! `Add` chip implemetation. +//! `Add` chip implementation. use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs index 8ad2793a1..05dd3732c 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -369,7 +369,7 @@ mod tests { circuits.push(MyCircuit { v_old: Value::known(v_old), v_new: Value::known(v_new), - rcv: Value::known(rcv), + rcv: Value::known(rcv.clone()), asset: Value::known(asset), split_flag: Value::known(split_flag), }); diff --git a/src/constants/reference_keys.rs b/src/constants/reference_keys.rs index 535528000..3b97dfea2 100644 --- a/src/constants/reference_keys.rs +++ b/src/constants/reference_keys.rs @@ -41,12 +41,11 @@ impl ReferenceKeys { #[cfg(test)] mod tests { use super::*; - use crate::keys::{FullViewingKey, Scope}; + use crate::keys::Scope; #[test] fn recipient() { - let sk = SpendingKey::from_bytes([0; 32]).unwrap(); - let fvk = FullViewingKey::from(&sk); + let fvk = ReferenceKeys::fvk(); let recipient = fvk.address_at(0u32, Scope::External); assert_eq!(recipient, ReferenceKeys::recipient()); diff --git a/src/constants/sinsemilla.rs b/src/constants/sinsemilla.rs index 5df103344..36e7f3875 100644 --- a/src/constants/sinsemilla.rs +++ b/src/constants/sinsemilla.rs @@ -224,7 +224,10 @@ mod tests { #[test] fn q_note_zsa_commitment_m() { - let domain = CommitDomain::new(NOTE_ZSA_COMMITMENT_PERSONALIZATION); + let domain = CommitDomain::new_with_separate_domains( + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + NOTE_COMMITMENT_PERSONALIZATION, + ); let point = domain.Q(); let coords = point.to_affine().coordinates().unwrap(); diff --git a/src/issuance.rs b/src/issuance.rs index 89356b320..33cbb66b9 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -23,8 +23,6 @@ use rand::RngCore; use crate::{ bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}, constants::reference_keys::ReferenceKeys, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, - issuance_sighash_versioning::{IssueSighashVersion, VerBIP340IssueAuthSig}, note::{rho_for_issuance_note, AssetBase, Nullifier, Rho}, value::NoteValue, Address, Note, @@ -38,6 +36,12 @@ use Error::{ MissingReferenceNoteOnFirstIssuance, ValueOverflow, }; +pub mod auth; +pub mod sighash_versioning; + +use auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}; +use sighash_versioning::{IssueSighashVersion, VerBIP340IssueAuthSig}; + /// Checks if a given note is a reference note. /// /// A reference note satisfies the following conditions: @@ -842,11 +846,13 @@ mod tests { IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, }, issuance::{ - compute_asset_desc_hash, is_reference_note, verify_issue_bundle, AssetRecord, - IssueAction, IssueBundle, IssueInfo, Signed, + auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + sighash_versioning::{IssueSighashVersion, VerBIP340IssueAuthSig}, + { + compute_asset_desc_hash, is_reference_note, verify_issue_bundle, AssetRecord, + IssueAction, IssueBundle, IssueInfo, Signed, + }, }, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, - issuance_sighash_versioning::{IssueSighashVersion, VerBIP340IssueAuthSig}, keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{rho_for_issuance_note, AssetBase, ExtractedNoteCommitment, Nullifier, Rho}, orchard_flavor::OrchardZSA, @@ -1976,13 +1982,16 @@ mod tests { pub mod testing { use crate::{ issuance::{ - AwaitingNullifier, IssueAction, IssueBundle, Prepared, Signed, VerBIP340IssueAuthSig, - }, - issuance_auth::{ - testing::arb_issuance_validating_key, IssueAuthSig, IssueAuthSigScheme, - IssueValidatingKey, ZSASchnorr, + auth::{ + testing::arb_issuance_validating_key, IssueAuthSig, IssueAuthSigScheme, + IssueValidatingKey, ZSASchnorr, + }, + sighash_versioning::IssueSighashVersion, + { + AwaitingNullifier, IssueAction, IssueBundle, Prepared, Signed, + VerBIP340IssueAuthSig, + }, }, - issuance_sighash_versioning::IssueSighashVersion, note::testing::arb_zsa_note, }; use nonempty::NonEmpty; diff --git a/src/issuance_auth.rs b/src/issuance/auth.rs similarity index 99% rename from src/issuance_auth.rs rename to src/issuance/auth.rs index b4be0fdef..77794ef72 100644 --- a/src/issuance_auth.rs +++ b/src/issuance/auth.rs @@ -6,7 +6,7 @@ //! # Example //! ``` //! use rand::rngs::OsRng; -//! use orchard::issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}; +//! use orchard::issuance::auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}; //! //! let mut rng = OsRng; //! let isk = IssueAuthKey::::random(&mut rng); diff --git a/src/issuance_sighash_versioning.rs b/src/issuance/sighash_versioning.rs similarity index 93% rename from src/issuance_sighash_versioning.rs rename to src/issuance/sighash_versioning.rs index effeabe9d..760022ee4 100644 --- a/src/issuance_sighash_versioning.rs +++ b/src/issuance/sighash_versioning.rs @@ -1,6 +1,6 @@ //! This module defines the versioning for issuance authorization signatures. -use crate::issuance_auth::{IssueAuthSig, IssueAuthSigScheme, ZSASchnorr}; +use crate::issuance::auth::{IssueAuthSig, IssueAuthSigScheme, ZSASchnorr}; /// The Issuance Sighash version. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/keys.rs b/src/keys.rs index 0513e66e1..7a175ca77 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -30,7 +30,10 @@ use crate::{ // Preserve '::' which specifies the EXTERNAL 'zip32' crate #[rustfmt::skip] -pub use ::zip32::{AccountId, ChildIndex, DiversifierIndex, Scope, hardened_only}; +pub use ::zip32::{AccountId, DiversifierIndex, Scope}; + +#[rustfmt::skip] +use ::zip32::{ChildIndex, hardened_only}; const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; const ZIP32_PURPOSE: u32 = 32; @@ -187,7 +190,7 @@ impl SpendValidatingKey { self.0.randomize(randomizer) } - /// Converts this spend key to its serialized form, + /// Converts this spend key validating to its serialized form, /// I2LEOSP_256(ak). #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn to_bytes(&self) -> [u8; 32] { @@ -977,7 +980,7 @@ mod tests { *, }; use crate::{ - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + issuance::auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, note::{AssetBase, ExtractedNoteCommitment, RandomSeed, Rho}, value::NoteValue, Note, diff --git a/src/lib.rs b/src/lib.rs index 4c9deded7..6c41af4b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,14 +33,12 @@ pub mod bundle; pub mod circuit; mod constants; pub mod issuance; -pub mod issuance_auth; -pub mod issuance_sighash_versioning; pub mod keys; pub mod note; pub mod orchard_flavor; -pub mod orchard_sighash_versioning; pub mod pczt; pub mod primitives; +pub mod sighash_versioning; mod spec; pub mod tree; pub mod value; @@ -52,12 +50,8 @@ mod test_vectors; pub use action::Action; pub use address::Address; pub use bundle::Bundle; -pub use constants::reference_keys::ReferenceKeys; pub use constants::MERKLE_DEPTH_ORCHARD as NOTE_COMMITMENT_TREE_DEPTH; -pub use note::{ - commitment::{ExtractedNoteCommitment, NoteCommitment}, - Note, -}; +pub use note::Note; pub use tree::Anchor; /// A proof of the validity of an Orchard [`Bundle`]. diff --git a/src/note.rs b/src/note.rs index 67808b81f..b77024175 100644 --- a/src/note.rs +++ b/src/note.rs @@ -18,6 +18,9 @@ use crate::{ Address, }; +pub(crate) mod asset_base; +pub use self::asset_base::AssetBase; + pub(crate) mod commitment; pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment}; @@ -70,9 +73,6 @@ impl Rho { } } -pub(crate) mod asset_base; -pub use self::asset_base::AssetBase; - /// The ZIP 212 seed randomness for a note. #[derive(Copy, Clone, Debug)] pub struct RandomSeed([u8; 32]); @@ -203,6 +203,37 @@ impl Note { asset: AssetBase, rho: Rho, rseed: RandomSeed, + ) -> CtOption { + Self::from_parts_internal( + recipient, + value, + asset, + rho, + rseed, + CtOption::new(rseed, 0u8.into()), + ) + } + + /// Creates a `Note` from its component parts. + /// + /// This additionally permits constructing a [Split Input note], which is necessary + /// for constructing certain patterns of bundles containing ZSA outputs. It is used by + /// the PCZT code, which is the only place where these notes are serialized. + /// + /// Returns `None` if a valid [`NoteCommitment`] cannot be derived from the note. + /// + /// # Caveats + /// + /// See [`Self::from_parts`]. + /// + /// [Split Input note]: https://zips.z.cash/zip-0226#split-notes + pub(crate) fn from_parts_internal( + recipient: Address, + value: NoteValue, + asset: AssetBase, + rho: Rho, + rseed: RandomSeed, + rseed_split_note: CtOption, ) -> CtOption { let note = Note { recipient, @@ -210,7 +241,7 @@ impl Note { asset, rho, rseed, - rseed_split_note: CtOption::new(rseed, 0u8.into()), + rseed_split_note, }; CtOption::new(note, note.commitment_inner().is_some()) } @@ -286,15 +317,10 @@ impl Note { &self.rseed } - /// Returns the rseed_split_note value of this note. - pub fn rseed_split_note(&self) -> CtOption { + pub(crate) fn rseed_split_note(&self) -> CtOption { self.rseed_split_note } - pub(crate) fn set_rseed_split_note(&mut self, rseed_split_note: RandomSeed) { - self.rseed_split_note = CtOption::new(rseed_split_note, 1u8.into()); - } - /// Derives the ephemeral secret key for this note. pub(crate) fn esk(&self) -> EphemeralSecretKey { EphemeralSecretKey(self.rseed.esk(&self.rho)) @@ -351,8 +377,14 @@ impl Note { ) } - /// Create a split note which has the same values than the input note except for - /// `rseed_split_note` which is equal to a random seed. + /// Creates a [Split Input note] from a Custom Asset note, for use on the Spend side + /// of an Output-only Action. + /// + /// # Panics + /// + /// Panics if `self.asset().is_native()`. + /// + /// [Split Input note]: https://zips.z.cash/zip-0226#split-notes pub fn create_split_note(self, rng: &mut impl RngCore) -> Self { Note { rseed_split_note: CtOption::new(RandomSeed::random(rng, &self.rho), 1u8.into()), @@ -429,7 +461,7 @@ pub mod testing { use crate::{ address::testing::arb_address, - issuance_auth::{IssueValidatingKey, ZSASchnorr}, + issuance::auth::{IssueValidatingKey, ZSASchnorr}, note::{asset_base::testing::arb_asset_base, nullifier::testing::arb_nullifier, AssetBase}, value::{testing::arb_note_value, NoteValue}, }; diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 9541c162b..4f4ce7b8c 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -2,9 +2,8 @@ use alloc::vec::Vec; use blake2b_simd::{Hash as Blake2bHash, Params}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use group::{Curve, Group, GroupEncoding}; +use group::{Group, GroupEncoding}; use nonempty::NonEmpty; -use pasta_curves::arithmetic::CurveAffine; use pasta_curves::{arithmetic::CurveExt, pallas}; use rand_core::CryptoRngCore; use subtle::{Choice, ConstantTimeEq, CtOption}; @@ -13,8 +12,10 @@ use crate::{ constants::fixed_bases::{ NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, }, - issuance::compute_asset_desc_hash, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + issuance::{ + auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, + compute_asset_desc_hash, + }, }; /// Note type identifier. @@ -30,23 +31,18 @@ impl PartialOrd for AssetBase { impl Ord for AssetBase { fn cmp(&self, other: &Self) -> Ordering { - let self_coord = self.0.to_affine().coordinates().unwrap(); - let other_coord = other.0.to_affine().coordinates().unwrap(); - self_coord - .x() - .cmp(other_coord.x()) - .then_with(|| self_coord.y().cmp(other_coord.y())) + self.0.to_bytes().cmp(&other.0.to_bytes()) } } /// Personalization for the ZSA asset digest generator pub const ZSA_ASSET_DIGEST_PERSONALIZATION: &[u8; 16] = b"ZSA-Asset-Digest"; -/// AssetDigest for the ZSA asset +/// Derives the Asset Digest for the given ZSA asset. /// -/// Defined in [ZIP-227: Issuance of Zcash Shielded Assets][assetdigest]. +/// Defined in [ZIP-227: Issuance of Zcash Shielded Assets][assetdigest]. /// -/// [assetdigest]: https://zips.z.cash/zip-0227.html#specification-asset-identifier-asset-digest-and-asset-base +/// [assetdigest]: https://zips.z.cash/zip-0227#asset-digests pub fn asset_digest(encode_asset_id: &[u8]) -> Blake2bHash { Params::new() .hash_length(64) @@ -64,10 +60,10 @@ pub fn encode_asset_id( ik: &IssueValidatingKey, asset_desc_hash: &[u8; 32], ) -> Vec { - let ik_encoding = ik.encode(); - let mut asset_id = Vec::with_capacity(1 + ik_encoding.len() + asset_desc_hash.len()); + let issuer = ik.encode(); + let mut asset_id = Vec::with_capacity(1 + issuer.len() + asset_desc_hash.len()); asset_id.push(version); - asset_id.extend(ik_encoding); + asset_id.extend(issuer); asset_id.extend_from_slice(&asset_desc_hash[..]); asset_id } @@ -85,9 +81,9 @@ impl AssetBase { /// Note type derivation. /// - /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][assetbase]. + /// Defined in [ZIP 227: Issuance of Zcash Shielded Assets][assetbase]. /// - /// [assetbase]: https://zips.z.cash/zip-0226.html#asset-identifiers + /// [assetbase]: https://zips.z.cash/zip-0227#asset-bases /// /// # Panics /// @@ -117,7 +113,7 @@ impl AssetBase { pub fn native() -> Self { AssetBase(pallas::Point::hash_to_curve( VALUE_COMMITMENT_PERSONALIZATION, - )(&NATIVE_ASSET_BASE_V_BYTES[..])) + )(&NATIVE_ASSET_BASE_V_BYTES)) } /// The base point used in value commitments. @@ -164,7 +160,7 @@ pub mod testing { use proptest::prelude::*; - use crate::issuance_auth::{ + use crate::issuance::auth::{ testing::arb_issuance_authorizing_key, IssueValidatingKey, ZSASchnorr, }; @@ -206,7 +202,7 @@ pub mod testing { #[cfg(test)] mod tests { use crate::{ - issuance_auth::{IssueValidatingKey, ZSASchnorr}, + issuance::auth::{IssueValidatingKey, ZSASchnorr}, note::AssetBase, }; diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 6bc04f5ed..de7606bee 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -40,7 +40,7 @@ impl NoteCommitment { /// /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit]. /// - /// [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment + /// [notecommit]: https://zips.z.cash/zip-0226#note-structure-and-commitment pub(crate) fn derive( g_d: [u8; 32], pk_d: [u8; 32], diff --git a/src/pczt/prover.rs b/src/pczt/prover.rs index 5a103f9bd..3a73c00ad 100644 --- a/src/pczt/prover.rs +++ b/src/pczt/prover.rs @@ -74,7 +74,10 @@ impl super::Bundle { .spend .alpha .ok_or(ProverError::MissingSpendAuthRandomizer)?; - let rcv = action.rcv.ok_or(ProverError::MissingValueCommitTrapdoor)?; + let rcv = action + .rcv + .clone() + .ok_or(ProverError::MissingValueCommitTrapdoor)?; Witnesses::from_action_context::(spend, output_note, alpha, rcv) .ok_or(ProverError::RhoMismatch) diff --git a/src/pczt/tx_extractor.rs b/src/pczt/tx_extractor.rs index 057dc2831..ad0f28ab6 100644 --- a/src/pczt/tx_extractor.rs +++ b/src/pczt/tx_extractor.rs @@ -5,8 +5,8 @@ use super::Action; use crate::{ bundle::{Authorization, Authorized, EffectsOnly}, orchard_flavor::OrchardVanilla, - orchard_sighash_versioning::{OrchardSighashVersion, VerBindingSig, VerSpendAuthSig}, primitives::redpallas::{self, Binding, SpendAuth}, + sighash_versioning::{OrchardSighashVersion, VerBindingSig, VerSpendAuthSig}, Proof, }; @@ -46,6 +46,7 @@ impl super::Bundle { .ok_or(TxExtractorError::MissingProof)?, bsk: bundle .bsk + .clone() .ok_or(TxExtractorError::MissingBindingSignatureSigningKey)?, }) }, diff --git a/src/pczt/verify.rs b/src/pczt/verify.rs index c6a22b9e0..e58576fbe 100644 --- a/src/pczt/verify.rs +++ b/src/pczt/verify.rs @@ -15,7 +15,10 @@ impl super::Action { pub fn verify_cv_net(&self) -> Result<(), VerifyError> { let spend_value = self.spend().value.ok_or(VerifyError::MissingValue)?; let output_value = self.output().value.ok_or(VerifyError::MissingValue)?; - let rcv = self.rcv.ok_or(VerifyError::MissingValueCommitTrapdoor)?; + let rcv = self + .rcv + .clone() + .ok_or(VerifyError::MissingValueCommitTrapdoor)?; let cv_net = ValueCommitment::derive(spend_value - output_value, rcv, AssetBase::native()); if cv_net.to_bytes() == self.cv_net.to_bytes() { diff --git a/src/primitives/orchard_primitives.rs b/src/primitives/orchard_primitives.rs index 96ef64a6c..d6f83b77b 100644 --- a/src/primitives/orchard_primitives.rs +++ b/src/primitives/orchard_primitives.rs @@ -10,8 +10,8 @@ use zcash_note_encryption::{note_bytes::NoteBytes, AEAD_TAG_SIZE}; use crate::{ bundle::{Authorization, Authorized}, note::AssetBase, - orchard_sighash_versioning::OrchardSighashVersion, primitives::zcash_note_encryption_domain::{Memo, MEMO_SIZE}, + sighash_versioning::OrchardSighashVersion, Bundle, Note, }; diff --git a/src/primitives/orchard_primitives_vanilla.rs b/src/primitives/orchard_primitives_vanilla.rs index 3d5ff74b4..833348568 100644 --- a/src/primitives/orchard_primitives_vanilla.rs +++ b/src/primitives/orchard_primitives_vanilla.rs @@ -17,7 +17,6 @@ use crate::{ }, note::{AssetBase, Note}, orchard_flavor::OrchardVanilla, - orchard_sighash_versioning::OrchardSighashVersion, primitives::{ orchard_primitives::OrchardPrimitives, zcash_note_encryption_domain::{ @@ -25,6 +24,7 @@ use crate::{ NOTE_VERSION_BYTE_V2, }, }, + sighash_versioning::OrchardSighashVersion, Bundle, }; diff --git a/src/primitives/orchard_primitives_zsa.rs b/src/primitives/orchard_primitives_zsa.rs index 537d1315d..be7afa67b 100644 --- a/src/primitives/orchard_primitives_zsa.rs +++ b/src/primitives/orchard_primitives_zsa.rs @@ -21,7 +21,6 @@ use crate::{ }, note::{AssetBase, Note}, orchard_flavor::OrchardZSA, - orchard_sighash_versioning::OrchardSighashVersion, primitives::{ orchard_primitives::OrchardPrimitives, zcash_note_encryption_domain::{ @@ -29,6 +28,7 @@ use crate::{ COMPACT_NOTE_SIZE_ZSA, MEMO_SIZE, NOTE_VERSION_BYTE_V3, }, }, + sighash_versioning::OrchardSighashVersion, Bundle, }; diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index 70155cfbf..f14c17061 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -23,7 +23,7 @@ pub type Binding = reddsa::orchard::Binding; impl SigType for Binding {} /// A RedPallas signing key. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct SigningKey(reddsa::SigningKey); impl From> for [u8; 32] { diff --git a/src/orchard_sighash_versioning.rs b/src/sighash_versioning.rs similarity index 100% rename from src/orchard_sighash_versioning.rs rename to src/sighash_versioning.rs diff --git a/src/value.rs b/src/value.rs index 54c377af0..2f221c6f3 100644 --- a/src/value.rs +++ b/src/value.rs @@ -218,7 +218,7 @@ impl ValueSum { ) } - pub(crate) fn into>(self) -> Result { + pub(crate) fn into_value_balance>(self) -> Result { i64::try_from(self) .map_err(BuildError::ValueSum) .and_then(|i| V::try_from(i).map_err(|_| BuildError::ValueSum(OverflowError))) @@ -285,7 +285,7 @@ impl From for ValueSum { } /// The blinding factor for a [`ValueCommitment`]. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct ValueCommitTrapdoor(pallas::Scalar); impl ValueCommitTrapdoor { @@ -396,6 +396,7 @@ impl ValueCommitment { #[allow(non_snake_case)] pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, asset: AssetBase) -> Self { let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); + let V = asset.cv_base(); let R = hasher(&VALUE_COMMITMENT_R_BYTES); let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); @@ -405,9 +406,7 @@ impl ValueCommitment { pallas::Scalar::from(abs_value) }; - let V_zsa = asset.cv_base(); - - ValueCommitment(V_zsa * value + R * rcv.0) + ValueCommitment(V * value + R * rcv.0) } pub(crate) fn into_bvk(self) -> redpallas::VerificationKey { diff --git a/tests/issuance_global_state.rs b/tests/issuance_global_state.rs index 6d7d688c7..750529d7c 100644 --- a/tests/issuance_global_state.rs +++ b/tests/issuance_global_state.rs @@ -6,6 +6,7 @@ use rand::{rngs::OsRng, RngCore}; use orchard::{ issuance::{ + auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, compute_asset_desc_hash, verify_issue_bundle, AssetRecord, Error::{ IssueActionPreviouslyFinalizedAssetBase, MissingReferenceNoteOnFirstIssuance, @@ -13,7 +14,6 @@ use orchard::{ }, IssueBundle, IssueInfo, Signed, }, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, keys::{FullViewingKey, Scope, SpendingKey}, note::{AssetBase, Nullifier}, value::NoteValue, diff --git a/tests/zsa.rs b/tests/zsa.rs index 66017e4b9..b5654a46c 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -8,10 +8,10 @@ use orchard::{ bundle::Authorized, circuit::{ProvingKey, VerifyingKey}, issuance::{ + auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, compute_asset_desc_hash, verify_issue_bundle, AwaitingNullifier, IssueBundle, IssueInfo, Signed, }, - issuance_auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment, Nullifier}, orchard_flavor::OrchardZSA, From 7b0093be4605ad221e0324e2ce63d3f0bba501f0 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 5 Jan 2026 12:11:52 +0000 Subject: [PATCH 02/14] Update .github/workflows/ci.yml Co-authored-by: Constance Beguier --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd837dc73..ed253248d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,6 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - steps: - uses: actions/checkout@v4 - name: Run tests From edf165ffa5e07cad0da954348f57baf6f5b81129 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 5 Jan 2026 12:12:03 +0000 Subject: [PATCH 03/14] Update src/circuit.rs Co-authored-by: Constance Beguier --- src/circuit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/circuit.rs b/src/circuit.rs index 668391bef..9eadffef7 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -267,7 +267,8 @@ impl Witnesses { } /// The verifying key for the Orchard Action circuit. -/// In practice this is constructed for either `OrchardVanilla` or `OrchardZSA`. +/// +/// In practice, this is constructed for either `OrchardVanilla` or `OrchardZSA`. #[derive(Debug, Clone)] pub struct VerifyingKey { pub(crate) params: halo2_proofs::poly::commitment::Params, From 90fb0d7bb7e9a3ab0dd4d730f701dadba79165e1 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 5 Jan 2026 12:12:27 +0000 Subject: [PATCH 04/14] Update src/keys.rs Co-authored-by: Constance Beguier --- src/keys.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keys.rs b/src/keys.rs index 7a175ca77..bbdb95ab9 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -190,7 +190,7 @@ impl SpendValidatingKey { self.0.randomize(randomizer) } - /// Converts this spend key validating to its serialized form, + /// Converts this spend validating key to its serialized form, /// I2LEOSP_256(ak). #[cfg_attr(feature = "unstable-frost", visibility::make(pub))] pub(crate) fn to_bytes(&self) -> [u8; 32] { From a13f2dde9b16ab7621046ab6786e0a7ea925c5dd Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 5 Jan 2026 12:29:13 +0000 Subject: [PATCH 05/14] Update src/circuit.rs Co-authored-by: Constance Beguier --- src/circuit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/circuit.rs b/src/circuit.rs index 9eadffef7..5c0db1d4d 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -288,7 +288,8 @@ impl VerifyingKey { } /// The proving key for the Orchard Action circuit. -/// In practice this is constructed for either `OrchardVanilla` or `OrchardZSA`. +/// +/// In practice, this is constructed for either `OrchardVanilla` or `OrchardZSA`. #[derive(Debug, Clone)] pub struct ProvingKey { params: halo2_proofs::poly::commitment::Params, From 1ced36493e325946e3c9014d537ee888a7f8efc1 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 12:34:58 +0000 Subject: [PATCH 06/14] Remove rustfmt::skip and mover ::zip32 upper in key.rs --- src/keys.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index bbdb95ab9..1ba8529f2 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -4,6 +4,7 @@ use alloc::vec::Vec; use core::fmt::Debug; use core2::io::{self, Read, Write}; +use ::zip32::{hardened_only, ChildIndex}; use aes::Aes256; use blake2b_simd::{Hash as Blake2bHash, Params}; use fpe::ff1::{BinaryNumeralString, FF1}; @@ -28,13 +29,8 @@ use crate::{ zip32::{self, ExtendedSpendingKey}, }; -// Preserve '::' which specifies the EXTERNAL 'zip32' crate -#[rustfmt::skip] pub use ::zip32::{AccountId, DiversifierIndex, Scope}; -#[rustfmt::skip] -use ::zip32::{ChildIndex, hardened_only}; - const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; const ZIP32_PURPOSE: u32 = 32; From 6c685f39a5352b6cc1c4aca764c574e47dfaee8b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 12:39:44 +0000 Subject: [PATCH 07/14] Restore a line removed to fix r2542313926 in actions.md --- book/src/design/actions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/design/actions.md b/book/src/design/actions.md index ec3649054..cec9684fa 100644 --- a/book/src/design/actions.md +++ b/book/src/design/actions.md @@ -31,6 +31,7 @@ we do not verify that the corresponding spent note commitment is part of the Mer For OrchardZSA, if the number of inputs exceeds the number of outputs, we use dummy output notes (as in Orchard) to fill all actions. +Conversely, if the number of outputs exceeds the number of inputs, we use split notes to fill the actions. In OrchardZSA, ensuring that the AssetBase is correctly created is crucial. For this reason, split notes are used instead of dummy spent notes. Split notes are essentially duplicates of actual spent notes, @@ -51,4 +52,3 @@ Each Orchard action has a memo field for its corresponding output, as with Sprou Sapling. We did at one point consider having a single Orchard memo field per transaction, and/or having a mechanism for enabling multiple recipients to decrypt the same memo, but these were decided against in order to keep the overall design simpler. - From 46f031cbd39d9850e388da7255b6398232d1b574 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 12:45:11 +0000 Subject: [PATCH 08/14] Rename orchard_flavor to flavor --- src/builder.rs | 8 ++++---- src/bundle/commitments.rs | 2 +- src/circuit/circuit_vanilla.rs | 4 ++-- src/circuit/circuit_zsa.rs | 4 ++-- src/{orchard_flavor.rs => flavor.rs} | 0 src/issuance.rs | 2 +- src/lib.rs | 2 +- src/pczt.rs | 4 ++-- src/pczt/parse.rs | 2 +- src/pczt/prover.rs | 2 +- src/pczt/tx_extractor.rs | 2 +- src/primitives/orchard_primitives_vanilla.rs | 4 ++-- src/primitives/orchard_primitives_zsa.rs | 4 ++-- 13 files changed, 20 insertions(+), 20 deletions(-) rename src/{orchard_flavor.rs => flavor.rs} (100%) diff --git a/src/builder.rs b/src/builder.rs index 52958e37b..a05971629 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -15,12 +15,12 @@ use crate::{ address::Address, builder::BuildError::{BurnNative, BurnZero}, bundle::{Authorization, Authorized, Bundle, Flags}, + flavor::OrchardVanilla, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, Rho, TransmittedNoteCiphertext}, - orchard_flavor::OrchardVanilla, primitives::redpallas::{self, Binding, SpendAuth}, primitives::{OrchardDomain, OrchardPrimitives}, sighash_versioning::{VerBindingSig, VerSpendAuthSig}, @@ -35,7 +35,7 @@ use { action::Action, bundle::derive_bvk, circuit::{Circuit, Instance, OrchardCircuit, ProvingKey, Witnesses}, - orchard_flavor::OrchardFlavor, + flavor::OrchardFlavor, }, nonempty::NonEmpty, }; @@ -1411,9 +1411,9 @@ pub mod testing { address::testing::arb_address, bundle::{Authorized, Bundle}, circuit::ProvingKey, + flavor::OrchardFlavor, keys::{testing::arb_spending_key, FullViewingKey, SpendAuthorizingKey, SpendingKey}, note::{testing::arb_note, AssetBase}, - orchard_flavor::OrchardFlavor, primitives::OrchardPrimitives, tree::{Anchor, MerkleHashOrchard, MerklePath}, value::{testing::arb_positive_note_value, NoteValue, MAX_NOTE_VALUE}, @@ -1559,9 +1559,9 @@ mod tests { bundle::{Authorized, Bundle}, circuit::ProvingKey, constants::MERKLE_DEPTH_ORCHARD, + flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, - orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::EMPTY_ROOTS, value::NoteValue, }; diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 6b2edaf4a..ade8a7168 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -190,6 +190,7 @@ mod tests { Authorized, Bundle, }, circuit::ProvingKey, + flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, issuance::{ auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, sighash_versioning::IssueSighashVersion, @@ -197,7 +198,6 @@ mod tests { }, keys::{FullViewingKey, Scope, SpendingKey}, note::{AssetBase, Nullifier}, - orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, sighash_versioning::OrchardSighashVersion, value::NoteValue, Anchor, diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs index bcda160e0..74f2383d1 100644 --- a/src/circuit/circuit_vanilla.rs +++ b/src/circuit/circuit_vanilla.rs @@ -36,8 +36,8 @@ use crate::{ ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X, RK_Y, }, constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, + flavor::OrchardVanilla, note::AssetBase, - orchard_flavor::OrchardVanilla, }; impl OrchardCircuit for OrchardVanilla { @@ -641,9 +641,9 @@ mod tests { use crate::{ bundle::Flags, circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, Witnesses, K}, + flavor::OrchardVanilla, keys::SpendValidatingKey, note::{AssetBase, Note, Rho}, - orchard_flavor::OrchardVanilla, tree::MerklePath, value::{ValueCommitTrapdoor, ValueCommitment}, }; diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index e2567128c..19ec190ea 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -41,8 +41,8 @@ use crate::{ ENABLE_OUTPUT, ENABLE_SPEND, ENABLE_ZSA, NF_OLD, RK_X, RK_Y, }, constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, + flavor::OrchardZSA, note::AssetBase, - orchard_flavor::OrchardZSA, }; impl OrchardCircuit for OrchardZSA { @@ -883,9 +883,9 @@ mod tests { AdditionalZsaWitnesses, Circuit, Instance, Proof, ProvingKey, VerifyingKey, Witnesses, K, }, + flavor::OrchardZSA, keys::{FullViewingKey, Scope, SpendValidatingKey, SpendingKey}, note::{commitment::NoteCommitTrapdoor, AssetBase, Note, NoteCommitment, Nullifier, Rho}, - orchard_flavor::OrchardZSA, primitives::redpallas::VerificationKey, tree::MerklePath, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, diff --git a/src/orchard_flavor.rs b/src/flavor.rs similarity index 100% rename from src/orchard_flavor.rs rename to src/flavor.rs diff --git a/src/issuance.rs b/src/issuance.rs index 33cbb66b9..76479241b 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -841,6 +841,7 @@ mod tests { use crate::{ builder::{Builder, BundleType}, circuit::ProvingKey, + flavor::OrchardZSA, issuance::Error::{ IncorrectRhoDerivation, InvalidIssueBundleSig, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, @@ -855,7 +856,6 @@ mod tests { }, keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{rho_for_issuance_note, AssetBase, ExtractedNoteCommitment, Nullifier, Rho}, - orchard_flavor::OrchardZSA, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, Address, Anchor, Bundle, Note, diff --git a/src/lib.rs b/src/lib.rs index 6c41af4b7..f4da3456f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,10 +32,10 @@ pub mod bundle; #[cfg(feature = "circuit")] pub mod circuit; mod constants; +pub mod flavor; pub mod issuance; pub mod keys; pub mod note; -pub mod orchard_flavor; pub mod pczt; pub mod primitives; pub mod sighash_versioning; diff --git a/src/pczt.rs b/src/pczt.rs index 8a924cf70..8d4249092 100644 --- a/src/pczt.rs +++ b/src/pczt.rs @@ -12,9 +12,9 @@ use zip32::ChildIndex; use crate::{ bundle::Flags, + flavor::OrchardVanilla, keys::{FullViewingKey, SpendingKey}, note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext}, - orchard_flavor::OrchardVanilla, primitives::redpallas::{self, Binding, SpendAuth}, tree::MerklePath, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -343,9 +343,9 @@ mod tests { builder::{Builder, BundleType}, circuit::ProvingKey, constants::MERKLE_DEPTH_ORCHARD, + flavor::OrchardVanilla, keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment, RandomSeed, Rho}, - orchard_flavor::OrchardVanilla, pczt::Zip32Derivation, tree::{MerkleHashOrchard, EMPTY_ROOTS}, value::NoteValue, diff --git a/src/pczt/parse.rs b/src/pczt/parse.rs index 76414d908..fa98c98cf 100644 --- a/src/pczt/parse.rs +++ b/src/pczt/parse.rs @@ -11,9 +11,9 @@ use zip32::ChildIndex; use super::{Action, Bundle, Output, Spend, Zip32Derivation}; use crate::{ bundle::Flags, + flavor::OrchardVanilla, keys::{FullViewingKey, SpendingKey}, note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext}, - orchard_flavor::OrchardVanilla, primitives::{ redpallas::{self, SpendAuth}, OrchardPrimitives, diff --git a/src/pczt/prover.rs b/src/pczt/prover.rs index 3a73c00ad..6b5b98f93 100644 --- a/src/pczt/prover.rs +++ b/src/pczt/prover.rs @@ -6,8 +6,8 @@ use rand::{CryptoRng, RngCore}; use crate::{ builder::SpendInfo, circuit::{Circuit, Instance, ProvingKey, Witnesses}, + flavor::OrchardVanilla, note::{AssetBase, Rho}, - orchard_flavor::OrchardVanilla, Note, Proof, }; diff --git a/src/pczt/tx_extractor.rs b/src/pczt/tx_extractor.rs index ad0f28ab6..10cfe9f0b 100644 --- a/src/pczt/tx_extractor.rs +++ b/src/pczt/tx_extractor.rs @@ -4,7 +4,7 @@ use rand::{CryptoRng, RngCore}; use super::Action; use crate::{ bundle::{Authorization, Authorized, EffectsOnly}, - orchard_flavor::OrchardVanilla, + flavor::OrchardVanilla, primitives::redpallas::{self, Binding, SpendAuth}, sighash_versioning::{OrchardSighashVersion, VerBindingSig, VerSpendAuthSig}, Proof, diff --git a/src/primitives/orchard_primitives_vanilla.rs b/src/primitives/orchard_primitives_vanilla.rs index 833348568..3c35b6f25 100644 --- a/src/primitives/orchard_primitives_vanilla.rs +++ b/src/primitives/orchard_primitives_vanilla.rs @@ -15,8 +15,8 @@ use crate::{ }, Authorization, Authorized, }, + flavor::OrchardVanilla, note::{AssetBase, Note}, - orchard_flavor::OrchardVanilla, primitives::{ orchard_primitives::OrchardPrimitives, zcash_note_encryption_domain::{ @@ -129,6 +129,7 @@ mod tests { use crate::{ action::Action, address::Address, + flavor::OrchardVanilla, keys::{ DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey, @@ -137,7 +138,6 @@ mod tests { testing::arb_native_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext, }, - orchard_flavor::OrchardVanilla, primitives::{ compact_action::CompactAction, orchard_domain::OrchardDomain, diff --git a/src/primitives/orchard_primitives_zsa.rs b/src/primitives/orchard_primitives_zsa.rs index be7afa67b..29a366953 100644 --- a/src/primitives/orchard_primitives_zsa.rs +++ b/src/primitives/orchard_primitives_zsa.rs @@ -19,8 +19,8 @@ use crate::{ }, Authorization, Authorized, }, + flavor::OrchardZSA, note::{AssetBase, Note}, - orchard_flavor::OrchardZSA, primitives::{ orchard_primitives::OrchardPrimitives, zcash_note_encryption_domain::{ @@ -176,6 +176,7 @@ mod tests { use crate::{ action::Action, address::Address, + flavor::OrchardZSA, keys::{ DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey, @@ -184,7 +185,6 @@ mod tests { testing::arb_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext, }, - orchard_flavor::OrchardZSA, primitives::{ compact_action::CompactAction, orchard_domain::OrchardDomain, From b4dcf4a69c80210a03da99cc63451a07894b1301 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 13:01:31 +0000 Subject: [PATCH 09/14] Rename orchard_flavor to flavor in benches and integration tests --- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- benches/utils.rs | 2 +- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/benches/circuit.rs b/benches/circuit.rs index 6c5ac21c7..328616538 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -11,7 +11,7 @@ use orchard::{ circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, - orchard_flavor::{OrchardVanilla, OrchardZSA}, + flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index b4ed3f8d7..6c391d979 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -4,7 +4,7 @@ use orchard::{ circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetBase, - orchard_flavor::{OrchardVanilla, OrchardZSA}, + flavor::{OrchardVanilla, OrchardZSA}, primitives::{CompactAction, OrchardDomain}, value::NoteValue, Anchor, Bundle, diff --git a/benches/utils.rs b/benches/utils.rs index 05bcfd5eb..486a5b8e0 100644 --- a/benches/utils.rs +++ b/benches/utils.rs @@ -2,7 +2,7 @@ use criterion::{measurement::Measurement, BenchmarkGroup, Criterion}; use orchard::{ builder::BundleType, - orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, + flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, }; pub(crate) trait OrchardFlavorBench: OrchardFlavor { diff --git a/tests/builder.rs b/tests/builder.rs index 3cf55faa8..8e4056866 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -5,7 +5,7 @@ use orchard::{ circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment}, - orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, + flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, primitives::{OrchardDomain, OrchardPrimitives}, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, diff --git a/tests/zsa.rs b/tests/zsa.rs index b5654a46c..66f8e5d92 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -14,7 +14,7 @@ use orchard::{ }, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment, Nullifier}, - orchard_flavor::OrchardZSA, + flavor::OrchardZSA, primitives::OrchardDomain, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, From 0d6baa7c706628ba10b11b2d7cfed4e0f1eede4d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 13:05:47 +0000 Subject: [PATCH 10/14] Run cargo fmr after renaming orchard_flavor to flavor --- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/benches/circuit.rs b/benches/circuit.rs index 328616538..045288dab 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -9,9 +9,9 @@ use pprof::criterion::{Output, PProfProfiler}; use orchard::{ builder::Builder, circuit::{ProvingKey, VerifyingKey}, + flavor::{OrchardVanilla, OrchardZSA}, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, - flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 6c391d979..0bcaa9aeb 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -2,9 +2,9 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use orchard::{ builder::Builder, circuit::ProvingKey, + flavor::{OrchardVanilla, OrchardZSA}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetBase, - flavor::{OrchardVanilla, OrchardZSA}, primitives::{CompactAction, OrchardDomain}, value::NoteValue, Anchor, Bundle, diff --git a/tests/builder.rs b/tests/builder.rs index 8e4056866..9bd1927df 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -3,9 +3,9 @@ use orchard::{ builder::{Builder, BundleType}, bundle::{Authorized, Flags}, circuit::{ProvingKey, VerifyingKey}, + flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment}, - flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, primitives::{OrchardDomain, OrchardPrimitives}, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, diff --git a/tests/zsa.rs b/tests/zsa.rs index 66f8e5d92..0f769ea1a 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -7,6 +7,7 @@ use orchard::{ builder::{Builder, BundleType}, bundle::Authorized, circuit::{ProvingKey, VerifyingKey}, + flavor::OrchardZSA, issuance::{ auth::{IssueAuthKey, IssueValidatingKey, ZSASchnorr}, compute_asset_desc_hash, verify_issue_bundle, AwaitingNullifier, IssueBundle, IssueInfo, @@ -14,7 +15,6 @@ use orchard::{ }, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment, Nullifier}, - flavor::OrchardZSA, primitives::OrchardDomain, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, From 947357d3c5edced2c6817d30041fc6717703bec7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 14:38:31 +0000 Subject: [PATCH 11/14] Remove --release from cargo test in ci.yml to match the upstream --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed253248d..82bac7c12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: env: # Disable LTO in CI to avoid very slow/hanging release test builds on macOS (rustc/LLVM). CARGO_PROFILE_RELEASE_LTO: "off" - run: cargo test --verbose --release + run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code From 1acf8a7f4d8bb7da39a9215c62064db34bbf16a5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 5 Jan 2026 15:30:39 +0000 Subject: [PATCH 12/14] Try to remove CARGO_PROFILE_RELEASE_LTO from ci.yml --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82bac7c12..30c6f0639 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,9 +12,6 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run tests - env: - # Disable LTO in CI to avoid very slow/hanging release test builds on macOS (rustc/LLVM). - CARGO_PROFILE_RELEASE_LTO: "off" run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code From dc655c096895925d8991a239c5ce4779cbe1294b Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 6 Jan 2026 10:25:39 +0100 Subject: [PATCH 13/14] Add doc comment for rseed_split_note function --- src/note.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/note.rs b/src/note.rs index b77024175..7a3e392f4 100644 --- a/src/note.rs +++ b/src/note.rs @@ -317,6 +317,7 @@ impl Note { &self.rseed } + /// Returns the rseed_split_note value of this note. pub(crate) fn rseed_split_note(&self) -> CtOption { self.rseed_split_note } From 807a25b8daf9770d1c1a958a11a85e71959267a0 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 6 Jan 2026 10:28:09 +0100 Subject: [PATCH 14/14] Fix clippy warnings --- src/bundle/commitments.rs | 2 +- src/issuance.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index ade8a7168..3b5018aac 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -328,7 +328,7 @@ mod tests { compute_asset_desc_hash(&NonEmpty::from_slice(b"second asset").unwrap()); let (mut bundle, asset) = IssueBundle::new( - ik.clone(), + ik, asset_desc_hash_1, Some(IssueInfo { recipient, diff --git a/src/issuance.rs b/src/issuance.rs index 76479241b..becc2bff7 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -1498,7 +1498,7 @@ mod tests { compute_asset_desc_hash(&NonEmpty::from_slice(b"asset desc").unwrap()); let (bundle, _) = IssueBundle::new( - ik.clone(), + ik, asset_desc_hash, Some(IssueInfo { recipient,