Skip to content

Commit 0376f0a

Browse files
committed
Determine range constraints from fixed lookup.
1 parent 4bb99be commit 0376f0a

File tree

5 files changed

+37
-23
lines changed

5 files changed

+37
-23
lines changed

executor/src/witgen/data_structures/mutable_state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ impl<'a, T: FieldElement, Q: QueryCallback<T>> MutableState<'a, T, Q> {
5656
identity_id: u64,
5757
known_inputs: &BitVec,
5858
range_constraints: &[Option<RangeConstraint<T>>],
59-
) -> bool {
59+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
6060
// TODO We are currently ignoring bus interaction (also, but not only because there is no
6161
// unique machine responsible for handling a bus send), so just answer "false" if the identity
6262
// has no responsible machine.
6363
self.responsible_machine(identity_id)
6464
.ok()
65-
.is_some_and(|mut machine| {
65+
.and_then(|mut machine| {
6666
machine.can_process_call_fully(identity_id, known_inputs, range_constraints)
6767
})
6868
}

executor/src/witgen/jit/witgen_inference.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,17 @@ impl<'a, T: FieldElement, FixedEval: FixedEvaluator<T>> WitgenInference<'a, T, F
203203
.collect_vec();
204204
let known = evaluated.iter().map(|e| e.is_some()).collect();
205205

206-
if !can_process_call.can_process_call_fully(lookup_id, &known, &range_constraints) {
206+
let Some(new_range_constraints) =
207+
can_process_call.can_process_call_fully(lookup_id, &known, &range_constraints)
208+
else {
207209
log::trace!(
208210
"Sub-machine cannot process call fully (will retry later): {lookup_id}, arguments: {}",
209211
arguments.iter().zip(known).map(|(arg, known)| {
210212
format!("{arg} [{}]", if known { "known" } else { "unknown" })
211213
}).format(", "));
212214
return ProcessResult::empty();
213-
}
215+
};
216+
// TODO process range constraints.
214217
let args = evaluated
215218
.into_iter()
216219
.zip(arguments)
@@ -480,16 +483,17 @@ pub trait FixedEvaluator<T: FieldElement> {
480483
}
481484

482485
pub trait CanProcessCall<T: FieldElement> {
483-
/// Returns true if a call to the machine that handles the given identity
486+
/// Returns Some(..) if a call to the machine that handles the given identity
484487
/// can always be processed with the given known inputs and range constraints
485488
/// on the parameters.
489+
/// The value in the Option is a vector of new range constraints.
486490
/// @see Machine::can_process_call
487491
fn can_process_call_fully(
488492
&self,
489493
_identity_id: u64,
490494
_known_inputs: &BitVec,
491495
_range_constraints: &[Option<RangeConstraint<T>>],
492-
) -> bool;
496+
) -> Option<Vec<Option<RangeConstraint<T>>>>;
493497
}
494498

495499
impl<T: FieldElement, Q: QueryCallback<T>> CanProcessCall<T> for &MutableState<'_, T, Q> {
@@ -498,7 +502,7 @@ impl<T: FieldElement, Q: QueryCallback<T>> CanProcessCall<T> for &MutableState<'
498502
identity_id: u64,
499503
known_inputs: &BitVec,
500504
range_constraints: &[Option<RangeConstraint<T>>],
501-
) -> bool {
505+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
502506
MutableState::can_process_call_fully(self, identity_id, known_inputs, range_constraints)
503507
}
504508
}

