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