1use std::collections::BTreeSet;
7
8use crate::BlackBoxFunc;
9use crate::native_types::Witness;
10
11use acir_field::AcirField;
12use msgpack_tagged::MsgpackTagged;
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use thiserror::Error;
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
18#[derive(Serialize, Deserialize, MsgpackTagged)]
19#[cfg_attr(feature = "arb", derive(proptest_derive::Arbitrary))]
20pub enum FunctionInput<F> {
21 #[tag(0)]
23 Constant(F),
24 #[tag(1)]
26 Witness(Witness),
27}
28
29impl<F: std::fmt::Display> std::fmt::Display for FunctionInput<F> {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match &self {
32 FunctionInput::Constant(constant) => {
33 write!(f, "{constant}")
34 }
35 FunctionInput::Witness(witness) => {
36 write!(f, "{witness}")
37 }
38 }
39 }
40}
41
42impl<F> FunctionInput<F> {
43 pub fn is_constant(&self) -> bool {
44 match self {
45 FunctionInput::Constant(_) => true,
46 FunctionInput::Witness(_) => false,
47 }
48 }
49
50 pub fn to_witness(&self) -> Witness {
51 match self {
52 FunctionInput::Constant(_) => unreachable!("ICE - Expected Witness"),
53 FunctionInput::Witness(witness) => *witness,
54 }
55 }
56}
57
58#[derive(Clone, PartialEq, Eq, Debug, Error)]
59#[error("FunctionInput value has too many bits: value: {value}, {value_num_bits} >= {max_bits}")]
60pub struct InvalidInputBitSize {
61 pub value: String,
62 pub value_num_bits: u32,
63 pub max_bits: u32,
64}
65
66#[derive(Clone, PartialEq, Eq, Hash)]
83#[derive(Serialize, Deserialize, MsgpackTagged)]
84pub enum BlackBoxFuncCall<F> {
85 #[tag(0)]
92 AES128Encrypt {
93 #[tag(0)]
94 inputs: Vec<FunctionInput<F>>,
95 #[tag(1)]
96 iv: Box<[FunctionInput<F>; 16]>,
97 #[tag(2)]
98 key: Box<[FunctionInput<F>; 16]>,
99 #[tag(3)]
100 outputs: Vec<Witness>,
101 },
102 #[tag(1)]
109 AND {
110 #[tag(0)]
111 lhs: FunctionInput<F>,
112 #[tag(1)]
113 rhs: FunctionInput<F>,
114 #[tag(2)]
115 num_bits: u32,
116 #[tag(3)]
117 output: Witness,
118 },
119 #[tag(2)]
126 XOR {
127 #[tag(0)]
128 lhs: FunctionInput<F>,
129 #[tag(1)]
130 rhs: FunctionInput<F>,
131 #[tag(2)]
132 num_bits: u32,
133 #[tag(3)]
134 output: Witness,
135 },
136 #[tag(3)]
140 RANGE {
141 #[tag(0)]
142 input: FunctionInput<F>,
143 #[tag(1)]
144 num_bits: u32,
145 },
146 #[tag(4)]
152 Blake2s {
153 #[tag(0)]
154 inputs: Vec<FunctionInput<F>>,
155 #[tag(1)]
156 outputs: Box<[Witness; 32]>,
157 },
158 #[tag(5)]
163 Blake3 {
164 #[tag(0)]
165 inputs: Vec<FunctionInput<F>>,
166 #[tag(1)]
167 outputs: Box<[Witness; 32]>,
168 },
169 #[tag(6)]
193 EcdsaSecp256k1 {
194 #[tag(0)]
195 public_key_x: Box<[FunctionInput<F>; 32]>,
196 #[tag(1)]
197 public_key_y: Box<[FunctionInput<F>; 32]>,
198 #[serde(
199 serialize_with = "serialize_big_array",
200 deserialize_with = "deserialize_big_array_into_box"
201 )]
202 #[tag(2)]
203 signature: Box<[FunctionInput<F>; 64]>,
204 #[tag(3)]
205 hashed_message: Box<[FunctionInput<F>; 32]>,
206 #[tag(4)]
207 predicate: FunctionInput<F>,
208 #[tag(5)]
209 output: Witness,
210 },
211 #[tag(7)]
215 EcdsaSecp256r1 {
216 #[tag(0)]
217 public_key_x: Box<[FunctionInput<F>; 32]>,
218 #[tag(1)]
219 public_key_y: Box<[FunctionInput<F>; 32]>,
220 #[serde(
221 serialize_with = "serialize_big_array",
222 deserialize_with = "deserialize_big_array_into_box"
223 )]
224 #[tag(2)]
225 signature: Box<[FunctionInput<F>; 64]>,
226 #[tag(3)]
227 hashed_message: Box<[FunctionInput<F>; 32]>,
228 #[tag(4)]
229 predicate: FunctionInput<F>,
230 #[tag(5)]
231 output: Witness,
232 },
233 #[tag(8)]
257 MultiScalarMul {
258 #[tag(0)]
259 points: Vec<FunctionInput<F>>,
260 #[tag(1)]
261 scalars: Vec<FunctionInput<F>>,
262 #[tag(2)]
263 predicate: FunctionInput<F>,
264 #[tag(3)]
265 outputs: (Witness, Witness),
266 },
267 #[tag(9)]
285 EmbeddedCurveAdd {
286 #[tag(0)]
287 input1: Box<[FunctionInput<F>; 2]>,
288 #[tag(1)]
289 input2: Box<[FunctionInput<F>; 2]>,
290 #[tag(2)]
291 predicate: FunctionInput<F>,
292 #[tag(3)]
293 outputs: (Witness, Witness),
294 },
295 #[tag(10)]
299 Keccakf1600 {
300 #[tag(0)]
301 inputs: Box<[FunctionInput<F>; 25]>,
302 #[tag(1)]
303 outputs: Box<[Witness; 25]>,
304 },
305 #[tag(11)]
328 RecursiveAggregation {
329 #[tag(0)]
331 verification_key: Vec<FunctionInput<F>>,
332 #[tag(1)]
333 proof: Vec<FunctionInput<F>>,
334 #[tag(2)]
338 public_inputs: Vec<FunctionInput<F>>,
339 #[tag(3)]
343 key_hash: FunctionInput<F>,
344 #[tag(4)]
351 proof_type: u32,
352 #[tag(5)]
355 predicate: FunctionInput<F>,
356 },
357 #[tag(12)]
366 Poseidon2Permutation {
367 #[tag(0)]
369 inputs: Vec<FunctionInput<F>>,
370 #[tag(1)]
372 outputs: Vec<Witness>,
373 },
374 #[tag(13)]
382 Sha256Compression {
383 #[tag(0)]
385 inputs: Box<[FunctionInput<F>; 16]>,
386 #[tag(1)]
388 hash_values: Box<[FunctionInput<F>; 8]>,
389 #[tag(2)]
391 outputs: Box<[Witness; 8]>,
392 },
393}
394
395impl<F> BlackBoxFuncCall<F> {
396 pub fn get_black_box_func(&self) -> BlackBoxFunc {
397 match self {
398 BlackBoxFuncCall::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt,
399 BlackBoxFuncCall::AND { .. } => BlackBoxFunc::AND,
400 BlackBoxFuncCall::XOR { .. } => BlackBoxFunc::XOR,
401 BlackBoxFuncCall::RANGE { .. } => BlackBoxFunc::RANGE,
402 BlackBoxFuncCall::Blake2s { .. } => BlackBoxFunc::Blake2s,
403 BlackBoxFuncCall::Blake3 { .. } => BlackBoxFunc::Blake3,
404 BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1,
405 BlackBoxFuncCall::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1,
406 BlackBoxFuncCall::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul,
407 BlackBoxFuncCall::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd,
408 BlackBoxFuncCall::Keccakf1600 { .. } => BlackBoxFunc::Keccakf1600,
409 BlackBoxFuncCall::RecursiveAggregation { .. } => BlackBoxFunc::RecursiveAggregation,
410 BlackBoxFuncCall::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation,
411 BlackBoxFuncCall::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression,
412 }
413 }
414
415 pub fn name(&self) -> &str {
416 self.get_black_box_func().name()
417 }
418
419 pub fn bit_size(&self) -> Option<u32> {
420 match self {
421 BlackBoxFuncCall::AND { num_bits, .. }
422 | BlackBoxFuncCall::XOR { num_bits, .. }
423 | BlackBoxFuncCall::RANGE { num_bits, .. } => Some(*num_bits),
424 _ => None,
425 }
426 }
427
428 pub fn get_outputs_vec(&self) -> Vec<Witness> {
429 match self {
430 BlackBoxFuncCall::Blake2s { outputs, .. }
431 | BlackBoxFuncCall::Blake3 { outputs, .. } => outputs.to_vec(),
432
433 BlackBoxFuncCall::Keccakf1600 { outputs, .. } => outputs.to_vec(),
434
435 BlackBoxFuncCall::Sha256Compression { outputs, .. } => outputs.to_vec(),
436
437 BlackBoxFuncCall::AES128Encrypt { outputs, .. }
438 | BlackBoxFuncCall::Poseidon2Permutation { outputs, .. } => outputs.clone(),
439
440 BlackBoxFuncCall::AND { output, .. }
441 | BlackBoxFuncCall::XOR { output, .. }
442 | BlackBoxFuncCall::EcdsaSecp256k1 { output, .. }
443 | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output],
444 BlackBoxFuncCall::MultiScalarMul { outputs, .. }
445 | BlackBoxFuncCall::EmbeddedCurveAdd { outputs, .. } => {
446 vec![outputs.0, outputs.1]
447 }
448 BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => {
449 vec![]
450 }
451 }
452 }
453}
454
455impl<F: Copy + AcirField> BlackBoxFuncCall<F> {
456 pub fn get_inputs_vec(&self) -> Vec<FunctionInput<F>> {
457 match self {
458 BlackBoxFuncCall::Blake2s { inputs, outputs: _ }
459 | BlackBoxFuncCall::Blake3 { inputs, outputs: _ }
460 | BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs: _ } => inputs.clone(),
461
462 BlackBoxFuncCall::Keccakf1600 { inputs, outputs: _ } => inputs.to_vec(),
463 BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs: _ } => {
464 [inputs, iv.as_slice(), key.as_slice()].concat()
465 }
466 BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs: _ } => {
467 [inputs.as_slice(), hash_values.as_slice()].concat()
468 }
469 BlackBoxFuncCall::AND { lhs, rhs, output: _, num_bits: _ }
470 | BlackBoxFuncCall::XOR { lhs, rhs, output: _, num_bits: _ } => {
471 vec![*lhs, *rhs]
472 }
473 BlackBoxFuncCall::RANGE { input, num_bits: _ } => vec![*input],
474
475 BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs: _ } => {
476 [points.as_slice(), scalars.as_slice(), &[*predicate]].concat()
477 }
478 BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs: _ } => {
479 vec![input1[0], input1[1], input2[0], input2[1], *predicate]
480 }
481 BlackBoxFuncCall::EcdsaSecp256k1 {
482 public_key_x,
483 public_key_y,
484 signature,
485 hashed_message,
486 predicate,
487 output: _,
488 } => [
489 public_key_x.as_slice(),
490 public_key_y.as_slice(),
491 signature.as_slice(),
492 hashed_message.as_slice(),
493 &[*predicate],
494 ]
495 .concat(),
496 BlackBoxFuncCall::EcdsaSecp256r1 {
497 public_key_x,
498 public_key_y,
499 signature,
500 hashed_message,
501 predicate,
502 output: _,
503 } => [
504 public_key_x.as_slice(),
505 public_key_y.as_slice(),
506 signature.as_slice(),
507 hashed_message.as_slice(),
508 &[*predicate],
509 ]
510 .concat(),
511 BlackBoxFuncCall::RecursiveAggregation {
512 verification_key: key,
513 proof,
514 public_inputs,
515 key_hash,
516 proof_type: _,
517 predicate,
518 } => [key.as_slice(), proof, public_inputs, &[*key_hash], &[*predicate]].concat(),
519 }
520 }
521
522 pub fn get_input_witnesses(&self) -> BTreeSet<Witness> {
523 let mut result = BTreeSet::new();
524 for input in self.get_inputs_vec() {
525 if let FunctionInput::Witness(w) = input {
526 result.insert(w);
527 }
528 }
529 result
530 }
531
532 pub fn get_predicate(&self) -> Option<Witness> {
533 let predicate = match self {
534 BlackBoxFuncCall::AES128Encrypt { .. }
535 | BlackBoxFuncCall::AND { .. }
536 | BlackBoxFuncCall::XOR { .. }
537 | BlackBoxFuncCall::RANGE { .. }
538 | BlackBoxFuncCall::Blake2s { .. }
539 | BlackBoxFuncCall::Blake3 { .. }
540 | BlackBoxFuncCall::Keccakf1600 { .. }
541 | BlackBoxFuncCall::Poseidon2Permutation { .. }
542 | BlackBoxFuncCall::Sha256Compression { .. } => FunctionInput::Constant(F::one()),
543 BlackBoxFuncCall::EcdsaSecp256k1 { predicate, .. }
544 | BlackBoxFuncCall::EcdsaSecp256r1 { predicate, .. }
545 | BlackBoxFuncCall::MultiScalarMul { predicate, .. }
546 | BlackBoxFuncCall::EmbeddedCurveAdd { predicate, .. }
547 | BlackBoxFuncCall::RecursiveAggregation { predicate, .. } => *predicate,
548 };
549 if predicate.is_constant() { None } else { Some(predicate.to_witness()) }
550 }
551}
552
553impl<F: std::fmt::Display + Copy> std::fmt::Display for BlackBoxFuncCall<F> {
554 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
555 let uppercase_name = self.name().to_uppercase();
556 write!(f, "BLACKBOX::{uppercase_name} ")?;
557
558 match self {
559 BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => {
560 let inputs = slice_to_string(inputs);
561 let iv = slice_to_string(&iv.to_vec());
562 let key = slice_to_string(&key.to_vec());
563 let outputs = slice_to_string(outputs);
564 write!(f, "inputs: {inputs}, iv: {iv}, key: {key}, outputs: {outputs}")?;
565 }
566 BlackBoxFuncCall::AND { lhs, rhs, num_bits, output }
567 | BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => {
568 write!(f, "lhs: {lhs}, rhs: {rhs}, output: {output}, bits: {num_bits}")?;
569 }
570 BlackBoxFuncCall::RANGE { input, num_bits } => {
571 write!(f, "input: {input}, bits: {num_bits}")?;
572 }
573 BlackBoxFuncCall::Blake2s { inputs, outputs }
574 | BlackBoxFuncCall::Blake3 { inputs, outputs } => {
575 let inputs = slice_to_string(inputs);
576 let outputs = slice_to_string(&outputs.to_vec());
577 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
578 }
579 BlackBoxFuncCall::EcdsaSecp256k1 {
580 public_key_x,
581 public_key_y,
582 signature,
583 hashed_message,
584 predicate,
585 output,
586 }
587 | BlackBoxFuncCall::EcdsaSecp256r1 {
588 public_key_x,
589 public_key_y,
590 signature,
591 hashed_message,
592 predicate,
593 output,
594 } => {
595 let public_key_x = slice_to_string(&public_key_x.to_vec());
596 let public_key_y = slice_to_string(&public_key_y.to_vec());
597 let signature = slice_to_string(&signature.to_vec());
598 let hashed_message = slice_to_string(&hashed_message.to_vec());
599 write!(
600 f,
601 "public_key_x: {public_key_x}, public_key_y: {public_key_y}, signature: {signature}, hashed_message: {hashed_message}, predicate: {predicate}, output: {output}"
602 )?;
603 }
604 BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } => {
605 let points = slice_to_string(points);
606 let scalars = slice_to_string(scalars);
607 write!(
608 f,
609 "points: {points}, scalars: {scalars}, predicate: {predicate}, outputs: [{}, {}]",
610 outputs.0, outputs.1
611 )?;
612 }
613 BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } => {
614 let input1 = slice_to_string(&input1.to_vec());
615 let input2 = slice_to_string(&input2.to_vec());
616 write!(
617 f,
618 "input1: {input1}, input2: {input2}, predicate: {predicate}, outputs: [{}, {}]",
619 outputs.0, outputs.1
620 )?;
621 }
622 BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => {
623 let inputs = slice_to_string(&inputs.to_vec());
624 let outputs = slice_to_string(&outputs.to_vec());
625 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
626 }
627 BlackBoxFuncCall::RecursiveAggregation {
628 verification_key,
629 proof,
630 public_inputs,
631 key_hash,
632 proof_type,
633 predicate,
634 } => {
635 let verification_key = slice_to_string(verification_key);
636 let proof = slice_to_string(proof);
637 let public_inputs = slice_to_string(public_inputs);
638 write!(
639 f,
640 "verification_key: {verification_key}, proof: {proof}, public_inputs: {public_inputs}, key_hash: {key_hash}, proof_type: {proof_type}, predicate: {predicate}"
641 )?;
642 }
643 BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => {
644 let inputs = slice_to_string(inputs);
645 let outputs = slice_to_string(outputs);
646 write!(f, "inputs: {inputs}, outputs: {outputs}")?;
647 }
648 BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => {
649 let inputs = slice_to_string(&inputs.to_vec());
650 let hash_values = slice_to_string(&hash_values.to_vec());
651 let outputs = slice_to_string(&outputs.to_vec());
652 write!(f, "inputs: {inputs}, hash_values: {hash_values}, outputs: {outputs}")?;
653 }
654 }
655
656 Ok(())
657 }
658}
659
660fn slice_to_string<D: std::fmt::Display>(inputs: &[D]) -> String {
661 let inputs = inputs.iter().map(|i| i.to_string()).collect::<Vec<String>>().join(", ");
662 format!("[{inputs}]")
663}
664
665impl<F: std::fmt::Display + Copy> std::fmt::Debug for BlackBoxFuncCall<F> {
666 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
667 std::fmt::Display::fmt(self, f)
668 }
669}
670
671fn serialize_big_array<S, F: Serialize>(
672 big_array: &[FunctionInput<F>; 64],
673 s: S,
674) -> Result<S::Ok, S::Error>
675where
676 S: Serializer,
677{
678 use serde_big_array::BigArray;
679
680 (*big_array).serialize(s)
681}
682
683fn deserialize_big_array_into_box<'de, D, F: Deserialize<'de>>(
684 deserializer: D,
685) -> Result<Box<[FunctionInput<F>; 64]>, D::Error>
686where
687 D: Deserializer<'de>,
688{
689 use serde_big_array::BigArray;
690
691 let big_array: [FunctionInput<F>; 64] = BigArray::deserialize(deserializer)?;
692 Ok(Box::new(big_array))
693}
694
695#[cfg(test)]
696mod tests {
697
698 use crate::{circuit::Opcode, native_types::Witness};
699 use acir_field::{AcirField, FieldElement};
700
701 use super::{BlackBoxFuncCall, FunctionInput};
702
703 fn keccakf1600_opcode<F: AcirField>() -> Opcode<F> {
704 let inputs: Box<[FunctionInput<F>; 25]> =
705 Box::new(std::array::from_fn(|i| FunctionInput::Witness(Witness(i as u32 + 1))));
706 let outputs: Box<[Witness; 25]> = Box::new(std::array::from_fn(|i| Witness(i as u32 + 26)));
707
708 Opcode::BlackBoxFuncCall(BlackBoxFuncCall::Keccakf1600 { inputs, outputs })
709 }
710
711 #[test]
712 fn keccakf1600_serialization_roundtrip() {
713 use crate::serialization::{msgpack_deserialize, msgpack_serialize};
714
715 let opcode = keccakf1600_opcode::<FieldElement>();
716 let buf = msgpack_serialize(&opcode, true).unwrap();
717 let recovered_opcode = msgpack_deserialize(&buf).unwrap();
718 assert_eq!(opcode, recovered_opcode);
719 }
720}
721
722#[cfg(feature = "arb")]
723mod arb {
724 use acir_field::AcirField;
725 use proptest::prelude::*;
726
727 use crate::native_types::Witness;
728
729 use super::{BlackBoxFuncCall, FunctionInput};
730
731 impl<F> Arbitrary for BlackBoxFuncCall<F>
733 where
734 F: AcirField + Arbitrary,
735 {
736 type Parameters = ();
737 type Strategy = BoxedStrategy<Self>;
738
739 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
740 let input = any::<FunctionInput<F>>();
741 let input_vec = any::<Vec<FunctionInput<F>>>();
742 let input_arr_2 = any::<Box<[FunctionInput<F>; 2]>>();
743 let input_arr_3 = any::<Box<[FunctionInput<F>; 3]>>();
744 let input_arr_8 = any::<Box<[FunctionInput<F>; 8]>>();
745 let input_arr_16 = any::<Box<[FunctionInput<F>; 16]>>();
746 let input_arr_25 = any::<Box<[FunctionInput<F>; 25]>>();
747 let input_arr_32 = any::<Box<[FunctionInput<F>; 32]>>();
748 let input_arr_64 = any::<Box<[FunctionInput<F>; 64]>>();
749 let witness = any::<Witness>();
750 let witness_vec = any::<Vec<Witness>>();
751 let witness_arr_8 = any::<Box<[Witness; 8]>>();
752 let witness_arr_25 = any::<Box<[Witness; 25]>>();
753 let witness_arr_32 = any::<Box<[Witness; 32]>>();
754
755 let witness_arr_16 = any::<Box<[Witness; 16]>>();
758 let case_aes128_encrypt =
759 (input_arr_16.clone(), input_arr_16.clone(), input_arr_16.clone(), witness_arr_16)
760 .prop_map(|(inputs, iv, key, outputs)| BlackBoxFuncCall::AES128Encrypt {
761 inputs: inputs.to_vec(),
762 iv,
763 key,
764 outputs: outputs.to_vec(),
765 });
766
767 let case_and = (input_arr_3.clone(), input_arr_8.clone(), witness.clone()).prop_map(
768 |(lhs, rhs, output)| BlackBoxFuncCall::AND {
769 lhs: lhs[0],
770 rhs: rhs[1],
771 num_bits: 8,
772 output,
773 },
774 );
775
776 let case_xor = (input_arr_3, input_arr_8.clone(), witness.clone()).prop_map(
777 |(lhs, rhs, output)| BlackBoxFuncCall::XOR {
778 lhs: lhs[0],
779 rhs: rhs[1],
780 num_bits: 8,
781 output,
782 },
783 );
784
785 let case_range = witness.clone().prop_map(|witness| BlackBoxFuncCall::RANGE {
786 input: FunctionInput::Witness(witness),
787 num_bits: 32,
788 });
789
790 let case_blake2s =
791 (input_arr_8.clone(), witness_arr_32.clone()).prop_map(|(inputs, outputs)| {
792 BlackBoxFuncCall::Blake2s { inputs: inputs.to_vec(), outputs }
793 });
794
795 let case_blake3 =
796 (input_arr_8.clone(), witness_arr_32).prop_map(|(inputs, outputs)| {
797 BlackBoxFuncCall::Blake3 { inputs: inputs.to_vec(), outputs }
798 });
799
800 let case_ecdsa_secp256k1 = (
801 input_arr_32.clone(),
802 input_arr_32.clone(),
803 input_arr_64.clone(),
804 input_arr_32.clone(),
805 witness.clone(),
806 input.clone(),
807 )
808 .prop_map(
809 |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| {
810 BlackBoxFuncCall::EcdsaSecp256k1 {
811 public_key_x,
812 public_key_y,
813 signature,
814 hashed_message,
815 output,
816 predicate,
817 }
818 },
819 );
820
821 let case_ecdsa_secp256r1 = (
822 input_arr_32.clone(),
823 input_arr_32.clone(),
824 input_arr_64,
825 input_arr_32,
826 witness.clone(),
827 input.clone(),
828 )
829 .prop_map(
830 |(public_key_x, public_key_y, signature, hashed_message, output, predicate)| {
831 BlackBoxFuncCall::EcdsaSecp256r1 {
832 public_key_x,
833 public_key_y,
834 signature,
835 hashed_message,
836 output,
837 predicate,
838 }
839 },
840 );
841
842 let case_multi_scalar_mul = (
843 input_vec.clone(),
844 input_vec.clone(),
845 input.clone(),
846 witness.clone(),
847 witness.clone(),
848 )
849 .prop_map(|(points, scalars, predicate, w1, w2)| {
850 BlackBoxFuncCall::MultiScalarMul {
851 points,
852 scalars,
853 predicate,
854 outputs: (w1, w2),
855 }
856 });
857
858 let case_embedded_curve_add =
859 (input_arr_2.clone(), input_arr_2, input.clone(), witness.clone(), witness)
860 .prop_map(|(input1, input2, predicate, w1, w2)| {
861 BlackBoxFuncCall::EmbeddedCurveAdd {
862 input1,
863 input2,
864 predicate,
865 outputs: (w1, w2),
866 }
867 });
868
869 let case_keccakf1600 = (input_arr_25, witness_arr_25)
870 .prop_map(|(inputs, outputs)| BlackBoxFuncCall::Keccakf1600 { inputs, outputs });
871
872 let case_recursive_aggregation = (
873 input_vec.clone(),
874 input_vec.clone(),
875 input_vec.clone(),
876 input.clone(),
877 any::<u32>(),
878 input,
879 )
880 .prop_map(
881 |(verification_key, proof, public_inputs, key_hash, proof_type, predicate)| {
882 BlackBoxFuncCall::RecursiveAggregation {
883 verification_key,
884 proof,
885 public_inputs,
886 key_hash,
887 proof_type,
888 predicate,
889 }
890 },
891 );
892
893 let case_poseidon2_permutation =
894 (input_vec, witness_vec).prop_map(|(inputs, outputs)| {
895 BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs }
896 });
897
898 let case_sha256_compression = (input_arr_16, input_arr_8, witness_arr_8).prop_map(
899 |(inputs, hash_values, outputs)| BlackBoxFuncCall::Sha256Compression {
900 inputs,
901 hash_values,
902 outputs,
903 },
904 );
905
906 prop_oneof![
907 case_aes128_encrypt,
908 case_and,
909 case_xor,
910 case_range,
911 case_blake2s,
912 case_blake3,
913 case_ecdsa_secp256k1,
914 case_ecdsa_secp256r1,
915 case_multi_scalar_mul,
916 case_embedded_curve_add,
917 case_keccakf1600,
918 case_recursive_aggregation,
919 case_poseidon2_permutation,
920 case_sha256_compression,
921 ]
922 .boxed()
923 }
924 }
925}