Skip to content

Commit

Permalink
Include the cost of the whole spend in get_conditions_from_spendbundl…
Browse files Browse the repository at this point in the history
…e's return value.
  • Loading branch information
AmineKhaldi committed Aug 27, 2024
1 parent e032f9d commit bced560
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
65 changes: 54 additions & 11 deletions crates/chia-consensus/src/spendbundle_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::gen::conditions::{
};
use crate::gen::flags::MEMPOOL_MODE;
use crate::gen::run_block_generator::subtract_cost;
use crate::gen::solution_generator::solution_generator;
use crate::gen::validation_error::ValidationErr;
use crate::spendbundle_validation::get_flags_for_height_and_constants;
use chia_protocol::SpendBundle;
Expand All @@ -30,11 +31,13 @@ pub fn get_conditions_from_spendbundle(
let mut ret = SpendBundleConditions::default();
let mut state = ParseState::default();

let mut spends_info = Vec::new();
for coin_spend in &spend_bundle.coin_spends {
let byte_cost = (coin_spend.puzzle_reveal.len() + coin_spend.solution.len()) as u64
* constants.cost_per_byte;

subtract_cost(a, &mut cost_left, byte_cost)?;
spends_info.push((
coin_spend.coin,
&coin_spend.puzzle_reveal,
&coin_spend.solution,
));

// process the spend
let puz = node_from_bytes(a, coin_spend.puzzle_reveal.as_slice())?;
Expand All @@ -61,6 +64,10 @@ pub fn get_conditions_from_spendbundle(
)?;
}

let spend_generator_length = solution_generator(spends_info)?.len();
let byte_cost = spend_generator_length as u64 * constants.cost_per_byte;
subtract_cost(a, &mut cost_left, byte_cost)?;

validate_conditions(a, &ret, state, a.nil(), flags)?;
assert!(max_cost >= cost_left);
ret.cost = max_cost - cost_left;
Expand All @@ -74,6 +81,7 @@ mod tests {
use super::*;
use crate::allocator::make_allocator;
use crate::gen::conditions::{ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF};
use crate::gen::run_block_generator::run_block_generator2;
use chia_bls::Signature;
use chia_protocol::CoinSpend;
use chia_traits::Streamable;
Expand All @@ -82,8 +90,8 @@ mod tests {
use std::fs::read;

#[rstest]
#[case("3000253", 8, 2, 46_860_870)]
#[case("1000101", 34, 15, 231_687_677)]
#[case("3000253", 8, 2, 51_240_870)]
#[case("1000101", 34, 15, 250_107_677)]
fn test_get_conditions_from_spendbundle(
#[case] filename: &str,
#[case] spends: usize,
Expand All @@ -108,6 +116,32 @@ mod tests {
.fold(0, |sum, spend| sum + spend.create_coin.len());
assert_eq!(create_coins, additions);
assert_eq!(conditions.cost, cost);
// Generate a block with the same spend bundle and compare its cost
let program_spends: Vec<_> = bundle
.coin_spends
.iter()
.map(|coin_spend| {
(
coin_spend.coin,
&coin_spend.puzzle_reveal,
&coin_spend.solution,
)
})
.collect();
let program = solution_generator(program_spends).expect("solution_generator failed");
let blocks: &[&[u8]] = &[];
let block_conds = run_block_generator2::<_, MempoolVisitor, _>(
&mut a,
program.as_slice(),
blocks,
11_000_000_000,
MEMPOOL_MODE,
&TEST_CONSTANTS,
)
.expect("run_block_generator2 failed");
const QUOTE_COST: u64 = 20;
// run_block_generator2 wraps the probram in a quote
assert_eq!(conditions.cost, block_conds.cost - QUOTE_COST);
}

#[rstest]
Expand All @@ -117,7 +151,7 @@ mod tests {
#[case] filename: &str,
#[values(0, 1, 1_000_000, 5_000_000)] height: u32,
) {
let cost = 76_825_866;
let cost = 77_365_866;
let spend = CoinSpend::from_bytes(
&read(format!("../../ff-tests/{filename}.spend")).expect("read file"),
)
Expand Down Expand Up @@ -306,12 +340,21 @@ mod tests {
// block will likely be smaller because the compression makes it
// smaller.
let block_byte_cost = generator_buffer.len() as u64 * TEST_CONSTANTS.cost_per_byte;
let bundle_byte_cost = bundle
let program_spends: Vec<_> = bundle
.coin_spends
.iter()
.map(|s| s.puzzle_reveal.len() + s.solution.len())
.sum::<usize>() as u64
* TEST_CONSTANTS.cost_per_byte;
.map(|coin_spend| {
(
coin_spend.coin,
&coin_spend.puzzle_reveal,
&coin_spend.solution,
)
})
.collect();
let spend_generator_length = solution_generator(program_spends)
.expect("solution_generator failed")
.len();
let bundle_byte_cost = spend_generator_length as u64 * TEST_CONSTANTS.cost_per_byte;
println!("block_cost: {block_cost} bytes: {block_byte_cost}");
println!("bundle_cost: {} bytes: {bundle_byte_cost}", conditions.cost);
assert!(conditions.cost - bundle_byte_cost <= block_cost - block_byte_cost);
Expand Down
15 changes: 9 additions & 6 deletions crates/chia-consensus/src/spendbundle_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,15 @@ ff01\
coin_spends,
aggregated_signature: G2Element::default(),
};
let result = validate_clvm_and_signature(&spend_bundle, 5526552044, &TEST_CONSTANTS, 236);
let Ok((conds, _, _)) = result else {
panic!("failed");
};
assert_eq!(conds.cost, 5526552044);
let result = validate_clvm_and_signature(&spend_bundle, 5526552043, &TEST_CONSTANTS, 236);
let expected_cost = 5_527_140_044;
let max_cost = expected_cost;
let test_height = 236;
let (conds, _, _) =
validate_clvm_and_signature(&spend_bundle, max_cost, &TEST_CONSTANTS, test_height)
.expect("validate_clvm_and_signature failed");
assert_eq!(conds.cost, expected_cost);
let result =
validate_clvm_and_signature(&spend_bundle, max_cost - 1, &TEST_CONSTANTS, test_height);
assert!(matches!(result, Err(ErrorCode::CostExceeded)));
}

Expand Down

0 comments on commit bced560

Please sign in to comment.