executor/src/witgen/machines/double_sorted_witness_machine_32.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ impl<'a, T: FieldElement> Machine<'a, T> for DoubleSortedWitnesses32<'a, T> {
191191
identity_id: u64,
192192
known_arguments: &BitVec,
193193
range_constraints: &[Option<RangeConstraint<T>>],
194-
) -> bool {
194+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
195195
assert!(self.parts.connections.contains_key(&identity_id));
196196
assert_eq!(known_arguments.len(), 4);
197197
assert_eq!(range_constraints.len(), 4);
@@ -200,19 +200,22 @@ impl<'a, T: FieldElement> Machine<'a, T> for DoubleSortedWitnesses32<'a, T> {
200200

201201
// We need to known operation_id, step and address for all calls.
202202
if !known_arguments[0] || !known_arguments[1] || !known_arguments[2] {
203-
return false;
203+
return None;
204204
}
205205

206206
// For the value, it depends: If we write, we need to know it, if we read we do not need to know it.
207207
if known_arguments[3] {
208208
// It is known, so we are good anyway.
209-
true
209+
Some(vec![None; 4])
210210
} else {
211211
// It is not known, so we can only process if we do not write.
212-
range_constraints[0].as_ref().is_some_and(|rc| {
213-
!rc.allows_value(T::from(OPERATION_ID_BOOTLOADER_WRITE))
214-
&& !rc.allows_value(T::from(OPERATION_ID_WRITE))
215-
})
212+
range_constraints[0]
213+
.as_ref()
214+
.is_some_and(|rc| {
215+
!rc.allows_value(T::from(OPERATION_ID_BOOTLOADER_WRITE))
216+
&& !rc.allows_value(T::from(OPERATION_ID_WRITE))
217+
})
218+
.then(|| vec![None; 4])
216219
}
217220
}
218221

executor/src/witgen/machines/fixed_lookup_machine.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,10 @@ impl<'a, T: FieldElement> Machine<'a, T> for FixedLookup<'a, T> {
302302
&mut self,
303303
identity_id: u64,
304304
known_arguments: &BitVec,
305-
_range_constraints: &[Option<RangeConstraint<T>>],
306-
) -> bool {
305+
range_constraints: &[Option<RangeConstraint<T>>],
306+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
307307
if !Self::is_responsible(&self.connections[&identity_id]) {
308-
return false;
308+
return None;
309309
}
310310
let index = self
311311
.indices
@@ -317,7 +317,12 @@ impl<'a, T: FieldElement> Machine<'a, T> for FixedLookup<'a, T> {
317317
create_index(self.fixed_data, application, &self.connections)
318318
});
319319
// Check that if there is a match, it is unique.
320-
index.values().all(|value| value.0.is_some())
320+
if index.values().all(|value| value.0.is_some()) {
321+
// TODO determine new range constraints.
322+
Some(range_constraints.to_vec())
323+
} else {
324+
None
325+
}
321326
}
322327

323328
fn process_plookup<Q: crate::witgen::QueryCallback<T>>(

executor/src/witgen/machines/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,23 @@ pub trait Machine<'a, T: FieldElement>: Send + Sync {
5555
);
5656
}
5757

58-
/// Returns true if this machine can alway fully process a call via the given
58+
/// Returns Some(..) if this machine can alway fully process a call via the given
5959
/// identity, the set of known arguments and a list of range constraints
6060
/// on the parameters. Note that the range constraints can be imposed both
6161
/// on inputs and on outputs.
62-
/// If this returns true, then corresponding calls to `process_lookup_direct`
62+
/// If this returns Some(..), then corresponding calls to `process_lookup_direct`
6363
/// are safe.
64+
/// The value returned inside the option is a vector of range constraints on the arguments,
65+
/// which again can be imposed both on inputs and on outputs.
6466
/// The function requires `&mut self` because it usually builds an index structure
6567
/// or something similar.
6668
fn can_process_call_fully(
6769
&mut self,
6870
_identity_id: u64,
6971
_known_arguments: &BitVec,
7072
_range_constraints: &[Option<RangeConstraint<T>>],
71-
) -> bool {
72-
false
73+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
74+
None
7375
}
7476

7577
/// Like `process_plookup`, but also records the time spent in this machine.
@@ -188,7 +190,7 @@ impl<'a, T: FieldElement> Machine<'a, T> for KnownMachine<'a, T> {
188190
identity_id: u64,
189191
known_arguments: &BitVec,
190192
range_constraints: &[Option<RangeConstraint<T>>],
191-
) -> bool {
193+
) -> Option<Vec<Option<RangeConstraint<T>>>> {
192194
match self {
193195
KnownMachine::SecondStageMachine(m) => {
194196
m.can_process_call_fully(identity_id, known_arguments, range_constraints)

0 commit comments

Comments
 (0)