Skip to content

Commit

Permalink
relax coin amount in fast-forward logic
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Dec 12, 2023
1 parent e3ed6a4 commit aa1269f
Showing 1 changed file with 8 additions and 40 deletions.
48 changes: 8 additions & 40 deletions src/fast_forward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ pub fn fast_forward_singleton(
return Err(Error::CoinAmountEven);
}

// in the case of fast-forwarding a spend, we require the amount to remain
// unchanged
if coin.amount != new_coin.amount || coin.amount != new_parent.amount {
return Err(Error::CoinAmountMismatch);
}

// we can only fast-forward spends of singletons whose puzzle hash doesn't
// change
if coin.puzzle_hash != new_parent.puzzle_hash || coin.puzzle_hash != new_coin.puzzle_hash {
Expand All @@ -126,14 +120,6 @@ pub fn fast_forward_singleton(
return Err(Error::NotSingletonModHash);
}

// we can only fast-forward if the coin amount stay the same
// this is to minimize the risk of producing an invalid spend, after
// fast-forward. e.g. we might end up attempting to spend more that the
// amount of the coin
if coin.amount != new_solution.lineage_proof.parent_amount || coin.amount != new_parent.amount {
return Err(Error::CoinAmountMismatch);
}

// given the parent's parent, the parent's inner puzzle and parent's amount,
// we can compute the hash of the curried inner puzzle for our parent coin
let parent_puzzle_hash = curry_and_treehash(
Expand Down Expand Up @@ -169,6 +155,7 @@ pub fn fast_forward_singleton(

// update the solution to use the new parent coin's information
new_solution.lineage_proof.parent_parent_coin_id = new_parent.parent_coin_info;
new_solution.amount = new_coin.amount;

let expected_new_parent = new_parent.coin_id();

Expand Down Expand Up @@ -206,6 +193,7 @@ mod tests {
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)]
new_parents_parent: &str,
#[values(0, 1, 3, 5)] new_amount: u64,
) {
let spend_bytes = fs::read(format!("ff-tests/{spend_file}.spend")).expect("read file");
let spend = CoinSpend::from_bytes(&spend_bytes).expect("parse CoinSpend");
Expand All @@ -225,7 +213,11 @@ mod tests {
let new_coin = Coin {
parent_coin_info: new_parent_coin.coin_id().into(),
puzzle_hash,
amount: spend.coin.amount,
amount: if new_amount == 0 {
spend.coin.amount
} else {
new_amount
},
};

// perform fast-forward
Expand Down Expand Up @@ -345,30 +337,6 @@ mod tests {
);
}

#[test]
fn test_amount_mismatch() {
run_ff_test(
|_a, coin, _new_coin, _new_parent, _puzzle, _solution| {
coin.amount = 3;
},
Error::CoinAmountMismatch,
);

run_ff_test(
|_a, _coin, new_coin, _new_parent, _puzzle, _solution| {
new_coin.amount = 3;
},
Error::CoinAmountMismatch,
);

run_ff_test(
|_a, _coin, _new_coin, new_parent, _puzzle, _solution| {
new_parent.amount = 3;
},
Error::CoinAmountMismatch,
);
}

fn parse_solution(a: &mut Allocator, solution: &[u8]) -> SingletonSolution<NodePtr> {
let new_solution = node_from_bytes(a, solution).expect("parse solution");
SingletonSolution::from_clvm(a, new_solution).expect("parse solution")
Expand Down Expand Up @@ -423,7 +391,7 @@ mod tests {

*solution = serialize_solution(a, &new_solution);
},
Error::CoinAmountMismatch,
Error::ParentCoinMismatch,
);
}

Expand Down

0 comments on commit aa1269f

Please sign in to comment.