Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made Amount more generic. #52

Merged
9 commits merged into from
Aug 11, 2023
3 changes: 3 additions & 0 deletions masp_primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ sha2 = "0.9"
# - Metrics
memuse = "0.2.1"

# - Checked arithmetic
num-traits = "0.2.14"

# - Secret management
subtle = "2.2.3"

Expand Down
33 changes: 17 additions & 16 deletions masp_primitives/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
pedersen_hash::{pedersen_hash, Personalization},
Node, ValueCommitment,
},
transaction::components::amount::Amount,
transaction::components::amount::{I32Sum, ValueSum},
};
use borsh::{BorshDeserialize, BorshSerialize};
use group::{Curve, GroupEncoding};
Expand All @@ -16,7 +16,7 @@ use std::{
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AllowedConversion {
/// The asset type that the note represents
assets: Amount,
assets: I32Sum,
/// Memorize generator because it's expensive to recompute
generator: jubjub::ExtendedPoint,
}
Expand Down Expand Up @@ -71,15 +71,15 @@ impl AllowedConversion {
}
}

impl From<AllowedConversion> for Amount {
fn from(allowed_conversion: AllowedConversion) -> Amount {
impl From<AllowedConversion> for I32Sum {
fn from(allowed_conversion: AllowedConversion) -> I32Sum {
allowed_conversion.assets
}
}

impl From<Amount> for AllowedConversion {
impl From<I32Sum> for AllowedConversion {
/// Produces an asset generator without cofactor cleared
fn from(assets: Amount) -> Self {
fn from(assets: I32Sum) -> Self {
let mut asset_generator = jubjub::ExtendedPoint::identity();
for (asset, value) in assets.components() {
// Compute the absolute value (failing if -i64::MAX is
Expand Down Expand Up @@ -123,7 +123,7 @@ impl BorshDeserialize for AllowedConversion {
/// computation of checking whether the asset generator corresponds to the
/// deserialized amount.
fn deserialize(buf: &mut &[u8]) -> borsh::maybestd::io::Result<Self> {
let assets = Amount::read(buf)?;
let assets = I32Sum::read(buf)?;
let gen_bytes =
<<jubjub::ExtendedPoint as GroupEncoding>::Repr as BorshDeserialize>::deserialize(buf)?;
let generator = Option::from(jubjub::ExtendedPoint::from_bytes(&gen_bytes))
Expand Down Expand Up @@ -174,15 +174,15 @@ impl SubAssign for AllowedConversion {

impl Sum for AllowedConversion {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(AllowedConversion::from(Amount::zero()), Add::add)
iter.fold(AllowedConversion::from(ValueSum::zero()), Add::add)
}
}

#[cfg(test)]
mod tests {
use crate::asset_type::AssetType;
use crate::convert::AllowedConversion;
use crate::transaction::components::amount::Amount;
use crate::transaction::components::amount::ValueSum;

/// Generate ZEC asset type
fn zec() -> AssetType {
Expand All @@ -199,11 +199,12 @@ mod tests {
#[test]
fn test_homomorphism() {
// Left operand
let a = Amount::from_pair(zec(), 5).unwrap()
+ Amount::from_pair(btc(), 6).unwrap()
+ Amount::from_pair(xan(), 7).unwrap();
let a = ValueSum::from_pair(zec(), 5i32).unwrap()
+ ValueSum::from_pair(btc(), 6i32).unwrap()
+ ValueSum::from_pair(xan(), 7i32).unwrap();
// Right operand
let b = Amount::from_pair(zec(), 2).unwrap() + Amount::from_pair(xan(), 10).unwrap();
let b =
ValueSum::from_pair(zec(), 2i32).unwrap() + ValueSum::from_pair(xan(), 10i32).unwrap();
// Test homomorphism
assert_eq!(
AllowedConversion::from(a.clone() + b.clone()),
Expand All @@ -213,9 +214,9 @@ mod tests {
#[test]
fn test_serialization() {
// Make conversion
let a: AllowedConversion = (Amount::from_pair(zec(), 5).unwrap()
+ Amount::from_pair(btc(), 6).unwrap()
+ Amount::from_pair(xan(), 7).unwrap())
let a: AllowedConversion = (ValueSum::from_pair(zec(), 5i32).unwrap()
+ ValueSum::from_pair(btc(), 6i32).unwrap()
+ ValueSum::from_pair(xan(), 7i32).unwrap())
.into();
// Serialize conversion
let mut data = Vec::new();
Expand Down
8 changes: 4 additions & 4 deletions masp_primitives/src/sapling/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
redjubjub::{PublicKey, Signature},
Node,
},
transaction::components::{Amount, GROTH_PROOF_SIZE},
transaction::components::{I128Sum, GROTH_PROOF_SIZE},
};

use super::{Diversifier, PaymentAddress, ProofGenerationKey, Rseed};
Expand Down Expand Up @@ -73,7 +73,7 @@ pub trait TxProver {
fn binding_sig(
&self,
ctx: &mut Self::SaplingProvingContext,
amount: &Amount,
amount: &I128Sum,
sighash: &[u8; 32],
) -> Result<Signature, ()>;
}
Expand All @@ -92,7 +92,7 @@ pub mod mock {
redjubjub::{PublicKey, Signature},
Diversifier, Node, PaymentAddress, ProofGenerationKey, Rseed,
},
transaction::components::{Amount, GROTH_PROOF_SIZE},
transaction::components::{I128Sum, GROTH_PROOF_SIZE},
};

use super::TxProver;
Expand Down Expand Up @@ -169,7 +169,7 @@ pub mod mock {
fn binding_sig(
&self,
_ctx: &mut Self::SaplingProvingContext,
_value: &Amount,
_value: &I128Sum,
_sighash: &[u8; 32],
) -> Result<Signature, ()> {
Err(())
Expand Down
14 changes: 7 additions & 7 deletions masp_primitives/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{

use self::{
components::{
amount::Amount,
amount::{I128Sum, ValueSum},
sapling::{
self, ConvertDescriptionV5, OutputDescriptionV5, SpendDescription, SpendDescriptionV5,
},
Expand Down Expand Up @@ -269,10 +269,10 @@ impl<A: Authorization> TransactionData<A> {
}

impl<A: Authorization> TransactionData<A> {
pub fn sapling_value_balance(&self) -> Amount {
pub fn sapling_value_balance(&self) -> I128Sum {
self.sapling_bundle
.as_ref()
.map_or(Amount::zero(), |b| b.value_balance.clone())
.map_or(ValueSum::zero(), |b| b.value_balance.clone())
}
}

Expand Down Expand Up @@ -355,8 +355,8 @@ impl Transaction {
})
}

fn read_amount<R: Read>(mut reader: R) -> io::Result<Amount> {
Amount::read(&mut reader).map_err(|_| {
fn read_i128_sum<R: Read>(mut reader: R) -> io::Result<I128Sum> {
I128Sum::read(&mut reader).map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidData,
"Amount valueBalance out of range",
Expand Down Expand Up @@ -407,9 +407,9 @@ impl Transaction {
let n_converts = cd_v5s.len();
let n_outputs = od_v5s.len();
let value_balance = if n_spends > 0 || n_outputs > 0 {
Self::read_amount(&mut reader)?
Self::read_i128_sum(&mut reader)?
} else {
Amount::zero()
ValueSum::zero()
};

let spend_anchor = if n_spends > 0 {
Expand Down
61 changes: 24 additions & 37 deletions masp_primitives/src/transaction/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Structs for building transactions.

use std::convert::TryInto;
use std::error;
use std::fmt;
use std::sync::mpsc::Sender;
Expand All @@ -19,7 +18,7 @@ use crate::{
sapling::{prover::TxProver, Diversifier, Node, Note, PaymentAddress},
transaction::{
components::{
amount::{Amount, BalanceError, MAX_MONEY},
amount::{BalanceError, I128Sum, U64Sum, ValueSum, MAX_MONEY},
sapling::{
self,
builder::{SaplingBuilder, SaplingMetadata},
Expand All @@ -43,10 +42,10 @@ const DEFAULT_TX_EXPIRY_DELTA: u32 = 20;
pub enum Error<FeeError> {
/// Insufficient funds were provided to the transaction builder; the given
/// additional amount is required in order to construct the transaction.
InsufficientFunds(Amount),
InsufficientFunds(I128Sum),
/// The transaction has inputs in excess of outputs and fees; the user must
/// add a change output.
ChangeRequired(Amount),
ChangeRequired(U64Sum),
/// An error occurred in computing the fees for a transaction.
Fee(FeeError),
/// An overflow or underflow occurred when computing value balances
Expand Down Expand Up @@ -251,7 +250,7 @@ impl<P: consensus::Parameters, R: RngCore> Builder<P, R> {
value: u64,
memo: MemoBytes,
) -> Result<(), sapling::builder::Error> {
if value > MAX_MONEY.try_into().unwrap() {
if value > MAX_MONEY {
return Err(sapling::builder::Error::InvalidAmount);
}
self.sapling_builder
Expand All @@ -273,9 +272,9 @@ impl<P: consensus::Parameters, R: RngCore> Builder<P, R> {
&mut self,
to: &TransparentAddress,
asset_type: AssetType,
value: i64,
value: u64,
) -> Result<(), transparent::builder::Error> {
if value < 0 || value > MAX_MONEY {
if value > MAX_MONEY {
return Err(transparent::builder::Error::InvalidAmount);
}

Expand All @@ -293,13 +292,13 @@ impl<P: consensus::Parameters, R: RngCore> Builder<P, R> {
}

/// Returns the sum of the transparent, Sapling, and TZE value balances.
pub fn value_balance(&self) -> Result<Amount, BalanceError> {
pub fn value_balance(&self) -> Result<I128Sum, BalanceError> {
let value_balances = [
self.transparent_builder.value_balance()?,
self.sapling_builder.value_balance(),
];

Ok(value_balances.into_iter().sum::<Amount>())
Ok(value_balances.into_iter().sum::<I128Sum>())
}

/// Builds a transaction from the configured spends and outputs.
Expand All @@ -326,7 +325,7 @@ impl<P: consensus::Parameters, R: RngCore> Builder<P, R> {
fn build_internal<FE>(
self,
prover: &impl TxProver,
fee: Amount,
fee: U64Sum,
) -> Result<(Transaction, SaplingMetadata), Error<FE>> {
let consensus_branch_id = BranchId::for_height(&self.params, self.target_height);

Expand All @@ -338,9 +337,9 @@ impl<P: consensus::Parameters, R: RngCore> Builder<P, R> {
//

// After fees are accounted for, the value balance of the transaction must be zero.
let balance_after_fees = self.value_balance()? - fee;
let balance_after_fees = self.value_balance()? - I128Sum::from_sum(fee);

if balance_after_fees != Amount::zero() {
if balance_after_fees != ValueSum::zero() {
return Err(Error::InsufficientFunds(-balance_after_fees));
};

Expand Down Expand Up @@ -480,17 +479,16 @@ mod tests {
merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::Rseed,
transaction::{
components::amount::{Amount, DEFAULT_FEE, MAX_MONEY},
sapling::builder::{self as build_s},
transparent::builder::{self as build_t},
components::amount::{I128Sum, ValueSum, DEFAULT_FEE},
sapling::builder as build_s,
TransparentAddress,
},
zip32::ExtendedSpendingKey,
};

use super::{Builder, Error};

#[test]
/*#[test]
fn fails_on_overflow_output() {
let extsk = ExtendedSpendingKey::master(&[]);
let dfvk = extsk.to_diversifiable_full_viewing_key();
Expand All @@ -507,12 +505,12 @@ mod tests {
Some(ovk),
to,
zec(),
MAX_MONEY as u64 + 1,
MAX_MONEY + 1,
MemoBytes::empty()
),
Err(build_s::Error::InvalidAmount)
);
}
}*/

/// Generate ZEC asset type
fn zec() -> AssetType {
Expand Down Expand Up @@ -565,21 +563,6 @@ mod tests {
);
}

#[test]
fn fails_on_negative_transparent_output() {
let mut rng = OsRng;

let transparent_address = TransparentAddress(rng.gen::<[u8; 20]>());
let tx_height = TEST_NETWORK
.activation_height(NetworkUpgrade::MASP)
.unwrap();
let mut builder = Builder::new(TEST_NETWORK, tx_height);
assert_eq!(
builder.add_transparent_output(&transparent_address, zec(), -1,),
Err(build_t::Error::InvalidAmount)
);
}

#[test]
fn fails_on_negative_change() {
let mut rng = OsRng;
Expand All @@ -597,7 +580,9 @@ mod tests {
let builder = Builder::new(TEST_NETWORK, tx_height);
assert_eq!(
builder.mock_build(),
Err(Error::InsufficientFunds(DEFAULT_FEE.clone()))
Err(Error::InsufficientFunds(I128Sum::from_sum(
DEFAULT_FEE.clone()
)))
);
}

Expand All @@ -615,7 +600,8 @@ mod tests {
assert_eq!(
builder.mock_build(),
Err(Error::InsufficientFunds(
Amount::from_pair(zec(), 50000).unwrap() + &*DEFAULT_FEE
I128Sum::from_pair(zec(), 50000).unwrap()
+ &I128Sum::from_sum(DEFAULT_FEE.clone())
))
);
}
Expand All @@ -630,7 +616,8 @@ mod tests {
assert_eq!(
builder.mock_build(),
Err(Error::InsufficientFunds(
Amount::from_pair(zec(), 50000).unwrap() + &*DEFAULT_FEE
I128Sum::from_pair(zec(), 50000).unwrap()
+ &I128Sum::from_sum(DEFAULT_FEE.clone())
))
);
}
Expand Down Expand Up @@ -663,7 +650,7 @@ mod tests {
assert_eq!(
builder.mock_build(),
Err(Error::InsufficientFunds(
Amount::from_pair(zec(), 1).unwrap()
ValueSum::from_pair(zec(), 1).unwrap()
))
);
}
Expand Down
4 changes: 3 additions & 1 deletion masp_primitives/src/transaction/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ pub mod amount;
pub mod sapling;
pub mod transparent;
pub use self::{
amount::Amount,
amount::{
I128Sum, I16Sum, I32Sum, I64Sum, I8Sum, U128Sum, U16Sum, U32Sum, U64Sum, U8Sum, ValueSum,
},
sapling::{ConvertDescription, OutputDescription, SpendDescription},
transparent::{TxIn, TxOut},
};
Expand Down
Loading
Loading