diff --git a/masp_primitives/src/transaction/builder.rs b/masp_primitives/src/transaction/builder.rs index 1745ef39..fc65dcfd 100644 --- a/masp_primitives/src/transaction/builder.rs +++ b/masp_primitives/src/transaction/builder.rs @@ -18,7 +18,7 @@ use crate::{ sapling::{prover::TxProver, Diversifier, Node, Note, PaymentAddress}, transaction::{ components::{ - amount::{BalanceError, FromNt, I128Sum, U64Sum, ValueSum, MAX_MONEY}, + amount::{BalanceError, I128Sum, U64Sum, ValueSum, MAX_MONEY}, sapling::{ self, builder::{SaplingBuilder, SaplingMetadata}, @@ -337,7 +337,7 @@ impl Builder { // // After fees are accounted for, the value balance of the transaction must be zero. - let balance_after_fees = self.value_balance()? - I128Sum::from(FromNt(fee)); + let balance_after_fees = self.value_balance()? - I128Sum::from_sum(fee); if balance_after_fees != ValueSum::zero() { return Err(Error::InsufficientFunds(-balance_after_fees)); @@ -479,7 +479,7 @@ mod tests { merkle_tree::{CommitmentTree, IncrementalWitness}, sapling::Rseed, transaction::{ - components::amount::{FromNt, I128Sum, ValueSum, DEFAULT_FEE}, + components::amount::{I128Sum, ValueSum, DEFAULT_FEE}, sapling::builder as build_s, TransparentAddress, }, @@ -580,7 +580,9 @@ mod tests { let builder = Builder::new(TEST_NETWORK, tx_height); assert_eq!( builder.mock_build(), - Err(Error::InsufficientFunds(FromNt(DEFAULT_FEE.clone()).into())) + Err(Error::InsufficientFunds(I128Sum::from_sum( + DEFAULT_FEE.clone() + ))) ); } @@ -599,7 +601,7 @@ mod tests { builder.mock_build(), Err(Error::InsufficientFunds( I128Sum::from_pair(zec(), 50000).unwrap() - + &I128Sum::from(FromNt(DEFAULT_FEE.clone())) + + &I128Sum::from_sum(DEFAULT_FEE.clone()) )) ); } @@ -615,7 +617,7 @@ mod tests { builder.mock_build(), Err(Error::InsufficientFunds( I128Sum::from_pair(zec(), 50000).unwrap() - + &I128Sum::from(FromNt(DEFAULT_FEE.clone())) + + &I128Sum::from_sum(DEFAULT_FEE.clone()) )) ); } diff --git a/masp_primitives/src/transaction/components.rs b/masp_primitives/src/transaction/components.rs index 7e76b55b..cc041955 100644 --- a/masp_primitives/src/transaction/components.rs +++ b/masp_primitives/src/transaction/components.rs @@ -5,8 +5,7 @@ pub mod sapling; pub mod transparent; pub use self::{ amount::{ - FromNt, I128Sum, I16Sum, I32Sum, I64Sum, I8Sum, TryFromNt, U128Sum, U16Sum, U32Sum, U64Sum, - U8Sum, ValueSum, + I128Sum, I16Sum, I32Sum, I64Sum, I8Sum, U128Sum, U16Sum, U32Sum, U64Sum, U8Sum, ValueSum, }, sapling::{ConvertDescription, OutputDescription, SpendDescription}, transparent::{TxIn, TxOut}, diff --git a/masp_primitives/src/transaction/components/amount.rs b/masp_primitives/src/transaction/components/amount.rs index 56f2c287..fac323c5 100644 --- a/masp_primitives/src/transaction/components/amount.rs +++ b/masp_primitives/src/transaction/components/amount.rs @@ -17,12 +17,12 @@ pub static ref DEFAULT_FEE: U64Sum = ValueSum::from_pair(zec(), 1000).unwrap(); } /// A type-safe representation of some quantity of Zcash. /// -/// An Amount can only be constructed from an integer that is within the valid monetary +/// An ValueSum can only be constructed from an integer that is within the valid monetary /// range of `{-MAX_MONEY..MAX_MONEY}` (where `MAX_MONEY` = i64::MAX). /// However, this range is not preserved as an invariant internally; it is possible to -/// add two valid Amounts together to obtain an invalid Amount. It is the user's -/// responsibility to handle the result of serializing potentially-invalid Amounts. In -/// particular, a `Transaction` containing serialized invalid Amounts will be rejected +/// add two valid ValueSums together to obtain an invalid ValueSum. It is the user's +/// responsibility to handle the result of serializing potentially-invalid ValueSums. In +/// particular, a `Transaction` containing serialized invalid ValueSums will be rejected /// by the network consensus rules. /// @@ -49,13 +49,13 @@ pub type U128Sum = ValueSum; #[derive(Clone, Default, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, Hash)] pub struct ValueSum< Unit: Hash + Ord + BorshSerialize + BorshDeserialize, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq, ->(pub BTreeMap); + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq, +>(pub BTreeMap); -impl memuse::DynamicUsage for ValueSum +impl memuse::DynamicUsage for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, { #[inline(always)] fn dynamic_usage(&self) -> usize { @@ -70,16 +70,16 @@ where } } -impl ValueSum +impl ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, { - /// Creates a non-negative Amount from a Magnitude. - pub fn from_nonnegative(atype: Unit, amount: Magnitude) -> Result { - if amount == Magnitude::default() { + /// Creates a non-negative ValueSum from a Value. + pub fn from_nonnegative(atype: Unit, amount: Value) -> Result { + if amount == Value::default() { Ok(Self::zero()) - } else if Magnitude::default() <= amount { + } else if Value::default() <= amount { let mut ret = BTreeMap::new(); ret.insert(atype, amount); Ok(ValueSum(ret)) @@ -89,14 +89,14 @@ where } } -impl ValueSum +impl ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default, { - /// Creates an Amount from a Magnitude. - pub fn from_pair(atype: Unit, amount: Magnitude) -> Result { - if amount == Magnitude::default() { + /// Creates an ValueSum from a Value. + pub fn from_pair(atype: Unit, amount: Value) -> Result { + if amount == Value::default() { Ok(Self::zero()) } else { let mut ret = BTreeMap::new(); @@ -105,44 +105,49 @@ where } } - /// Filters out everything but the given AssetType from this Amount + /// Filters out everything but the given AssetType from this ValueSum pub fn project(&self, index: Unit) -> Self { let val = self.0.get(&index).copied().unwrap_or_default(); Self::from_pair(index, val).unwrap() } - /// Get the given AssetType within this Amount - pub fn get(&self, index: &Unit) -> Magnitude { - *self.0.get(index).unwrap_or(&Magnitude::default()) + /// Get the given AssetType within this ValueSum + pub fn get(&self, index: &Unit) -> Value { + *self.0.get(index).unwrap_or(&Value::default()) } } -impl ValueSum +impl ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, { - /// Returns a zero-valued Amount. + /// Returns a zero-valued ValueSum. pub fn zero() -> Self { ValueSum(BTreeMap::new()) } + /// Check if ValueSum is zero + pub fn is_zero(&self) -> bool { + self.0.is_empty() + } + /// Returns an iterator over the amount's non-zero asset-types - pub fn asset_types(&self) -> Keys<'_, Unit, Magnitude> { + pub fn asset_types(&self) -> Keys<'_, Unit, Value> { self.0.keys() } /// Returns an iterator over the amount's non-zero components - pub fn components(&self) -> Iter<'_, Unit, Magnitude> { + pub fn components(&self) -> Iter<'_, Unit, Value> { self.0.iter() } /// Returns an iterator over the amount's non-zero components - pub fn into_components(self) -> IntoIter { + pub fn into_components(self) -> IntoIter { self.0.into_iter() } - /// Filters out the given AssetType from this Amount + /// Filters out the given AssetType from this ValueSum pub fn reject(&self, index: Unit) -> Self { let mut val = self.clone(); val.0.remove(&index); @@ -151,7 +156,7 @@ where } impl ValueSum { - /// Deserialize an Amount object from a list of amounts denominated by + /// Deserialize an ValueSum object from a list of amounts denominated by /// different assets pub fn read(reader: &mut R) -> std::io::Result { let vec = Vector::read(reader, |reader| { @@ -173,7 +178,7 @@ impl ValueSum { Ok(ret) } - /// Serialize an Amount object into a list of amounts denominated by + /// Serialize an ValueSum object into a list of amounts denominated by /// distinct asset types pub fn write(&self, writer: &mut W) -> std::io::Result<()> { let vec: Vec<_> = self.components().collect(); @@ -186,7 +191,7 @@ impl ValueSum { } impl ValueSum { - /// Deserialize an Amount object from a list of amounts denominated by + /// Deserialize an ValueSum object from a list of amounts denominated by /// different assets pub fn read(reader: &mut R) -> std::io::Result { let vec = Vector::read(reader, |reader| { @@ -208,7 +213,7 @@ impl ValueSum { Ok(ret) } - /// Serialize an Amount object into a list of amounts denominated by + /// Serialize an ValueSum object into a list of amounts denominated by /// distinct asset types pub fn write(&self, writer: &mut W) -> std::io::Result<()> { let vec: Vec<_> = self.components().collect(); @@ -221,7 +226,7 @@ impl ValueSum { } impl ValueSum { - /// Deserialize an Amount object from a list of amounts denominated by + /// Deserialize an ValueSum object from a list of amounts denominated by /// different assets pub fn read(reader: &mut R) -> std::io::Result { let vec = Vector::read(reader, |reader| { @@ -243,7 +248,7 @@ impl ValueSum { Ok(ret) } - /// Serialize an Amount object into a list of amounts denominated by + /// Serialize an ValueSum object into a list of amounts denominated by /// distinct asset types pub fn write(&self, writer: &mut W) -> std::io::Result<()> { let vec: Vec<_> = self.components().collect(); @@ -255,27 +260,27 @@ impl ValueSum { } } -impl From for ValueSum +impl From for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + One, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + One, { fn from(atype: Unit) -> Self { let mut ret = BTreeMap::new(); - ret.insert(atype, Magnitude::one()); + ret.insert(atype, Value::one()); ValueSum(ret) } } -impl PartialOrd for ValueSum +impl PartialOrd for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, { /// One ValueSum is more than or equal to another if each corresponding /// coordinate is more than or equal to the other's. fn partial_cmp(&self, other: &Self) -> Option { - let zero = Magnitude::default(); + let zero = Value::default(); let mut ordering = Some(Ordering::Equal); for k in self.0.keys().chain(other.0.keys()) { let v1 = self.0.get(k).unwrap_or(&zero); @@ -340,10 +345,10 @@ impl_index!(i128); impl_index!(u128); -impl MulAssign for ValueSum +impl MulAssign for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -352,15 +357,15 @@ where + PartialOrd + CheckedMul, { - fn mul_assign(&mut self, rhs: Magnitude) { + fn mul_assign(&mut self, rhs: Value) { *self = self.clone() * rhs; } } -impl Mul for ValueSum +impl Mul for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -369,9 +374,9 @@ where + PartialOrd + CheckedMul, { - type Output = ValueSum; + type Output = ValueSum; - fn mul(self, rhs: Magnitude) -> Self::Output { + fn mul(self, rhs: Value) -> Self::Output { let mut comps = BTreeMap::new(); for (atype, amount) in self.0.iter() { comps.insert( @@ -379,15 +384,15 @@ where amount.checked_mul(&rhs).expect("overflow detected"), ); } - comps.retain(|_, v| *v != Magnitude::default()); + comps.retain(|_, v| *v != Value::default()); ValueSum(comps) } } -impl AddAssign<&ValueSum> for ValueSum +impl AddAssign<&ValueSum> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -396,15 +401,15 @@ where + PartialOrd + CheckedAdd, { - fn add_assign(&mut self, rhs: &ValueSum) { + fn add_assign(&mut self, rhs: &ValueSum) { *self = self.clone() + rhs; } } -impl AddAssign> for ValueSum +impl AddAssign> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -413,15 +418,15 @@ where + PartialOrd + CheckedAdd, { - fn add_assign(&mut self, rhs: ValueSum) { + fn add_assign(&mut self, rhs: ValueSum) { *self += &rhs } } -impl Add<&ValueSum> for ValueSum +impl Add<&ValueSum> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -430,9 +435,9 @@ where + PartialOrd + CheckedAdd, { - type Output = ValueSum; + type Output = ValueSum; - fn add(self, rhs: &ValueSum) -> Self::Output { + fn add(self, rhs: &ValueSum) -> Self::Output { let mut comps = self.0.clone(); for (atype, amount) in rhs.components() { comps.insert( @@ -442,15 +447,15 @@ where .expect("overflow detected"), ); } - comps.retain(|_, v| *v != Magnitude::default()); + comps.retain(|_, v| *v != Value::default()); ValueSum(comps) } } -impl Add> for ValueSum +impl Add> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -459,17 +464,17 @@ where + PartialOrd + CheckedAdd, { - type Output = ValueSum; + type Output = ValueSum; - fn add(self, rhs: ValueSum) -> Self::Output { + fn add(self, rhs: ValueSum) -> Self::Output { self + &rhs } } -impl SubAssign<&ValueSum> for ValueSum +impl SubAssign<&ValueSum> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -478,15 +483,15 @@ where + PartialOrd + CheckedSub, { - fn sub_assign(&mut self, rhs: &ValueSum) { + fn sub_assign(&mut self, rhs: &ValueSum) { *self = self.clone() - rhs } } -impl SubAssign> for ValueSum +impl SubAssign> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -495,15 +500,15 @@ where + PartialOrd + CheckedSub, { - fn sub_assign(&mut self, rhs: ValueSum) { + fn sub_assign(&mut self, rhs: ValueSum) { *self -= &rhs } } -impl Neg for ValueSum +impl Neg for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq @@ -512,7 +517,7 @@ where + PartialOrd + CheckedNeg, { - type Output = ValueSum; + type Output = ValueSum; fn neg(mut self) -> Self::Output { let mut comps = BTreeMap::new(); @@ -522,19 +527,19 @@ where amount.checked_neg().expect("overflow detected"), ); } - comps.retain(|_, v| *v != Magnitude::default()); + comps.retain(|_, v| *v != Value::default()); ValueSum(comps) } } -impl Sub<&ValueSum> for ValueSum +impl Sub<&ValueSum> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + CheckedSub, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + CheckedSub, { - type Output = ValueSum; + type Output = ValueSum; - fn sub(self, rhs: &ValueSum) -> Self::Output { + fn sub(self, rhs: &ValueSum) -> Self::Output { let mut comps = self.0.clone(); for (atype, amount) in rhs.components() { comps.insert( @@ -544,27 +549,27 @@ where .expect("overflow detected"), ); } - comps.retain(|_, v| *v != Magnitude::default()); + comps.retain(|_, v| *v != Value::default()); ValueSum(comps) } } -impl Sub> for ValueSum +impl Sub> for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + CheckedSub, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + CheckedSub, { - type Output = ValueSum; + type Output = ValueSum; - fn sub(self, rhs: ValueSum) -> Self::Output { + fn sub(self, rhs: ValueSum) -> Self::Output { self - &rhs } } -impl Sum for ValueSum +impl Sum for ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + Default + PartialOrd, Self: Add, { fn sum>(iter: I) -> Self { @@ -572,39 +577,32 @@ where } } -/// Workaround for the blanket implementation of TryFrom -pub struct TryFromNt(pub X); - -impl TryFrom>> - for ValueSum +impl ValueSum where Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, - Output: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + TryFrom, + Output: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, { - type Error = >::Error; - - fn try_from(x: TryFromNt>) -> Result { + pub fn try_from_sum( + x: ValueSum, + ) -> Result>::Error> + where + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, + Output: TryFrom, + { let mut comps = BTreeMap::new(); - for (atype, amount) in x.0 .0 { + for (atype, amount) in x.0 { comps.insert(atype, amount.try_into()?); } Ok(Self(comps)) } -} -/// Workaround for the blanket implementation of TryFrom -pub struct FromNt(pub X); - -impl From>> for ValueSum -where - Unit: Hash + Ord + BorshSerialize + BorshDeserialize + Clone, - Magnitude: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, - Output: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy + From, -{ - fn from(x: FromNt>) -> Self { + pub fn from_sum(x: ValueSum) -> Self + where + Value: BorshSerialize + BorshDeserialize + PartialEq + Eq + Copy, + Output: From, + { let mut comps = BTreeMap::new(); - for (atype, amount) in x.0 .0 { + for (atype, amount) in x.0 { comps.insert(atype, amount.into()); } Self(comps) @@ -625,12 +623,12 @@ impl std::fmt::Display for BalanceError { BalanceError::Overflow => { write!( f, - "Amount addition resulted in a value outside the valid range." + "ValueSum addition resulted in a value outside the valid range." ) } BalanceError::Underflow => write!( f, - "Amount subtraction resulted in a value outside the valid range." + "ValueSum subtraction resulted in a value outside the valid range." ), } } @@ -699,10 +697,10 @@ mod tests { ); //let max_money_p1 = b"\x01\x94\xf3O\xfdd\xef\n\xc3i\x08\xfd\xdf\xec\x05hX\x06)\xc4Vq\x0f\xa1\x86\x83\x12\xa8\x7f\xbf\n\xa5\t\x01\x40\x07\x5a\xf0\x75\x07\x00"; - //assert!(Amount::read(&mut max_money_p1.as_ref()).is_err()); + //assert!(ValueSum::read(&mut max_money_p1.as_ref()).is_err()); //let mut neg_max_money = [0u8; 41]; - //let mut amount = Amount::from_pair(zec(), -MAX_MONEY).unwrap(); + //let mut amount = ValueSum::from_pair(zec(), -MAX_MONEY).unwrap(); //*amount.0.get_mut(&zec()).unwrap() = i64::MIN; //amount.write(&mut neg_max_money.as_mut()); //dbg!(std::str::from_utf8(&neg_max_money.as_ref().iter().map(|b| std::ascii::escape_default(*b)).flatten().collect::>()).unwrap()); diff --git a/masp_primitives/src/transaction/components/sapling/builder.rs b/masp_primitives/src/transaction/components/sapling/builder.rs index ceda98a8..9d5594ca 100644 --- a/masp_primitives/src/transaction/components/sapling/builder.rs +++ b/masp_primitives/src/transaction/components/sapling/builder.rs @@ -25,7 +25,7 @@ use crate::{ transaction::{ builder::Progress, components::{ - amount::{FromNt, I128Sum, I32Sum, ValueSum, MAX_MONEY}, + amount::{I128Sum, I32Sum, ValueSum, MAX_MONEY}, sapling::{ fees, Authorization, Authorized, Bundle, ConvertDescription, GrothProofBytes, OutputDescription, SpendDescription, @@ -438,7 +438,7 @@ impl SaplingBuilder

{ } let allowed_amt: I32Sum = allowed.clone().into(); - self.value_balance += I128Sum::from(FromNt(allowed_amt)) * (value as i128); + self.value_balance += I128Sum::from_sum(allowed_amt) * (value as i128); self.converts.push(ConvertDescriptionInfo { allowed,