impl operators for Amount

This commit is contained in:
Jack Grigg
2019-07-25 20:53:42 +01:00
parent 0ea4408d46
commit ab60b8804a
2 changed files with 48 additions and 12 deletions

View File

@@ -44,7 +44,7 @@ impl Error {
pub enum ErrorKind { pub enum ErrorKind {
AnchorMismatch, AnchorMismatch,
BindingSig, BindingSig,
ChangeIsNegative(i64), ChangeIsNegative(Amount),
InvalidAddress, InvalidAddress,
InvalidAmount, InvalidAmount,
InvalidWitness, InvalidWitness,
@@ -252,7 +252,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
let alpha = Fs::random(&mut self.rng); let alpha = Fs::random(&mut self.rng);
self.mtx.value_balance.0 += note.value as i64; self.mtx.value_balance += Amount(note.value as i64);
self.spends.push(SpendDescriptionInfo { self.spends.push(SpendDescriptionInfo {
extsk, extsk,
@@ -275,7 +275,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
) -> Result<(), Error> { ) -> Result<(), Error> {
let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?; let output = SaplingOutput::new(&mut self.rng, ovk, to, value, memo)?;
self.mtx.value_balance.0 -= value.0; self.mtx.value_balance -= value;
self.outputs.push(output); self.outputs.push(output);
@@ -329,14 +329,14 @@ impl<R: RngCore + CryptoRng> Builder<R> {
// //
// Valid change // Valid change
let change = self.mtx.value_balance.0 let change = self.mtx.value_balance
- self.fee.0 - self.fee
- self - self
.mtx .mtx
.vout .vout
.iter() .iter()
.map(|output| output.value.0) .map(|output| output.value)
.sum::<i64>(); .sum::<Amount>();
if change.is_negative() { if change.is_negative() {
return Err(Error(ErrorKind::ChangeIsNegative(change))); return Err(Error(ErrorKind::ChangeIsNegative(change)));
} }
@@ -362,7 +362,7 @@ impl<R: RngCore + CryptoRng> Builder<R> {
return Err(Error(ErrorKind::NoChangeAddress)); return Err(Error(ErrorKind::NoChangeAddress));
}; };
self.add_sapling_output(change_address.0, change_address.1, Amount(change), None)?; self.add_sapling_output(change_address.0, change_address.1, change, None)?;
} }
// //
@@ -591,7 +591,7 @@ mod tests {
{ {
let builder = Builder::new(0); let builder = Builder::new(0);
match builder.build(1, MockTxProver) { match builder.build(1, MockTxProver) {
Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-10000)), Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-10000))),
Ok(_) => panic!("Should have failed"), Ok(_) => panic!("Should have failed"),
} }
} }
@@ -608,7 +608,7 @@ mod tests {
.add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None) .add_sapling_output(ovk.clone(), to.clone(), Amount(50000), None)
.unwrap(); .unwrap();
match builder.build(1, MockTxProver) { match builder.build(1, MockTxProver) {
Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))),
Ok(_) => panic!("Should have failed"), Ok(_) => panic!("Should have failed"),
} }
} }
@@ -621,7 +621,7 @@ mod tests {
.add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(50000)) .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(50000))
.unwrap(); .unwrap();
match builder.build(1, MockTxProver) { match builder.build(1, MockTxProver) {
Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-60000)), Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-60000))),
Ok(_) => panic!("Should have failed"), Ok(_) => panic!("Should have failed"),
} }
} }
@@ -653,7 +653,7 @@ mod tests {
.add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000)) .add_transparent_output(&TransparentAddress::PublicKey([0; 20]), Amount(20000))
.unwrap(); .unwrap();
match builder.build(1, MockTxProver) { match builder.build(1, MockTxProver) {
Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(-1)), Err(e) => assert_eq!(e.kind(), &ErrorKind::ChangeIsNegative(Amount(-1))),
Ok(_) => panic!("Should have failed"), Ok(_) => panic!("Should have failed"),
} }
} }

View File

@@ -1,5 +1,7 @@
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use std::io::{self, Read}; use std::io::{self, Read};
use std::iter::Sum;
use std::ops::{Add, AddAssign, Sub, SubAssign};
const COIN: i64 = 1_0000_0000; const COIN: i64 = 1_0000_0000;
const MAX_MONEY: i64 = 21_000_000 * COIN; const MAX_MONEY: i64 = 21_000_000 * COIN;
@@ -58,6 +60,40 @@ impl Amount {
} }
} }
impl Add<Amount> for Amount {
type Output = Amount;
fn add(self, rhs: Amount) -> Amount {
Amount(self.0 + rhs.0)
}
}
impl AddAssign<Amount> for Amount {
fn add_assign(&mut self, rhs: Amount) {
*self = *self + rhs
}
}
impl Sub<Amount> for Amount {
type Output = Amount;
fn sub(self, rhs: Amount) -> Amount {
Amount(self.0 - rhs.0)
}
}
impl SubAssign<Amount> for Amount {
fn sub_assign(&mut self, rhs: Amount) {
*self = *self - rhs
}
}
impl Sum for Amount {
fn sum<I: Iterator<Item = Amount>>(iter: I) -> Amount {
iter.fold(Amount::zero(), Add::add)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Amount, MAX_MONEY}; use super::{Amount, MAX_MONEY};