From 8011e0d57a5d245e0a0e678590dd17fd7d992664 Mon Sep 17 00:00:00 2001 From: Hazel OHearn Date: Tue, 23 Aug 2022 16:23:15 -0300 Subject: [PATCH] add value_balance to builder --- CHANGELOG.md | 1 + src/builder.rs | 20 ++++++++++++++++++++ src/value.rs | 6 ++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5077477b..4ddee2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to Rust's notion of ## [0.2.0] - 2022-06-24 ### Added - `orchard::bundle::BatchValidator` +- `orchard::builder::Builder::value_balance` - `orchard::note_encryption`: - `CompactAction::from_parts` - `CompactAction::nullifier` diff --git a/src/builder.rs b/src/builder.rs index fd1e9fd5..fe6b6226 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -302,6 +302,26 @@ impl Builder { Ok(()) } + /// The net value of the bundle to be built. The value of all spends, + /// minus the value of all outputs. + /// + /// Useful for balancing a transaction, as the value balance of an individual bundle + /// can be non-zero, but a transaction may not have a positive total value balance. + pub fn value_balance>(&self) -> Result { + let value_balance = self + .spends + .iter() + .map(|spend| spend.note.value() - NoteValue::zero()) + .chain( + self.recipients + .iter() + .map(|recipient| NoteValue::zero() - recipient.value), + ) + .fold(Some(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)) + } + /// Builds a bundle containing the given spent notes and recipients. /// /// The returned bundle will have no proof or signatures; these can be applied with diff --git a/src/value.rs b/src/value.rs index a760e77b..71727577 100644 --- a/src/value.rs +++ b/src/value.rs @@ -5,8 +5,9 @@ //! (with maximum value [`MAX_NOTE_VALUE`]), and is serialized in a note plaintext. //! - [`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`]. +//! - `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`]. //! //! 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 @@ -32,6 +33,7 @@ //! [`Action`]: crate::action::Action //! [`Bundle`]: crate::bundle::Bundle //! [`Bundle::value_balance`]: crate::bundle::Bundle::value_balance +//! [`Builder::value_balance`]: crate::builder::Builder::value_balance //! [`Builder::add_recipient`]: crate::builder::Builder::add_recipient //! [Rust documentation]: https://doc.rust-lang.org/stable/std/primitive.i64.html