/ circuit / account / src / compute_key / ternary.rs
ternary.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm 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  
 16  use super::*;
 17  
 18  impl<A: Alpha> Ternary for ComputeKey<A> {
 19      type Boolean = Boolean<A>;
 20      type Output = ComputeKey<A>;
 21  
 22      /// Returns `first` if `condition` is `true`, otherwise returns `second`.
 23      fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output {
 24          Self {
 25              pk_sig: Group::ternary(condition, &first.pk_sig, &second.pk_sig),
 26              pr_sig: Group::ternary(condition, &first.pr_sig, &second.pr_sig),
 27              sk_prf: Scalar::ternary(condition, &first.sk_prf, &second.sk_prf),
 28          }
 29      }
 30  }
 31  
 32  impl<A: Alpha> Metrics<dyn Ternary<Boolean = Boolean<A>, Output = ComputeKey<A>>> for ComputeKey<A> {
 33      type Case = (Mode, Mode, Mode);
 34  
 35      fn count(case: &Self::Case) -> Count {
 36          match case {
 37              (Mode::Constant, _, _)
 38              | (Mode::Public, Mode::Constant, Mode::Constant)
 39              | (Mode::Private, Mode::Constant, Mode::Constant) => Count::is(0, 0, 0, 0),
 40              _ => Count::is(0, 0, 5, 5),
 41          }
 42      }
 43  }
 44  
 45  impl<A: Alpha> OutputMode<dyn Ternary<Boolean = Boolean<A>, Output = Self>> for ComputeKey<A> {
 46      type Case = (CircuitType<Boolean<A>>, Mode, Mode);
 47  
 48      fn output_mode(parameter: &Self::Case) -> Mode {
 49          match parameter.0.mode().is_constant() {
 50              true => match &parameter.0 {
 51                  CircuitType::Constant(constant) => match constant.eject_value() {
 52                      true => parameter.1,
 53                      false => parameter.2,
 54                  },
 55                  _ => A::halt("The constant condition is required to determine output mode."),
 56              },
 57              false => Mode::Private,
 58          }
 59      }
 60  }
 61  
 62  #[cfg(test)]
 63  mod tests {
 64      use super::*;
 65      use crate::Circuit;
 66      use console::TestRng;
 67  
 68      fn check_ternary(
 69          name: &str,
 70          expected: console::ComputeKey<<Circuit as Environment>::Network>,
 71          condition: Boolean<Circuit>,
 72          a: ComputeKey<Circuit>,
 73          b: ComputeKey<Circuit>,
 74      ) {
 75          Circuit::scope(name, || {
 76              let case = format!("({} ? {:?} : {:?})", condition.eject_value(), a.eject_value(), b.eject_value());
 77              let candidate = ComputeKey::ternary(&condition, &a, &b);
 78              assert_eq!(expected, candidate.eject_value(), "{case}");
 79              assert_count!(Ternary(Boolean, ComputeKey, ComputeKey) => ComputeKey, &(condition.eject_mode(), a.eject_mode(), b.eject_mode()));
 80              assert_output_mode!(Ternary(Boolean, ComputeKey, ComputeKey) => ComputeKey, &(CircuitType::from(&condition), a.eject_mode(), b.eject_mode()), candidate);
 81          });
 82      }
 83  
 84      #[test]
 85      fn test_constant_condition() {
 86          let mut rng = TestRng::default();
 87  
 88          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
 89          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
 90  
 91          // false ? Constant : Constant
 92          let expected = second;
 93          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
 94          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
 95          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
 96          check_ternary("false ? Constant : Constant", expected, condition, a, b);
 97  
 98          // false ? Constant : Public
 99          let expected = second;
100          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
101          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
102          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
103          check_ternary("false ? Constant : Public", expected, condition, a, b);
104  
105          // false ? Public : Constant
106          let expected = second;
107          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
108          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
109          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
110          check_ternary("false ? Public : Constant", expected, condition, a, b);
111  
112          // false ? Public : Public
113          let expected = second;
114          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
115          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
116          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
117          check_ternary("false ? Public : Public", expected, condition, a, b);
118  
119          // false ? Public : Private
120          let expected = second;
121          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
122          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
123          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
124          check_ternary("false ? Public : Private", expected, condition, a, b);
125  
126          // false ? Private : Private
127          let expected = second;
128          let condition = Boolean::<Circuit>::new(Mode::Constant, false);
129          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
130          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
131          check_ternary("false ? Private : Private", expected, condition, a, b);
132  
133          // true ? Constant : Constant
134          let expected = first;
135          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
136          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
137          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
138          check_ternary("true ? Constant : Constant", expected, condition, a, b);
139  
140          // true ? Constant : Public
141          let expected = first;
142          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
143          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
144          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
145          check_ternary("true ? Constant : Public", expected, condition, a, b);
146  
147          // true ? Public : Constant
148          let expected = first;
149          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
150          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
151          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
152          check_ternary("true ? Public : Constant", expected, condition, a, b);
153  
154          // true ? Public : Public
155          let expected = first;
156          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
157          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
158          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
159          check_ternary("true ? Public : Public", expected, condition, a, b);
160  
161          // true ? Public : Private
162          let expected = first;
163          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
164          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
165          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
166          check_ternary("true ? Public : Private", expected, condition, a, b);
167  
168          // true ? Private : Private
169          let expected = first;
170          let condition = Boolean::<Circuit>::new(Mode::Constant, true);
171          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
172          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
173          check_ternary("true ? Private : Private", expected, condition, a, b);
174      }
175  
176      #[test]
177      fn test_public_condition_and_constant_inputs() {
178          let mut rng = TestRng::default();
179  
180          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
181          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
182  
183          // false ? Constant : Constant
184          let expected = second;
185          let condition = Boolean::<Circuit>::new(Mode::Public, false);
186          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
187          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
188          check_ternary("false ? Constant : Constant", expected, condition, a, b);
189  
190          // true ? Constant : Constant
191          let expected = first;
192          let condition = Boolean::<Circuit>::new(Mode::Public, true);
193          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
194          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
195          check_ternary("true ? Constant : Constant", expected, condition, a, b);
196      }
197  
198      #[test]
199      fn test_public_condition_and_mixed_inputs() {
200          let mut rng = TestRng::default();
201  
202          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
203          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
204  
205          // false ? Constant : Public
206          let expected = second;
207          let condition = Boolean::<Circuit>::new(Mode::Public, false);
208          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
209          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
210          check_ternary("false ? Constant : Public", expected, condition, a, b);
211  
212          // false ? Public : Constant
213          let expected = second;
214          let condition = Boolean::<Circuit>::new(Mode::Public, false);
215          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
216          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
217          check_ternary("false ? Public : Constant", expected, condition, a, b);
218  
219          // true ? Constant : Public
220          let expected = first;
221          let condition = Boolean::<Circuit>::new(Mode::Public, true);
222          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
223          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
224          check_ternary("true ? Constant : Public", expected, condition, a, b);
225  
226          // true ? Public : Constant
227          let expected = first;
228          let condition = Boolean::<Circuit>::new(Mode::Public, true);
229          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
230          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
231          check_ternary("true ? Public : Constant", expected, condition, a, b);
232      }
233  
234      #[test]
235      fn test_private_condition_and_constant_inputs() {
236          let mut rng = TestRng::default();
237  
238          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
239          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
240  
241          // false ? Constant : Constant
242          let expected = second;
243          let condition = Boolean::<Circuit>::new(Mode::Private, false);
244          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
245          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
246          check_ternary("false ? Constant : Constant", expected, condition, a, b);
247  
248          // true ? Constant : Constant
249          let expected = first;
250          let condition = Boolean::<Circuit>::new(Mode::Private, true);
251          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
252          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
253          check_ternary("true ? Constant : Constant", expected, condition, a, b);
254      }
255  
256      #[test]
257      fn test_private_condition_and_mixed_inputs() {
258          let mut rng = TestRng::default();
259  
260          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
261          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
262  
263          // false ? Constant : Public
264          let expected = second;
265          let condition = Boolean::<Circuit>::new(Mode::Private, false);
266          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
267          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
268          check_ternary("false ? Constant : Public", expected, condition, a, b);
269  
270          // false ? Public : Constant
271          let expected = second;
272          let condition = Boolean::<Circuit>::new(Mode::Private, false);
273          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
274          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
275          check_ternary("false ? Public : Constant", expected, condition, a, b);
276  
277          // true ? Constant : Public
278          let expected = first;
279          let condition = Boolean::<Circuit>::new(Mode::Private, true);
280          let a = ComputeKey::<Circuit>::new(Mode::Constant, first);
281          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
282          check_ternary("true ? Constant : Public", expected, condition, a, b);
283  
284          // true ? Public : Constant
285          let expected = first;
286          let condition = Boolean::<Circuit>::new(Mode::Private, true);
287          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
288          let b = ComputeKey::<Circuit>::new(Mode::Constant, second);
289          check_ternary("true ? Public : Constant", expected, condition, a, b);
290      }
291  
292      #[test]
293      fn test_public_condition_and_variable_inputs() {
294          let mut rng = TestRng::default();
295  
296          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
297          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
298  
299          // false ? Public : Public
300          let expected = second;
301          let condition = Boolean::<Circuit>::new(Mode::Public, false);
302          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
303          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
304          check_ternary("false ? Public : Public", expected, condition, a, b);
305  
306          // false ? Public : Private
307          let expected = second;
308          let condition = Boolean::<Circuit>::new(Mode::Public, false);
309          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
310          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
311          check_ternary("false ? Public : Private", expected, condition, a, b);
312  
313          // false ? Private : Public
314          let expected = second;
315          let condition = Boolean::<Circuit>::new(Mode::Public, false);
316          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
317          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
318          check_ternary("false ? Private : Public", expected, condition, a, b);
319  
320          // false ? Private : Private
321          let expected = second;
322          let condition = Boolean::<Circuit>::new(Mode::Public, false);
323          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
324          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
325          check_ternary("false ? Private : Private", expected, condition, a, b);
326  
327          // true ? Public : Public
328          let expected = first;
329          let condition = Boolean::<Circuit>::new(Mode::Public, true);
330          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
331          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
332          check_ternary("true ? Public : Public", expected, condition, a, b);
333  
334          // true ? Public : Private
335          let expected = first;
336          let condition = Boolean::<Circuit>::new(Mode::Public, true);
337          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
338          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
339          check_ternary("true ? Public : Private", expected, condition, a, b);
340  
341          // true ? Private : Public
342          let expected = first;
343          let condition = Boolean::<Circuit>::new(Mode::Public, true);
344          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
345          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
346          check_ternary("true ? Private : Public", expected, condition, a, b);
347  
348          // true ? Private : Private
349          let expected = first;
350          let condition = Boolean::<Circuit>::new(Mode::Public, true);
351          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
352          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
353          check_ternary("true ? Private : Private", expected, condition, a, b);
354      }
355  
356      #[test]
357      fn test_private_condition_and_variable_inputs() {
358          let mut rng = TestRng::default();
359  
360          let first = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
361          let second = console::ComputeKey::try_from(console::PrivateKey::new(&mut rng).unwrap()).unwrap();
362  
363          // false ? Public : Public
364          let expected = second;
365          let condition = Boolean::<Circuit>::new(Mode::Private, false);
366          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
367          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
368          check_ternary("false ? Public : Public", expected, condition, a, b);
369  
370          // false ? Public : Private
371          let expected = second;
372          let condition = Boolean::<Circuit>::new(Mode::Private, false);
373          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
374          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
375          check_ternary("false ? Public : Private", expected, condition, a, b);
376  
377          // false ? Private : Public
378          let expected = second;
379          let condition = Boolean::<Circuit>::new(Mode::Private, false);
380          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
381          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
382          check_ternary("false ? Private : Public", expected, condition, a, b);
383  
384          // false ? Private : Private
385          let expected = second;
386          let condition = Boolean::<Circuit>::new(Mode::Private, false);
387          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
388          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
389          check_ternary("false ? Private : Private", expected, condition, a, b);
390  
391          // true ? Public : Public
392          let expected = first;
393          let condition = Boolean::<Circuit>::new(Mode::Private, true);
394          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
395          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
396          check_ternary("true ? Public : Public", expected, condition, a, b);
397  
398          // true ? Public : Private
399          let expected = first;
400          let condition = Boolean::<Circuit>::new(Mode::Private, true);
401          let a = ComputeKey::<Circuit>::new(Mode::Public, first);
402          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
403          check_ternary("true ? Public : Private", expected, condition, a, b);
404  
405          // true ? Private : Public
406          let expected = first;
407          let condition = Boolean::<Circuit>::new(Mode::Private, true);
408          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
409          let b = ComputeKey::<Circuit>::new(Mode::Public, second);
410          check_ternary("true ? Private : Public", expected, condition, a, b);
411  
412          // true ? Private : Private
413          let expected = first;
414          let condition = Boolean::<Circuit>::new(Mode::Private, true);
415          let a = ComputeKey::<Circuit>::new(Mode::Private, first);
416          let b = ComputeKey::<Circuit>::new(Mode::Private, second);
417          check_ternary("true ? Private : Private", expected, condition, a, b);
418      }
419  }