Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 28 additions & 13 deletions pallas-validate/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,25 @@ pub fn empty_value() -> Value {
Value::Multiasset(0, std::collections::BTreeMap::new())
}

fn add_lovelace(first: Coin, second: Coin, err: &ValidationError) -> Result<Coin, ValidationError> {
first.checked_add(second).ok_or_else(|| err.clone())
}

pub fn add_values(
first: &Value,
second: &Value,
err: &ValidationError,
) -> Result<Value, ValidationError> {
match (first, second) {
(Value::Coin(f), Value::Coin(s)) => Ok(Value::Coin(f + s)),
(Value::Multiasset(f, fma), Value::Coin(s)) => Ok(Value::Multiasset(f + s, fma.clone())),
(Value::Coin(f), Value::Multiasset(s, sma)) => Ok(Value::Multiasset(f + s, sma.clone())),
(Value::Coin(f), Value::Coin(s)) => Ok(Value::Coin(add_lovelace(*f, *s, err)?)),
(Value::Multiasset(f, fma), Value::Coin(s)) => {
Ok(Value::Multiasset(add_lovelace(*f, *s, err)?, fma.clone()))
}
(Value::Coin(f), Value::Multiasset(s, sma)) => {
Ok(Value::Multiasset(add_lovelace(*f, *s, err)?, sma.clone()))
}
(Value::Multiasset(f, fma), Value::Multiasset(s, sma)) => Ok(Value::Multiasset(
f + s,
add_lovelace(*f, *s, err)?,
coerce_to_coin(
&add_multiasset_values(&coerce_to_i64(fma), &coerce_to_i64(sma)),
err,
Expand All @@ -153,16 +161,20 @@ pub fn conway_add_values(
err: &ValidationError,
) -> Result<ConwayValue, ValidationError> {
match (first, second) {
(ConwayValue::Coin(f), ConwayValue::Coin(s)) => Ok(ConwayValue::Coin(f + s)),
(ConwayValue::Multiasset(f, fma), ConwayValue::Coin(s)) => {
Ok(ConwayValue::Multiasset(f + s, fma.clone()))
}
(ConwayValue::Coin(f), ConwayValue::Multiasset(s, sma)) => {
Ok(ConwayValue::Multiasset(f + s, sma.clone()))
(ConwayValue::Coin(f), ConwayValue::Coin(s)) => {
Ok(ConwayValue::Coin(add_lovelace(*f, *s, err)?))
}
(ConwayValue::Multiasset(f, fma), ConwayValue::Coin(s)) => Ok(ConwayValue::Multiasset(
add_lovelace(*f, *s, err)?,
fma.clone(),
)),
(ConwayValue::Coin(f), ConwayValue::Multiasset(s, sma)) => Ok(ConwayValue::Multiasset(
add_lovelace(*f, *s, err)?,
sma.clone(),
)),
(ConwayValue::Multiasset(f, fma), ConwayValue::Multiasset(s, sma)) => {
Ok(ConwayValue::Multiasset(
f + s,
add_lovelace(*f, *s, err)?,
conway_coerce_to_coin(
&conway_add_multiasset_values(&coerce_to_u64(fma), &coerce_to_u64(sma)),
err,
Expand Down Expand Up @@ -380,13 +392,16 @@ fn coerce_to_u64(value: &ConwayMultiasset<PositiveCoin>) -> ConwayMultiasset<u64

fn coerce_to_coin(
value: &Multiasset<i64>,
_err: &ValidationError,
err: &ValidationError,
) -> Result<Multiasset<Coin>, ValidationError> {
let mut res: Vec<(PolicyId, _)> = Vec::new();
for (policy, assets) in value.iter() {
let mut aa: Vec<(AssetName, Coin)> = Vec::new();
for (asset_name, amount) in assets.iter() {
aa.push((asset_name.clone(), *amount as u64));
aa.push((
asset_name.clone(),
u64::try_from(*amount).map_err(|_| err.clone())?,
));
}
res.push((*policy, aa.into_iter().collect()));
}
Expand Down
71 changes: 71 additions & 0 deletions pallas-validate/tests/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::collections::BTreeMap;

use pallas_primitives::{
AssetName, PolicyId,
alonzo::{Multiasset, Value},
conway::Value as ConwayValue,
};
use pallas_validate::utils::{
PostAlonzoError, ValidationError, add_minted_value, add_values, conway_add_values,
};

fn single_asset<A>(amount: A) -> Multiasset<A> {
let policy = PolicyId::from([0u8; 28]);
let asset_name = AssetName::from(b"asset".to_vec());

let mut assets = BTreeMap::new();
assets.insert(asset_name, amount);

let mut multiasset = BTreeMap::new();
multiasset.insert(policy, assets);
multiasset
}

#[test]
fn add_minted_value_rejects_burn_of_missing_asset() {
let err = ValidationError::PostAlonzo(PostAlonzoError::NegativeValue);

let result = add_minted_value(&Value::Coin(0), &single_asset(-1), &err);

assert!(matches!(
result,
Err(ValidationError::PostAlonzo(PostAlonzoError::NegativeValue))
));
}

#[test]
fn add_minted_value_rejects_burn_below_zero() {
let err = ValidationError::PostAlonzo(PostAlonzoError::NegativeValue);
let base = Value::Multiasset(0, single_asset(1));

let result = add_minted_value(&base, &single_asset(-2), &err);

assert!(matches!(
result,
Err(ValidationError::PostAlonzo(PostAlonzoError::NegativeValue))
));
}

#[test]
fn add_values_rejects_lovelace_overflow() {
let err = ValidationError::PostAlonzo(PostAlonzoError::NegativeValue);

let result = add_values(&Value::Coin(u64::MAX), &Value::Coin(1), &err);

assert!(matches!(
result,
Err(ValidationError::PostAlonzo(PostAlonzoError::NegativeValue))
));
}

#[test]
fn conway_add_values_rejects_lovelace_overflow() {
let err = ValidationError::PostAlonzo(PostAlonzoError::NegativeValue);

let result = conway_add_values(&ConwayValue::Coin(u64::MAX), &ConwayValue::Coin(1), &err);

assert!(matches!(
result,
Err(ValidationError::PostAlonzo(PostAlonzoError::NegativeValue))
));
}
Loading