From 4d57ab5501a8406049b01a1402e2fbb257b4fd6f Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 24 Sep 2024 08:34:45 +0200 Subject: [PATCH] fixup fuzzer --- .../fuzz/fuzz_targets/solution-generator.rs | 31 ++++----- .../src/gen/solution_generator.rs | 69 ++++--------------- 2 files changed, 26 insertions(+), 74 deletions(-) diff --git a/crates/chia-consensus/fuzz/fuzz_targets/solution-generator.rs b/crates/chia-consensus/fuzz/fuzz_targets/solution-generator.rs index 0793c3d0..5a6a2cb4 100644 --- a/crates/chia-consensus/fuzz/fuzz_targets/solution-generator.rs +++ b/crates/chia-consensus/fuzz/fuzz_targets/solution-generator.rs @@ -3,7 +3,7 @@ use chia_consensus::gen::solution_generator::{calculate_generator_length, soluti use chia_protocol::{Coin, CoinSpend}; use chia_traits::Streamable; use clvmr::{ - serde::{node_from_bytes, node_to_bytes}, + serde::{node_from_bytes_backrefs, node_to_bytes}, Allocator, }; use libfuzzer_sys::fuzz_target; @@ -13,7 +13,7 @@ fuzz_target!(|data: &[u8]| { let mut spends = Vec::::new(); let mut generator_input = Vec::<(Coin, Vec, Vec)>::new(); let mut data = Cursor::new(data); - let mut discrepancy: usize = 0; + let mut discrepancy: i64 = 0; let mut a = Allocator::new(); while let Ok(spend) = CoinSpend::parse::(&mut data) { spends.push(spend.clone()); @@ -23,30 +23,23 @@ fuzz_target!(|data: &[u8]| { spend.solution.to_vec(), )); // Check if puzzle or solution are atoms which can represented in a smaller form - let node = node_from_bytes(&mut a, spend.puzzle_reveal.as_ref()).expect("node"); - if node.is_atom() { - let puz = node_to_bytes(&a, node).expect("bytes"); - discrepancy += spend.puzzle_reveal.as_ref().len() - puz.len(); - } - let node = node_from_bytes(&mut a, spend.solution.as_ref()).expect("node"); - if node.is_atom() { - let sol = node_to_bytes(&a, node).expect("bytes"); - discrepancy += spend.solution.as_ref().len() - sol.len(); - } + let node = node_from_bytes_backrefs(&mut a, spend.puzzle_reveal.as_ref()).expect("node"); + let puz = node_to_bytes(&a, node).expect("bytes"); + discrepancy += spend.puzzle_reveal.as_ref().len() as i64 - puz.len() as i64; + let node = node_from_bytes_backrefs(&mut a, spend.solution.as_ref()).expect("node"); + let sol = node_to_bytes(&a, node).expect("bytes"); + discrepancy += spend.solution.as_ref().len() as i64 - sol.len() as i64; } if spends.is_empty() { return; } - let Ok(result) = solution_generator(generator_input) else { - return; - }; - - if result.len() != calculate_generator_length(spends.clone()) - discrepancy { + let result = solution_generator(generator_input).expect("solution_generator"); + if result.len() as i64 != calculate_generator_length(spends.clone()) as i64 - discrepancy { panic!("Debug spends: {:?}", spends); } assert_eq!( - result.len(), - calculate_generator_length(spends) - discrepancy + result.len() as i64, + calculate_generator_length(spends) as i64 - discrepancy ); }); diff --git a/crates/chia-consensus/src/gen/solution_generator.rs b/crates/chia-consensus/src/gen/solution_generator.rs index d6c2dbbf..9ba270a5 100644 --- a/crates/chia-consensus/src/gen/solution_generator.rs +++ b/crates/chia-consensus/src/gen/solution_generator.rs @@ -1,9 +1,7 @@ use chia_protocol::Coin; use chia_protocol::CoinSpend; use clvmr::allocator::{Allocator, NodePtr}; -use clvmr::serde::{ - node_from_bytes, node_from_bytes_backrefs, node_to_bytes, node_to_bytes_backrefs, -}; +use clvmr::serde::{node_from_bytes_backrefs, node_to_bytes, node_to_bytes_backrefs}; use std::io; // the tuple has the Coin, puzzle-reveal and solution @@ -42,42 +40,6 @@ where Ok(quote) } -// the tuple has the Coin, puzzle-reveal and solution -fn build_generator_no_backrefs(a: &mut Allocator, spends: I) -> io::Result -where - BufRef: AsRef<[u8]>, - I: IntoIterator, -{ - // the generator we produce here is just a quoted list. Nothing fancy. - // Its format is as follows: - // (q . ( ( ( parent-id puzzle-reveal amount solution ) ... ) ) ) - - let mut spend_list = a.nil(); - for s in spends { - let item = a.nil(); - // solution - let solution = node_from_bytes(a, s.2.as_ref())?; - let item = a.new_pair(solution, item)?; - // amount - let amount = a.new_number(s.0.amount.into())?; - let item = a.new_pair(amount, item)?; - // puzzle reveal - let puzzle = node_from_bytes(a, s.1.as_ref())?; - let item = a.new_pair(puzzle, item)?; - // parent-id - let parent_id = a.new_atom(&s.0.parent_coin_info)?; - let item = a.new_pair(parent_id, item)?; - - spend_list = a.new_pair(item, spend_list)?; - } - - // the list of spends is the first (and only) item in an outer list - spend_list = a.new_pair(spend_list, a.nil())?; - - let quote = a.new_pair(a.one(), spend_list)?; - Ok(quote) -} - fn clvm_bytes_len(val: u64) -> usize { if val < 0x80 { 1 @@ -127,7 +89,7 @@ where I: IntoIterator, { let mut a = Allocator::new(); - let generator = build_generator_no_backrefs(&mut a, spends)?; + let generator = build_generator(&mut a, spends)?; node_to_bytes(&a, generator) } @@ -145,6 +107,7 @@ where mod tests { use super::*; use chia_protocol::Program; + use chia_traits::Streamable; use clvmr::{run_program, ChiaDialect}; use hex_literal::hex; use rstest::rstest; @@ -371,7 +334,7 @@ mod tests { let mut spends: Vec<(Coin, &[u8], &[u8])> = Vec::new(); let mut coin_spends = Vec::::new(); let mut a = Allocator::new(); - let mut discrepancy: usize = 0; + let mut discrepancy: i64 = 0; let coin: Coin = Coin::new( hex!("ccd5bb71183532bff220ba46c268991a00000000000000000000000000036840").into(), @@ -381,24 +344,20 @@ mod tests { spends.push((coin, puzzle, solution)); coin_spends.push(CoinSpend { coin, - puzzle_reveal: Program::from(puzzle), - solution: Program::from(solution), + puzzle_reveal: Program::from_bytes(puzzle).expect("puzzle_reveal"), + solution: Program::from_bytes(solution).expect("solution"), }); - let node = node_from_bytes(&mut a, puzzle).expect("atom"); - if node.is_atom() { - let puz = node_to_bytes(&a, node).expect("bytes"); - discrepancy = puzzle.len() - puz.len(); - } - let node = node_from_bytes(&mut a, solution).expect("atom"); - if node.is_atom() { - let sol = node_to_bytes(&a, node).expect("bytes"); - discrepancy = solution.len() - sol.len(); - } + let node = node_from_bytes_backrefs(&mut a, puzzle).expect("puzzle"); + let puz = node_to_bytes(&a, node).expect("bytes"); + discrepancy += puzzle.len() as i64 - puz.len() as i64; + let node = node_from_bytes_backrefs(&mut a, solution).expect("solution"); + let sol = node_to_bytes(&a, node).expect("bytes"); + discrepancy += solution.len() as i64 - sol.len() as i64; let result = solution_generator(spends.clone()).expect("solution_generator"); assert_eq!( - result.len(), - calculate_generator_length(&coin_spends) - discrepancy + result.len() as i64, + calculate_generator_length(&coin_spends) as i64 - discrepancy ); }