Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
20 changes: 20 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Copy Markdown
Contributor

@daira daira Sep 19, 2022

Choose a reason for hiding this comment

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

Suggested change
/// can be non-zero, but a transaction may not have a positive total value balance.
/// can be non-zero. Each bundle's value balance is added to the transparent
/// transaction value pool, which [must not have a negative value]. (If it were
/// negative, the transaction would output more value than it receives in inputs.)
///
/// [must not have a negative value]: https://zips.z.cash/protocol/protocol.pdf#transactions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I forgot to commit this before merging. See #359.

pub fn value_balance<V: TryFrom<i64>>(&self) -> Result<V, value::OverflowError> {
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)?;
Comment thread
sellout marked this conversation as resolved.
i64::try_from(value_balance).and_then(|i| V::try_from(i).map_err(|_| value::OverflowError))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is correct because i64 can represent all of $[-$ MAX_MONEY, MAX_MONEY $]$.

}

/// Builds a bundle containing the given spent notes and recipients.
///
/// The returned bundle will have no proof or signatures; these can be applied with
Expand Down
6 changes: 4 additions & 2 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down