From fa50d551c8c7d969157d4b3d42e9cbda85548051 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 25 Jul 2019 18:30:56 +0100 Subject: [PATCH] Move Amount impl into a submodule --- .../src/transaction/components.rs | 90 +------------------ .../src/transaction/components/amount.rs | 89 ++++++++++++++++++ 2 files changed, 92 insertions(+), 87 deletions(-) create mode 100644 zcash_primitives/src/transaction/components/amount.rs diff --git a/zcash_primitives/src/transaction/components.rs b/zcash_primitives/src/transaction/components.rs index f04c5aa..f72dfc5 100644 --- a/zcash_primitives/src/transaction/components.rs +++ b/zcash_primitives/src/transaction/components.rs @@ -10,6 +10,9 @@ use std::io::{self, Read, Write}; use legacy::Script; use JUBJUB; +mod amount; +pub use self::amount::Amount; + // π_A + π_B + π_C pub const GROTH_PROOF_SIZE: usize = (48 + 96 + 48); // π_A + π_A' + π_B + π_B' + π_C + π_C' + π_K + π_H @@ -18,46 +21,6 @@ const PHGR_PROOF_SIZE: usize = (33 + 33 + 65 + 33 + 33 + 33 + 33 + 33); const ZC_NUM_JS_INPUTS: usize = 2; const ZC_NUM_JS_OUTPUTS: usize = 2; -const COIN: i64 = 1_0000_0000; -const MAX_MONEY: i64 = 21_000_000 * COIN; - -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Amount(pub i64); - -impl Amount { - // Read an Amount from a signed 64-bit little-endian integer. - pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { - let amount = reader.read_i64::()?; - if 0 <= amount && amount <= MAX_MONEY { - Ok(Amount(amount)) - } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { - Ok(Amount(amount)) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - if allow_negative { - "Amount not in {-MAX_MONEY..MAX_MONEY}" - } else { - "Amount not in {0..MAX_MONEY}" - }, - )) - } - } - - // Read an Amount from an unsigned 64-bit little-endian integer. - pub fn read_u64(mut reader: R) -> io::Result { - let amount = reader.read_u64::()?; - if amount <= MAX_MONEY as u64 { - Ok(Amount(amount as i64)) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidData, - "Amount not in {0..MAX_MONEY}", - )) - } - } -} - #[derive(Debug)] pub struct OutPoint { hash: [u8; 32], @@ -432,50 +395,3 @@ impl JSDescription { writer.write_all(&self.ciphertexts[1]) } } - -#[cfg(test)] -mod tests { - use super::{Amount, MAX_MONEY}; - - #[test] - fn amount_in_range() { - let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; - assert_eq!(Amount::read_u64(&zero[..]).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], false).unwrap(), Amount(0)); - assert_eq!(Amount::read_i64(&zero[..], true).unwrap(), Amount(0)); - - let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; - assert!(Amount::read_u64(&neg_one[..]).is_err()); - assert!(Amount::read_i64(&neg_one[..], false).is_err()); - assert_eq!(Amount::read_i64(&neg_one[..], true).unwrap(), Amount(-1)); - - let max_money = b"\x00\x40\x07\x5a\xf0\x75\x07\x00"; - assert_eq!(Amount::read_u64(&max_money[..]).unwrap(), Amount(MAX_MONEY)); - assert_eq!( - Amount::read_i64(&max_money[..], false).unwrap(), - Amount(MAX_MONEY) - ); - assert_eq!( - Amount::read_i64(&max_money[..], true).unwrap(), - Amount(MAX_MONEY) - ); - - let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; - assert!(Amount::read_u64(&max_money_p1[..]).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], false).is_err()); - assert!(Amount::read_i64(&max_money_p1[..], true).is_err()); - - let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money[..], false).is_err()); - assert_eq!( - Amount::read_i64(&neg_max_money[..], true).unwrap(), - Amount(-MAX_MONEY) - ); - - let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; - assert!(Amount::read_u64(&neg_max_money_m1[..]).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], false).is_err()); - assert!(Amount::read_i64(&neg_max_money_m1[..], true).is_err()); - } -} diff --git a/zcash_primitives/src/transaction/components/amount.rs b/zcash_primitives/src/transaction/components/amount.rs new file mode 100644 index 0000000..593e98c --- /dev/null +++ b/zcash_primitives/src/transaction/components/amount.rs @@ -0,0 +1,89 @@ +use byteorder::{LittleEndian, ReadBytesExt}; +use std::io::{self, Read}; + +const COIN: i64 = 1_0000_0000; +const MAX_MONEY: i64 = 21_000_000 * COIN; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Amount(pub i64); + +impl Amount { + // Read an Amount from a signed 64-bit little-endian integer. + pub fn read_i64(mut reader: R, allow_negative: bool) -> io::Result { + let amount = reader.read_i64::()?; + if 0 <= amount && amount <= MAX_MONEY { + Ok(Amount(amount)) + } else if allow_negative && -MAX_MONEY <= amount && amount < 0 { + Ok(Amount(amount)) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + if allow_negative { + "Amount not in {-MAX_MONEY..MAX_MONEY}" + } else { + "Amount not in {0..MAX_MONEY}" + }, + )) + } + } + + // Read an Amount from an unsigned 64-bit little-endian integer. + pub fn read_u64(mut reader: R) -> io::Result { + let amount = reader.read_u64::()?; + if amount <= MAX_MONEY as u64 { + Ok(Amount(amount as i64)) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "Amount not in {0..MAX_MONEY}", + )) + } + } +} + +#[cfg(test)] +mod tests { + use super::{Amount, MAX_MONEY}; + + #[test] + fn amount_in_range() { + let zero = b"\x00\x00\x00\x00\x00\x00\x00\x00"; + assert_eq!(Amount::read_u64(&zero[..]).unwrap(), Amount(0)); + assert_eq!(Amount::read_i64(&zero[..], false).unwrap(), Amount(0)); + assert_eq!(Amount::read_i64(&zero[..], true).unwrap(), Amount(0)); + + let neg_one = b"\xff\xff\xff\xff\xff\xff\xff\xff"; + assert!(Amount::read_u64(&neg_one[..]).is_err()); + assert!(Amount::read_i64(&neg_one[..], false).is_err()); + assert_eq!(Amount::read_i64(&neg_one[..], true).unwrap(), Amount(-1)); + + let max_money = b"\x00\x40\x07\x5a\xf0\x75\x07\x00"; + assert_eq!(Amount::read_u64(&max_money[..]).unwrap(), Amount(MAX_MONEY)); + assert_eq!( + Amount::read_i64(&max_money[..], false).unwrap(), + Amount(MAX_MONEY) + ); + assert_eq!( + Amount::read_i64(&max_money[..], true).unwrap(), + Amount(MAX_MONEY) + ); + + let max_money_p1 = b"\x01\x40\x07\x5a\xf0\x75\x07\x00"; + assert!(Amount::read_u64(&max_money_p1[..]).is_err()); + assert!(Amount::read_i64(&max_money_p1[..], false).is_err()); + assert!(Amount::read_i64(&max_money_p1[..], true).is_err()); + + let neg_max_money = b"\x00\xc0\xf8\xa5\x0f\x8a\xf8\xff"; + assert!(Amount::read_u64(&neg_max_money[..]).is_err()); + assert!(Amount::read_i64(&neg_max_money[..], false).is_err()); + assert_eq!( + Amount::read_i64(&neg_max_money[..], true).unwrap(), + Amount(-MAX_MONEY) + ); + + let neg_max_money_m1 = b"\xff\xbf\xf8\xa5\x0f\x8a\xf8\xff"; + assert!(Amount::read_u64(&neg_max_money_m1[..]).is_err()); + assert!(Amount::read_i64(&neg_max_money_m1[..], false).is_err()); + assert!(Amount::read_i64(&neg_max_money_m1[..], true).is_err()); + } +}