Skip to content

Commit

Permalink
Merge pull request #142 from Chia-Network/addition_removal_amounts
Browse files Browse the repository at this point in the history
additions_amount and removals_amounts
  • Loading branch information
arvidn authored Feb 28, 2023
2 parents 0e43677 + 184ec1b commit 584e16d
Show file tree
Hide file tree
Showing 27 changed files with 147 additions and 66 deletions.
13 changes: 2 additions & 11 deletions fuzz/fuzz_targets/parse-conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,7 @@ fuzz_target!(|data: &[u8]| {
let mut a = Allocator::new();
let input = make_tree(&mut a, &mut BitCursor::new(data), false);

let mut ret = SpendBundleConditions {
spends: Vec::new(),
reserve_fee: 0,
height_absolute: 0,
seconds_absolute: 0,
before_height_absolute: None,
before_seconds_absolute: None,
agg_sig_unsafe: Vec::new(),
cost: 0,
};
let mut ret = SpendBundleConditions::default();

let amount = 1337_u64;
let parent_id: Bytes32 = b"12345678901234567890123456789012".into();
Expand All @@ -40,7 +31,7 @@ fuzz_target!(|data: &[u8]| {
.into(),
);

let mut state = ParseState::new();
let mut state = ParseState::default();

for flags in &[0, ENABLE_ASSERT_BEFORE | COND_ARGS_NIL, ENABLE_ASSERT_BEFORE | STRICT_ARGS_COUNT, NO_UNKNOWN_CONDS] {

Expand Down
108 changes: 68 additions & 40 deletions src/gen/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ pub struct Spend {
// spend bundle level, like reserve_fee and absolute time locks. Other
// conditions are per spend, like relative time-locks and create coins (because
// they have an implied parent coin ID).
#[derive(Debug)]
#[derive(Debug, Default)]
pub struct SpendBundleConditions {
pub spends: Vec<Spend>,
// conditions
Expand All @@ -406,8 +406,15 @@ pub struct SpendBundleConditions {
// run_block_generator() will include CLVM cost and byte cost (making this
// the total cost)
pub cost: u64,

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

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

#[derive(Default)]
pub struct ParseState {
// hashing of the announcements is deferred until parsing is complete. This
// means less work up-front, in case parsing/validation fails
Expand Down Expand Up @@ -437,29 +444,6 @@ pub struct ParseState {
// there may still be duplicates here. We defer creating a hash set of the
// actual hashes until the end, and only if there are any puzzle assertions
spent_puzzles: HashSet<NodePtr>,

// 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 {
pub fn new() -> ParseState {
ParseState {
announce_coin: HashSet::new(),
announce_puzzle: HashSet::new(),
assert_coin: HashSet::new(),
assert_puzzle: HashSet::new(),
assert_concurrent_spend: HashSet::new(),
assert_concurrent_puzzle: HashSet::new(),
spent_coins: HashSet::new(),
spent_puzzles: HashSet::new(),
removal_amount: 0,
addition_amount: 0,
}
}
}

pub(crate) fn parse_single_spend(
Expand Down Expand Up @@ -487,7 +471,7 @@ pub(crate) fn parse_single_spend(

state.spent_puzzles.insert(puzzle_hash);

state.removal_amount += my_amount as u128;
ret.removal_amount += my_amount as u128;

let coin_spend = Spend {
parent_id,
Expand Down Expand Up @@ -567,7 +551,7 @@ pub fn parse_conditions(
if !spend.create_coin.insert(new_coin) {
return Err(ValidationErr(c, ErrorCode::DuplicateOutput));
}
state.addition_amount += amount as u128;
ret.addition_amount += amount as u128;
}
Condition::AssertSecondsRelative(s) => {
// keep the most strict condition. i.e. the highest limit
Expand Down Expand Up @@ -722,18 +706,8 @@ pub fn parse_spends(
max_cost: Cost,
flags: u32,
) -> Result<SpendBundleConditions, ValidationErr> {
let mut ret = SpendBundleConditions {
spends: Vec::new(),
reserve_fee: 0,
height_absolute: 0,
seconds_absolute: 0,
before_height_absolute: None,
before_seconds_absolute: None,
agg_sig_unsafe: Vec::new(),
cost: 0,
};

let mut state = ParseState::new();
let mut ret = SpendBundleConditions::default();
let mut state = ParseState::default();

let mut cost_left = max_cost;

Expand All @@ -748,13 +722,13 @@ pub fn parse_spends(
parse_single_spend(&mut ret, a, &mut state, spend, flags, &mut cost_left)?;
}

if state.removal_amount < state.addition_amount {
if ret.removal_amount < ret.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 {
if ret.removal_amount - ret.addition_amount < ret.reserve_fee as u128 {
// the actual fee is lower than the reserved fee
return Err(ValidationErr(spends, ErrorCode::ReserveFeeConditionFailed));
}
Expand Down Expand Up @@ -1942,6 +1916,8 @@ fn test_multiple_assert_my_puzzle_hash() {

assert_eq!(conds.cost, 0);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -1978,6 +1954,8 @@ fn test_single_create_coin() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -1999,6 +1977,8 @@ fn test_create_coin_max_amount() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 0xffffffffffffffff);
assert_eq!(conds.addition_amount, 0xffffffffffffffff);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 0xffffffffffffffff));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2063,6 +2043,8 @@ fn test_create_coin_with_hint() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2084,6 +2066,8 @@ fn test_create_coin_extra_arg() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2103,6 +2087,8 @@ fn test_create_coin_with_multiple_hints() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2123,6 +2109,8 @@ fn test_create_coin_with_hint_as_atom() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2142,6 +2130,8 @@ fn test_create_coin_with_invalid_hint_as_terminator() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2173,6 +2163,8 @@ fn test_create_coin_with_short_hint() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2193,6 +2185,8 @@ fn test_create_coin_with_long_hint() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2214,6 +2208,8 @@ fn test_create_coin_with_pair_hint() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2235,6 +2231,8 @@ fn test_create_coin_with_cons_hint() {

assert_eq!(conds.cost, CREATE_COIN_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2255,6 +2253,8 @@ fn test_multiple_create_coin() {

assert_eq!(conds.cost, CREATE_COIN_COST * 2);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 42 + 43);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2325,6 +2325,8 @@ fn test_single_agg_sig_me() {

assert_eq!(conds.cost, AGG_SIG_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand All @@ -2347,6 +2349,8 @@ fn test_duplicate_agg_sig_me() {

assert_eq!(conds.cost, AGG_SIG_COST * 2);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2421,6 +2425,8 @@ fn test_single_agg_sig_unsafe() {

assert_eq!(conds.cost, AGG_SIG_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2465,6 +2471,8 @@ fn test_agg_sig_unsafe_invalid_terminator() {

assert_eq!(conds.cost, AGG_SIG_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2500,6 +2508,8 @@ fn test_agg_sig_me_invalid_terminator() {

assert_eq!(conds.cost, AGG_SIG_COST);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2537,6 +2547,8 @@ fn test_duplicate_agg_sig_unsafe() {

assert_eq!(conds.cost, AGG_SIG_COST * 2);
assert_eq!(conds.spends.len(), 1);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);
let spend = &conds.spends[0];
assert_eq!(*spend.coin_id, test_coin_id(H1, H2, 123));
assert_eq!(a.atom(spend.puzzle_hash), H2);
Expand Down Expand Up @@ -2664,6 +2676,8 @@ fn test_always_true() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);

// there is one spend
assert_eq!(conds.spends.len(), 1);
Expand All @@ -2686,6 +2700,8 @@ fn test_always_true_with_arg() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);

// there is one spend
assert_eq!(conds.spends.len(), 1);
Expand Down Expand Up @@ -2732,6 +2748,8 @@ fn test_concurrent_spend() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 246);
assert_eq!(conds.addition_amount, 0);

// there are two spends
assert_eq!(conds.spends.len(), 2);
Expand Down Expand Up @@ -2809,6 +2827,8 @@ fn test_assert_concurrent_spend_self() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);

// there are two spends
assert_eq!(conds.spends.len(), 1);
Expand Down Expand Up @@ -2855,6 +2875,8 @@ fn test_concurrent_puzzle() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 246);
assert_eq!(conds.addition_amount, 0);

// there are two spends
assert_eq!(conds.spends.len(), 2);
Expand Down Expand Up @@ -2931,6 +2953,8 @@ fn test_assert_concurrent_puzzle_self() {
assert_eq!(conds.height_absolute, 0);
assert_eq!(conds.seconds_absolute, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);

// there are two spends
assert_eq!(conds.spends.len(), 1);
Expand Down Expand Up @@ -3035,6 +3059,8 @@ fn test_impossible_constraints_single_spend(
assert_eq!(conds.agg_sig_unsafe.len(), 0);
assert_eq!(conds.reserve_fee, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 123);
assert_eq!(conds.addition_amount, 0);

assert_eq!(conds.spends.len(), 1);
let spend = &conds.spends[0];
Expand Down Expand Up @@ -3131,6 +3157,8 @@ fn test_impossible_constraints_separate_spends(
assert_eq!(conds.agg_sig_unsafe.len(), 0);
assert_eq!(conds.reserve_fee, 0);
assert_eq!(conds.cost, 0);
assert_eq!(conds.removal_amount, 246);
assert_eq!(conds.addition_amount, 0);

assert_eq!(conds.spends.len(), 2);
let spend = &conds.spends[0];
Expand Down
12 changes: 3 additions & 9 deletions src/gen/run_puzzle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,10 @@ pub fn run_puzzle(
let Reduction(clvm_cost, conditions) = run_program(a, &dialect, puzzle, solution, max_cost)?;

let mut ret = SpendBundleConditions {
spends: Vec::new(),
reserve_fee: 0,
height_absolute: 0,
seconds_absolute: 0,
before_height_absolute: None,
before_seconds_absolute: None,
agg_sig_unsafe: Vec::new(),
cost: 0,
removal_amount: amount as u128,
..Default::default()
};
let mut state = ParseState::new();
let mut state = ParseState::default();

let puzzle_hash = tree_hash(a, puzzle);
let coin_id = Arc::<Bytes32>::new(
Expand Down
Loading

0 comments on commit 584e16d

Please sign in to comment.