From c034e4cb1678eae0de6939b6df3a83c899f3451f Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Mon, 3 Jun 2024 18:56:55 +0100 Subject: [PATCH] remove calls to run_block_generator in get_npc --- .../src/gen/run_block_generator.rs | 2 +- .../src/multiprocess_validation.rs | 10 +- crates/chia-consensus/src/npc_result.rs | 98 ++++++++++++------- 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/crates/chia-consensus/src/gen/run_block_generator.rs b/crates/chia-consensus/src/gen/run_block_generator.rs index d48db1b47..4fb0bdf5c 100644 --- a/crates/chia-consensus/src/gen/run_block_generator.rs +++ b/crates/chia-consensus/src/gen/run_block_generator.rs @@ -14,7 +14,7 @@ use clvmr::run_program::run_program; use clvmr::serde::{node_from_bytes, node_from_bytes_backrefs, node_from_bytes_backrefs_record}; use std::collections::{HashMap, HashSet}; -fn subtract_cost(a: &Allocator, cost_left: &mut Cost, subtract: Cost) -> Result<(), ValidationErr> { +pub fn subtract_cost(a: &Allocator, cost_left: &mut Cost, subtract: Cost) -> Result<(), ValidationErr> { if subtract > *cost_left { Err(ValidationErr(a.nil(), ErrorCode::CostExceeded)) } else { diff --git a/crates/chia-consensus/src/multiprocess_validation.rs b/crates/chia-consensus/src/multiprocess_validation.rs index 9246ec0c1..5a5f9e25e 100644 --- a/crates/chia-consensus/src/multiprocess_validation.rs +++ b/crates/chia-consensus/src/multiprocess_validation.rs @@ -7,15 +7,12 @@ use crate::gen::flags::{ use crate::gen::owned_conditions::OwnedSpendBundleConditions; use crate::gen::solution_generator::solution_generator; use crate::gen::validation_error::ErrorCode; -use crate::generator_types::BlockGenerator; use crate::npc_result::get_name_puzzle_conditions; use chia_bls::aggregate_verify; use chia_bls::BlsCache; use chia_bls::PublicKey; use chia_protocol::Coin; -use chia_protocol::Program; use chia_protocol::SpendBundle; -use chia_traits::Streamable; use clvmr::{ENABLE_BLS_OPS_OUTSIDE_GUARD, ENABLE_FIXED_DIV}; use std::sync::{Arc, Mutex}; // use std::thread; @@ -60,7 +57,11 @@ fn validate_clvm_and_signature( let start_time = Instant::now(); let additional_data: chia_protocol::BytesImpl<32> = constants.agg_sig_me_additional_data; let program: Vec = simple_solution_generator(spend_bundle)?; - let npcresult = get_name_puzzle_conditions(program, max_cost, true, height, &constants)?; + let npcresult = match get_name_puzzle_conditions(program, max_cost, true, height, &constants) { + Ok(result) => result, + Err(error) => return Err(error.1) + }; + let (pks, msgs) = pkm_pairs(npcresult.clone(), additional_data.as_slice())?; // Verify aggregated signature if !{ @@ -171,6 +172,7 @@ mod tests { use crate::consensus_constants::TEST_CONSTANTS; use chia_bls::Signature; use chia_protocol::CoinSpend; + use chia_protocol::Program; #[test] fn test_validate_no_pks() { diff --git a/crates/chia-consensus/src/npc_result.rs b/crates/chia-consensus/src/npc_result.rs index 6aa2fcbae..ff598fb52 100644 --- a/crates/chia-consensus/src/npc_result.rs +++ b/crates/chia-consensus/src/npc_result.rs @@ -1,14 +1,20 @@ use crate::allocator::make_allocator; use crate::consensus_constants::ConsensusConstants; -use crate::gen::conditions::EmptyVisitor; -use crate::gen::conditions::SpendBundleConditions; +use crate::gen::conditions::{process_single_spend, validate_conditions, EmptyVisitor, ParseState, SpendBundleConditions}; +use clvm_utils::{tree_hash_cached, TreeHash}; +use clvmr::run_program::run_program; +use clvmr::reduction::Reduction; use crate::gen::flags::MEMPOOL_MODE; use crate::gen::owned_conditions::OwnedSpendBundleConditions; -use crate::gen::run_block_generator::{run_block_generator, run_block_generator2}; -use crate::gen::validation_error::{ErrorCode, ValidationErr}; +use crate::gen::run_block_generator::{extract_n, subtract_cost}; +use std::collections::{HashMap, HashSet}; +use clvmr::chia_dialect::ChiaDialect; +use clvmr::serde::node_from_bytes; +use clvmr::allocator::{Allocator, NodePtr}; +use crate::gen::validation_error::{first, ErrorCode, ValidationErr}; use crate::multiprocess_validation::get_flags_for_height_and_constants; -#[cfg(feature = "py-bindings")] -use chia_py_streamable_macro::{PyGetters, PyJsonDict, PyStreamable}; +// #[cfg(feature = "py-bindings")] +// use chia_py_streamable_macro::{PyGetters, PyJsonDict, PyStreamable}; use clvmr::chia_dialect::LIMIT_HEAP; // we may be able to remove this struct and just return a Rust native Result @@ -32,39 +38,59 @@ pub fn get_name_puzzle_conditions( mempool_mode: bool, height: u32, constants: &ConsensusConstants, -) -> Result { +) -> Result { let mut flags = get_flags_for_height_and_constants(height, constants); if mempool_mode { flags |= MEMPOOL_MODE }; - let block_args = Vec::>::new(); - let mut a2 = make_allocator(LIMIT_HEAP); - let sbc_result: Result = - if height >= constants.hard_fork_fix_height { - run_block_generator2::<_, EmptyVisitor>( - &mut a2, - generator_program.as_slice(), - &block_args, - max_cost, - flags, - ) - } else { - run_block_generator::<_, EmptyVisitor>( - &mut a2, - generator_program.as_slice(), - &block_args, - max_cost, - flags, - ) - }; - match sbc_result { - Ok(sbc) => { - let result = OwnedSpendBundleConditions::from(&a2, sbc); - match result { - Ok(r) => Ok(r), - Err(_) => Err(ErrorCode::InvalidSpendBundle), - } - } - Err(e) => Err(e.1), + // below is an adapted version of the code from run_block_generators::run_block_generator2() + // it assumes no block references are passed in + let mut cost_left = max_cost; + let dialect = ChiaDialect::new(flags); + let mut a: Allocator = make_allocator(LIMIT_HEAP); + let program = node_from_bytes(&mut a, generator_program.as_slice())?; + let env = a.nil(); + let Reduction(clvm_cost, mut all_spends) = run_program(&mut a, &dialect, program, env, cost_left)?; + + subtract_cost(&a, &mut cost_left, clvm_cost)?; + all_spends = first(&a, all_spends)?; + let mut ret = SpendBundleConditions::default(); + let mut state = ParseState::default(); + let mut cache = HashMap::::new(); + + while let Some((spend, rest)) = a.next(all_spends) { + all_spends = rest; + // process the spend + let [parent_id, puzzle, amount, solution, _spend_level_extra] = + extract_n::<5>(&a, spend, ErrorCode::InvalidCondition)?; + + let Reduction(clvm_cost, conditions) = + run_program(&mut a, &dialect, puzzle, solution, cost_left)?; + + subtract_cost(&a, &mut cost_left, clvm_cost)?; + + let buf = tree_hash_cached(&a, puzzle, &HashSet::::new(), &mut cache); + let puzzle_hash = a.new_atom(&buf)?; + + process_single_spend::( + &a, + &mut ret, + &mut state, + parent_id, + puzzle_hash, + amount, + conditions, + flags, + &mut cost_left, + )?; + } + if a.atom_len(all_spends) != 0 { + return Err(ValidationErr(all_spends, ErrorCode::GeneratorRuntimeError)); } + + validate_conditions(&a, &ret, state, a.nil(), flags)?; + + ret.cost = max_cost - cost_left; + let Ok(osbc) = OwnedSpendBundleConditions::from(&a, ret) else {return Err(ValidationErr(all_spends, ErrorCode::InvalidSpendBundle))}; + Ok(osbc) }