diff --git a/executor/src/witgen/machines/dynamic_machine.rs b/executor/src/witgen/machines/dynamic_machine.rs index 7c95996a0..78cfecc42 100644 --- a/executor/src/witgen/machines/dynamic_machine.rs +++ b/executor/src/witgen/machines/dynamic_machine.rs @@ -230,6 +230,8 @@ impl<'a, T: FieldElement> DynamicMachine<'a, T> { &self.parts, SolverState::new(data, self.publics.clone()), mutable_state, + self.degree, + true, ); if let Some(outer_query) = outer_query { processor = processor.with_outer_query(outer_query); diff --git a/executor/src/witgen/machines/second_stage_machine.rs b/executor/src/witgen/machines/second_stage_machine.rs index 412bdb499..c957eeb72 100644 --- a/executor/src/witgen/machines/second_stage_machine.rs +++ b/executor/src/witgen/machines/second_stage_machine.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use powdr_ast::analyzed::Identity; use powdr_number::{DegreeType, FieldElement}; use std::collections::{BTreeMap, HashMap}; @@ -82,8 +83,17 @@ impl<'a, T: FieldElement> SecondStageMachine<'a, T> { parts.prover_functions, ); + let witness_sizes = fixed_data + .witness_cols + .values() + .filter_map(|w| w.external_values.as_ref()) + .map(|values| values.len()) + .unique() + .collect::>(); + let degree = witness_sizes.into_iter().exactly_one().unwrap() as DegreeType; + Self { - degree: parts.common_degree_range().max, + degree, name, fixed_data, parts, @@ -159,6 +169,8 @@ impl<'a, T: FieldElement> SecondStageMachine<'a, T> { &self.parts, SolverState::new(data, self.publics.clone()), mutable_state, + self.degree, + false, ); processor.run(true); let (updated_data, degree) = processor.finish(); diff --git a/executor/src/witgen/mod.rs b/executor/src/witgen/mod.rs index 1ce6d6c93..e1b59edad 100644 --- a/executor/src/witgen/mod.rs +++ b/executor/src/witgen/mod.rs @@ -570,7 +570,14 @@ impl<'a, T> FixedColumn<'a, T> { } pub fn values(&self, size: DegreeType) -> &[T] { - self.values.get_by_size(size).unwrap() + self.values.get_by_size(size).unwrap_or_else(|| { + panic!( + "Fixed column {} does not have a value for size {}. Available sizes: {:?}", + self.name, + size, + self.values.available_sizes() + ) + }) } pub fn values_max_size(&self) -> &[T] { diff --git a/executor/src/witgen/vm_processor.rs b/executor/src/witgen/vm_processor.rs index 65968eb4a..adc44c1d2 100644 --- a/executor/src/witgen/vm_processor.rs +++ b/executor/src/witgen/vm_processor.rs @@ -68,6 +68,9 @@ pub struct VmProcessor<'a, 'c, T: FieldElement, Q: QueryCallback> { last_report_time: Instant, processor: Processor<'a, 'c, T, Q>, progress_bar: ProgressBar, + /// If true, we'll periodically check if we are in a loop. If yes, we'll add new rows by + /// copying the old ones and check the constraints. + loop_detection: bool, } impl<'a, 'c, T: FieldElement, Q: QueryCallback> VmProcessor<'a, 'c, T, Q> { @@ -79,11 +82,11 @@ impl<'a, 'c, T: FieldElement, Q: QueryCallback> VmProcessor<'a, 'c, T, Q> { parts: &'c MachineParts<'a, T>, mutable_data: SolverState<'a, T>, mutable_state: &'c MutableState<'a, T, Q>, + degree: DegreeType, + loop_detection: bool, ) -> Self { let degree_range = parts.common_degree_range(); - let degree = degree_range.max; - let (identities_with_next, identities_without_next): (Vec<_>, Vec<_>) = parts .identities .iter() @@ -118,6 +121,7 @@ impl<'a, 'c, T: FieldElement, Q: QueryCallback> VmProcessor<'a, 'c, T, Q> { last_report_time: Instant::now(), processor, progress_bar, + loop_detection, } } @@ -181,7 +185,11 @@ impl<'a, 'c, T: FieldElement, Q: QueryCallback> VmProcessor<'a, 'c, T, Q> { } // Check if we are in a loop. - if looping_period.is_none() && row_index % 100 == 0 && row_index > 0 { + if looping_period.is_none() + && row_index % 100 == 0 + && row_index > 0 + && self.loop_detection + { looping_period = self.rows_are_repeating(row_index); if let Some(p) = looping_period { log::log!(