|
1 | | -use chia_bls::{aggregate_verify_gt, hash_to_g2}; |
| 1 | +use chia_bls::{PublicKey, aggregate_verify_gt, hash_to_g2}; |
2 | 2 | use chia_consensus::{ |
3 | | - allocator::make_allocator, consensus_constants::ConsensusConstants, |
4 | | - owned_conditions::OwnedSpendBundleConditions, spendbundle_conditions::run_spendbundle, |
5 | | - validation_error::ErrorCode, |
| 3 | + allocator::make_allocator, |
| 4 | + conditions::{ |
| 5 | + ELIGIBLE_FOR_DEDUP, MempoolVisitor, ParseState, SpendBundleConditions, |
| 6 | + process_single_spend, validate_conditions, |
| 7 | + }, |
| 8 | + consensus_constants::ConsensusConstants, |
| 9 | + flags::COMPUTE_FINGERPRINT, |
| 10 | + owned_conditions::OwnedSpendBundleConditions, |
| 11 | + puzzle_fingerprint::compute_puzzle_fingerprint, |
| 12 | + run_block_generator::subtract_cost, |
| 13 | + solution_generator::calculate_generator_length, |
| 14 | + validation_error::{ErrorCode, ValidationErr}, |
6 | 15 | }; |
7 | | -use chia_protocol::SpendBundle; |
| 16 | +use chia_protocol::{Bytes, SpendBundle}; |
| 17 | +use chia_sdk_types::run_puzzle_with_cost; |
8 | 18 | use chia_sha2::Sha256; |
9 | | -use clvmr::LIMIT_HEAP; |
| 19 | +use clvm_utils::tree_hash; |
| 20 | +use clvmr::{Allocator, LIMIT_HEAP, reduction::Reduction, serde::node_from_bytes}; |
10 | 21 |
|
11 | 22 | // TODO: This function is copied here because WASM doesn't support std::time::Instant |
12 | 23 | // Should this be changed upstream? |
@@ -49,3 +60,68 @@ pub fn validate_clvm_and_signature( |
49 | 60 | // Collect results |
50 | 61 | Ok(conditions) |
51 | 62 | } |
| 63 | + |
| 64 | +// TODO: This function is copied here because the upstream doesn't support custom dialects, and |
| 65 | +// we want to use the debug dialect for testing Rue puzzles in the simulator. |
| 66 | +// Should this be changed upstream? |
| 67 | +#[allow(clippy::type_complexity)] |
| 68 | +pub fn run_spendbundle( |
| 69 | + a: &mut Allocator, |
| 70 | + spend_bundle: &SpendBundle, |
| 71 | + max_cost: u64, |
| 72 | + flags: u32, |
| 73 | + constants: &ConsensusConstants, |
| 74 | +) -> Result<(SpendBundleConditions, Vec<(PublicKey, Bytes)>), ValidationErr> { |
| 75 | + // below is an adapted version of the code from run_block_generators::run_block_generator2() |
| 76 | + // it assumes no block references are passed in |
| 77 | + let mut cost_left = max_cost; |
| 78 | + let mut ret = SpendBundleConditions::default(); |
| 79 | + let mut state = ParseState::default(); |
| 80 | + // We don't pay the size cost (nor execution cost) of being wrapped by a |
| 81 | + // quote (in solution_generator). |
| 82 | + let generator_length_without_quote = calculate_generator_length(&spend_bundle.coin_spends) - 2; |
| 83 | + |
| 84 | + let byte_cost = generator_length_without_quote as u64 * constants.cost_per_byte; |
| 85 | + subtract_cost(a, &mut cost_left, byte_cost)?; |
| 86 | + |
| 87 | + for coin_spend in &spend_bundle.coin_spends { |
| 88 | + // process the spend |
| 89 | + let puz = node_from_bytes(a, coin_spend.puzzle_reveal.as_slice())?; |
| 90 | + let sol = node_from_bytes(a, coin_spend.solution.as_slice())?; |
| 91 | + let parent = a.new_atom(coin_spend.coin.parent_coin_info.as_slice())?; |
| 92 | + let amount = a.new_number(coin_spend.coin.amount.into())?; |
| 93 | + let Reduction(clvm_cost, conditions) = run_puzzle_with_cost(a, puz, sol, cost_left, false)?; |
| 94 | + |
| 95 | + ret.execution_cost += clvm_cost; |
| 96 | + subtract_cost(a, &mut cost_left, clvm_cost)?; |
| 97 | + |
| 98 | + let buf = tree_hash(a, puz); |
| 99 | + if coin_spend.coin.puzzle_hash != buf.into() { |
| 100 | + return Err(ValidationErr(puz, ErrorCode::WrongPuzzleHash)); |
| 101 | + } |
| 102 | + let puzzle_hash = a.new_atom(&buf)?; |
| 103 | + let spend = process_single_spend::<MempoolVisitor>( |
| 104 | + a, |
| 105 | + &mut ret, |
| 106 | + &mut state, |
| 107 | + parent, |
| 108 | + puzzle_hash, |
| 109 | + amount, |
| 110 | + conditions, |
| 111 | + flags, |
| 112 | + &mut cost_left, |
| 113 | + clvm_cost, |
| 114 | + constants, |
| 115 | + )?; |
| 116 | + |
| 117 | + if (spend.flags & ELIGIBLE_FOR_DEDUP) != 0 && (flags & COMPUTE_FINGERPRINT) != 0 { |
| 118 | + spend.fingerprint = compute_puzzle_fingerprint(a, conditions)?; |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + validate_conditions(a, &ret, &state, a.nil(), flags)?; |
| 123 | + |
| 124 | + assert!(max_cost >= cost_left); |
| 125 | + ret.cost = max_cost - cost_left; |
| 126 | + Ok((ret, state.pkm_pairs)) |
| 127 | +} |
0 commit comments