From a2321885ca25487595b2a004397b9d1296c93014 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 24 Jan 2025 18:18:14 -0700 Subject: [PATCH 01/16] Move circuit-dependent test utils behind the `circuit` feature. --- src/builder.rs | 2 +- src/bundle.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b370fb3c2..a72dcf6c3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1134,7 +1134,7 @@ impl OutputView for OutputInfo { } /// Generators for property testing. -#[cfg(any(test, feature = "test-dependencies"))] +#[cfg(all(feature = "circuit", any(test, feature = "test-dependencies")))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use alloc::vec::Vec; diff --git a/src/bundle.rs b/src/bundle.rs index c1d1c18b4..f081cf41c 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -533,10 +533,9 @@ pub mod testing { use proptest::prelude::*; use crate::{ - circuit::Proof, primitives::redpallas::{self, testing::arb_binding_signing_key}, value::{testing::arb_note_value_bounded, NoteValue, ValueSum, MAX_NOTE_VALUE}, - Anchor, + Anchor, Proof, }; use super::{Action, Authorized, Bundle, Flags}; From 116c6e34031ac453ba43378689d4620a83b45a7d Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 28 Jan 2025 18:30:04 -0700 Subject: [PATCH 02/16] Work around missing dependencies on updated ubuntu-latest --- .github/workflows/ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e6a6c3ae..db2625946 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 @@ -28,6 +27,8 @@ jobs: - uses: dtolnay/rust-toolchain@stable id: toolchain - run: rustup override set ${{steps.toolchain.outputs.name}} + - if: matrix.os == 'ubuntu-latest' + run: sudo apt-get -y install libfontconfig1-dev - name: Remove lockfile to build with latest dependencies run: rm Cargo.lock - name: Build crate @@ -79,7 +80,6 @@ jobs: container: image: xd009642/tarpaulin:develop-nightly options: --security-opt seccomp=unconfined - steps: - uses: actions/checkout@v4 - name: Generate coverage report @@ -94,6 +94,7 @@ jobs: - uses: actions/checkout@v4 - run: cargo fetch # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. + - run: sudo apt-get -y install libfontconfig1-dev - name: Check intra-doc links run: cargo doc --all-features --document-private-items From 2fa54f91aec5984e9fe08b3d7864e20ce7e2bdaa Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 28 Jan 2025 15:32:37 -0700 Subject: [PATCH 03/16] Avoid unused import warnings in downstream crates. --- src/constants.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/constants.rs b/src/constants.rs index 7f40b5394..62548f9c1 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -3,7 +3,9 @@ pub mod fixed_bases; pub mod sinsemilla; pub mod util; +#[cfg(feature = "circuit")] pub use self::sinsemilla::{OrchardCommitDomains, OrchardHashDomains}; +#[cfg(feature = "circuit")] pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV}; /// $\mathsf{MerkleDepth^{Orchard}}$ From 92bd43a4595e6d5c21470e137166787e1b2f99cf Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 8 May 2025 14:57:49 -0600 Subject: [PATCH 04/16] Fix additional problems with missing feature flags in test code. --- src/builder.rs | 2 +- src/constants/sinsemilla.rs | 2 +- src/pczt.rs | 2 +- src/spec.rs | 8 +++++--- tests/builder.rs | 2 ++ 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index a72dcf6c3..428bb057d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1274,7 +1274,7 @@ pub mod testing { } } -#[cfg(test)] +#[cfg(all(test, feature = "circuit"))] mod tests { use rand::rngs::OsRng; diff --git a/src/constants/sinsemilla.rs b/src/constants/sinsemilla.rs index 84198f39e..34843fcca 100644 --- a/src/constants/sinsemilla.rs +++ b/src/constants/sinsemilla.rs @@ -132,7 +132,7 @@ impl CommitDomains for Or } } -#[cfg(test)] +#[cfg(all(test, feature = "circuit"))] mod tests { use super::*; use crate::constants::{ diff --git a/src/pczt.rs b/src/pczt.rs index 38cc0a757..c5ab397ee 100644 --- a/src/pczt.rs +++ b/src/pczt.rs @@ -301,7 +301,7 @@ pub struct Zip32Derivation { derivation_path: Vec, } -#[cfg(test)] +#[cfg(all(test, feature = "circuit"))] mod tests { use bridgetree::BridgeTree; use ff::{Field, PrimeField}; diff --git a/src/spec.rs b/src/spec.rs index b9702eead..187f5c073 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -318,13 +318,15 @@ pub fn i2lebsp(int: u64) -> [bool; NUM_BITS] { mod tests { use super::{i2lebsp, lebs2ip}; - use group::Group; - use halo2_proofs::arithmetic::CurveExt; - use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; #[test] + #[cfg(feature = "circuit")] fn diversify_hash_substitution() { + use group::Group; + use halo2_proofs::arithmetic::CurveExt; + use pasta_curves::pallas; + assert!(!bool::from( pallas::Point::hash_to_curve("z.cash:Orchard-gd")(&[]).is_identity() )); diff --git a/tests/builder.rs b/tests/builder.rs index 8ce67e92a..0e0904cd7 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "circuit")] + use bridgetree::BridgeTree; use incrementalmerkletree::Hashable; use orchard::{ From cc05aeed17b3a98f835d0eff58e6783cd449a527 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 8 May 2025 15:19:11 -0600 Subject: [PATCH 05/16] Update `subtle` dependency to version `2.6` This update was missed in the 0.10.1 release. Fixes #466 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6de0e327c..87d2d13de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ nonempty = "0.7" poseidon = { package = "halo2_poseidon", version = "0.1" } serde = { version = "1.0", default-features = false, features = ["derive"] } sinsemilla = "0.1" -subtle = { version = "2.3", default-features = false } +subtle = { version = "2.6", default-features = false } zcash_note_encryption = "0.4" incrementalmerkletree = { version = "0.7", default-features = false } zcash_spec = "0.1" From ca77cd8232339d9ab322ff8344454b1dc861882f Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 8 May 2025 14:59:42 -0600 Subject: [PATCH 06/16] Release orchard version 0.10.2 --- CHANGELOG.md | 5 +++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72fda69df..60c5610be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to Rust's notion of ## [Unreleased] +## [0.10.2] - 2025-05-08 + +### Fixed +- Fixes problems in test compilation under `--no-default-features` + ## [0.10.1] - 2024-12-16 ### Added diff --git a/Cargo.lock b/Cargo.lock index 2cb57d90e..cab7af559 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,7 +1446,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.10.1" +version = "0.10.2" dependencies = [ "aes", "bitvec", diff --git a/Cargo.toml b/Cargo.toml index 87d2d13de..a810c25be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orchard" -version = "0.10.1" +version = "0.10.2" authors = [ "Sean Bowe ", "Jack Grigg ", From 22d46302faf7fcfb53922160588e5a4c5bee07af Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 21 Nov 2025 10:06:09 +0000 Subject: [PATCH 07/16] pczt: Support applying external spendAuthSigs to Spends --- CHANGELOG.md | 7 +++++++ src/pczt.rs | 4 ++++ src/pczt/signer.rs | 25 ++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee564427..510f9d44b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to Rust's notion of ## [Unreleased] +### Added +- `orchard::pczt::Action::apply_signature` + +### Changed +- `orchard::pczt::SignerError` has added variants: + - `InvalidExternalSignature` + ## [0.11.0] - 2025-02-20 ### Added diff --git a/src/pczt.rs b/src/pczt.rs index 0f0de492f..e4872f900 100644 --- a/src/pczt.rs +++ b/src/pczt.rs @@ -480,6 +480,10 @@ mod tests { for action in pczt_bundle.actions_mut() { if action.spend.zip32_derivation.as_ref() == Some(&zip32_derivation) { action.sign(sighash, &ask, rng).unwrap(); + + // We can also apply the signature as an external signature. + let signature = action.spend().spend_auth_sig().clone().expect("signed"); + action.apply_signature(sighash, signature).unwrap(); } } diff --git a/src/pczt/signer.rs b/src/pczt/signer.rs index 7f5f8028c..4ba3480b5 100644 --- a/src/pczt/signer.rs +++ b/src/pczt/signer.rs @@ -1,6 +1,9 @@ use rand::{CryptoRng, RngCore}; -use crate::{keys::SpendAuthorizingKey, primitives::redpallas}; +use crate::{ + keys::SpendAuthorizingKey, + primitives::redpallas::{self, SpendAuth}, +}; impl super::Action { /// Signs the Orchard spend with the given spend authorizing key. @@ -29,11 +32,31 @@ impl super::Action { Err(SignerError::WrongSpendAuthorizingKey) } } + + /// Applies the given signature to the Orchard spend, if valid. + /// + /// It is the caller's responsibility to perform any semantic validity checks on the + /// PCZT (for example, comfirming that the change amounts are correct) before calling + /// this method. + pub fn apply_signature( + &mut self, + sighash: [u8; 32], + signature: redpallas::Signature, + ) -> Result<(), SignerError> { + if self.spend.rk.verify(&sighash, &signature).is_ok() { + self.spend.spend_auth_sig = Some(signature); + Ok(()) + } else { + Err(SignerError::InvalidExternalSignature) + } + } } /// Errors that can occur while signing an Orchard action in a PCZT. #[derive(Debug)] pub enum SignerError { + /// A provided external signature was not valid for the action's spend. + InvalidExternalSignature, /// The Signer role requires `alpha` to be set. MissingSpendAuthRandomizer, /// The provided `ask` does not own the action's spent note. From 88cf5f912bf99d1a313d724240ae039cc80ef59e Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Dec 2025 22:51:52 +0000 Subject: [PATCH 08/16] Migrate to published `halo2_gadgets 0.4` --- Cargo.lock | 25 ++++++++----------------- Cargo.toml | 8 ++------ 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e09110f36..0d05dade1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -975,14 +975,15 @@ dependencies = [ [[package]] name = "halo2_gadgets" -version = "0.3.1" -source = "git+https://github.com/zcash/halo2?rev=2308caf68c48c02468b66cfc452dad54e355e32f#2308caf68c48c02468b66cfc452dad54e355e32f" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45824ce0dd12e91ec0c68ebae2a7ed8ae19b70946624c849add59f1d1a62a143" dependencies = [ "arrayvec", "bitvec", "ff", "group", - "halo2_poseidon 0.1.0 (git+https://github.com/zcash/halo2?rev=2308caf68c48c02468b66cfc452dad54e355e32f)", + "halo2_poseidon", "halo2_proofs", "lazy_static", "pasta_curves", @@ -1011,21 +1012,11 @@ dependencies = [ "pasta_curves", ] -[[package]] -name = "halo2_poseidon" -version = "0.1.0" -source = "git+https://github.com/zcash/halo2?rev=2308caf68c48c02468b66cfc452dad54e355e32f#2308caf68c48c02468b66cfc452dad54e355e32f" -dependencies = [ - "bitvec", - "ff", - "group", - "pasta_curves", -] - [[package]] name = "halo2_proofs" -version = "0.3.1" -source = "git+https://github.com/zcash/halo2?rev=2308caf68c48c02468b66cfc452dad54e355e32f#2308caf68c48c02468b66cfc452dad54e355e32f" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05713f117155643ce10975e0bee44a274bcda2f4bb5ef29a999ad67c1fa8d4d3" dependencies = [ "blake2b_simd", "ff", @@ -1459,7 +1450,7 @@ dependencies = [ "getset", "group", "halo2_gadgets", - "halo2_poseidon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2_poseidon", "halo2_proofs", "hex", "image", diff --git a/Cargo.toml b/Cargo.toml index 07b1a66e9..0d78e6f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ zip32 = { version = "0.2.0", default-features = false } visibility = "0.1.1" # Circuit -halo2_gadgets = { version = "0.3", optional = true, default-features = false } +halo2_gadgets = { version = "0.4", optional = true, default-features = false } halo2_proofs = { version = "0.3", optional = true, default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } # Boilerplate @@ -67,7 +67,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 -halo2_gadgets = { version = "0.3", features = ["test-dependencies"] } +halo2_gadgets = { version = "0.4", features = ["test-dependencies"] } hex = "0.4" proptest = ">=1.0.0, <1.7.0" zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } @@ -107,7 +107,3 @@ debug = true [profile.bench] debug = true - -[patch.crates-io] -halo2_gadgets = { git = "https://github.com/zcash/halo2", rev = "2308caf68c48c02468b66cfc452dad54e355e32f" } -halo2_proofs = { git = "https://github.com/zcash/halo2", rev = "2308caf68c48c02468b66cfc452dad54e355e32f" } From b2e0a4247a84f24a0a7e136184596129b39450db Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 4 Dec 2025 23:37:07 +0000 Subject: [PATCH 09/16] Make all error enums `#[non_exhaustive]` This allows future error variants to be added without a SemVer break. --- CHANGELOG.md | 14 ++++++++++++++ src/builder.rs | 2 ++ src/pczt/io_finalizer.rs | 1 + src/pczt/parse.rs | 1 + src/pczt/prover.rs | 1 + src/pczt/signer.rs | 1 + src/pczt/tx_extractor.rs | 1 + src/pczt/updater.rs | 1 + src/pczt/verify.rs | 1 + src/zip32.rs | 1 + 10 files changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510f9d44b..ded0b7647 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,20 @@ and this project adheres to Rust's notion of ### Changed - `orchard::pczt::SignerError` has added variants: - `InvalidExternalSignature` +- All error enums in this crate are now `#[non_exhaustive]`, to allow future + error variants to be added without a SemVer break: + - `orchard::builder`: + - `BuildError` + - `SpendError` + - `orchard::pczt`: + - `IoFinalizerError` + - `ParseError` + - `ProverError` + - `SignerError` + - `TxExtractorError` + - `UpdaterError` + - `VerifyError` + - `orchard::zip32::Error` ## [0.11.0] - 2025-02-20 diff --git a/src/builder.rs b/src/builder.rs index 5566e3a39..08ecf41d2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -117,6 +117,7 @@ impl BundleType { /// An error type for the kinds of errors that can occur during bundle construction. #[derive(Debug)] +#[non_exhaustive] pub enum BuildError { /// Spends are disabled for the provided bundle type. SpendsDisabled, @@ -181,6 +182,7 @@ impl From for BuildError { /// An error type for adding a spend to the builder. #[derive(Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum SpendError { /// Spends aren't enabled for this builder. SpendsDisabled, diff --git a/src/pczt/io_finalizer.rs b/src/pczt/io_finalizer.rs index 6f9a7ec9c..56bef8a10 100644 --- a/src/pczt/io_finalizer.rs +++ b/src/pczt/io_finalizer.rs @@ -60,6 +60,7 @@ impl super::Bundle { /// Errors that can occur while finalizing the I/O for a PCZT bundle. #[derive(Debug)] +#[non_exhaustive] pub enum IoFinalizerError { /// An error occurred while signing a dummy spend. DummySignature(SignerError), diff --git a/src/pczt/parse.rs b/src/pczt/parse.rs index f36e09de6..2162d00c8 100644 --- a/src/pczt/parse.rs +++ b/src/pczt/parse.rs @@ -294,6 +294,7 @@ impl Zip32Derivation { /// Errors that can occur while parsing a PCZT bundle. #[derive(Debug)] +#[non_exhaustive] pub enum ParseError { /// An invalid anchor was provided. InvalidAnchor, diff --git a/src/pczt/prover.rs b/src/pczt/prover.rs index 73ce0c863..3d0012e39 100644 --- a/src/pczt/prover.rs +++ b/src/pczt/prover.rs @@ -108,6 +108,7 @@ impl super::Bundle { /// Errors that can occur while creating Orchard proofs for a PCZT. #[derive(Debug)] +#[non_exhaustive] pub enum ProverError { /// The output note's components do not produce a valid note commitment. InvalidOutputNote, diff --git a/src/pczt/signer.rs b/src/pczt/signer.rs index 4ba3480b5..857f1c2b5 100644 --- a/src/pczt/signer.rs +++ b/src/pczt/signer.rs @@ -54,6 +54,7 @@ impl super::Action { /// Errors that can occur while signing an Orchard action in a PCZT. #[derive(Debug)] +#[non_exhaustive] pub enum SignerError { /// A provided external signature was not valid for the action's spend. InvalidExternalSignature, diff --git a/src/pczt/tx_extractor.rs b/src/pczt/tx_extractor.rs index f2daf9e87..af6973ed5 100644 --- a/src/pczt/tx_extractor.rs +++ b/src/pczt/tx_extractor.rs @@ -104,6 +104,7 @@ impl super::Bundle { /// Errors that can occur while extracting a regular Orchard bundle from a PCZT bundle. #[derive(Debug)] +#[non_exhaustive] pub enum TxExtractorError { /// The Transaction Extractor role requires `bsk` to be set. MissingBindingSignatureSigningKey, diff --git a/src/pczt/updater.rs b/src/pczt/updater.rs index 5d032b1f0..2b7ed5e49 100644 --- a/src/pczt/updater.rs +++ b/src/pczt/updater.rs @@ -71,6 +71,7 @@ impl ActionUpdater<'_> { /// Errors that can occur while updating an Orchard bundle in a PCZT. #[derive(Debug)] +#[non_exhaustive] pub enum UpdaterError { /// An out-of-bounds index was provided when looking up an action. InvalidIndex, diff --git a/src/pczt/verify.rs b/src/pczt/verify.rs index 463125a25..3a2fb7f77 100644 --- a/src/pczt/verify.rs +++ b/src/pczt/verify.rs @@ -143,6 +143,7 @@ impl super::Output { /// Errors that can occur while verifying a PCZT bundle. #[derive(Debug)] +#[non_exhaustive] pub enum VerifyError { /// The output note's components do not produce the expected `cmx`. InvalidExtractedNoteCommitment, diff --git a/src/zip32.rs b/src/zip32.rs index 93b1cf5c8..a18020132 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -22,6 +22,7 @@ const ZIP32_ORCHARD_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashOrchardFVFP"; /// Errors produced in derivation of extended spending keys #[derive(Debug, PartialEq, Eq)] +#[non_exhaustive] pub enum Error { /// A seed resulted in an invalid spending key InvalidSpendingKey, From fcf1cb1ad7773f1e733a55f1b61b4024cc60a024 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Dec 2025 12:56:53 +0000 Subject: [PATCH 10/16] Migrated all error types to be `#[non_exhaustive]` enums --- CHANGELOG.md | 8 ++++++++ src/builder.rs | 34 +++++++++++++++++++++------------- src/value.rs | 37 ++++++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a17c036ba..fc5afc816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,11 @@ and this project adheres to Rust's notion of ### Added - `orchard::pczt::Action::apply_signature` +- `orchard::value::BalanceError` ### Changed +- `orchard::builder::BuildError::ValueSum` variant now contains + `orchard::value::BalanceError`. - `orchard::pczt::SignerError` has added variants: - `InvalidExternalSignature` - All error enums in this crate are now `#[non_exhaustive]`, to allow future @@ -27,6 +30,11 @@ and this project adheres to Rust's notion of - `UpdaterError` - `VerifyError` - `orchard::zip32::Error` +- `orchard::builder::OutputError` has been changed from a zero-sized struct to + a `#[non_exhaustive]` enum with (for now) a single variant. + +### Removed +- `orchard::value::OverflowError` (use `BalanceError` instead). ## [0.10.2] - 2025-05-08 diff --git a/src/builder.rs b/src/builder.rs index eeca08387..363a136c4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -20,7 +20,7 @@ use crate::{ note_encryption::OrchardNoteEncryption, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, - value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, + value::{self, BalanceError, NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, Proof, }; @@ -132,7 +132,7 @@ pub enum BuildError { Proof(halo2_proofs::plonk::Error), /// An overflow error occurred while attempting to construct the value /// for a bundle. - ValueSum(value::OverflowError), + ValueSum(value::BalanceError), /// External signature is not valid. InvalidExternalSignature, /// A signature is valid for more than one input. This should never happen if `alpha` @@ -174,8 +174,8 @@ impl From for BuildError { } } -impl From for BuildError { - fn from(e: value::OverflowError) -> Self { +impl From for BuildError { + fn from(e: value::BalanceError) -> Self { BuildError::ValueSum(e) } } @@ -206,13 +206,20 @@ impl fmt::Display for SpendError { #[cfg(feature = "std")] impl std::error::Error for SpendError {} -/// The only error that can occur here is if outputs are disabled for this builder. +/// An error type for adding an output to the builder. #[derive(Debug, PartialEq, Eq)] -pub struct OutputError; +#[non_exhaustive] +pub enum OutputError { + /// Outputs aren't enabled for this builder. + OutputsDisabled, +} impl fmt::Display for OutputError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Outputs are not enabled for this builder") + use OutputError::*; + f.write_str(match self { + OutputsDisabled => "Outputs are not enabled for this builder", + }) } } @@ -596,7 +603,7 @@ impl Builder { ) -> Result<(), OutputError> { let flags = self.bundle_type.flags(); if !flags.outputs_enabled() { - return Err(OutputError); + return Err(OutputError::OutputsDisabled); } self.outputs @@ -627,7 +634,7 @@ impl Builder { /// /// [added]: https://zips.z.cash/protocol/protocol.pdf#orchardbalance /// [must not have a negative value]: https://zips.z.cash/protocol/protocol.pdf#transactions - pub fn value_balance>(&self) -> Result { + pub fn value_balance>(&self) -> Result { let value_balance = self .spends .iter() @@ -638,8 +645,9 @@ impl Builder { .map(|output| NoteValue::zero() - output.value), ) .try_fold(ValueSum::zero(), |acc, note_value| acc + note_value) - .ok_or(OverflowError)?; - i64::try_from(value_balance).and_then(|i| V::try_from(i).map_err(|_| value::OverflowError)) + .ok_or(BalanceError::Overflow)?; + i64::try_from(value_balance) + .and_then(|i| V::try_from(i).map_err(|_| value::BalanceError::Overflow)) } /// Builds a bundle containing the given spent notes and outputs. @@ -717,7 +725,7 @@ pub fn bundle>( let result_value_balance: V = i64::try_from(value_balance) .map_err(BuildError::ValueSum) .and_then(|i| { - V::try_from(i).map_err(|_| BuildError::ValueSum(value::OverflowError)) + V::try_from(i).map_err(|_| BuildError::ValueSum(value::BalanceError::Overflow)) })?; // Compute the transaction binding signing key. @@ -835,7 +843,7 @@ fn build_bundle( let value_balance = pre_actions .iter() .try_fold(ValueSum::zero(), |acc, action| acc + action.value_sum()) - .ok_or(OverflowError)?; + .ok_or(BalanceError::Overflow)?; finisher(pre_actions, flags, value_balance, bundle_meta, rng) } diff --git a/src/value.rs b/src/value.rs index 516bf8e18..67ac8787f 100644 --- a/src/value.rs +++ b/src/value.rs @@ -71,18 +71,29 @@ pub const MAX_NOTE_VALUE: u64 = u64::MAX; pub const VALUE_SUM_RANGE: RangeInclusive = -(MAX_NOTE_VALUE as i128)..=MAX_NOTE_VALUE as i128; -/// A value operation overflowed. +/// A type for balance violations in amount addition and subtraction +/// (overflow and underflow of allowed ranges). #[derive(Debug)] -pub struct OverflowError; +#[non_exhaustive] +pub enum BalanceError { + /// Two values were added or subtracted, and the result overflowed the valid range for + /// the value. + /// + /// Normally this range is [`VALUE_SUM_RANGE`], but when interacting with value + /// balances it may be `i64`. + Overflow, +} -impl fmt::Display for OverflowError { +impl fmt::Display for BalanceError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Orchard value operation overflowed") + match self { + Self::Overflow => write!(f, "Orchard value operation overflowed"), + } } } #[cfg(feature = "std")] -impl std::error::Error for OverflowError {} +impl std::error::Error for BalanceError {} /// The non-negative value of an individual Orchard note. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -212,25 +223,25 @@ impl Add for ValueSum { } } -impl<'a> Sum<&'a ValueSum> for Result { +impl<'a> Sum<&'a ValueSum> for Result { fn sum>(mut iter: I) -> Self { iter.try_fold(ValueSum(0), |acc, v| acc + *v) - .ok_or(OverflowError) + .ok_or(BalanceError::Overflow) } } -impl Sum for Result { +impl Sum for Result { fn sum>(mut iter: I) -> Self { iter.try_fold(ValueSum(0), |acc, v| acc + v) - .ok_or(OverflowError) + .ok_or(BalanceError::Overflow) } } impl TryFrom for i64 { - type Error = OverflowError; + type Error = BalanceError; fn try_from(v: ValueSum) -> Result { - i64::try_from(v.0).map_err(|_| OverflowError) + i64::try_from(v.0).map_err(|_| BalanceError::Overflow) } } @@ -464,7 +475,7 @@ mod tests { use super::{ testing::{arb_note_value_bounded, arb_trapdoor, arb_value_sum_bounded}, - OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum, MAX_NOTE_VALUE, + BalanceError, ValueCommitTrapdoor, ValueCommitment, ValueSum, MAX_NOTE_VALUE, }; use crate::primitives::redpallas; @@ -480,7 +491,7 @@ mod tests { let value_balance = values .iter() .map(|(value, _)| value) - .sum::>() + .sum::>() .expect("we generate values that won't overflow"); let bsk = values From 3661d41da09b155253d71e32cfd0a03f7180beda Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Dec 2025 12:58:06 +0000 Subject: [PATCH 11/16] `impl std::error::Error` for all error types --- CHANGELOG.md | 10 ++++++++++ src/pczt/io_finalizer.rs | 23 +++++++++++++++++++++ src/pczt/parse.rs | 33 ++++++++++++++++++++++++++++++ src/pczt/prover.rs | 39 ++++++++++++++++++++++++++++++++++++ src/pczt/signer.rs | 21 ++++++++++++++++++++ src/pczt/tx_extractor.rs | 26 ++++++++++++++++++++++++ src/pczt/updater.rs | 13 ++++++++++++ src/pczt/verify.rs | 43 ++++++++++++++++++++++++++++++++++++++++ src/zip32.rs | 3 ++- 9 files changed, 210 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5afc816..749598bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,16 @@ and this project adheres to Rust's notion of ### Added - `orchard::pczt::Action::apply_signature` - `orchard::value::BalanceError` +- `impl std::error::Error` for the following errors: + - `orchard::pczt`: + - `IoFinalizerError` + - `ParseError` + - `ProverError` + - `SignerError` + - `TxExtractorError` + - `UpdaterError` + - `VerifyError` + - `orchard::zip32::Error` ### Changed - `orchard::builder::BuildError::ValueSum` variant now contains diff --git a/src/pczt/io_finalizer.rs b/src/pczt/io_finalizer.rs index 56bef8a10..73f7d00d8 100644 --- a/src/pczt/io_finalizer.rs +++ b/src/pczt/io_finalizer.rs @@ -1,3 +1,5 @@ +use core::fmt; + use alloc::vec::Vec; use rand::{CryptoRng, RngCore}; @@ -70,3 +72,24 @@ pub enum IoFinalizerError { /// inconsistent. ValueCommitMismatch, } + +impl fmt::Display for IoFinalizerError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IoFinalizerError::DummySignature(e) => { + write!(f, "An error occurred while signing a dummy spend: {e}") + } + IoFinalizerError::MissingValueCommitTrapdoor => write!( + f, + "The IO Finalizer role requires all `rcv` fields to be set" + ), + IoFinalizerError::ValueCommitMismatch => write!( + f, + "`cv_net`, `rcv`, and `value_sum` within the Orchard bundle are inconsistent." + ), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for IoFinalizerError {} diff --git a/src/pczt/parse.rs b/src/pczt/parse.rs index 2162d00c8..e8e06c10c 100644 --- a/src/pczt/parse.rs +++ b/src/pczt/parse.rs @@ -1,3 +1,5 @@ +use core::fmt; + use alloc::collections::BTreeMap; use alloc::string::String; use alloc::vec::Vec; @@ -335,3 +337,34 @@ pub enum ParseError { /// The provided `flags` field had unexpected bits set. UnexpectedFlagBitsSet, } + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParseError::InvalidAnchor => write!(f, "invalid anchor"), + ParseError::InvalidBindingSignatureSigningKey => write!(f, "invalid `bsk`"), + ParseError::InvalidDummySpendingKey => write!(f, "invalid `dummy_sk`"), + ParseError::InvalidEncCiphertext => write!(f, "invalid `enc_ciphertext`"), + ParseError::InvalidExtractedNoteCommitment => write!(f, "invalid `cmx`"), + ParseError::InvalidFullViewingKey => write!(f, "invalid `fvk`"), + ParseError::InvalidNullifier => write!(f, "invalid `nullifier`"), + ParseError::InvalidOutCiphertext => write!(f, "invalid `out_ciphertext`"), + ParseError::InvalidRandomizedKey => write!(f, "invalid `rk`"), + ParseError::InvalidRandomSeed => write!(f, "invalid `rseed`"), + ParseError::InvalidRecipient => write!(f, "invalid `recipient`"), + ParseError::InvalidRho => write!(f, "invalid `rho`"), + ParseError::InvalidSpendAuthRandomizer => write!(f, "invalid `alpha`"), + ParseError::InvalidValueCommitment => write!(f, "invalid `cv_net`"), + ParseError::InvalidValueCommitTrapdoor => write!(f, "invalid `rcv`"), + ParseError::InvalidWitness => write!(f, "invalid `witness`"), + ParseError::InvalidZip32Derivation => write!(f, "invalid `zip32_derivation`"), + ParseError::MissingRho => { + write!(f, "`rho` must be provided whenever `rseed` is provided") + } + ParseError::UnexpectedFlagBitsSet => write!(f, "`flags` field had unexpected bits set"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseError {} diff --git a/src/pczt/prover.rs b/src/pczt/prover.rs index 3d0012e39..b585997d3 100644 --- a/src/pczt/prover.rs +++ b/src/pczt/prover.rs @@ -1,3 +1,5 @@ +use core::fmt; + use alloc::vec::Vec; use halo2_proofs::plonk; @@ -137,3 +139,40 @@ pub enum ProverError { /// The provided `fvk` does not own the spent note. WrongFvkForNote, } + +impl fmt::Display for ProverError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ProverError::InvalidOutputNote => write!(f, "output note is invalid"), + ProverError::InvalidSpendNote => write!(f, "spent note is invalid"), + ProverError::MissingFullViewingKey => { + write!(f, "`fvk` must be set for the Prover role") + } + ProverError::MissingRandomSeed => { + write!(f, "`rseed` fields must be set for the Prover role") + } + ProverError::MissingRecipient => { + write!(f, "`recipient` fields must be set for the Prover role") + } + ProverError::MissingRho => write!(f, "`rho` must be set for the Prover role"), + ProverError::MissingSpendAuthRandomizer => { + write!(f, "`alpha` must be set for the Prover role") + } + ProverError::MissingValue => { + write!(f, "`value` fields must be set for the Prover role") + } + ProverError::MissingValueCommitTrapdoor => { + write!(f, "`rcv` must be set for the Prover role") + } + ProverError::MissingWitness => write!(f, "`witness` must be set for the Prover role"), + ProverError::ProofFailed(e) => write!(f, "Failed to create proof: {e}"), + ProverError::RhoMismatch => { + write!(f, "output's `rho` does not match spent note's nullifier") + } + ProverError::WrongFvkForNote => write!(f, "`fvk` does not own the action's spent note"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ProverError {} diff --git a/src/pczt/signer.rs b/src/pczt/signer.rs index 857f1c2b5..f31977710 100644 --- a/src/pczt/signer.rs +++ b/src/pczt/signer.rs @@ -1,3 +1,5 @@ +use core::fmt; + use rand::{CryptoRng, RngCore}; use crate::{ @@ -63,3 +65,22 @@ pub enum SignerError { /// The provided `ask` does not own the action's spent note. WrongSpendAuthorizingKey, } + +impl fmt::Display for SignerError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + SignerError::InvalidExternalSignature => { + write!(f, "External signature is invalid for the action's spend") + } + SignerError::MissingSpendAuthRandomizer => { + write!(f, "`alpha` must be set for the Signer role") + } + SignerError::WrongSpendAuthorizingKey => { + write!(f, "provided `ask` does not own the action's spent note") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SignerError {} diff --git a/src/pczt/tx_extractor.rs b/src/pczt/tx_extractor.rs index af6973ed5..e80d60249 100644 --- a/src/pczt/tx_extractor.rs +++ b/src/pczt/tx_extractor.rs @@ -1,3 +1,5 @@ +use core::fmt; + use nonempty::NonEmpty; use rand::{CryptoRng, RngCore}; @@ -116,6 +118,30 @@ pub enum TxExtractorError { ValueSumOutOfRange, } +impl fmt::Display for TxExtractorError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + TxExtractorError::MissingBindingSignatureSigningKey => { + write!(f, "`bsk` must be set for the Transaction Extractor role") + } + TxExtractorError::MissingProof => write!( + f, + "Orchard `zkproof` must be set for the Transaction Extractor role" + ), + TxExtractorError::MissingSpendAuthSig => write!( + f, + "`spend_auth_sig` fields must all be set for the Transaction Extractor role" + ), + TxExtractorError::ValueSumOutOfRange => { + write!(f, "value sum does not fit into a `valueBalance`") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TxExtractorError {} + /// Authorizing data for a bundle of actions that is just missing a binding signature. #[derive(Debug)] pub struct Unbound { diff --git a/src/pczt/updater.rs b/src/pczt/updater.rs index 2b7ed5e49..b1214af44 100644 --- a/src/pczt/updater.rs +++ b/src/pczt/updater.rs @@ -1,3 +1,5 @@ +use core::fmt; + use alloc::string::String; use alloc::vec::Vec; @@ -76,3 +78,14 @@ pub enum UpdaterError { /// An out-of-bounds index was provided when looking up an action. InvalidIndex, } + +impl fmt::Display for UpdaterError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + UpdaterError::InvalidIndex => write!(f, "Action index is out-of-bounds"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UpdaterError {} diff --git a/src/pczt/verify.rs b/src/pczt/verify.rs index 3a2fb7f77..49249a448 100644 --- a/src/pczt/verify.rs +++ b/src/pczt/verify.rs @@ -1,3 +1,5 @@ +use core::fmt; + use crate::{ keys::{FullViewingKey, SpendValidatingKey}, note::{ExtractedNoteCommitment, Rho}, @@ -176,3 +178,44 @@ pub enum VerifyError { /// The provided `fvk` does not own the spent note. WrongFvkForNote, } + +impl fmt::Display for VerifyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + VerifyError::InvalidExtractedNoteCommitment => { + write!(f, "output note doesn't match `cmx`") + } + VerifyError::InvalidNullifier => write!(f, "spent note doesn't match `nullifier`"), + VerifyError::InvalidOutputNote => write!(f, "invalid output note"), + VerifyError::InvalidRandomizedVerificationKey => { + write!(f, "spend's `fvk` and `alpha` do not match `rk`") + } + VerifyError::InvalidSpendNote => write!(f, "invalid spent note"), + VerifyError::InvalidValueCommitment => { + write!(f, "`cv_net` doesn't match the note values and `rcv`") + } + VerifyError::MismatchedFullViewingKey => { + write!(f, "Provided full viewing key doesn't match the `fvk` field") + } + VerifyError::MissingFullViewingKey => write!(f, "`fvk` missing for dummy note"), + VerifyError::MissingRandomSeed => { + write!(f, "`rseed` missing for `nullifier` verification") + } + VerifyError::MissingRecipient => { + write!(f, "`recipient` missing for `nullifier` verification") + } + VerifyError::MissingRho => write!(f, "`rho` missing for `nullifier` verification"), + VerifyError::MissingSpendAuthRandomizer => { + write!(f, "`alpha` missing for `rk` verification") + } + VerifyError::MissingValue => write!(f, "`value` missing"), + VerifyError::MissingValueCommitTrapdoor => { + write!(f, "`rcv` missing for `cv_net` verification") + } + VerifyError::WrongFvkForNote => write!(f, "`fvk` does not own the action's spent note"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for VerifyError {} diff --git a/src/zip32.rs b/src/zip32.rs index a18020132..1454e7930 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -36,7 +36,8 @@ impl fmt::Display for Error { } } -//impl std::error::Error for Error {} +#[cfg(feature = "std")] +impl std::error::Error for Error {} /// An Orchard full viewing key fingerprint struct FvkFingerprint([u8; 32]); From 648ef34225549bd6da8a5ec268a556fd21873877 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 5 Dec 2025 16:20:20 +0000 Subject: [PATCH 12/16] orchard 0.12.0 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 749598bc5..16f8fbcf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to Rust's notion of ## [Unreleased] +## [0.12.0] - 2025-12-05 + ### Added - `orchard::pczt::Action::apply_signature` - `orchard::value::BalanceError` diff --git a/Cargo.lock b/Cargo.lock index 0d05dade1..3e7f607b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1438,7 +1438,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.11.0" +version = "0.12.0" dependencies = [ "aes", "bitvec", diff --git a/Cargo.toml b/Cargo.toml index 9d4b330d0..9f962c8fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "orchard" -version = "0.11.0" +version = "0.12.0" authors = [ - "Sean Bowe ", + "Sean Bowe", "Jack Grigg ", "Daira-Emma Hopwood ", "Ying Tong Lai", From 49d01cc0f10a429cf79736ca036993c8fd632e76 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 2 Mar 2026 04:41:41 +0000 Subject: [PATCH 13/16] CI: Use pinned dependencies where possible for `build-nostd` --- .github/workflows/ci.yml | 2 ++ .github/workflows/lints-stable.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 354bda346..14c13b13b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,8 @@ jobs: - name: Show Cargo.toml for the synthetic crate working-directory: ./ci-build run: cat Cargo.toml + - name: Copy pinned dependencies into synthetic crate + run: cp crate_root/Cargo.lock ci-build/ - name: Add target working-directory: ./ci-build run: rustup target add ${{ matrix.target }} diff --git a/.github/workflows/lints-stable.yml b/.github/workflows/lints-stable.yml index a5c24af8e..3ea0ac8a2 100644 --- a/.github/workflows/lints-stable.yml +++ b/.github/workflows/lints-stable.yml @@ -53,6 +53,8 @@ jobs: - name: Show Cargo.toml for the synthetic crate working-directory: ./ci-build run: cat Cargo.toml + - name: Copy pinned dependencies into synthetic crate + run: cp crate_root/Cargo.lock ci-build/ - name: Add target working-directory: ./ci-build run: rustup target add ${{ matrix.target }} From b7e95f549d521c8366044627931fd74c4288b252 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 27 Feb 2026 10:23:16 -0700 Subject: [PATCH 14/16] Make pczt::Bundle::extract take `self` by reference. --- CHANGELOG.md | 4 ++++ src/pczt/tx_extractor.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f8fbcf8..96126a262 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to Rust's notion of ## [Unreleased] +### Changed +- `orchard::pczt::Bundle::extract` now takes its `self` argument by + reference instead of by value. + ## [0.12.0] - 2025-12-05 ### Added diff --git a/src/pczt/tx_extractor.rs b/src/pczt/tx_extractor.rs index e80d60249..4c98a33f0 100644 --- a/src/pczt/tx_extractor.rs +++ b/src/pczt/tx_extractor.rs @@ -28,7 +28,7 @@ impl super::Bundle { /// /// [regular `Bundle`]: crate::Bundle pub fn extract>( - self, + &self, ) -> Result>, TxExtractorError> { self.to_tx_data( |action| { From 6b12c77260aa7fac0d804983fc31b71b584d48e0 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 27 Feb 2026 14:58:21 -0700 Subject: [PATCH 15/16] Fix clippy lints. --- src/circuit.rs | 2 +- src/value.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 2003a84d5..06474cc9e 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1115,7 +1115,7 @@ mod tests { let mut rng = OsRng; let (circuit, instance) = generate_circuit_instance(OsRng); - let instances = &[instance.clone()]; + let instances = core::slice::from_ref(&instance); let pk = ProvingKey::build(); let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); diff --git a/src/value.rs b/src/value.rs index 67ac8787f..053ad5838 100644 --- a/src/value.rs +++ b/src/value.rs @@ -6,8 +6,8 @@ //! - [`ValueSum`], the sum of note values within an Orchard [`Action`] or [`Bundle`]. //! It is a signed 64-bit integer (with range [`VALUE_SUM_RANGE`]). //! - `valueBalanceOrchard`, which is a signed 63-bit integer. This is represented -//! by a user-defined type parameter on [`Bundle`], returned by -//! [`Bundle::value_balance`] and [`Builder::value_balance`]. +//! by a user-defined type parameter on [`Bundle`], returned by +//! [`Bundle::value_balance`] and [`Builder::value_balance`]. //! //! If your specific instantiation of the Orchard protocol requires a smaller bound on //! valid note values (for example, Zcash's `MAX_MONEY` fits into a 51-bit integer), you From 4b39a10c9ccd871fd08fbd40b583c3ff6ce39db2 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 9 Mar 2026 13:42:23 +0100 Subject: [PATCH 16/16] Fix issues --- Cargo.lock | 5 +++++ src/builder.rs | 2 +- src/value.rs | 8 ++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 882943564..f63644de0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2649,3 +2649,8 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[patch.unused]] +name = "halo2_proofs" +version = "0.3.1" +source = "git+https://github.com/zcash/halo2?rev=2308caf68c48c02468b66cfc452dad54e355e32f#2308caf68c48c02468b66cfc452dad54e355e32f" diff --git a/src/builder.rs b/src/builder.rs index d2138ef56..2fe3498b8 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -898,7 +898,7 @@ pub fn bundle, FL: OrchardFlavor>( i64::try_from(value_balance).map_err(BuildError::ValueSum)?; let result_value_balance = V::try_from(zatoshi_value_balance) - .map_err(|_| BuildError::ValueSum(value::OverflowError))?; + .map_err(|_| BuildError::ValueSum(value::BalanceError::Overflow))?; // Compute the transaction binding signing key. let bsk = pre_actions diff --git a/src/value.rs b/src/value.rs index da06976bf..281814518 100644 --- a/src/value.rs +++ b/src/value.rs @@ -237,7 +237,7 @@ impl ValueSum { 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))) + .and_then(|i| V::try_from(i).map_err(|_| BuildError::ValueSum(BalanceError::Overflow))) } } @@ -505,7 +505,7 @@ mod tests { use super::{ testing::{arb_note_value_bounded, arb_trapdoor, arb_value_sum_bounded}, - BalanceError, ValueCommitTrapdoor, ValueCommitment, ValueSum, MAX_NOTE_VALUE, + ValueCommitTrapdoor, ValueCommitment, ValueSum, MAX_NOTE_VALUE, }; use crate::{ note::asset_base::testing::arb_asset_base, note::AssetBase, primitives::redpallas, @@ -540,7 +540,7 @@ mod tests { let sum = four_values .iter() .cloned() - .sum::>() + .sum::>() .expect("we generate values that won't overflow"); let fifth = negate_value_sum(sum); @@ -566,7 +566,7 @@ mod tests { let zatoshi_value_balance = zatoshi_values .iter() .map(|(value, _)| value) - .sum::>() + .sum::>() .expect("we generate values that won't overflow"); let zatoshi_values_with_asset: Vec<(ValueSum, ValueCommitTrapdoor, AssetBase)> =