From 855558e3028fd2ec34b2349b5563898120005a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Thu, 9 Nov 2023 13:00:17 -0500 Subject: [PATCH 1/4] refactor: Refactor codebase by removing MultiFrame struct usage - Removed the entire `MultiFrame` struct execution across multiple files. - Altered import statements to match the changes in the codebase. --- src/circuit/circuit_frame.rs | 403 +---------------------------------- src/circuit/mod.rs | 1 - src/proof/supernova.rs | 15 +- 3 files changed, 3 insertions(+), 416 deletions(-) diff --git a/src/circuit/circuit_frame.rs b/src/circuit/circuit_frame.rs index cd1b68d8ab..50010afb3f 100644 --- a/src/circuit/circuit_frame.rs +++ b/src/circuit/circuit_frame.rs @@ -1,10 +1,8 @@ -use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; -use bellpepper::util_cs::{witness_cs::WitnessCS, Comparable}; +use bellpepper::util_cs::Comparable; use bellpepper_core::{boolean::Boolean, num::AllocatedNum, ConstraintSystem, SynthesisError}; -use rayon::prelude::*; use tracing::{debug, info}; use crate::{ @@ -13,9 +11,7 @@ use crate::{ data::GlobalAllocations, pointer::{AllocatedContPtr, AllocatedPtr, AsAllocatedHashComponents}, }, - config::lurk_config, field::LurkField, - hash::HashConst, hash_witness::{ ConsCircuitWitness, ConsName, ContCircuitWitness, ContName, HashCircuitWitnessCache, }, @@ -32,7 +28,7 @@ use crate::circuit::circuit_frame::constraints::{ }; use crate::circuit::gadgets::hashes::{AllocatedConsWitness, AllocatedContWitness}; use crate::coprocessor::Coprocessor; -use crate::eval::{Frame, Meta, Witness, IO}; +use crate::eval::{Frame, Witness, IO}; use crate::expr::Thunk; use crate::hash_witness::HashWitness; use crate::lurk_sym_ptr; @@ -54,19 +50,6 @@ pub struct CircuitFrame<'a, F: LurkField, C: Coprocessor> { _p: PhantomData, } -#[derive(Debug, Clone)] -pub struct MultiFrame<'a, F: LurkField, C: Coprocessor> { - pub store: Option<&'a Store>, - pub input: Option>, - pub output: Option>, - pub frames: Option>>, - pub cached_witness: Option>, - pub count: usize, - pub folding_config: Arc>, - pub meta: Meta, - pub next_pc: Option, -} - impl<'a, F: LurkField, C: Coprocessor> CircuitFrame<'a, F, C> { pub fn blank() -> Self { Self { @@ -89,394 +72,12 @@ impl<'a, F: LurkField, C: Coprocessor> CircuitFrame<'a, F, C> { } } -impl<'a, F: LurkField, C: Coprocessor> MultiFrame<'a, F, C> { - pub fn blank(folding_config: Arc>, meta: Meta) -> Self { - let count = match meta { - Meta::Lurk => folding_config.reduction_count(), - Meta::Coprocessor(_zptr) => 1, - }; - Self { - store: None, - input: None, - output: None, - frames: None, - next_pc: None, - cached_witness: None, - count, - folding_config, - meta, - } - } - - pub fn get_store(&self) -> &Store { - self.store.expect("store missing") - } - - pub fn from_frames( - count: usize, - frames: &[Frame, Witness, F, C>], - store: &'a Store, - folding_config: &Arc>, - ) -> Vec { - match &**folding_config { - FoldingConfig::IVC(..) => Self::from_frames_ivc(count, frames, store, folding_config), - FoldingConfig::NIVC(..) => Self::from_frames_nivc(count, frames, store, folding_config), - } - } - - fn from_frames_ivc( - // we need this count, even though folding_config contains reduction_count - // because it might be overridden in the case of a coprocoessor, which should have rc=1. - // This is not ideal and might not *actually* be needed. - count: usize, - frames: &[Frame, Witness, F, C>], - store: &'a Store, - folding_config: &Arc>, - ) -> Vec { - // `count` is the number of `Frames` to include per `MultiFrame`. - let total_frames = frames.len(); - let n = (total_frames + count - 1) / count; - let mut multi_frames = Vec::with_capacity(n); - - let mut meta = None; - for chunk in frames.chunks(count) { - let mut inner_frames = Vec::with_capacity(count); - - for x in chunk { - let circuit_frame = CircuitFrame::from_frame(x, store); - meta.get_or_insert(x.meta); - inner_frames.push(circuit_frame); - } - - let last_frame = chunk.last().expect("chunk must not be empty"); - let last_circuit_frame = inner_frames - .last() - .expect("chunk must not be empty") - .clone(); - - // Fill out the MultiFrame, if needed, and capture output of the final actual frame. - inner_frames.resize(count, last_circuit_frame.clone()); - - let output = last_frame.output; - debug_assert!(!inner_frames.is_empty()); - - let meta = meta.unwrap_or(Meta::Lurk); - - let mf = MultiFrame { - store: Some(store), - input: Some(chunk[0].input), - output: Some(output), - frames: Some(inner_frames), - next_pc: None, - cached_witness: None, - count, - folding_config: folding_config.clone(), - meta, - }; - - multi_frames.push(mf); - } - - multi_frames - } - - fn from_frames_nivc( - count: usize, - frames: &[Frame, Witness, F, C>], - store: &'a Store, - folding_config: &Arc>, - ) -> Vec { - let mut steps = Vec::new(); - let mut last_meta = frames[0].meta; - let mut consecutive_frames = Vec::new(); - - for frame in frames { - if frame.meta == last_meta { - let padding_frame = frame.clone(); - consecutive_frames.push(padding_frame); - } else { - if last_meta == Meta::Lurk { - consecutive_frames.push(frame.clone()); - } - let new_steps = MultiFrame::from_frames_ivc( - if last_meta == Meta::Lurk { count } else { 1 }, - &consecutive_frames, - store, - folding_config, - ) - .into_iter(); - - steps.extend(new_steps); - consecutive_frames.truncate(0); - consecutive_frames.push(frame.clone()); - last_meta = frame.meta; - } - } - - // TODO: refactor - if !consecutive_frames.is_empty() { - let new_steps = - MultiFrame::from_frames_ivc(count, &consecutive_frames, store, folding_config) - .into_iter(); - - steps.extend(new_steps); - } - - if !steps.is_empty() { - let penultimate = steps.len() - 1; - for i in 0..(penultimate - 1) { - steps[i].next_pc = Some(steps[i + 1].circuit_index()); - } - } - steps - } - - pub fn synthesize_frames>( - &self, - cs: &mut CS, - store: &Store, - input_expr: AllocatedPtr, - input_env: AllocatedPtr, - input_cont: AllocatedContPtr, - frames: &[CircuitFrame<'_, F, C>], - g: &GlobalAllocations, - ) -> (AllocatedPtr, AllocatedPtr, AllocatedContPtr) { - if cs.is_witness_generator() - && lurk_config(None, None) - .perf - .parallelism - .synthesis - .is_parallel() - { - self.synthesize_frames_parallel( - cs, - store, - &input_expr, - &input_env, - &input_cont, - frames, - g, - ) - } else { - self.synthesize_frames_sequential( - cs, store, input_expr, input_env, input_cont, frames, &None, g, - ) - } - } - - pub fn synthesize_frames_sequential>( - &self, - cs: &mut CS, - store: &Store, - input_expr: AllocatedPtr, - input_env: AllocatedPtr, - input_cont: AllocatedContPtr, - frames: &[CircuitFrame<'_, F, C>], - cons_and_cont_witnesses: &Option, ContCircuitWitness)>>, - g: &GlobalAllocations, - ) -> (AllocatedPtr, AllocatedPtr, AllocatedContPtr) { - let mut hash_circuit_witness_cache = HashMap::new(); - - let acc = (input_expr, input_env, input_cont); - - let (_, (new_expr, new_env, new_cont)) = - frames.iter().fold((0, acc), |(i, allocated_io), frame| { - info!("synthesizing frame {i}"); - if let Some(next_input) = frame.input { - // Ensure all intermediate allocated I/O values match the provided execution trace. - - let next_expr_hash = store.hash_expr(&next_input.expr); - let next_env_hash = store.hash_expr(&next_input.env); - let next_cont_hash = store.hash_cont(&next_input.cont); - - assert_eq!( - allocated_io.0.tag().get_value(), - next_expr_hash.map(|x| x.tag_field()), - "expr tag mismatch" - ); - assert_eq!( - allocated_io.0.hash().get_value(), - next_expr_hash.map(|x| *x.value()), - "expr mismatch" - ); - assert_eq!( - allocated_io.1.tag().get_value(), - next_env_hash.map(|x| x.tag_field()), - "env tag mismatch" - ); - assert_eq!( - allocated_io.1.hash().get_value(), - next_env_hash.map(|x| *x.value()), - "env mismatch" - ); - assert_eq!( - allocated_io.2.tag().get_value(), - next_cont_hash.map(|x| x.tag_field()), - "cont tag mismatch" - ); - assert_eq!( - allocated_io.2.hash().get_value(), - next_cont_hash.map(|x| *x.value()), - "cont mismatch" - ); - }; - let (cons_witnesses, cont_witnesses) = - if let Some(cons_and_cont_witnesses) = &cons_and_cont_witnesses { - ( - Some(cons_and_cont_witnesses[i].0.clone()), - Some(cons_and_cont_witnesses[i].1.clone()), - ) - } else { - (None, None) - }; - - let new_allocated_io = frame - .synthesize( - cs, - i, - allocated_io, - &self.folding_config, - g, - &mut hash_circuit_witness_cache, - cons_witnesses, - cont_witnesses, - ) - .unwrap(); - - (i + 1, new_allocated_io) - }); - - (new_expr, new_env, new_cont) - } - - pub fn synthesize_frames_parallel>( - &self, - cs: &mut CS, - store: &Store, - input_expr: &AllocatedPtr, - input_env: &AllocatedPtr, - input_cont: &AllocatedContPtr, - frames: &[CircuitFrame<'_, F, C>], - g: &GlobalAllocations, - ) -> (AllocatedPtr, AllocatedPtr, AllocatedContPtr) { - assert!(cs.is_witness_generator()); - let config = lurk_config(None, None); - assert!(config.perf.parallelism.synthesis.is_parallel()); - - // TODO: this probably belongs in config, perhaps per-Flow. - const MIN_CHUNK_SIZE: usize = 10; - - let num_frames = frames.len(); - - let chunk_size = config - .perf - .parallelism - .synthesis - .chunk_size(num_frames, MIN_CHUNK_SIZE); - - let css = frames - .par_chunks(chunk_size) - .enumerate() - .map(|(i, chunk)| { - let (input_expr, input_env, input_cont) = if i == 0 { - (input_expr.clone(), input_env.clone(), input_cont.clone()) - } else { - let previous_frame = &frames[i * chunk_size]; - let mut bogus_cs = WitnessCS::new(); - let x = previous_frame.input.unwrap().expr; - let input_expr = - AllocatedPtr::alloc_ptr(&mut bogus_cs, store, || Ok(&x)).unwrap(); - let y = previous_frame.input.unwrap().env; - let input_env = - AllocatedPtr::alloc_ptr(&mut bogus_cs, store, || Ok(&y)).unwrap(); - let z = previous_frame.input.unwrap().cont; - let input_cont = - AllocatedContPtr::alloc_cont_ptr(&mut bogus_cs, store, || Ok(&z)).unwrap(); - (input_expr, input_env, input_cont) - }; - - let cons_and_cont_witnesses = { - macro_rules! f { - () => { - |frame| { - let cons_circuit_witness: ConsCircuitWitness = frame - .witness - .map(|x| x.conses) - .unwrap_or_else(|| HashWitness::new_blank()) - .into(); - - let cons_constants: HashConst<'_, F> = - store.poseidon_constants().constants(4.into()); - - // Force generating the witness. This is the important part! - cons_circuit_witness.circuit_witness_blocks(store, &cons_constants); - - let cont_circuit_witness: ContCircuitWitness = frame - .witness - .map(|x| x.conts) - .unwrap_or_else(|| HashWitness::new_blank()) - .into(); - - let cont_constants: HashConst<'_, F> = - store.poseidon_constants().constants(8.into()); - - // Force generating the witness. This is the important part! - cont_circuit_witness.circuit_witness_blocks(store, &cont_constants); - - (cons_circuit_witness, cont_circuit_witness) - } - }; - } - - if config.perf.parallelism.poseidon_witnesses.is_parallel() { - chunk.par_iter().map(f!()).collect::>() - } else { - chunk.iter().map(f!()).collect::>() - } - }; - - let mut cs = WitnessCS::new(); - - let output = self.synthesize_frames_sequential( - &mut cs, - store, - input_expr, - input_env, - input_cont, - chunk, - &Some(cons_and_cont_witnesses), - g, - ); - - (cs, output) - }) - .collect::>(); - - let mut final_output = None; - - for (frames_cs, output) in css { - final_output = Some(output); - - let aux = frames_cs.aux_slice(); - cs.extend_aux(aux); - } - - final_output.unwrap() - } -} - impl> CircuitFrame<'_, F, C> { pub fn precedes(&self, maybe_next: &Self) -> bool { self.output == maybe_next.input } } -impl> MultiFrame<'_, F, C> { - pub fn precedes(&self, maybe_next: &Self) -> bool { - self.output == maybe_next.input - } -} - type AllocatedIO = (AllocatedPtr, AllocatedPtr, AllocatedContPtr); impl> CircuitFrame<'_, F, C> { diff --git a/src/circuit/mod.rs b/src/circuit/mod.rs index 825d4d4c62..9a017ade4a 100644 --- a/src/circuit/mod.rs +++ b/src/circuit/mod.rs @@ -7,7 +7,6 @@ use crate::store::Store; pub mod gadgets; pub mod circuit_frame; -pub(crate) use circuit_frame::*; pub trait ToInputs { fn to_inputs(&self, store: &Store) -> Vec; diff --git a/src/proof/supernova.rs b/src/proof/supernova.rs index 86fefe20fc..3a0f58e109 100644 --- a/src/proof/supernova.rs +++ b/src/proof/supernova.rs @@ -14,10 +14,9 @@ use nova::{ }; use serde::{Deserialize, Serialize}; use std::{marker::PhantomData, ops::Index, sync::Arc}; -use tracing::{debug, info}; +use tracing::info; use crate::{ - circuit::MultiFrame, coprocessor::Coprocessor, error::ProofError, eval::{lang::Lang, Meta}, @@ -356,18 +355,6 @@ impl> FoldingConfig { } } -impl<'a, F: LurkField, C: Coprocessor> MultiFrame<'a, F, C> { - /// Return the circuit index assigned to this `MultiFrame`'s inner computation, as labeled by its `Meta`, and determined by its `FoldingConfig`. - pub fn circuit_index(&self) -> usize { - debug!( - "getting circuit_index for {:?}: {}", - &self.meta, - self.folding_config.circuit_index(&self.meta) - ); - self.folding_config.circuit_index(&self.meta) - } -} - /// Computes a cache key of a supernova primary circuit. The point is that if a circuit /// changes in any way but has the same `rc`/`Lang`, then we still want the /// public params to stay in sync with the changes. From f0a8f078558a0bf812dc17e508135ec5c27009b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Thu, 9 Nov 2023 13:17:31 -0500 Subject: [PATCH 2/4] refactor: Remove dead code - Removed the method `chunk_size` from the `Flow` enum in `config.rs`. - Eliminated several imports in `circuit_frame.rs`, including `ConsCircuitWitness`, `ContCircuitWitness`, `HashCircuitWitnessCache`, `Frame` from `eval`, and `HashWitness`. - Removed the function `from_frame` from `CircuitFrame` implementation and significantly pared down the `synthesize` function within the same implementation. - Introduced `#[allow(dead_code)]` annotations on `reduce_expression` and `apply_continuation` functions, marking them as currently unused but potentially useful in the next few commits --- src/circuit/circuit_frame.rs | 91 ++---------------------------------- src/config.rs | 12 ----- 2 files changed, 4 insertions(+), 99 deletions(-) diff --git a/src/circuit/circuit_frame.rs b/src/circuit/circuit_frame.rs index 50010afb3f..15e4321506 100644 --- a/src/circuit/circuit_frame.rs +++ b/src/circuit/circuit_frame.rs @@ -12,9 +12,7 @@ use crate::{ pointer::{AllocatedContPtr, AllocatedPtr, AsAllocatedHashComponents}, }, field::LurkField, - hash_witness::{ - ConsCircuitWitness, ConsName, ContCircuitWitness, ContName, HashCircuitWitnessCache, - }, + hash_witness::{ConsName, ContName}, store::NamedConstants, tag::Tag, }; @@ -28,9 +26,8 @@ use crate::circuit::circuit_frame::constraints::{ }; use crate::circuit::gadgets::hashes::{AllocatedConsWitness, AllocatedContWitness}; use crate::coprocessor::Coprocessor; -use crate::eval::{Frame, Witness, IO}; +use crate::eval::{Witness, IO}; use crate::expr::Thunk; -use crate::hash_witness::HashWitness; use crate::lurk_sym_ptr; use crate::proof::supernova::FoldingConfig; use crate::ptr::Ptr; @@ -60,16 +57,6 @@ impl<'a, F: LurkField, C: Coprocessor> CircuitFrame<'a, F, C> { _p: Default::default(), } } - - pub fn from_frame(frame: &Frame, Witness, F, C>, store: &'a Store) -> Self { - CircuitFrame { - store: Some(store), - input: Some(frame.input), - output: Some(frame.output), - witness: Some(frame.witness), - _p: Default::default(), - } - } } impl> CircuitFrame<'_, F, C> { @@ -78,78 +65,6 @@ impl> CircuitFrame<'_, F, C> { } } -type AllocatedIO = (AllocatedPtr, AllocatedPtr, AllocatedContPtr); - -impl> CircuitFrame<'_, F, C> { - #[tracing::instrument(skip_all, name = "CircuitFrame::synthesize", level = "debug")] - pub(crate) fn synthesize>( - &self, - cs: &mut CS, - i: usize, - inputs: AllocatedIO, - folding_config: &Arc>, - g: &GlobalAllocations, - _hash_circuit_witness_cache: &mut HashCircuitWitnessCache, // Currently unused. - cons_circuit_witness: Option>, - cont_circuit_witness: Option>, - ) -> Result, SynthesisError> { - let (input_expr, input_env, input_cont) = inputs; - let reduce = |store| { - let cons_circuit_witness = if let Some(ccw) = cons_circuit_witness { - ccw - } else { - let cons_witness = self - .witness - .map_or_else(|| HashWitness::new_blank(), |x| x.conses); - - (cons_witness).into() - }; - - let mut allocated_cons_witness = AllocatedConsWitness::from_cons_witness( - &mut cs.namespace(|| format!("allocated_cons_witness {i}")), - store, - &cons_circuit_witness, - )?; - - let cont_circuit_witness = if let Some(ccw) = cont_circuit_witness { - ccw - } else { - let cont_witness = self - .witness - .map_or_else(|| HashWitness::new_blank(), |x| x.conts); - (cont_witness).into() - }; - - let mut allocated_cont_witness = AllocatedContWitness::from_cont_witness( - &mut cs.namespace(|| format!("allocated_cont_witness {i}")), - store, - &cont_circuit_witness, - )?; - - reduce_expression( - &mut cs.namespace(|| format!("reduce expression {i}")), - &input_expr, - &input_env, - &input_cont, - &self.witness, - &mut allocated_cons_witness, - &mut allocated_cont_witness, - store, - folding_config, - g, - ) - }; - - if let Some(store) = self.store { - reduce(store) - } else { - let store: Store = Default::default(); - store.hydrate_scalar_cache(); - reduce(&store) - } - } -} - #[derive(Default)] struct Results<'a, F: LurkField> { expr_tag_clauses: Vec>, @@ -390,6 +305,7 @@ impl<'a, F: LurkField> CompResults<'a, F> { } } +#[allow(dead_code)] //TODO(huitseeker): remove before flight (issue #874) fn reduce_expression, C: Coprocessor>( cs: &mut CS, expr: &AllocatedPtr, @@ -2674,6 +2590,7 @@ fn make_thunk>( Ok((result_expr, result_env, result_cont)) } +#[allow(dead_code)] // TODO(huitseeker): remove before flight (issue #874) fn apply_continuation>( mut cs: CS, cont: &AllocatedContPtr, diff --git a/src/config.rs b/src/config.rs index aa0a86d52f..d2fd0a3148 100644 --- a/src/config.rs +++ b/src/config.rs @@ -225,18 +225,6 @@ impl Flow { Self::ParallelN(threads) => *threads, } } - - /// Returns the number of parallel steps to run per thread with `rayon::prelude::par_chunks()` - pub fn chunk_size(&self, total_n: usize, min_chunk_size: usize) -> usize { - if self.is_sequential() { - total_n - } else { - let num_threads = self.num_threads(); - let divides_evenly = total_n % num_threads == 0; - - ((total_n / num_threads) + usize::from(!divides_evenly)).max(min_chunk_size) - } - } } /// Shortcut to easily set `PerfConfig` From e9ca21036301c56db2dd2f24418447576b7237fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Thu, 9 Nov 2023 13:23:59 -0500 Subject: [PATCH 3/4] refactor: Refactor dead code - Eliminated redundant code and unused imports across multiple files, - Removed obsolete methods, such as `num_threads` from config module, `new` and `new_dummy` from `Slot` struct, and `from_cons_witness` and `from_cont_witness`. --- src/circuit/gadgets/hashes.rs | 240 +--------------------------------- src/config.rs | 9 -- src/hash_witness.rs | 4 - 3 files changed, 3 insertions(+), 250 deletions(-) diff --git a/src/circuit/gadgets/hashes.rs b/src/circuit/gadgets/hashes.rs index c1239ec9ab..1f1c566e14 100644 --- a/src/circuit/gadgets/hashes.rs +++ b/src/circuit/gadgets/hashes.rs @@ -6,16 +6,12 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError}; use neptune::circuit2::poseidon_hash_allocated as poseidon_hash; use neptune::circuit2_witness::{poseidon_hash_allocated_witness, poseidon_hash_scalar_witness}; -use crate::circuit::gadgets::pointer::{AllocatedPtr, AsAllocatedHashComponents}; +use crate::circuit::gadgets::pointer::AllocatedPtr; -use crate::config::lurk_config; use crate::field::{FWrap, LurkField}; -use crate::hash::{HashConst, HashConstants}; -use crate::hash_witness::{ - ConsCircuitWitness, ConsName, ContCircuitWitness, ContName, Digest, HashName, WitnessBlock, -}; +use crate::hash::HashConst; +use crate::hash_witness::{ConsName, ContName, Digest, HashName, WitnessBlock}; use crate::ptr::ContPtr; -use crate::store::Store; #[derive(Clone, Debug)] pub struct AllocatedHash { @@ -34,25 +30,6 @@ pub(crate) struct Slot { } impl Slot> { - pub(crate) fn new(name: Name, allocated: AllocatedHash) -> Self { - Self { - name: Ok(name), - allocated, - consumed: false, - } - } - pub(crate) fn new_dummy(allocated: AllocatedHash) -> Self { - Self { - name: Err(()), - allocated, - consumed: false, - } - } - - #[allow(dead_code)] - pub(crate) fn is_dummy(&self) -> bool { - self.name.is_err() - } pub(crate) fn is_blank(&self) -> bool { self.allocated.digest.get_value().is_none() } @@ -98,77 +75,6 @@ pub(crate) type AllocatedContWitness<'a, F> = AllocatedWitness = HashMap>, (Vec, F)>; -impl AllocatedPtrHash { - fn alloc>( - cs: &mut CS, - constants: &HashConstants, - preimage: Vec>, - hash_circuit_witness_cache: Option<&mut HashCircuitWitnessCache>, - ) -> Result { - let constants = constants.constants((2 * preimage.len()).into()); - - let pr: Vec> = preimage - .iter() - .flat_map(|x| x.as_allocated_hash_components()) - .cloned() - .collect(); - - let digest = constants.hash(cs, pr, hash_circuit_witness_cache)?; - - Ok(Self { preimage, digest }) - } - - fn alloc_with_witness>( - cs: &mut CS, - constants: &HashConstants, - preimage: Vec>, - block: &(WitnessBlock, Digest), - ) -> Result { - let constants = constants.constants((2 * preimage.len()).into()); - - let pr: Vec> = preimage - .iter() - .flat_map(|x| x.as_allocated_hash_components()) - .cloned() - .collect(); - - let digest = constants.hash_with_witness(cs, pr, Some(block))?; - - Ok(Self { preimage, digest }) - } -} - -impl AllocatedNumHash { - fn alloc>( - cs: &mut CS, - constants: &HashConstants, - preimage: Vec>, - hash_circuit_witness_cache: Option<&mut HashCircuitWitnessCache>, - ) -> Result { - let constants = constants.constants(preimage.len().into()); - - let pr: Vec> = preimage.to_vec(); - - let digest = constants.hash(cs, pr, hash_circuit_witness_cache)?; - - Ok(Self { preimage, digest }) - } - fn alloc_with_witness>( - cs: &mut CS, - constants: &HashConstants, - preimage: Vec>, - block: &(WitnessBlock, Digest), - ) -> Result { - let constants = constants.constants(preimage.len().into()); - - let pr: Vec> = preimage.to_vec(); - - let digest = constants.hash_with_witness(cs, pr, Some(block))?; - - Ok(Self { preimage, digest }) - } -} - impl<'a, F: LurkField> HashConst<'a, F> { #[allow(dead_code)] fn cache_hash_witness>( @@ -269,70 +175,6 @@ impl<'a, F: LurkField> HashConst<'a, F> { } impl<'a, F: LurkField> AllocatedConsWitness<'a, F> { - pub fn from_cons_witness>( - cs: &mut CS, - s: &Store, - cons_circuit_witness: &'a ConsCircuitWitness, - ) -> Result { - let cons_witness = cons_circuit_witness.hash_witness; - let mut slots = Vec::with_capacity(cons_witness.slots.len()); - - let names_and_ptrs = cons_circuit_witness.names_and_ptrs(s); - let cons_constants: HashConst<'_, F> = s.poseidon_constants().constants(4.into()); - - let circuit_witness_blocks = if cs.is_witness_generator() - && lurk_config(None, None) - .perf - .witness_generation - .precompute_neptune - { - Some(cons_circuit_witness.circuit_witness_blocks(s, &cons_constants)) - } else { - None - }; - - for (i, (name, spr)) in names_and_ptrs.iter().enumerate() { - let cs = &mut cs.namespace(|| format!("slot-{i}")); - - let allocated_car = AllocatedPtr::alloc(&mut cs.namespace(|| "car"), || { - spr.as_ref() - .map(|x| x.car) - .ok_or(SynthesisError::AssignmentMissing) - })?; - - let allocated_cdr = AllocatedPtr::alloc(&mut cs.namespace(|| "cdr"), || { - spr.as_ref() - .map(|x| x.cdr) - .ok_or(SynthesisError::AssignmentMissing) - })?; - - let allocated_hash = if let Some(blocks) = circuit_witness_blocks { - AllocatedPtrHash::alloc_with_witness( - &mut cs.namespace(|| "cons"), - s.poseidon_constants(), - vec![allocated_car, allocated_cdr], - &blocks[i], - )? - } else { - AllocatedPtrHash::alloc( - &mut cs.namespace(|| "cons"), - s.poseidon_constants(), - vec![allocated_car, allocated_cdr], - None, - )? - }; - - if spr.is_some() { - slots.push(Slot::new(*name, allocated_hash)); - } else { - slots.push(Slot::new_dummy(allocated_hash)); - } - } - - Ok(Self { - slots: slots.to_vec(), - }) - } pub fn get_cons( &mut self, @@ -396,82 +238,6 @@ impl<'a, F: LurkField> AllocatedContWitness<'a, F> { } } - pub fn from_cont_witness>( - cs: &mut CS, - s: &Store, - cont_circuit_witness: &'a ContCircuitWitness, - ) -> Result { - let cont_witness = cont_circuit_witness.hash_witness; - let mut slots = Vec::with_capacity(cont_witness.slots.len()); - - let names_and_ptrs = cont_circuit_witness.names_and_ptrs(s); - let cont_constants: HashConst<'_, F> = s.poseidon_constants().constants(8.into()); - - let circuit_witness_blocks = if cs.is_witness_generator() - && lurk_config(None, None) - .perf - .witness_generation - .precompute_neptune - { - Some(cont_circuit_witness.circuit_witness_blocks(s, &cont_constants)) - } else { - None - }; - - for (i, (name, spr)) in names_and_ptrs.iter().enumerate() { - let cs = &mut cs.namespace(|| format!("slot-{i}")); - - let components = spr.as_ref().map(|spr| spr.components); - let allocated_components = if let Some(components) = components { - components - .iter() - .enumerate() - .map(|(i, component)| { - AllocatedNum::alloc(&mut cs.namespace(|| format!("component_{i}")), || { - Ok(*component) - }) - .unwrap() - }) - .collect::>() - } else { - (0..8usize) - .map(|i| { - AllocatedNum::alloc( - &mut cs.namespace(|| format!("component_{i}")), - // This should never be called, because this branch is only taken when stub is blank. - || Err(SynthesisError::AssignmentMissing), - ) - .unwrap() - }) - .collect::>() - }; - - let allocated_hash = if let Some(blocks) = circuit_witness_blocks { - AllocatedNumHash::alloc_with_witness( - &mut cs.namespace(|| "cont"), - s.poseidon_constants(), - allocated_components, - &blocks[i], - )? - } else { - AllocatedNumHash::alloc( - &mut cs.namespace(|| "cont"), - s.poseidon_constants(), - allocated_components, - None, - )? - }; - - if spr.as_ref().map(|spr| spr.cont).is_some() { - slots.push(Slot::new(*name, allocated_hash)); - } else { - slots.push(Slot::new_dummy(allocated_hash)); - } - } - - Ok(Self { slots }) - } - pub fn get_components( &mut self, name: ContName, diff --git a/src/config.rs b/src/config.rs index d2fd0a3148..41c0618a9c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -216,15 +216,6 @@ impl Flow { pub fn is_parallel(&self) -> bool { !self.is_sequential() } - - /// Returns the number of parallel threads to run - pub fn num_threads(&self) -> usize { - match self { - Self::Sequential => 1, - Self::Parallel => num_cpus::get(), - Self::ParallelN(threads) => *threads, - } - } } /// Shortcut to easily set `PerfConfig` diff --git a/src/hash_witness.rs b/src/hash_witness.rs index 2adcc6be24..c824225b7a 100644 --- a/src/hash_witness.rs +++ b/src/hash_witness.rs @@ -455,10 +455,6 @@ impl< Self::new_from_stub(Stub::Dummy) } - pub fn new_blank() -> Self { - Self::new_from_stub(Stub::Blank) - } - pub fn get_assigned_slot(&mut self, name: Name) -> &mut Stub { let i = name.index(); let (slot_name, p) = self.slots[i]; From f18bc273d19d7af02fcfa03b13339b01ccad7cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Thu, 9 Nov 2023 13:27:22 -0500 Subject: [PATCH 4/4] refactor: Refactor `CircuitHashWitness` and remove `HashConst` - Eliminated the `HashConst` struct from the `hash_witness.rs` source file. - Removed the unused `circuit_witness_blocks` and `names_and_ptrs` methods for the `CircuitHashWitness`. --- src/circuit/gadgets/hashes.rs | 1 - src/hash_witness.rs | 38 ----------------------------------- 2 files changed, 39 deletions(-) diff --git a/src/circuit/gadgets/hashes.rs b/src/circuit/gadgets/hashes.rs index 1f1c566e14..eca3103486 100644 --- a/src/circuit/gadgets/hashes.rs +++ b/src/circuit/gadgets/hashes.rs @@ -175,7 +175,6 @@ impl<'a, F: LurkField> HashConst<'a, F> { } impl<'a, F: LurkField> AllocatedConsWitness<'a, F> { - pub fn get_cons( &mut self, name: ConsName, diff --git a/src/hash_witness.rs b/src/hash_witness.rs index c824225b7a..9a49935f70 100644 --- a/src/hash_witness.rs +++ b/src/hash_witness.rs @@ -8,7 +8,6 @@ use once_cell::sync::OnceCell; use crate::cont::Continuation; use crate::error::ReductionError; use crate::field::{FWrap, LurkField}; -use crate::hash::HashConst; use crate::lurk_sym_ptr; use crate::ptr::{ContPtr, Ptr}; use crate::state::State; @@ -359,43 +358,6 @@ impl, const L: usize, F: LurkField> } } -impl, const L: usize, F: LurkField> - CircuitHashWitness -where - T::ScalarPtrRepr: Debug, -{ - pub fn names_and_ptrs(&self, s: &Store) -> &Vec<(Name, Option)> { - self.names_and_ptrs.get_or_init(|| { - self.hash_witness - .slots - .iter() - .map(|(name, x)| (*name, (*x).to_scalar_ptr_repr(s))) - .collect::>() - }) - } - - /// Precompute the witness blocks for all the named hashes. - pub fn circuit_witness_blocks( - &self, - s: &Store, - hash_constants: &HashConst<'_, F>, - ) -> &HashCircuitWitnessBlocks { - self.circuit_witness_blocks.get_or_init(|| { - // TODO: In order to be interesting or useful, this should call a Neptune - // API function (which doesn't exist yet) to perform batched witness-generation. - // That code could be optimized and parallelized, eventually even performed on GPU. - self.names_and_ptrs(s) - .iter() - .map(|(_, scalar_ptr_repr)| { - let scalar_ptr_repr = scalar_ptr_repr.as_ref().unwrap(); - let preimage = scalar_ptr_repr.preimage(); - hash_constants.cache_hash_witness_aux(&preimage) - }) - .collect::>() - }) - } -} - pub type ConsWitness = HashWitness, MAX_CONSES_PER_REDUCTION, F>; pub type ContWitness = HashWitness, MAX_CONTS_PER_REDUCTION, F>;