1use std::collections::BTreeSet;
7
8use crate::BlackBoxFunc;
9use crate::native_types::Witness;
10
11use acir_field::AcirField;
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13use thiserror::Error;
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
17#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
18pub enum FunctionInput<F> {
19 Constant(F),
21 Witness(Witness),
23}
24
25impl<F: std::fmt::Display> std::fmt::Display for FunctionInput<F> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 match &self {
28 FunctionInput::Constant(constant) => {
29 write!(f, "{constant}")
30 }
31 FunctionInput::Witness(witness) => {
32 write!(f, "w{}", witness.0)
33 }
34 }
35 }
36}
37
38impl<F> FunctionInput<F> {
39 pub fn is_constant(&self) -> bool {
40 match self {
41 FunctionInput::Constant(_) => true,
42 FunctionInput::Witness(_) => false,
43 }
44 }
45
46 pub fn to_witness(&self) -> Witness {
47 match self {
48 FunctionInput::Constant(_) => unreachable!("ICE - Expected Witness"),
49 FunctionInput::Witness(witness) => *witness,
50 }
51 }
52}
53
54#[derive(Clone, PartialEq, Eq, Debug, Error)]
55#[error("FunctionInput value has too many bits: value: {value}, {value_num_bits} >= {max_bits}")]
56pub struct InvalidInputBitSize {
57 pub value: String,
58 pub value_num_bits: u32,
59 pub max_bits: u32,
60}
61
62#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
68pub enum BlackBoxFuncCall<F> {
69 AES128Encrypt {
76 inputs: Vec<FunctionInput<F>>,
77 iv: Box<[FunctionInput<F>; 16]>,
78 key: Box<[FunctionInput<F>; 16]>,
79 outputs: Vec<Witness>,
80 },
81 AND { lhs: FunctionInput<F>, rhs: FunctionInput<F>, num_bits: u32, output: Witness },
88 XOR { lhs: FunctionInput<F>, rhs: FunctionInput<F>, num_bits: u32, output: Witness },
95 RANGE { input: FunctionInput<F>, num_bits: u32 },
99 Blake2s { inputs: Vec<FunctionInput<F>>, outputs: Box<[Witness; 32]> },
105 Blake3 { inputs: Vec<FunctionInput<F>>, outputs: Box<[Witness; 32]> },
110 EcdsaSecp256k1 {
132 public_key_x: Box<[FunctionInput<F>; 32]>,
133 public_key_y: Box<[FunctionInput<F>; 32]>,
134 #[serde(
135 serialize_with = "serialize_big_array",
136 deserialize_with = "deserialize_big_array_into_box"
137 )]
138 signature: Box<[FunctionInput<F>; 64]>,
139 hashed_message: Box<[FunctionInput<F>; 32]>,
140 predicate: FunctionInput<F>,
141 output: Witness,
142 },
143 EcdsaSecp256r1 {
147 public_key_x: Box<[FunctionInput<F>; 32]>,
148 public_key_y: Box<[FunctionInput<F>; 32]>,
149 #[serde(
150 serialize_with = "serialize_big_array",
151 deserialize_with = "deserialize_big_array_into_box"
152 )]
153 signature: Box<[FunctionInput<F>; 64]>,
154 hashed_message: Box<[FunctionInput<F>; 32]>,
155 predicate: FunctionInput<F>,
156 output: Witness,
157 },
158 MultiScalarMul {
177 points: Vec<FunctionInput<F>>,
178 scalars: Vec<FunctionInput<F>>,
179 predicate: FunctionInput<F>,
180 outputs: (Witness, Witness, Witness),
181 },
182 EmbeddedCurveAdd {
192 input1: Box<[FunctionInput<F>; 3]>,
193 input2: Box<[FunctionInput<F>; 3]>,
194 predicate: FunctionInput<F>,
195 outputs: (Witness, Witness, Witness),
196 },
197 Keccakf1600 { inputs: Box<[FunctionInput<F>; 25]>, outputs: Box<[Witness; 25]> },
201 RecursiveAggregation {
224 verification_key: Vec<FunctionInput<F>>,
226 proof: Vec<FunctionInput<F>>,
227 public_inputs: Vec<FunctionInput<F>>,
231 key_hash: FunctionInput<F>,
235 proof_type: u32,
242 predicate: FunctionInput<F>,
244 },
245 Poseidon2Permutation {
254 inputs: Vec<FunctionInput<F>>,
256 outputs: Vec<Witness>,
258 },
259 Sha256Compression {
267 inputs: Box<[FunctionInput<F>; 16]>,
269 hash_values: Box<[FunctionInput<F>; 8]>,
271 outputs: Box<[Witness; 8]>,
273 },
274}
275
276impl<F> BlackBoxFuncCall<F> {
277 pub fn get_black_box_func(&self) -> BlackBoxFunc {
278 match self {
279 BlackBoxFuncCall::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt,
280 BlackBoxFuncCall::AND { .. } => BlackBoxFunc::AND,
281 BlackBoxFuncCall::XOR { .. } => BlackBoxFunc::XOR,
282 BlackBoxFuncCall::RANGE { .. } => BlackBoxFunc::RANGE,
283 BlackBoxFuncCall::Blake2s { .. } => BlackBoxFunc::Blake2s,
284 BlackBoxFuncCall::Blake3 { .. } => BlackBoxFunc::Blake3,
285 BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1,
286 BlackBoxFuncCall::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1,
287 BlackBoxFuncCall::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul,
288 BlackBoxFuncCall::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd,
289 BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600,
290 BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation,
291 BlackBoxFuncCall::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation,
292 BlackBoxFuncCall::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression,
293 }
294 }
295
296 pub fn name(&self) -> &str {
297 self.get_black_box_func().name()
298 }
299
300 pub fn bit_size(&self) -> Option<u32> {
301 match self {
302 BlackBoxFuncCall::AND { num_bits, .. }
303 | BlackBoxFuncCall::XOR { num_bits, .. }
304 | BlackBoxFuncCall::RANGE { num_bits, .. } => Some(*num_bits),
305 _ => None,
306 }
307 }
308
309 pub fn get_outputs_vec(&self) -> Vec<Witness> {
310 match self {
311 BlackBoxFuncCall::Blake2s { outputs, .. }
312 | BlackBoxFuncCall::Blake3 { outputs, .. } => outputs.to_vec(),
313
314 BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(),
315
316 BlackBoxFuncCall::Sha256Compression { outputs, .. } => outputs.to_vec(),
317
318 BlackBoxFuncCall::AES128Encrypt { outputs, .. }
319 | BlackBoxFuncCall::Poseidon2Permutation { outputs, .. } => outputs.clone(),
320
321 BlackBoxFuncCall::AND { output, .. }
322 | BlackBoxFuncCall::XOR { output, .. }
323 | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. }
324 | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output],
325 BlackBoxFuncCall::MultiScalarMul { outputs, .. }
326 | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => {
327 vec![outputs.0, outputs.1, outputs.2]
328 }
329 BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => {
330 vec![]
331 }
332 }
333 }
334}
335
336impl<F: Copy + AcirField> BlackBoxFuncCall<F> {
337 pub fn get_inputs_vec(&self) -> Vec<FunctionInput<F>> {
338 match self {
339 BlackBoxFuncCall::Blake2s { inputs, outputs: _ }
340 | BlackBoxFuncCall::Blake3 { inputs, outputs: _ }
341 | BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs: _ } => inputs.clone(),
342
343 BlackBoxFuncCall::Keccakf1600 { inputs, outputs: _ } => inputs.to_vec(),
344 BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs: _ } => {
345 [inputs, iv.as_slice(), key.as_slice()].concat()
346 }
347 BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs: _ } => {
348 [inputs.as_slice(), hash_values.as_slice()].concat()
349 }
350 BlackBoxFuncCall::AND { lhs, rhs, output: _, num_bits: _ }
351 | BlackBoxFuncCall::XOR { lhs, rhs, output: _, num_bits: _ } => {
352 vec![*lhs, *rhs]
353 }
354 BlackBoxFuncCall::RANGE { input, num_bits: _ } => vec![*input],
355
356 BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs: _ } => {
357 [points.as_slice(), scalars.as_slice(), &[*predicate]].concat()
358 }
359 BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs: _ } => {
360 vec![input1[0], input1[1], input1[2], input2[0], input2[1], input2[2], *predicate]
361 }
362 BlackBoxFuncCall::EcdsaSecp256k1 {
363 public_key_x,
364 public_key_y,
365 signature,
366 hashed_message,
367 predicate,
368 output: _,
369 } => [
370 public_key_x.as_slice(),
371 public_key_y.as_slice(),
372 signature.as_slice(),
373 hashed_message.as_slice(),
374 &[*predicate],
375 ]
376 .concat(),
377 BlackBoxFuncCall::EcdsaSecp256r1 {
378 public_key_x,
379 public_key_y,
380 signature,
381 hashed_message,
382 predicate,
383 output: _,
384 } => [
385 public_key_x.as_slice(),
386 public_key_y.as_slice(),
387 signature.as_slice(),
388 hashed_message.as_slice(),
389 &[*predicate],
390 ]
391 .concat(),
392 BlackBoxFuncCall::RecursiveAggregation {
393 verification_key: key,
394 proof,
395 public_inputs,
396 key_hash,
397 proof_type: _,
398 predicate,
399 } => [key.as_slice(), proof, public_inputs, &[*key_hash], &[*predicate]].concat(),
400 }
401 }
402
403 pub fn get_input_witnesses(&self) -> BTreeSet<Witness> {
404 let mut result = BTreeSet::new();
405 for input in self.get_inputs_vec() {
406 if let FunctionInput::Witness(w) = input {
407 result.insert(w);
408 }
409 }
410 result
411 }
412
413 pub fn get_predicate(&self) -> Option<Witness> {
414 let predicate = match self {
415 BlackBoxFuncCall::AES128Encrypt { .. }
416 | BlackBoxFuncCall::AND { .. }
417 | BlackBoxFuncCall::XOR { .. }
418 | BlackBoxFuncCall::RANGE { .. }
419 | BlackBoxFuncCall::Blake2s { .. }
420 | BlackBoxFuncCall::Blake3 { .. }
421 | BlackBoxFuncCall::Keccakf1600 { .. }
422 | BlackBoxFuncCall::Poseidon2Permutation { .. }
423 | BlackBoxFuncCall::Sha256Compression { .. } => FunctionInput::Constant(F::one()),
424 BlackBoxFuncCall::EcdsaSecp256k1 { predicate, .. }
425 | BlackBoxFuncCall::EcdsaSecp256r1 { predicate, .. }
426 | BlackBoxFuncCall::MultiScalarMul { predicate, .. }
427 | BlackBoxFuncCall::EmbeddedCurveAdd { predicate, .. }
428 | BlackBoxFuncCall::RecursiveAggregation { predicate, .. } => *predicate,
429 };
430 if predicate.is_constant() { None } else { Some(predicate.to_witness()) }
431 }
432}
433
434impl<F: std::fmt::Display + Copy> std::fmt::Display for BlackBoxFuncCall<F> {
435 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
436 let uppercase_name = self.name().to_uppercase();
437 write!(f, "BLACKBOX::{uppercase_name} ")?;
438
439 match self {
440 BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => {
441 let inputs = slice_to_string(inputs);
442 let iv = slice_to_string(&iv.to_vec());
443 let key = slice_to_string(&key.to_vec());
444 let outputs = slice_to_string(outputs);
445 write!(f, "inputs: {inputs}, iv: {iv}, key: {key}, outputs: {outputs}")?;
446 }
447 BlackBoxFuncCall::AND { lhs, rhs, num_bits, output }
448 | BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => {
449 write!(f, "lhs: {lhs}, rhs: {rhs}, output: {output}, bits: {num_bits}")?;
450 }
451 BlackBoxFuncCall::RANGE { input, num_bits } => {
452 write!(f, "input: {input}, bits: {num_bits}")?;
453 }
454 BlackBoxFuncCall::Blake2s { inputs, outputs }
455 | BlackBoxFuncCall::Blake3 { inputs, outputs } => {
456 let inputs = slice_to_string(inputs);
457 let outputs = slice_to_string(&outputs.to_vec());
458 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
459 }
460 BlackBoxFuncCall::EcdsaSecp256k1 {
461 public_key_x,
462 public_key_y,
463 signature,
464 hashed_message,
465 predicate,
466 output,
467 }
468 | BlackBoxFuncCall::EcdsaSecp256r1 {
469 public_key_x,
470 public_key_y,
471 signature,
472 hashed_message,
473 predicate,
474 output,
475 } => {
476 let public_key_x = slice_to_string(&public_key_x.to_vec());
477 let public_key_y = slice_to_string(&public_key_y.to_vec());
478 let signature = slice_to_string(&signature.to_vec());
479 let hashed_message = slice_to_string(&hashed_message.to_vec());
480 write!(
481 f,
482 "public_key_x: {public_key_x}, public_key_y: {public_key_y}, signature: {signature}, hashed_message: {hashed_message}, predicate: {predicate}, output: {output}"
483 )?;
484 }
485 BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } => {
486 let points = slice_to_string(points);
487 let scalars = slice_to_string(scalars);
488 write!(
489 f,
490 "points: {points}, scalars: {scalars}, predicate: {predicate}, outputs: [{}, {}, {}]",
491 outputs.0, outputs.1, outputs.2
492 )?;
493 }
494 BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } => {
495 let input1 = slice_to_string(&input1.to_vec());
496 let input2 = slice_to_string(&input2.to_vec());
497 write!(
498 f,
499 "input1: {input1}, input2: {input2}, predicate: {predicate}, outputs: [{}, {}, {}]",
500 outputs.0, outputs.1, outputs.2
501 )?;
502 }
503 BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => {
504 let inputs = slice_to_string(&inputs.to_vec());
505 let outputs = slice_to_string(&outputs.to_vec());
506 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
507 }
508 BlackBoxFuncCall::RecursiveAggregation {
509 verification_key,
510 proof,
511 public_inputs,
512 key_hash,
513 proof_type,
514 predicate,
515 } => {
516 let verification_key = slice_to_string(verification_key);
517 let proof = slice_to_string(proof);
518 let public_inputs = slice_to_string(public_inputs);
519 write!(
520 f,
521 "verification_key: {verification_key}, proof: {proof}, public_inputs: {public_inputs}, key_hash: {key_hash}, proof_type: {proof_type}, predicate: {predicate}"
522 )?;
523 }
524 BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => {
525 let inputs = slice_to_string(inputs);
526 let outputs = slice_to_string(outputs);
527 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
528 }
529 BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => {
530 let inputs = slice_to_string(&inputs.to_vec());
531 let hash_values = slice_to_string(&hash_values.to_vec());
532 let outputs = slice_to_string(&outputs.to_vec());
533 write!(f, "inputs: {inputs}, hash_values: {hash_values}, outputs: {outputs}")?;
534 }
535 }
536
537 Ok(())
538 }
539}
540
541fn slice_to_string<D: std::fmt::Display>(inputs: &[D]) -> String {
542 let inputs = inputs.iter().map(|i| i.to_string()).collect::<Vec<String>>().join(", ");
543 format!("[{inputs}]")
544}
545
546impl<F: std::fmt::Display + Copy> std::fmt::Debug for BlackBoxFuncCall<F> {
547 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
548 std::fmt::Display::fmt(self, f)
549 }
550}
551
552fn serialize_big_array<S, F: Serialize>(
553 big_array: &[FunctionInput<F>; 64],
554 s: S,
555) -> Result<S::Ok, S::Error>
556where
557 S: Serializer,
558{
559 use serde_big_array::BigArray;
560
561 (*big_array).serialize(s)
562}
563
564fn deserialize_big_array_into_box<'de, D, F: Deserialize<'de>>(
565 deserializer: D,
566) -> Result<Box<[FunctionInput<F>; 64]>, D::Error>
567where
568 D: Deserializer<'de>,
569{
570 use serde_big_array::BigArray;
571
572 let big_array: [FunctionInput<F>; 64] = BigArray::deserialize(deserializer)?;
573 Ok(Box::new(big_array))
574}
575
576#[cfg(test)]
577mod tests {
578
579 use crate::{circuit::Opcode, native_types::Witness};
580 use acir_field::{AcirField, FieldElement};
581
582 use super::{BlackBoxFuncCall, FunctionInput};
583
584 fn keccakf1600_opcode<F: AcirField>() -> Opcode<F> {
585 let inputs: Box<[FunctionInput<F>; 25]> =
586 Box::new(std::array::from_fn(|i| FunctionInput::Witness(Witness(i as u32 + 1))));
587 let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26)));
588
589 Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs })
590 }
591
592 #[test]
593 fn keccakf1600_serialization_roundtrip() {
594 use crate::serialization::{msgpack_deserialize, msgpack_serialize};
595
596 let opcode = keccakf1600_opcode::<FieldElement>();
597 let buf = msgpack_serialize(&opcode, true).unwrap();
598 let recovered_opcode = msgpack_deserialize(&buf).unwrap();
599 assert_eq!(opcode, recovered_opcode);
600 }
601}
602
603#[cfg(feature = "arb")]
604mod arb {
605 use acir_field::AcirField;
606 use proptest::prelude::*;
607
608 use crate::native_types::Witness;
609
610 use super::{BlackBoxFuncCall, FunctionInput};
611
612 impl<F> Arbitrary for BlackBoxFuncCall<F>
614 where
615 F: AcirField + Arbitrary,
616 {
617 type Parameters = ();
618 type Strategy = BoxedStrategy<Self>;
619
620 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
621 let input = any::<FunctionInput<F>>();
622 let input_vec = any::<Vec<FunctionInput<F>>>();
623 let input_arr_3 = any::<Box<[FunctionInput<F>; 3]>>();
624 let input_arr_8 = any::<Box<[FunctionInput<F>; 8]>>();
625 let input_arr_16 = any::<Box<[FunctionInput<F>; 16]>>();
626 let input_arr_25 = any::<Box<[FunctionInput<F>; 25]>>();
627 let input_arr_32 = any::<Box<[FunctionInput<F>; 32]>>();
628 let input_arr_64 = any::<Box<[FunctionInput<F>; 64]>>();
629 let witness = any::<Witness>();
630 let witness_vec = any::<Vec<Witness>>();
631 let witness_arr_8 = any::<Box<[Witness; 8]>>();
632 let witness_arr_25 = any::<Box<[Witness; 25]>>();
633 let witness_arr_32 = any::<Box<[Witness; 32]>>();
634
635 let witness_arr_16 = any::<Box<[Witness; 16]>>();
638 let case_aes128_encrypt =
639 (input_arr_16.clone(), input_arr_16.clone(), input_arr_16.clone(), witness_arr_16)
640 .prop_map(|(inputs, iv, key, outputs)| BlackBoxFuncCall::AES128Encrypt {
641 inputs: inputs.to_vec(),
642 iv,
643 key,
644 outputs: outputs.to_vec(),
645 });
646
647 let case_and = (input_arr_3.clone(), input_arr_8.clone(), witness.clone()).prop_map(
648 |(lhs, rhs, output)| BlackBoxFuncCall::AND {
649 lhs: lhs[0],
650 rhs: rhs[1],
651 num_bits: 8,
652 output,
653 },
654 );
655
656 let case_xor = (input_arr_3.clone(), input_arr_8.clone(), witness.clone()).prop_map(
657 |(lhs, rhs, output)| BlackBoxFuncCall::XOR {
658 lhs: lhs[0],
659 rhs: rhs[1],
660 num_bits: 8,
661 output,
662 },
663 );
664
665 let case_range = witness.clone().prop_map(|witness| BlackBoxFuncCall::RANGE {
666 input: FunctionInput::Witness(witness),
667 num_bits: 32,
668 });
669
670 let case_blake2s =
671 (input_arr_8.clone(), witness_arr_32.clone()).prop_map(|(inputs, outputs)| {
672 BlackBoxFuncCall::Blake2s { inputs: inputs.to_vec(), outputs }
673 });
674
675 let case_blake3 =
676 (input_arr_8.clone(), witness_arr_32).prop_map(|(inputs, outputs)| {
677 BlackBoxFuncCall::Blake3 { inputs: inputs.to_vec(), outputs }
678 });
679
680 let case_ecdsa_secp256k1 = (
681 input_arr_32.clone(),
682 input_arr_32.clone(),
683 input_arr_64.clone(),
684 input_arr_32.clone(),
685 witness.clone(),
686 input.clone(),
687 )
688 .prop_map(
689 |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| {
690 BlackBoxFuncCall::EcdsaSecp256k1 {
691 public_key_x,
692 public_key_y,
693 signature,
694 hashed_message,
695 output,
696 predicate,
697 }
698 },
699 );
700
701 let case_ecdsa_secp256r1 = (
702 input_arr_32.clone(),
703 input_arr_32.clone(),
704 input_arr_64,
705 input_arr_32,
706 witness.clone(),
707 input.clone(),
708 )
709 .prop_map(
710 |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| {
711 BlackBoxFuncCall::EcdsaSecp256r1 {
712 public_key_x,
713 public_key_y,
714 signature,
715 hashed_message,
716 output,
717 predicate,
718 }
719 },
720 );
721
722 let case_multi_scalar_mul = (
723 input_vec.clone(),
724 input_vec.clone(),
725 input.clone(),
726 witness.clone(),
727 witness.clone(),
728 witness.clone(),
729 )
730 .prop_map(|(points, scalars, predicate, w1, w2, w3)| {
731 BlackBoxFuncCall::MultiScalarMul {
732 points,
733 scalars,
734 predicate,
735 outputs: (w1, w2, w3),
736 }
737 });
738
739 let case_embedded_curve_add = (
740 input_arr_3.clone(),
741 input_arr_3,
742 input.clone(),
743 witness.clone(),
744 witness.clone(),
745 witness,
746 )
747 .prop_map(|(input1, input2, predicate, w1, w2, w3)| {
748 BlackBoxFuncCall::EmbeddedCurveAdd {
749 input1,
750 input2,
751 predicate,
752 outputs: (w1, w2, w3),
753 }
754 });
755
756 let case_keccakf1600 = (input_arr_25, witness_arr_25)
757 .prop_map(|(inputs, outputs)| BlackBoxFuncCall::Keccakf1600 { inputs, outputs });
758
759 let case_recursive_aggregation = (
760 input_vec.clone(),
761 input_vec.clone(),
762 input_vec.clone(),
763 input.clone(),
764 any::<u32>(),
765 input,
766 )
767 .prop_map(
768 |(verification_key, proof, public_inputs, key_hash, proof_type, predicate)| {
769 BlackBoxFuncCall::RecursiveAggregation {
770 verification_key,
771 proof,
772 public_inputs,
773 key_hash,
774 proof_type,
775 predicate,
776 }
777 },
778 );
779
780 let case_poseidon2_permutation =
781 (input_vec, witness_vec).prop_map(|(inputs, outputs)| {
782 BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs }
783 });
784
785 let case_sha256_compression = (input_arr_16, input_arr_8, witness_arr_8).prop_map(
786 |(inputs, hash_values, outputs)| BlackBoxFuncCall::Sha256Compression {
787 inputs,
788 hash_values,
789 outputs,
790 },
791 );
792
793 prop_oneof![
794 case_aes128_encrypt,
795 case_and,
796 case_xor,
797 case_range,
798 case_blake2s,
799 case_blake3,
800 case_ecdsa_secp256k1,
801 case_ecdsa_secp256r1,
802 case_multi_scalar_mul,
803 case_embedded_curve_add,
804 case_keccakf1600,
805 case_recursive_aggregation,
806 case_poseidon2_permutation,
807 case_sha256_compression,
808 ]
809 .boxed()
810 }
811 }
812}