snarkvm_circuit_types_field/
ternary.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<E: Environment> Ternary for Field<E> {
19    type Boolean = Boolean<E>;
20    type Output = Self;
21
22    /// Returns `first` if `condition` is `true`, otherwise returns `second`.
23    fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output {
24        // Constant `condition`
25        if condition.is_constant() {
26            match condition.eject_value() {
27                true => first.clone(),
28                false => second.clone(),
29            }
30        }
31        // Constant `first` and `second`
32        else if first.is_constant() && second.is_constant() {
33            let not_condition = Field::from_boolean(&!condition);
34            let condition = Field::from_boolean(condition);
35            (condition * first) + (not_condition * second)
36        }
37        // Variables
38        else {
39            // Initialize the witness.
40            let witness = witness!(|condition, first, second| match condition {
41                true => first,
42                false => second,
43            });
44
45            //
46            // Ternary Enforcement
47            // -------------------------------------------------------
48            //    witness = condition * a + (1 - condition) * b
49            // => witness = b + condition * (a - b)
50            // => (a - b) * condition = witness - b
51            //
52            //
53            // Assumption
54            // -------------------------------------------------------
55            // If a == b, either values suffices as a valid witness,
56            // and we may forgo the cases below. Else, we consider
57            // the following four cases.
58            //
59            //
60            // Case 1: condition = 0 AND witness = a (dishonest)
61            // -------------------------------------------------------
62            // (a - b) * 0 = a - b
63            //           0 = a - b
64            // => if a != b, as LHS != RHS, the witness is incorrect.
65            //
66            //
67            // Case 2: condition = 0 AND witness = b (honest)
68            // -------------------------------------------------------
69            // (a - b) * 0 = b - b
70            //           0 = 0
71            // => as LHS == RHS, the witness is correct.
72            //
73            //
74            // Case 3: condition = 1 AND witness = a (honest)
75            // -------------------------------------------------------
76            // (a - b) * 1 = a - b
77            //       a - b = a - b
78            // => as LHS == RHS, the witness is correct.
79            //
80            //
81            // Case 4: condition = 1 AND witness = b (dishonest)
82            // -------------------------------------------------------
83            // (a - b) * 1 = b - b
84            //       a - b = 0
85            // => if a != b, as LHS != RHS, the witness is incorrect.
86            //
87            E::enforce(|| ((first - second), condition, (&witness - second)));
88
89            witness
90        }
91    }
92}
93
94impl<E: Environment> Metrics<dyn Ternary<Boolean = Boolean<E>, Output = Field<E>>> for Field<E> {
95    type Case = (Mode, Mode, Mode);
96
97    fn count(case: &Self::Case) -> Count {
98        match case {
99            (Mode::Constant, _, _)
100            | (Mode::Public, Mode::Constant, Mode::Constant)
101            | (Mode::Private, Mode::Constant, Mode::Constant) => Count::is(0, 0, 0, 0),
102            _ => Count::is(0, 0, 1, 1),
103        }
104    }
105}
106
107impl<E: Environment> OutputMode<dyn Ternary<Boolean = Boolean<E>, Output = Field<E>>> for Field<E> {
108    type Case = (CircuitType<Boolean<E>>, Mode, Mode);
109
110    fn output_mode(parameter: &Self::Case) -> Mode {
111        match parameter.0.mode().is_constant() {
112            true => match &parameter.0 {
113                CircuitType::Constant(circuit) => match circuit.eject_value() {
114                    true => parameter.1,
115                    false => parameter.2,
116                },
117                _ => E::halt("Circuit is required to determine output mode."),
118            },
119            false => Mode::Private,
120        }
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127    use snarkvm_circuit_environment::Circuit;
128
129    fn check_ternary(
130        name: &str,
131        expected: console::Field<<Circuit as Environment>::Network>,
132        condition: Boolean<Circuit>,
133        a: Field<Circuit>,
134        b: Field<Circuit>,
135    ) {
136        Circuit::scope(name, || {
137            let case = format!("({} ? {} : {})", condition.eject_value(), a.eject_value(), b.eject_value());
138            let candidate = Field::ternary(&condition, &a, &b);
139            assert_eq!(expected, candidate.eject_value(), "{case}");
140            assert_count!(Ternary(Boolean, Field, Field) => Field, &(condition.eject_mode(), a.eject_mode(), b.eject_mode()));
141            assert_output_mode!(Ternary(Boolean, Field, Field) => Field, &(CircuitType::from(&condition), a.eject_mode(), b.eject_mode()), candidate);
142        });
143    }
144
145    #[test]
146    fn test_constant_condition() {
147        let mut rng = TestRng::default();
148
149        let first = Uniform::rand(&mut rng);
150        let second = Uniform::rand(&mut rng);
151
152        // false ? Constant : Constant
153        let expected = second;
154        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
155        let a = Field::<Circuit>::new(Mode::Constant, first);
156        let b = Field::<Circuit>::new(Mode::Constant, second);
157        check_ternary("false ? Constant : Constant", expected, condition, a, b);
158
159        // false ? Constant : Public
160        let expected = second;
161        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
162        let a = Field::<Circuit>::new(Mode::Constant, first);
163        let b = Field::<Circuit>::new(Mode::Public, second);
164        check_ternary("false ? Constant : Public", expected, condition, a, b);
165
166        // false ? Public : Constant
167        let expected = second;
168        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
169        let a = Field::<Circuit>::new(Mode::Public, first);
170        let b = Field::<Circuit>::new(Mode::Constant, second);
171        check_ternary("false ? Public : Constant", expected, condition, a, b);
172
173        // false ? Public : Public
174        let expected = second;
175        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
176        let a = Field::<Circuit>::new(Mode::Public, first);
177        let b = Field::<Circuit>::new(Mode::Public, second);
178        check_ternary("false ? Public : Public", expected, condition, a, b);
179
180        // false ? Public : Private
181        let expected = second;
182        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
183        let a = Field::<Circuit>::new(Mode::Public, first);
184        let b = Field::<Circuit>::new(Mode::Private, second);
185        check_ternary("false ? Public : Private", expected, condition, a, b);
186
187        // false ? Private : Private
188        let expected = second;
189        let condition = Boolean::<Circuit>::new(Mode::Constant, false);
190        let a = Field::<Circuit>::new(Mode::Private, first);
191        let b = Field::<Circuit>::new(Mode::Private, second);
192        check_ternary("false ? Private : Private", expected, condition, a, b);
193
194        // true ? Constant : Constant
195        let expected = first;
196        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
197        let a = Field::<Circuit>::new(Mode::Constant, first);
198        let b = Field::<Circuit>::new(Mode::Constant, second);
199        check_ternary("true ? Constant : Constant", expected, condition, a, b);
200
201        // true ? Constant : Public
202        let expected = first;
203        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
204        let a = Field::<Circuit>::new(Mode::Constant, first);
205        let b = Field::<Circuit>::new(Mode::Public, second);
206        check_ternary("true ? Constant : Public", expected, condition, a, b);
207
208        // true ? Public : Constant
209        let expected = first;
210        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
211        let a = Field::<Circuit>::new(Mode::Public, first);
212        let b = Field::<Circuit>::new(Mode::Constant, second);
213        check_ternary("true ? Public : Constant", expected, condition, a, b);
214
215        // true ? Public : Public
216        let expected = first;
217        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
218        let a = Field::<Circuit>::new(Mode::Public, first);
219        let b = Field::<Circuit>::new(Mode::Public, second);
220        check_ternary("true ? Public : Public", expected, condition, a, b);
221
222        // true ? Public : Private
223        let expected = first;
224        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
225        let a = Field::<Circuit>::new(Mode::Public, first);
226        let b = Field::<Circuit>::new(Mode::Private, second);
227        check_ternary("true ? Public : Private", expected, condition, a, b);
228
229        // true ? Private : Private
230        let expected = first;
231        let condition = Boolean::<Circuit>::new(Mode::Constant, true);
232        let a = Field::<Circuit>::new(Mode::Private, first);
233        let b = Field::<Circuit>::new(Mode::Private, second);
234        check_ternary("true ? Private : Private", expected, condition, a, b);
235    }
236
237    #[test]
238    fn test_public_condition_and_constant_inputs() {
239        let mut rng = TestRng::default();
240
241        let first = Uniform::rand(&mut rng);
242        let second = Uniform::rand(&mut rng);
243
244        // false ? Constant : Constant
245        let expected = second;
246        let condition = Boolean::<Circuit>::new(Mode::Public, false);
247        let a = Field::<Circuit>::new(Mode::Constant, first);
248        let b = Field::<Circuit>::new(Mode::Constant, second);
249        check_ternary("false ? Constant : Constant", expected, condition, a, b);
250
251        // true ? Constant : Constant
252        let expected = first;
253        let condition = Boolean::<Circuit>::new(Mode::Public, true);
254        let a = Field::<Circuit>::new(Mode::Constant, first);
255        let b = Field::<Circuit>::new(Mode::Constant, second);
256        check_ternary("true ? Constant : Constant", expected, condition, a, b);
257    }
258
259    #[test]
260    fn test_public_condition_and_mixed_inputs() {
261        let mut rng = TestRng::default();
262
263        let first = Uniform::rand(&mut rng);
264        let second = Uniform::rand(&mut rng);
265
266        // false ? Constant : Public
267        let expected = second;
268        let condition = Boolean::<Circuit>::new(Mode::Public, false);
269        let a = Field::<Circuit>::new(Mode::Constant, first);
270        let b = Field::<Circuit>::new(Mode::Public, second);
271        check_ternary("false ? Constant : Public", expected, condition, a, b);
272
273        // false ? Public : Constant
274        let expected = second;
275        let condition = Boolean::<Circuit>::new(Mode::Public, false);
276        let a = Field::<Circuit>::new(Mode::Public, first);
277        let b = Field::<Circuit>::new(Mode::Constant, second);
278        check_ternary("false ? Public : Constant", expected, condition, a, b);
279
280        // true ? Constant : Public
281        let expected = first;
282        let condition = Boolean::<Circuit>::new(Mode::Public, true);
283        let a = Field::<Circuit>::new(Mode::Constant, first);
284        let b = Field::<Circuit>::new(Mode::Public, second);
285        check_ternary("true ? Constant : Public", expected, condition, a, b);
286
287        // true ? Public : Constant
288        let expected = first;
289        let condition = Boolean::<Circuit>::new(Mode::Public, true);
290        let a = Field::<Circuit>::new(Mode::Public, first);
291        let b = Field::<Circuit>::new(Mode::Constant, second);
292        check_ternary("true ? Public : Constant", expected, condition, a, b);
293    }
294
295    #[test]
296    fn test_private_condition_and_constant_inputs() {
297        let mut rng = TestRng::default();
298
299        let first = Uniform::rand(&mut rng);
300        let second = Uniform::rand(&mut rng);
301
302        // false ? Constant : Constant
303        let expected = second;
304        let condition = Boolean::<Circuit>::new(Mode::Private, false);
305        let a = Field::<Circuit>::new(Mode::Constant, first);
306        let b = Field::<Circuit>::new(Mode::Constant, second);
307        check_ternary("false ? Constant : Constant", expected, condition, a, b);
308
309        // true ? Constant : Constant
310        let expected = first;
311        let condition = Boolean::<Circuit>::new(Mode::Private, true);
312        let a = Field::<Circuit>::new(Mode::Constant, first);
313        let b = Field::<Circuit>::new(Mode::Constant, second);
314        check_ternary("true ? Constant : Constant", expected, condition, a, b);
315    }
316
317    #[test]
318    fn test_private_condition_and_mixed_inputs() {
319        let mut rng = TestRng::default();
320
321        let first = Uniform::rand(&mut rng);
322        let second = Uniform::rand(&mut rng);
323
324        // false ? Constant : Public
325        let expected = second;
326        let condition = Boolean::<Circuit>::new(Mode::Private, false);
327        let a = Field::<Circuit>::new(Mode::Constant, first);
328        let b = Field::<Circuit>::new(Mode::Public, second);
329        check_ternary("false ? Constant : Public", expected, condition, a, b);
330
331        // false ? Public : Constant
332        let expected = second;
333        let condition = Boolean::<Circuit>::new(Mode::Private, false);
334        let a = Field::<Circuit>::new(Mode::Public, first);
335        let b = Field::<Circuit>::new(Mode::Constant, second);
336        check_ternary("false ? Public : Constant", expected, condition, a, b);
337
338        // true ? Constant : Public
339        let expected = first;
340        let condition = Boolean::<Circuit>::new(Mode::Private, true);
341        let a = Field::<Circuit>::new(Mode::Constant, first);
342        let b = Field::<Circuit>::new(Mode::Public, second);
343        check_ternary("true ? Constant : Public", expected, condition, a, b);
344
345        // true ? Public : Constant
346        let expected = first;
347        let condition = Boolean::<Circuit>::new(Mode::Private, true);
348        let a = Field::<Circuit>::new(Mode::Public, first);
349        let b = Field::<Circuit>::new(Mode::Constant, second);
350        check_ternary("true ? Public : Constant", expected, condition, a, b);
351    }
352
353    #[test]
354    fn test_public_condition_and_variable_inputs() {
355        let mut rng = TestRng::default();
356
357        let first = Uniform::rand(&mut rng);
358        let second = Uniform::rand(&mut rng);
359
360        // false ? Public : Public
361        let expected = second;
362        let condition = Boolean::<Circuit>::new(Mode::Public, false);
363        let a = Field::<Circuit>::new(Mode::Public, first);
364        let b = Field::<Circuit>::new(Mode::Public, second);
365        check_ternary("false ? Public : Public", expected, condition, a, b);
366
367        // false ? Public : Private
368        let expected = second;
369        let condition = Boolean::<Circuit>::new(Mode::Public, false);
370        let a = Field::<Circuit>::new(Mode::Public, first);
371        let b = Field::<Circuit>::new(Mode::Private, second);
372        check_ternary("false ? Public : Private", expected, condition, a, b);
373
374        // false ? Private : Public
375        let expected = second;
376        let condition = Boolean::<Circuit>::new(Mode::Public, false);
377        let a = Field::<Circuit>::new(Mode::Private, first);
378        let b = Field::<Circuit>::new(Mode::Public, second);
379        check_ternary("false ? Private : Public", expected, condition, a, b);
380
381        // false ? Private : Private
382        let expected = second;
383        let condition = Boolean::<Circuit>::new(Mode::Public, false);
384        let a = Field::<Circuit>::new(Mode::Private, first);
385        let b = Field::<Circuit>::new(Mode::Private, second);
386        check_ternary("false ? Private : Private", expected, condition, a, b);
387
388        // true ? Public : Public
389        let expected = first;
390        let condition = Boolean::<Circuit>::new(Mode::Public, true);
391        let a = Field::<Circuit>::new(Mode::Public, first);
392        let b = Field::<Circuit>::new(Mode::Public, second);
393        check_ternary("true ? Public : Public", expected, condition, a, b);
394
395        // true ? Public : Private
396        let expected = first;
397        let condition = Boolean::<Circuit>::new(Mode::Public, true);
398        let a = Field::<Circuit>::new(Mode::Public, first);
399        let b = Field::<Circuit>::new(Mode::Private, second);
400        check_ternary("true ? Public : Private", expected, condition, a, b);
401
402        // true ? Private : Public
403        let expected = first;
404        let condition = Boolean::<Circuit>::new(Mode::Public, true);
405        let a = Field::<Circuit>::new(Mode::Private, first);
406        let b = Field::<Circuit>::new(Mode::Public, second);
407        check_ternary("true ? Private : Public", expected, condition, a, b);
408
409        // true ? Private : Private
410        let expected = first;
411        let condition = Boolean::<Circuit>::new(Mode::Public, true);
412        let a = Field::<Circuit>::new(Mode::Private, first);
413        let b = Field::<Circuit>::new(Mode::Private, second);
414        check_ternary("true ? Private : Private", expected, condition, a, b);
415    }
416
417    #[test]
418    fn test_private_condition_and_variable_inputs() {
419        let mut rng = TestRng::default();
420
421        let first = Uniform::rand(&mut rng);
422        let second = Uniform::rand(&mut rng);
423
424        // false ? Public : Public
425        let expected = second;
426        let condition = Boolean::<Circuit>::new(Mode::Private, false);
427        let a = Field::<Circuit>::new(Mode::Public, first);
428        let b = Field::<Circuit>::new(Mode::Public, second);
429        check_ternary("false ? Public : Public", expected, condition, a, b);
430
431        // false ? Public : Private
432        let expected = second;
433        let condition = Boolean::<Circuit>::new(Mode::Private, false);
434        let a = Field::<Circuit>::new(Mode::Public, first);
435        let b = Field::<Circuit>::new(Mode::Private, second);
436        check_ternary("false ? Public : Private", expected, condition, a, b);
437
438        // false ? Private : Public
439        let expected = second;
440        let condition = Boolean::<Circuit>::new(Mode::Private, false);
441        let a = Field::<Circuit>::new(Mode::Private, first);
442        let b = Field::<Circuit>::new(Mode::Public, second);
443        check_ternary("false ? Private : Public", expected, condition, a, b);
444
445        // false ? Private : Private
446        let expected = second;
447        let condition = Boolean::<Circuit>::new(Mode::Private, false);
448        let a = Field::<Circuit>::new(Mode::Private, first);
449        let b = Field::<Circuit>::new(Mode::Private, second);
450        check_ternary("false ? Private : Private", expected, condition, a, b);
451
452        // true ? Public : Public
453        let expected = first;
454        let condition = Boolean::<Circuit>::new(Mode::Private, true);
455        let a = Field::<Circuit>::new(Mode::Public, first);
456        let b = Field::<Circuit>::new(Mode::Public, second);
457        check_ternary("true ? Public : Public", expected, condition, a, b);
458
459        // true ? Public : Private
460        let expected = first;
461        let condition = Boolean::<Circuit>::new(Mode::Private, true);
462        let a = Field::<Circuit>::new(Mode::Public, first);
463        let b = Field::<Circuit>::new(Mode::Private, second);
464        check_ternary("true ? Public : Private", expected, condition, a, b);
465
466        // true ? Private : Public
467        let expected = first;
468        let condition = Boolean::<Circuit>::new(Mode::Private, true);
469        let a = Field::<Circuit>::new(Mode::Private, first);
470        let b = Field::<Circuit>::new(Mode::Public, second);
471        check_ternary("true ? Private : Public", expected, condition, a, b);
472
473        // true ? Private : Private
474        let expected = first;
475        let condition = Boolean::<Circuit>::new(Mode::Private, true);
476        let a = Field::<Circuit>::new(Mode::Private, first);
477        let b = Field::<Circuit>::new(Mode::Private, second);
478        check_ternary("true ? Private : Private", expected, condition, a, b);
479    }
480}