halo2_axiom/circuit/
value.rs

1use std::borrow::Borrow;
2use std::ops::{Add, Mul, Neg, Sub};
3
4use group::ff::Field;
5
6use crate::plonk::{Assigned, Error};
7
8/// A value that might exist within a circuit.
9///
10/// This behaves like `Option<V>` but differs in two key ways:
11/// - It does not expose the enum cases, or provide an `Option::unwrap` equivalent. This
12///   helps to ensure that unwitnessed values correctly propagate.
13/// - It provides pass-through implementations of common traits such as `Add` and `Mul`,
14///   for improved usability.
15#[derive(Clone, Copy, Debug)]
16pub struct Value<V> {
17    inner: Option<V>,
18}
19
20impl<V> Default for Value<V> {
21    fn default() -> Self {
22        Self::unknown()
23    }
24}
25
26impl<V> Value<V> {
27    /// Constructs an unwitnessed value.
28    pub const fn unknown() -> Self {
29        Self { inner: None }
30    }
31
32    /// Constructs a known value.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use halo2_axiom::circuit::Value;
38    ///
39    /// let v = Value::known(37);
40    /// ```
41    pub const fn known(value: V) -> Self {
42        Self { inner: Some(value) }
43    }
44
45    /// Obtains the inner value for assigning into the circuit.
46    ///
47    /// Returns `Error::Synthesis` if this is [`Value::unknown()`].
48    pub(crate) fn assign(self) -> Result<V, Error> {
49        self.inner.ok_or(Error::Synthesis)
50    }
51
52    /// Converts from `&Value<V>` to `Value<&V>`.
53    pub fn as_ref(&self) -> Value<&V> {
54        Value {
55            inner: self.inner.as_ref(),
56        }
57    }
58
59    /// Converts from `&mut Value<V>` to `Value<&mut V>`.
60    pub fn as_mut(&mut self) -> Value<&mut V> {
61        Value {
62            inner: self.inner.as_mut(),
63        }
64    }
65
66    /// ONLY FOR INTERNAL CRATE USAGE; DO NOT EXPOSE!
67    pub(crate) fn into_option(self) -> Option<V> {
68        self.inner
69    }
70
71    /// Enforces an assertion on the contained value, if known.
72    ///
73    /// The assertion is ignored if `self` is [`Value::unknown()`]. Do not try to enforce
74    /// circuit constraints with this method!
75    ///
76    /// # Panics
77    ///
78    /// Panics if `f` returns `false`.
79    pub fn assert_if_known<F: FnOnce(&V) -> bool>(&self, f: F) {
80        if let Some(value) = self.inner.as_ref() {
81            assert!(f(value));
82        }
83    }
84
85    /// Checks the contained value for an error condition, if known.
86    ///
87    /// The error check is ignored if `self` is [`Value::unknown()`]. Do not try to
88    /// enforce circuit constraints with this method!
89    pub fn error_if_known_and<F: FnOnce(&V) -> bool>(&self, f: F) -> Result<(), Error> {
90        match self.inner.as_ref() {
91            Some(value) if f(value) => Err(Error::Synthesis),
92            _ => Ok(()),
93        }
94    }
95
96    /// Maps a `Value<V>` to `Value<W>` by applying a function to the contained value.
97    pub fn map<W, F: FnOnce(V) -> W>(self, f: F) -> Value<W> {
98        Value {
99            inner: self.inner.map(f),
100        }
101    }
102
103    /// Returns [`Value::unknown()`] if the value is [`Value::unknown()`], otherwise calls
104    /// `f` with the wrapped value and returns the result.
105    pub fn and_then<W, F: FnOnce(V) -> Value<W>>(self, f: F) -> Value<W> {
106        match self.inner {
107            Some(v) => f(v),
108            None => Value::unknown(),
109        }
110    }
111
112    /// Zips `self` with another `Value`.
113    ///
114    /// If `self` is `Value::known(s)` and `other` is `Value::known(o)`, this method
115    /// returns `Value::known((s, o))`. Otherwise, [`Value::unknown()`] is returned.
116    pub fn zip<W>(self, other: Value<W>) -> Value<(V, W)> {
117        Value {
118            inner: self.inner.zip(other.inner),
119        }
120    }
121}
122
123impl<V, W> Value<(V, W)> {
124    /// Unzips a value containing a tuple of two values.
125    ///
126    /// If `self` is `Value::known((a, b)), this method returns
127    /// `(Value::known(a), Value::known(b))`. Otherwise,
128    /// `(Value::unknown(), Value::unknown())` is returned.
129    pub fn unzip(self) -> (Value<V>, Value<W>) {
130        match self.inner {
131            Some((a, b)) => (Value::known(a), Value::known(b)),
132            None => (Value::unknown(), Value::unknown()),
133        }
134    }
135}
136
137impl<V> Value<&V> {
138    /// Maps a `Value<&V>` to a `Value<V>` by copying the contents of the value.
139    #[must_use = "`self` will be dropped if the result is not used"]
140    pub fn copied(self) -> Value<V>
141    where
142        V: Copy,
143    {
144        Value {
145            inner: self.inner.copied(),
146        }
147    }
148
149    /// Maps a `Value<&V>` to a `Value<V>` by cloning the contents of the value.
150    #[must_use = "`self` will be dropped if the result is not used"]
151    pub fn cloned(self) -> Value<V>
152    where
153        V: Clone,
154    {
155        Value {
156            inner: self.inner.cloned(),
157        }
158    }
159}
160
161impl<V> Value<&mut V> {
162    /// Maps a `Value<&mut V>` to a `Value<V>` by copying the contents of the value.
163    #[must_use = "`self` will be dropped if the result is not used"]
164    pub fn copied(self) -> Value<V>
165    where
166        V: Copy,
167    {
168        Value {
169            inner: self.inner.copied(),
170        }
171    }
172
173    /// Maps a `Value<&mut V>` to a `Value<V>` by cloning the contents of the value.
174    #[must_use = "`self` will be dropped if the result is not used"]
175    pub fn cloned(self) -> Value<V>
176    where
177        V: Clone,
178    {
179        Value {
180            inner: self.inner.cloned(),
181        }
182    }
183}
184
185impl<V: Copy, const LEN: usize> Value<[V; LEN]> {
186    /// Transposes a `Value<[V; LEN]>` into a `[Value<V>; LEN]`.
187    ///
188    /// [`Value::unknown()`] will be mapped to `[Value::unknown(); LEN]`.
189    pub fn transpose_array(self) -> [Value<V>; LEN] {
190        let mut ret = [Value::unknown(); LEN];
191        if let Some(arr) = self.inner {
192            for (entry, value) in ret.iter_mut().zip(arr) {
193                *entry = Value::known(value);
194            }
195        }
196        ret
197    }
198}
199
200impl<V, I> Value<I>
201where
202    I: IntoIterator<Item = V>,
203    I::IntoIter: ExactSizeIterator,
204{
205    /// Transposes a `Value<impl IntoIterator<Item = V>>` into a `Vec<Value<V>>`.
206    ///
207    /// [`Value::unknown()`] will be mapped to `vec![Value::unknown(); length]`.
208    ///
209    /// # Panics
210    ///
211    /// Panics if `self` is `Value::known(values)` and `values.len() != length`.
212    pub fn transpose_vec(self, length: usize) -> Vec<Value<V>> {
213        match self.inner {
214            Some(values) => {
215                let values = values.into_iter();
216                assert_eq!(values.len(), length);
217                values.map(Value::known).collect()
218            }
219            None => (0..length).map(|_| Value::unknown()).collect(),
220        }
221    }
222}
223
224//
225// FromIterator
226//
227
228impl<A, V: FromIterator<A>> FromIterator<Value<A>> for Value<V> {
229    /// Takes each element in the [`Iterator`]: if it is [`Value::unknown()`], no further
230    /// elements are taken, and the [`Value::unknown()`] is returned. Should no
231    /// [`Value::unknown()`] occur, a container of type `V` containing the values of each
232    /// [`Value`] is returned.
233    fn from_iter<I: IntoIterator<Item = Value<A>>>(iter: I) -> Self {
234        Self {
235            inner: iter.into_iter().map(|v| v.inner).collect(),
236        }
237    }
238}
239
240//
241// Neg
242//
243
244impl<V: Neg> Neg for Value<V> {
245    type Output = Value<V::Output>;
246
247    fn neg(self) -> Self::Output {
248        Value {
249            inner: self.inner.map(|v| -v),
250        }
251    }
252}
253
254//
255// Add
256//
257
258impl<V, O> Add for Value<V>
259where
260    V: Add<Output = O>,
261{
262    type Output = Value<O>;
263
264    fn add(self, rhs: Self) -> Self::Output {
265        Value {
266            inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
267        }
268    }
269}
270
271impl<V, O> Add for &Value<V>
272where
273    for<'v> &'v V: Add<Output = O>,
274{
275    type Output = Value<O>;
276
277    fn add(self, rhs: Self) -> Self::Output {
278        Value {
279            inner: self
280                .inner
281                .as_ref()
282                .zip(rhs.inner.as_ref())
283                .map(|(a, b)| a + b),
284        }
285    }
286}
287
288impl<V, O> Add<Value<&V>> for Value<V>
289where
290    for<'v> V: Add<&'v V, Output = O>,
291{
292    type Output = Value<O>;
293
294    fn add(self, rhs: Value<&V>) -> Self::Output {
295        Value {
296            inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
297        }
298    }
299}
300
301impl<V, O> Add<Value<V>> for Value<&V>
302where
303    for<'v> &'v V: Add<V, Output = O>,
304{
305    type Output = Value<O>;
306
307    fn add(self, rhs: Value<V>) -> Self::Output {
308        Value {
309            inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
310        }
311    }
312}
313
314impl<V, O> Add<&Value<V>> for Value<V>
315where
316    for<'v> V: Add<&'v V, Output = O>,
317{
318    type Output = Value<O>;
319
320    fn add(self, rhs: &Self) -> Self::Output {
321        self + rhs.as_ref()
322    }
323}
324
325impl<V, O> Add<Value<V>> for &Value<V>
326where
327    for<'v> &'v V: Add<V, Output = O>,
328{
329    type Output = Value<O>;
330
331    fn add(self, rhs: Value<V>) -> Self::Output {
332        self.as_ref() + rhs
333    }
334}
335
336//
337// Sub
338//
339
340impl<V, O> Sub for Value<V>
341where
342    V: Sub<Output = O>,
343{
344    type Output = Value<O>;
345
346    fn sub(self, rhs: Self) -> Self::Output {
347        Value {
348            inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
349        }
350    }
351}
352
353impl<V, O> Sub for &Value<V>
354where
355    for<'v> &'v V: Sub<Output = O>,
356{
357    type Output = Value<O>;
358
359    fn sub(self, rhs: Self) -> Self::Output {
360        Value {
361            inner: self
362                .inner
363                .as_ref()
364                .zip(rhs.inner.as_ref())
365                .map(|(a, b)| a - b),
366        }
367    }
368}
369
370impl<V, O> Sub<Value<&V>> for Value<V>
371where
372    for<'v> V: Sub<&'v V, Output = O>,
373{
374    type Output = Value<O>;
375
376    fn sub(self, rhs: Value<&V>) -> Self::Output {
377        Value {
378            inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
379        }
380    }
381}
382
383impl<V, O> Sub<Value<V>> for Value<&V>
384where
385    for<'v> &'v V: Sub<V, Output = O>,
386{
387    type Output = Value<O>;
388
389    fn sub(self, rhs: Value<V>) -> Self::Output {
390        Value {
391            inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
392        }
393    }
394}
395
396impl<V, O> Sub<&Value<V>> for Value<V>
397where
398    for<'v> V: Sub<&'v V, Output = O>,
399{
400    type Output = Value<O>;
401
402    fn sub(self, rhs: &Self) -> Self::Output {
403        self - rhs.as_ref()
404    }
405}
406
407impl<V, O> Sub<Value<V>> for &Value<V>
408where
409    for<'v> &'v V: Sub<V, Output = O>,
410{
411    type Output = Value<O>;
412
413    fn sub(self, rhs: Value<V>) -> Self::Output {
414        self.as_ref() - rhs
415    }
416}
417
418//
419// Mul
420//
421
422impl<V, O> Mul for Value<V>
423where
424    V: Mul<Output = O>,
425{
426    type Output = Value<O>;
427
428    fn mul(self, rhs: Self) -> Self::Output {
429        Value {
430            inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
431        }
432    }
433}
434
435impl<V, O> Mul for &Value<V>
436where
437    for<'v> &'v V: Mul<Output = O>,
438{
439    type Output = Value<O>;
440
441    fn mul(self, rhs: Self) -> Self::Output {
442        Value {
443            inner: self
444                .inner
445                .as_ref()
446                .zip(rhs.inner.as_ref())
447                .map(|(a, b)| a * b),
448        }
449    }
450}
451
452impl<V, O> Mul<Value<&V>> for Value<V>
453where
454    for<'v> V: Mul<&'v V, Output = O>,
455{
456    type Output = Value<O>;
457
458    fn mul(self, rhs: Value<&V>) -> Self::Output {
459        Value {
460            inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
461        }
462    }
463}
464
465impl<V, O> Mul<Value<V>> for Value<&V>
466where
467    for<'v> &'v V: Mul<V, Output = O>,
468{
469    type Output = Value<O>;
470
471    fn mul(self, rhs: Value<V>) -> Self::Output {
472        Value {
473            inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
474        }
475    }
476}
477
478impl<V, O> Mul<&Value<V>> for Value<V>
479where
480    for<'v> V: Mul<&'v V, Output = O>,
481{
482    type Output = Value<O>;
483
484    fn mul(self, rhs: &Self) -> Self::Output {
485        self * rhs.as_ref()
486    }
487}
488
489impl<V, O> Mul<Value<V>> for &Value<V>
490where
491    for<'v> &'v V: Mul<V, Output = O>,
492{
493    type Output = Value<O>;
494
495    fn mul(self, rhs: Value<V>) -> Self::Output {
496        self.as_ref() * rhs
497    }
498}
499
500//
501// Assigned<Field>
502//
503
504impl<F: Field> From<Value<F>> for Value<Assigned<F>> {
505    fn from(value: Value<F>) -> Self {
506        Self {
507            inner: value.inner.map(Assigned::from),
508        }
509    }
510}
511
512impl<F: Field> Add<Value<F>> for Value<Assigned<F>> {
513    type Output = Value<Assigned<F>>;
514
515    fn add(self, rhs: Value<F>) -> Self::Output {
516        Value {
517            inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
518        }
519    }
520}
521
522impl<F: Field> Add<F> for Value<Assigned<F>> {
523    type Output = Value<Assigned<F>>;
524
525    fn add(self, rhs: F) -> Self::Output {
526        self + Value::known(rhs)
527    }
528}
529
530impl<F: Field> Add<Value<F>> for Value<&Assigned<F>> {
531    type Output = Value<Assigned<F>>;
532
533    fn add(self, rhs: Value<F>) -> Self::Output {
534        Value {
535            inner: self.inner.zip(rhs.inner).map(|(a, b)| a + b),
536        }
537    }
538}
539
540impl<F: Field> Add<F> for Value<&Assigned<F>> {
541    type Output = Value<Assigned<F>>;
542
543    fn add(self, rhs: F) -> Self::Output {
544        self + Value::known(rhs)
545    }
546}
547
548impl<F: Field> Sub<Value<F>> for Value<Assigned<F>> {
549    type Output = Value<Assigned<F>>;
550
551    fn sub(self, rhs: Value<F>) -> Self::Output {
552        Value {
553            inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
554        }
555    }
556}
557
558impl<F: Field> Sub<F> for Value<Assigned<F>> {
559    type Output = Value<Assigned<F>>;
560
561    fn sub(self, rhs: F) -> Self::Output {
562        self - Value::known(rhs)
563    }
564}
565
566impl<F: Field> Sub<Value<F>> for Value<&Assigned<F>> {
567    type Output = Value<Assigned<F>>;
568
569    fn sub(self, rhs: Value<F>) -> Self::Output {
570        Value {
571            inner: self.inner.zip(rhs.inner).map(|(a, b)| a - b),
572        }
573    }
574}
575
576impl<F: Field> Sub<F> for Value<&Assigned<F>> {
577    type Output = Value<Assigned<F>>;
578
579    fn sub(self, rhs: F) -> Self::Output {
580        self - Value::known(rhs)
581    }
582}
583
584impl<F: Field> Mul<Value<F>> for Value<Assigned<F>> {
585    type Output = Value<Assigned<F>>;
586
587    fn mul(self, rhs: Value<F>) -> Self::Output {
588        Value {
589            inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
590        }
591    }
592}
593
594impl<F: Field> Mul<F> for Value<Assigned<F>> {
595    type Output = Value<Assigned<F>>;
596
597    fn mul(self, rhs: F) -> Self::Output {
598        self * Value::known(rhs)
599    }
600}
601
602impl<F: Field> Mul<Value<F>> for Value<&Assigned<F>> {
603    type Output = Value<Assigned<F>>;
604
605    fn mul(self, rhs: Value<F>) -> Self::Output {
606        Value {
607            inner: self.inner.zip(rhs.inner).map(|(a, b)| a * b),
608        }
609    }
610}
611
612impl<F: Field> Mul<F> for Value<&Assigned<F>> {
613    type Output = Value<Assigned<F>>;
614
615    fn mul(self, rhs: F) -> Self::Output {
616        self * Value::known(rhs)
617    }
618}
619
620impl<V> Value<V> {
621    /// Returns the field element corresponding to this value.
622    pub fn to_field<F: Field>(&self) -> Value<Assigned<F>>
623    where
624        for<'v> Assigned<F>: From<&'v V>,
625    {
626        Value {
627            inner: self.inner.as_ref().map(|v| v.into()),
628        }
629    }
630
631    /// Returns the field element corresponding to this value.
632    pub fn into_field<F: Field>(self) -> Value<Assigned<F>>
633    where
634        V: Into<Assigned<F>>,
635    {
636        Value {
637            inner: self.inner.map(|v| v.into()),
638        }
639    }
640
641    /// Doubles this field element.
642    ///
643    /// # Examples
644    ///
645    /// If you have a `Value<F: Field>`, convert it to `Value<Assigned<F>>` first:
646    /// ```
647    /// # use halo2curves::pasta::pallas::Base as F;
648    /// use halo2_axiom::{circuit::Value, plonk::Assigned};
649    ///
650    /// let v = Value::known(F::from(2));
651    /// let v: Value<Assigned<F>> = v.into();
652    /// v.double();
653    /// ```
654    pub fn double<F: Field>(&self) -> Value<Assigned<F>>
655    where
656        V: Borrow<Assigned<F>>,
657    {
658        Value {
659            inner: self.inner.as_ref().map(|v| v.borrow().double()),
660        }
661    }
662
663    /// Squares this field element.
664    pub fn square<F: Field>(&self) -> Value<Assigned<F>>
665    where
666        V: Borrow<Assigned<F>>,
667    {
668        Value {
669            inner: self.inner.as_ref().map(|v| v.borrow().square()),
670        }
671    }
672
673    /// Cubes this field element.
674    pub fn cube<F: Field>(&self) -> Value<Assigned<F>>
675    where
676        V: Borrow<Assigned<F>>,
677    {
678        Value {
679            inner: self.inner.as_ref().map(|v| v.borrow().cube()),
680        }
681    }
682
683    /// Inverts this assigned value (taking the inverse of zero to be zero).
684    pub fn invert<F: Field>(&self) -> Value<Assigned<F>>
685    where
686        V: Borrow<Assigned<F>>,
687    {
688        Value {
689            inner: self.inner.as_ref().map(|v| v.borrow().invert()),
690        }
691    }
692}
693
694impl<F: Field> Value<Assigned<F>> {
695    /// Evaluates this value directly, performing an unbatched inversion if necessary.
696    ///
697    /// If the denominator is zero, the returned value is zero.
698    pub fn evaluate(self) -> Value<F> {
699        Value {
700            inner: self.inner.map(|v| v.evaluate()),
701        }
702    }
703}