Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactors #632

Merged
merged 3 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/chia-consensus/benches/run-generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn run(c: &mut Criterion) {
let mut a = Allocator::new();
let start = Instant::now();

let conds = run_block_generator::<_, MempoolVisitor>(
let conds = run_block_generator::<_, MempoolVisitor, _>(
&mut a,
gen,
&block_refs,
Expand All @@ -69,7 +69,7 @@ fn run(c: &mut Criterion) {
let mut a = Allocator::new();
let start = Instant::now();

let conds = run_block_generator2::<_, MempoolVisitor>(
let conds = run_block_generator2::<_, MempoolVisitor, _>(
&mut a,
gen,
&block_refs,
Expand Down
8 changes: 4 additions & 4 deletions crates/chia-consensus/fuzz/fuzz_targets/run-generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
let mut a1 = make_allocator(LIMIT_HEAP);
let r1 = run_block_generator::<&[u8], MempoolVisitor>(
let r1 = run_block_generator::<&[u8], MempoolVisitor, _>(
&mut a1,
data,
&[],
[],
110_000_000,
ALLOW_BACKREFS,
&TEST_CONSTANTS,
);
drop(a1);

let mut a2 = make_allocator(LIMIT_HEAP);
let r2 = run_block_generator2::<&[u8], MempoolVisitor>(
let r2 = run_block_generator2::<&[u8], MempoolVisitor, _>(
&mut a2,
data,
&[],
[],
110_000_000,
ALLOW_BACKREFS,
&TEST_CONSTANTS,
Expand Down
62 changes: 41 additions & 21 deletions crates/chia-consensus/src/gen/run_block_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@ fn subtract_cost(a: &Allocator, cost_left: &mut Cost, subtract: Cost) -> Result<
}
}

/// Prepares the arguments passed to the block generator. They are in the form:
/// (DESERIALIZER_MOD (block1 block2 block3 ...))
pub fn setup_generator_args<GenBuf: AsRef<[u8]>, I: IntoIterator<Item = GenBuf>>(
a: &mut Allocator,
block_refs: I,
) -> Result<NodePtr, ValidationErr>
where
<I as IntoIterator>::IntoIter: DoubleEndedIterator,
{
let clvm_deserializer = node_from_bytes(a, &CLVM_DESERIALIZER)?;

// iterate in reverse order since we're building a linked list from
// the tail
let mut blocks = NodePtr::NIL;
for g in block_refs.into_iter().rev() {
let ref_gen = a.new_atom(g.as_ref())?;
blocks = a.new_pair(ref_gen, blocks)?;
}

// the first argument to the generator is the serializer, followed by a list
// of the blocks it requested.
let args = a.new_pair(blocks, NodePtr::NIL)?;
Ok(a.new_pair(clvm_deserializer, args)?)
}

// Runs the generator ROM and passes in the program (transactions generator).
// The program is expected to return a list of spends. Each item being:

Expand All @@ -38,14 +63,17 @@ fn subtract_cost(a: &Allocator, cost_left: &mut Cost, subtract: Cost) -> Result<
// the only reason we need to pass in the allocator is because the returned
// SpendBundleConditions contains NodePtr fields. If that's changed, we could
// create the allocator inside this functions as well.
pub fn run_block_generator<GenBuf: AsRef<[u8]>, V: SpendVisitor>(
pub fn run_block_generator<GenBuf: AsRef<[u8]>, V: SpendVisitor, I: IntoIterator<Item = GenBuf>>(
a: &mut Allocator,
program: &[u8],
block_refs: &[GenBuf],
block_refs: I,
max_cost: u64,
flags: u32,
constants: &ConsensusConstants,
) -> Result<SpendBundleConditions, ValidationErr> {
) -> Result<SpendBundleConditions, ValidationErr>
where
<I as IntoIterator>::IntoIter: DoubleEndedIterator,
{
let mut cost_left = max_cost;
let byte_cost = program.len() as u64 * constants.cost_per_byte;

Expand All @@ -58,10 +86,12 @@ pub fn run_block_generator<GenBuf: AsRef<[u8]>, V: SpendVisitor>(
node_from_bytes(a, program)?
};

// this is setting up the arguments to be passed to the generator ROM,
// not the actual generator (the ROM does that).
// iterate in reverse order since we're building a linked list from
// the tail
let mut args = a.nil();
for g in block_refs.iter().rev() {
for g in block_refs.into_iter().rev() {
let ref_gen = a.new_atom(g.as_ref())?;
args = a.new_pair(ref_gen, args)?;
}
Expand Down Expand Up @@ -112,39 +142,29 @@ pub fn extract_n<const N: usize>(
// you only pay cost for the generator, the puzzles and the conditions).
// it also does not apply the stack depth or object allocation limits the same,
// as each puzzle run in its own environment.
pub fn run_block_generator2<GenBuf: AsRef<[u8]>, V: SpendVisitor>(
pub fn run_block_generator2<GenBuf: AsRef<[u8]>, V: SpendVisitor, I: IntoIterator<Item = GenBuf>>(
a: &mut Allocator,
program: &[u8],
block_refs: &[GenBuf],
block_refs: I,
max_cost: u64,
flags: u32,
constants: &ConsensusConstants,
) -> Result<SpendBundleConditions, ValidationErr> {
) -> Result<SpendBundleConditions, ValidationErr>
where
<I as IntoIterator>::IntoIter: DoubleEndedIterator,
{
let byte_cost = program.len() as u64 * constants.cost_per_byte;

let mut cost_left = max_cost;
subtract_cost(a, &mut cost_left, byte_cost)?;

let clvm_deserializer = node_from_bytes(a, &CLVM_DESERIALIZER)?;
let (program, backrefs) = if (flags & ALLOW_BACKREFS) != 0 {
node_from_bytes_backrefs_record(a, program)?
} else {
(node_from_bytes(a, program)?, HashSet::<NodePtr>::new())
};

// iterate in reverse order since we're building a linked list from
// the tail
let mut blocks = a.nil();
for g in block_refs.iter().rev() {
let ref_gen = a.new_atom(g.as_ref())?;
blocks = a.new_pair(ref_gen, blocks)?;
}

// the first argument to the generator is the serializer, followed by a list
// of the blocks it requested.
let mut args = a.new_pair(blocks, a.nil())?;
args = a.new_pair(clvm_deserializer, args)?;

let args = setup_generator_args(a, block_refs)?;
let dialect = ChiaDialect::new(flags);

let Reduction(clvm_cost, mut all_spends) = run_program(a, &dialect, program, args, cost_left)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/chia-consensus/src/gen/test_generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ fn run_generator(#[case] name: &str) {
for (flags, expected) in zip(&[DEFAULT_FLAGS, DEFAULT_FLAGS | MEMPOOL_MODE], expected) {
println!("flags: {flags:x}");
let mut a = make_allocator(*flags);
let conds = run_block_generator::<_, MempoolVisitor>(
let conds = run_block_generator::<_, MempoolVisitor, _>(
&mut a,
&generator,
&block_refs,
Expand All @@ -246,7 +246,7 @@ fn run_generator(#[case] name: &str) {
};

let mut a = make_allocator(*flags);
let conds = run_block_generator2::<_, MempoolVisitor>(
let conds = run_block_generator2::<_, MempoolVisitor, _>(
&mut a,
&generator,
&block_refs,
Expand Down
4 changes: 2 additions & 2 deletions crates/chia-tools/src/bin/analyze-chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ fn main() {
// after the hard fork, we run blocks without paying for the
// CLVM generator ROM
let block_runner = if height >= 5_496_000 {
run_block_generator2::<_, EmptyVisitor>
run_block_generator2::<_, EmptyVisitor, _>
} else {
run_block_generator::<_, EmptyVisitor>
run_block_generator::<_, EmptyVisitor, _>
};

let generator = block
Expand Down
6 changes: 3 additions & 3 deletions crates/chia-tools/src/bin/test-block-generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ fn main() {
// after the hard fork, we run blocks without paying for the
// CLVM generator ROM
let block_runner = if height >= 5_496_000 {
run_block_generator2::<_, EmptyVisitor>
run_block_generator2::<_, EmptyVisitor, _>
} else {
run_block_generator::<_, EmptyVisitor>
run_block_generator::<_, EmptyVisitor, _>
};

let mut conditions =
Expand All @@ -181,7 +181,7 @@ fn main() {
}

if args.validate {
let mut baseline = run_block_generator::<_, EmptyVisitor>(
let mut baseline = run_block_generator::<_, EmptyVisitor, _>(
&mut a,
generator.as_ref(),
&block_refs,
Expand Down
11 changes: 0 additions & 11 deletions wheel/src/adapt_response.rs

This file was deleted.

56 changes: 24 additions & 32 deletions wheel/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::run_generator::{run_block_generator, run_block_generator2};
use crate::run_generator::{py_to_slice, run_block_generator, run_block_generator2};
use chia_consensus::allocator::make_allocator;
use chia_consensus::consensus_constants::ConsensusConstants;
use chia_consensus::gen::conditions::MempoolVisitor;
Expand Down Expand Up @@ -52,7 +52,6 @@ use std::iter::zip;

use crate::run_program::{run_chia_program, serialized_length};

use crate::adapt_response::eval_err_to_pyresult;
use chia_consensus::fast_forward::fast_forward_singleton as native_ff;
use chia_consensus::gen::get_puzzle_and_solution::get_puzzle_and_solution_for_coin as parse_puzzle_solution;
use chia_consensus::gen::validation_error::ValidationErr;
Expand Down Expand Up @@ -107,20 +106,15 @@ pub fn confirm_not_included_already_hashed(
}

#[pyfunction]
pub fn tree_hash(py: Python<'_>, blob: PyBuffer<u8>) -> PyResult<Bound<'_, PyBytes>> {
assert!(
blob.is_c_contiguous(),
"tree_hash() must be called with a contiguous buffer"
);
let slice =
unsafe { std::slice::from_raw_parts(blob.buf_ptr() as *const u8, blob.len_bytes()) };
pub fn tree_hash<'a>(py: Python<'a>, blob: PyBuffer<u8>) -> PyResult<Bound<'_, PyBytes>> {
let slice = py_to_slice::<'a>(blob);
Ok(PyBytes::new_bound(py, &tree_hash_from_bytes(slice)?))
}

#[allow(clippy::too_many_arguments)]
#[pyfunction]
pub fn get_puzzle_and_solution_for_coin(
py: Python<'_>,
pub fn get_puzzle_and_solution_for_coin<'a>(
py: Python<'a>,
program: PyBuffer<u8>,
args: PyBuffer<u8>,
max_cost: Cost,
Expand All @@ -131,12 +125,8 @@ pub fn get_puzzle_and_solution_for_coin(
) -> PyResult<(Bound<'_, PyBytes>, Bound<'_, PyBytes>)> {
let mut allocator = make_allocator(LIMIT_HEAP);

assert!(program.is_c_contiguous(), "program must be contiguous");
let program =
unsafe { std::slice::from_raw_parts(program.buf_ptr() as *const u8, program.len_bytes()) };

assert!(args.is_c_contiguous(), "args must be contiguous");
let args = unsafe { std::slice::from_raw_parts(args.buf_ptr() as *const u8, args.len_bytes()) };
let program = py_to_slice::<'a>(program);
let args = py_to_slice::<'a>(args);

let deserialize = if (flags & ALLOW_BACKREFS) != 0 {
node_from_bytes_backrefs
Expand All @@ -147,14 +137,19 @@ pub fn get_puzzle_and_solution_for_coin(
let args = deserialize(&mut allocator, args)?;
let dialect = &ChiaDialect::new(flags);

let r = py.allow_threads(|| -> Result<(NodePtr, NodePtr), EvalErr> {
let Reduction(_cost, result) =
run_program(&mut allocator, dialect, program, args, max_cost)?;
match parse_puzzle_solution(&allocator, result, find_parent, find_amount, find_ph) {
Err(ValidationErr(n, _)) => Err(EvalErr(n, "coin not found".to_string())),
Ok(pair) => Ok(pair),
}
});
let (puzzle, solution) = py
.allow_threads(|| -> Result<(NodePtr, NodePtr), EvalErr> {
let Reduction(_cost, result) =
run_program(&mut allocator, dialect, program, args, max_cost)?;
match parse_puzzle_solution(&allocator, result, find_parent, find_amount, find_ph) {
Err(ValidationErr(n, _)) => Err(EvalErr(n, "coin not found".to_string())),
Ok(pair) => Ok(pair),
}
})
.map_err(|e| {
let blob = node_to_bytes(&allocator, e.0).ok().map(hex::encode);
PyValueError::new_err((e.1, blob))
})?;

// keep serializing normally, until wallets support backrefs
let serialize = node_to_bytes;
Expand All @@ -165,13 +160,10 @@ pub fn get_puzzle_and_solution_for_coin(
node_to_bytes
};
*/
match r {
Err(eval_err) => eval_err_to_pyresult(eval_err, &allocator),
Ok((puzzle, solution)) => Ok((
PyBytes::new_bound(py, &serialize(&allocator, puzzle)?),
PyBytes::new_bound(py, &serialize(&allocator, solution)?),
)),
}
Ok((
PyBytes::new_bound(py, &serialize(&allocator, puzzle)?),
PyBytes::new_bound(py, &serialize(&allocator, solution)?),
))
}

#[pyfunction]
Expand Down
1 change: 0 additions & 1 deletion wheel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![allow(unsafe_code, clippy::needless_pass_by_value)]

mod adapt_response;
mod api;
mod run_generator;
mod run_program;
Loading
Loading