Skip to content

Commit

Permalink
check minting_coin failure as well as asserting that the true fee is …
Browse files Browse the repository at this point in the history
…>= reserve_fee, in run_generator
  • Loading branch information
arvidn committed Jan 9, 2023
1 parent 0812a9e commit 7e71671
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 11 deletions.
74 changes: 68 additions & 6 deletions src/gen/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ struct ParseState {
// compute the coin ID, and stick it in this set. It's reference counted
// since it may also be referenced by announcements
spent_coins: HashSet<Arc<Bytes32>>,

// the sum of all values of all spent coins
removal_amount: u128,

// the sum of all amounts of CREATE_COIN conditions
addition_amount: u128,
}

impl ParseState {
Expand All @@ -377,6 +383,8 @@ impl ParseState {
assert_coin: HashSet::new(),
assert_puzzle: HashSet::new(),
spent_coins: HashSet::new(),
removal_amount: 0,
addition_amount: 0,
}
}
}
Expand Down Expand Up @@ -404,6 +412,8 @@ fn parse_spend_conditions(
return Err(ValidationErr(spend, ErrorCode::DoubleSpend));
}

state.removal_amount += my_amount as u128;

let mut spend = Spend {
coin_id,
puzzle_hash,
Expand Down Expand Up @@ -466,6 +476,7 @@ fn parse_spend_conditions(
if !spend.create_coin.insert(new_coin) {
return Err(ValidationErr(c, ErrorCode::DuplicateOutput));
}
state.addition_amount += amount as u128;
}
Condition::AssertSecondsRelative(s) => {
// keep the most strict condition. i.e. the highest limit
Expand Down Expand Up @@ -564,6 +575,17 @@ pub fn parse_spends(
parse_spend_conditions(&mut ret, a, &mut state, spend, flags, &mut cost_left)?;
}

if state.removal_amount < state.addition_amount {
// The sum of removal amounts must not be less than the sum of addition
// amounts
return Err(ValidationErr(spends, ErrorCode::MintingCoin));
}

if state.removal_amount - state.addition_amount < ret.reserve_fee as u128 {
// the actual fee is lower than the reserved fee
return Err(ValidationErr(spends, ErrorCode::ReserveFeeConditionFailed));
}

// check all the assert announcements
// if there are no asserts, there is no need to hash all the announcements
if !state.assert_coin.is_empty() {
Expand Down Expand Up @@ -1342,9 +1364,36 @@ fn test_single_reserve_fee_extra_arg_mempool() {
fn test_reserve_fee_exceed_max() {
// RESERVE_FEE
// 0xfffffffffffffff0 + 0x10 just exceeds u64::MAX, which is higher than
// allowed
// allowed. Note that we need two coins to provide the removals to cover the
// reserve fee
// "((({h1} ({h2} (123 (((60 ({msg1} ))) (({h2} ({h2} (123 (((61 ({c11} )))))")
assert_eq!(
cond_test("((({h1} ({h2} (0x00ffffffffffffffff (((52 (0x00fffffffffffffff0 ))) (({h2} ({h1} (0x00ffffff (((52 (0x10 )))))")
.unwrap_err()
.1,
ErrorCode::ReserveFeeConditionFailed
);
}

#[test]
fn test_reserve_fee_insufficient_spends() {
// RESERVE_FEE
// We spend a coin with amount 123 but reserve fee 124
assert_eq!(
cond_test("((({h1} ({h2} (123 (((52 (124 ) ))))")
.unwrap_err()
.1,
ErrorCode::ReserveFeeConditionFailed
);
}

#[test]
fn test_reserve_fee_insufficient_fee() {
// RESERVE_FEE
// We spend a coin with amount 123 and create a coin worth 24 and reserve fee
// of 100 (which adds up to 124, i.e. not enough fee)
assert_eq!(
cond_test("((({h1} ({h2} (123 (((52 (0x00fffffffffffffff0 ) ((52 (0x10 ) ))))")
cond_test("((({h1} ({h2} (123 (((52 (100 ) ((51 ({h2} (24 )) )))")
.unwrap_err()
.1,
ErrorCode::ReserveFeeConditionFailed
Expand All @@ -1355,12 +1404,12 @@ fn test_reserve_fee_exceed_max() {
fn test_multiple_reserve_fee() {
// RESERVE_FEE
let (a, conds) =
cond_test("((({h1} ({h2} (123 (((52 (100 ) ((52 (25 ) ((52 (50 )))))").unwrap();
cond_test("((({h1} ({h2} (175 (((52 (100 ) ((52 (25 ) ((52 (50 )))))").unwrap();

assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 1);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 175));
assert_eq!(a.atom(spend.puzzle_hash), H2);
assert_eq!(spend.flags, ELIGIBLE_FOR_DEDUP);

Expand Down Expand Up @@ -2023,12 +2072,13 @@ fn test_single_create_coin() {
fn test_create_coin_max_amount() {
// CREATE_COIN
let (a, conds) =
cond_test("((({h1} ({h2} (123 (((51 ({h2} (0x00ffffffffffffffff )))))").unwrap();
cond_test("((({h1} ({h2} (0x00ffffffffffffffff (((51 ({h2} (0x00ffffffffffffffff )))))")
.unwrap();

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 0xffffffffffffffff));
assert_eq!(a.atom(spend.puzzle_hash), H2);
assert_eq!(spend.create_coin.len(), 1);
for c in &spend.create_coin {
Expand All @@ -2039,6 +2089,18 @@ fn test_create_coin_max_amount() {
assert_eq!(spend.flags, ELIGIBLE_FOR_DEDUP);
}

#[test]
fn test_minting_coin() {
// CREATE_COIN
// we spend a coin with value 123 but create a coin with value 124
assert_eq!(
cond_test("((({h1} ({h2} (123 (((51 ({h2} (124 )))))")
.unwrap_err()
.1,
ErrorCode::MintingCoin
);
}

#[test]
fn test_create_coin_amount_exceeds_max() {
// CREATE_COIN
Expand Down
2 changes: 2 additions & 0 deletions src/gen/validation_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub enum ErrorCode {
DuplicateOutput,
DoubleSpend,
CostExceeded,
MintingCoin,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -69,6 +70,7 @@ impl From<ErrorCode> for u32 {
ErrorCode::DuplicateOutput => 4,
ErrorCode::DoubleSpend => 5,
ErrorCode::CostExceeded => 23,
ErrorCode::MintingCoin => 20,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/generators/duplicate-create-coin.clvm
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (a (q 2 2 (c 2 (c (q 51 "abababababababababababababababab" 1) (c 5 ())))) (c (q 2 (i 11 (q 4 5 (a 2 (c 2 (c 5 (c (- 11 (q . 1)) ()))))) ()) 1) (q 600000))) 123 (() (q . ())))))
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (a (q 2 2 (c 2 (c (q 51 "abababababababababababababababab" 1) (c 5 ())))) (c (q 2 (i 11 (q 4 5 (a 2 (c 2 (c 5 (c (- 11 (q . 1)) ()))))) ()) 1) (q 600000))) 600000 (() (q . ())))))
FAILED: 4
4 changes: 2 additions & 2 deletions tests/generators/many-create-coin.clvm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (a (q 2 6 (c 2 (c (q 51 "abababababababababababababababab") (c 5 ())))) (c (q (a (i 5 (q 4 9 (a 4 (c 2 (c 13 (c 11 ()))))) (q 4 11 ())) 1) 2 (i 11 (q 4 (a 4 (c 2 (c 5 (c 11 ())))) (a 6 (c 2 (c 5 (c (- 11 (q . 1)) ()))))) ()) 1) (q 6094))) 123 (() (q . ())))))
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (a (q 2 6 (c 2 (c (q 51 "abababababababababababababababab") (c 5 ())))) (c (q (a (i 5 (q 4 9 (a 4 (c 2 (c 13 (c 11 ()))))) (q 4 11 ())) 1) 2 (i 11 (q 4 (a 4 (c 2 (c 5 (c 11 ())))) (a 6 (c 2 (c 5 (c (- 11 (q . 1)) ()))))) ()) 1) (q 6094))) 18605000 (() (q . ())))))
SPENDS:
- coin id: 393f42643b9593eab01a327ea2cf50494dd60c458936438b2f6db8ad07e48b41 ph: c69b40b3edfc197e6b6ec325d3f43f01a7c30b99d331fbc30c24a7a571d0a094
- coin id: 2a6991d3bfd05e5286e95ebdbb53978211dad6f00a2a50fc19995c1bfc933c11 ph: c69b40b3edfc197e6b6ec325d3f43f01a7c30b99d331fbc30c24a7a571d0a094
CREATE_COIN: ph: 6162616261626162616261626162616261626162616261626162616261626162 amount: 1
CREATE_COIN: ph: 6162616261626162616261626162616261626162616261626162616261626162 amount: 2
CREATE_COIN: ph: 6162616261626162616261626162616261626162616261626162616261626162 amount: 3
Expand Down
4 changes: 2 additions & 2 deletions tests/generators/multiple-reserve-fee.clvm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (q (52 100) (52 100) (52 100) ) 123 (() (q . ())))))
(q ((0x0101010101010101010101010101010101010101010101010101010101010101 (q (52 100) (52 100) (52 100) ) 400 (() (q . ())))))
RESERVE_FEE: 300
SPENDS:
- coin id: b55adcc290328357beb44e3a9a75793238438a9c784152f0b68c32e6953872b7 ph: 5d1f30b1fd2fdca436fa948c0c19fcc7986b911e5debfe137e471e5fa6e80fe3
- coin id: 93b602365f9c9f1b503f73ce316254a2753a3d9d1a1da54b82ad40c9c8152463 ph: 5d1f30b1fd2fdca436fa948c0c19fcc7986b911e5debfe137e471e5fa6e80fe3
cost (clvm + conditions): 35784

0 comments on commit 7e71671

Please sign in to comment.