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