diff --git a/zebra-chain/src/sapling/commitment.rs b/zebra-chain/src/sapling/commitment.rs index ad3b019c..dc49a639 100644 --- a/zebra-chain/src/sapling/commitment.rs +++ b/zebra-chain/src/sapling/commitment.rs @@ -137,6 +137,21 @@ impl NoteCommitment { #[derive(Clone, Copy, Deserialize, PartialEq, Serialize)] pub struct ValueCommitment(#[serde(with = "serde_helpers::AffinePoint")] pub jubjub::AffinePoint); +impl std::ops::Add for ValueCommitment { + type Output = Self; + + fn add(self, rhs: ValueCommitment) -> Self::Output { + let value = self.0.to_extended() + rhs.0.to_extended(); + ValueCommitment(value.into()) + } +} + +impl std::ops::AddAssign for ValueCommitment { + fn add_assign(&mut self, rhs: ValueCommitment) { + *self = *self + rhs + } +} + impl fmt::Debug for ValueCommitment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ValueCommitment") @@ -164,6 +179,32 @@ impl From for [u8; 32] { } } +impl std::ops::Sub for ValueCommitment { + type Output = Self; + + fn sub(self, rhs: ValueCommitment) -> Self::Output { + ValueCommitment((self.0.to_extended() - rhs.0.to_extended()).into()) + } +} + +impl std::ops::SubAssign for ValueCommitment { + fn sub_assign(&mut self, rhs: ValueCommitment) { + *self = *self - rhs; + } +} + +impl std::iter::Sum for ValueCommitment { + fn sum(iter: I) -> Self + where + I: Iterator, + { + iter.fold( + ValueCommitment(jubjub::AffinePoint::identity()), + std::ops::Add::add, + ) + } +} + /// LEBS2OSP256(repr_J(cv)) /// /// https://zips.z.cash/protocol/protocol.pdf#spendencoding