1use alloc::format;
30use alloc::string::String;
31use core::f64::consts::LOG2_10;
32use core::fmt::Display;
33use core::str::FromStr;
34
35use serde::Serialize;
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
39pub enum SecurityAssumption {
40 UniqueDecoding,
42
43 JohnsonBound,
52
53 CapacityBound,
57}
58
59impl SecurityAssumption {
60 #[must_use]
67 pub const fn log_eta(&self, log_inv_rate: usize) -> f64 {
68 match self {
69 Self::UniqueDecoding => panic!("log_eta is undefined for UniqueDecoding"),
70 Self::JohnsonBound => -(0.5 * log_inv_rate as f64 + LOG2_10 + 1.),
72 Self::CapacityBound => -(log_inv_rate as f64 + LOG2_10 + 1.),
74 }
75 }
76
77 #[must_use]
84 pub const fn log_eta_or_zero(&self, log_inv_rate: usize) -> f64 {
85 match self {
86 Self::UniqueDecoding => 0.,
87 _ => self.log_eta(log_inv_rate),
88 }
89 }
90
91 #[must_use]
99 pub const fn list_size_bits_at_log_eta(
100 &self,
101 log_degree: usize,
102 log_inv_rate: usize,
103 log_eta: f64,
104 ) -> f64 {
105 match self {
106 Self::UniqueDecoding => 0.,
108
109 Self::JohnsonBound => {
117 let log_inv_sqrt_rate: f64 = log_inv_rate as f64 / 2.;
118 log_inv_sqrt_rate - (1. + log_eta)
119 }
120
121 Self::CapacityBound => (log_degree + log_inv_rate) as f64 - log_eta,
123 }
124 }
125
126 #[must_use]
128 pub const fn list_size_bits(&self, log_degree: usize, log_inv_rate: usize) -> f64 {
129 self.list_size_bits_at_log_eta(log_degree, log_inv_rate, self.log_eta_or_zero(log_inv_rate))
130 }
131
132 #[must_use]
149 pub fn prox_gaps_error(
150 &self,
151 log_degree: usize,
152 log_inv_rate: usize,
153 field_size_bits: usize,
154 num_functions: usize,
155 ) -> f64 {
156 self.prox_gaps_error_at_log_eta(
157 log_degree,
158 log_inv_rate,
159 field_size_bits,
160 num_functions,
161 self.log_eta_or_zero(log_inv_rate),
162 )
163 }
164
165 #[must_use]
179 pub fn prox_gaps_error_at_log_eta(
180 &self,
181 log_degree: usize,
182 log_inv_rate: usize,
183 field_size_bits: usize,
184 num_functions: usize,
185 log_eta: f64,
186 ) -> f64 {
187 assert!(
188 num_functions >= 2,
189 "num_functions must be >= 2 to compute proximity gaps error",
190 );
191
192 match self {
193 Self::UniqueDecoding => {
195 let error = (log_degree + log_inv_rate) as f64;
196 let num_functions_1_log = libm::log2(num_functions as f64 - 1.);
197 field_size_bits as f64 - (error + num_functions_1_log)
198 }
199
200 Self::JohnsonBound => {
203 let log_sqrt_rho_over_2eta = -(log_inv_rate as f64) / 2. - 1. - log_eta;
204 let m = libm::ceil(libm::pow(2., log_sqrt_rho_over_2eta)).max(3.) as usize;
205 Self::prox_gaps_error_jb_at_m(
206 log_degree,
207 log_inv_rate,
208 field_size_bits,
209 num_functions,
210 m,
211 )
212 }
213
214 Self::CapacityBound => {
216 let error = (log_degree + 2 * log_inv_rate) as f64 - log_eta;
217 let num_functions_1_log = libm::log2(num_functions as f64 - 1.);
218 field_size_bits as f64 - (error + num_functions_1_log)
219 }
220 }
221 }
222
223 #[must_use]
252 pub fn prox_gaps_error_jb_at_m(
253 log_degree: usize,
254 log_inv_rate: usize,
255 field_size_bits: usize,
256 num_functions: usize,
257 m: usize,
258 ) -> f64 {
259 assert!(
260 num_functions >= 2,
261 "num_functions must be >= 2 to compute proximity gaps error",
262 );
263 let error =
264 crate::proximity::johnson_exceptional_line_count_log2(log_degree, log_inv_rate, m);
265 let num_functions_1_log = libm::log2(num_functions as f64 - 1.);
266 field_size_bits as f64 - (error + num_functions_1_log)
267 }
268
269 #[must_use]
274 pub fn log_1_delta(&self, log_inv_rate: usize) -> f64 {
275 let log_twenty_one_over_twenty = libm::log2(21. / 20.);
276 match self {
277 Self::UniqueDecoding => libm::log2(1. + libm::pow(2., -(log_inv_rate as f64))) - 1.,
278 Self::JohnsonBound => log_twenty_one_over_twenty - 0.5 * log_inv_rate as f64,
279 Self::CapacityBound => log_twenty_one_over_twenty - log_inv_rate as f64,
280 }
281 }
282
283 #[must_use]
285 pub fn queries(&self, protocol_security_level: usize, log_inv_rate: usize) -> usize {
286 let num_queries_f = -(protocol_security_level as f64) / self.log_1_delta(log_inv_rate);
287
288 libm::ceil(num_queries_f) as usize
289 }
290
291 #[must_use]
293 pub fn queries_error(&self, log_inv_rate: usize, num_queries: usize) -> f64 {
294 let num_queries = num_queries as f64;
295
296 -num_queries * self.log_1_delta(log_inv_rate)
297 }
298}
299
300impl Display for SecurityAssumption {
301 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
302 f.write_str(match self {
303 Self::JohnsonBound => "JohnsonBound",
304 Self::CapacityBound => "CapacityBound",
305 Self::UniqueDecoding => "UniqueDecoding",
306 })
307 }
308}
309
310impl FromStr for SecurityAssumption {
311 type Err = String;
312
313 fn from_str(s: &str) -> Result<Self, Self::Err> {
314 match s {
315 "JohnsonBound" => Ok(Self::JohnsonBound),
316 "CapacityBound" => Ok(Self::CapacityBound),
317 "UniqueDecoding" => Ok(Self::UniqueDecoding),
318 _ => Err(format!("Invalid soundness specification: {s}")),
319 }
320 }
321}
322
323#[cfg(test)]
324#[allow(clippy::cast_lossless)]
325mod tests {
326 use alloc::string::ToString;
327
328 use super::*;
329
330 pub(crate) const KOALABEAR_QUINTIC_BITS: usize = 155;
337
338 #[test]
339 fn test_soundness_type_display() {
340 assert_eq!(SecurityAssumption::JohnsonBound.to_string(), "JohnsonBound");
341 assert_eq!(
342 SecurityAssumption::CapacityBound.to_string(),
343 "CapacityBound"
344 );
345 assert_eq!(
346 SecurityAssumption::UniqueDecoding.to_string(),
347 "UniqueDecoding"
348 );
349 }
350
351 #[test]
352 fn test_soundness_type_from_str() {
353 assert_eq!(
354 SecurityAssumption::from_str("JohnsonBound"),
355 Ok(SecurityAssumption::JohnsonBound)
356 );
357 assert_eq!(
358 SecurityAssumption::from_str("CapacityBound"),
359 Ok(SecurityAssumption::CapacityBound)
360 );
361 assert_eq!(
362 SecurityAssumption::from_str("UniqueDecoding"),
363 Ok(SecurityAssumption::UniqueDecoding)
364 );
365
366 assert!(SecurityAssumption::from_str("InvalidType").is_err());
368 assert!(SecurityAssumption::from_str("").is_err()); }
370
371 #[test]
372 #[should_panic(expected = "num_functions must be >= 2")]
373 fn prox_gaps_error_panics_when_num_functions_is_one() {
374 let assumption = SecurityAssumption::UniqueDecoding;
375 let _ = assumption.prox_gaps_error(1, 1, 64, 1);
376 }
377
378 #[test]
379 #[should_panic(expected = "num_functions must be >= 2")]
380 fn prox_gaps_error_panics_when_num_functions_is_zero() {
381 let assumption = SecurityAssumption::UniqueDecoding;
382 let _ = assumption.prox_gaps_error(1, 1, 64, 0);
383 }
384
385 #[test]
386 #[should_panic(expected = "num_functions must be >= 2")]
387 fn explicit_johnson_gap_rejects_a_singleton_batch() {
388 let _ = SecurityAssumption::prox_gaps_error_jb_at_m(1, 1, 64, 1, 3);
389 }
390
391 #[test]
392 #[should_panic(expected = "num_functions must be >= 2")]
393 fn explicit_johnson_gap_rejects_an_empty_batch() {
394 let _ = SecurityAssumption::prox_gaps_error_jb_at_m(1, 1, 64, 0, 3);
395 }
396
397 #[test]
398 fn test_ud_errors() {
399 let assumption = SecurityAssumption::UniqueDecoding;
400
401 let log_degree = 20;
403 let degree = (1 << log_degree) as f64;
404 let log_inv_rate = 2;
405 let rate = 1. / (1 << log_inv_rate) as f64;
406
407 let field_size_bits = 128;
408
409 assert!(assumption.list_size_bits(log_degree, log_inv_rate) - 0. < 0.01);
411
412 let computed_error =
414 assumption.prox_gaps_error(log_degree, log_inv_rate, field_size_bits, 2);
415 let real_error_non_log = degree / rate;
416 let real_error = field_size_bits as f64 - real_error_non_log.log2();
417
418 assert!((computed_error - real_error).abs() < 0.01);
419 }
420
421 #[test]
422 fn test_jb_errors() {
423 let assumption = SecurityAssumption::JohnsonBound;
424
425 let log_degree = 20;
427 let log_inv_rate = 2;
428 let rate = 1. / (1 << log_inv_rate) as f64;
429
430 let eta = rate.sqrt() / 20.;
431
432 let field_size_bits = 128;
433
434 let real_list_size = 1. / (2. * eta * rate.sqrt());
436 let computed_list_size = assumption.list_size_bits(log_degree, log_inv_rate);
437 assert!((real_list_size.log2() - computed_list_size).abs() < 0.01);
438
439 let computed_error =
444 assumption.prox_gaps_error(log_degree, log_inv_rate, field_size_bits, 2);
445
446 let n = (1_u64 << (log_degree + log_inv_rate)) as f64;
448 let rho_minus = ((1_u64 << log_degree) - 1) as f64 / n;
449 let real_error_non_log = 8. * n * 10.5_f64.powi(3) / (3. * rho_minus);
450 let real_error = field_size_bits as f64 - real_error_non_log.log2();
451
452 assert!(
453 (computed_error - real_error).abs() < 0.01,
454 "computed: {computed_error}, expected: {real_error}"
455 );
456 }
457
458 #[test]
459 fn test_cb_errors() {
460 let assumption = SecurityAssumption::CapacityBound;
461
462 let log_degree = 20;
464 let degree = (1 << log_degree) as f64;
465 let log_inv_rate = 2;
466 let rate = 1. / (1 << log_inv_rate) as f64;
467
468 let eta = rate / 20.;
469
470 let field_size_bits = 128;
471
472 let real_list_size = degree / (rate * eta);
474 let computed_list_size = assumption.list_size_bits(log_degree, log_inv_rate);
475 assert!((real_list_size.log2() - computed_list_size).abs() < 0.01);
476
477 let computed_error =
479 assumption.prox_gaps_error(log_degree, log_inv_rate, field_size_bits, 2);
480 let real_error_non_log = degree / (eta * rate.powi(2));
481 let real_error = field_size_bits as f64 - real_error_non_log.log2();
482
483 assert!((computed_error - real_error).abs() < 0.01);
484 }
485
486 #[test]
487 #[should_panic(expected = "log_eta is undefined for UniqueDecoding")]
488 fn log_eta_panics_for_unique_decoding() {
489 let _ = SecurityAssumption::UniqueDecoding.log_eta(5);
494 }
495
496 #[test]
497 fn log_one_minus_delta_is_stable_at_large_inverse_rates() {
498 let log_twenty_one_over_twenty = libm::log2(21. / 20.);
499
500 for log_inv_rate in [31, 32, 63] {
501 let unique = SecurityAssumption::UniqueDecoding.log_1_delta(log_inv_rate);
502 let johnson = SecurityAssumption::JohnsonBound.log_1_delta(log_inv_rate);
503 let capacity = SecurityAssumption::CapacityBound.log_1_delta(log_inv_rate);
504
505 assert!(unique.is_finite());
506 assert!(johnson.is_finite());
507 assert!(capacity.is_finite());
508 assert!(
509 (unique - (libm::log2(1. + libm::pow(2., -(log_inv_rate as f64))) - 1.)).abs()
510 < 1e-12
511 );
512 assert!(
513 (johnson - (log_twenty_one_over_twenty - 0.5 * log_inv_rate as f64)).abs() < 1e-12
514 );
515 assert!((capacity - (log_twenty_one_over_twenty - log_inv_rate as f64)).abs() < 1e-12);
516 }
517 }
518
519 fn bci20_jb_prox_gaps_error(
524 log_degree: usize,
525 log_inv_rate: usize,
526 field_size_bits: usize,
527 ) -> f64 {
528 const M_PLUS_HALF: f64 = 10.5;
529 let log_n_squared = 2.0 * (log_degree + log_inv_rate) as f64;
530 let log_leading_constant = libm::log2(libm::pow(M_PLUS_HALF, 7.0) / 3.0);
531 let log_rho_pow_neg_three_halves = 1.5 * log_inv_rate as f64;
532 let error_bits = log_n_squared + log_leading_constant + log_rho_pow_neg_three_halves;
533 field_size_bits as f64 - error_bits
534 }
535
536 #[test]
537 fn jb_prox_gap_strictly_improves_over_old_bound() {
538 let jb = SecurityAssumption::JohnsonBound;
541 for log_degree in 10..=25 {
542 for log_inv_rate in 1..=4 {
543 let new_bits =
544 jb.prox_gaps_error(log_degree, log_inv_rate, KOALABEAR_QUINTIC_BITS, 2);
545 let old_bits =
546 bci20_jb_prox_gaps_error(log_degree, log_inv_rate, KOALABEAR_QUINTIC_BITS);
547
548 assert!(
549 new_bits > old_bits,
550 "no improvement at log_degree={log_degree}, log_inv_rate={log_inv_rate}: \
551 new={new_bits:.4}, old={old_bits:.4}"
552 );
553
554 let log_n = (log_degree + log_inv_rate) as f64;
555 let rho = 2.0_f64.powi(-(log_inv_rate as i32));
556 let rho_minus = rho * (1.0 - 2.0_f64.powi(-(log_degree as i32)));
557 let new_count_log =
558 libm::log2(8.0 * 2.0_f64.powf(log_n) * 10.5_f64.powi(3) / (3.0 * rho_minus));
559 let old_count_log =
560 libm::log2(10.5_f64.powi(7) / 3.0) + 2.0 * log_n + 1.5 * log_inv_rate as f64;
561 let observed = new_bits - old_bits;
562 let expected = old_count_log - new_count_log;
563
564 assert!(
565 (observed - expected).abs() < 1e-9,
566 "gap mismatch at log_degree={log_degree}, log_inv_rate={log_inv_rate}: \
567 expected={expected:.6}, got={observed:.6}"
568 );
569 }
570 }
571 }
572
573 #[test]
574 fn jb_prox_gap_scales_by_log_curve_degree() {
575 let jb = SecurityAssumption::JohnsonBound;
577 let log_degree = 20;
578 let log_inv_rate = 2;
579
580 let line_bits = jb.prox_gaps_error(log_degree, log_inv_rate, KOALABEAR_QUINTIC_BITS, 2);
581
582 for (num_functions, expected_loss) in [(3_usize, 1.0_f64), (5, 2.0), (9, 3.0)] {
583 let curve_bits = jb.prox_gaps_error(
584 log_degree,
585 log_inv_rate,
586 KOALABEAR_QUINTIC_BITS,
587 num_functions,
588 );
589
590 let loss = line_bits - curve_bits;
591
592 assert!(
593 (loss - expected_loss).abs() < 1e-9,
594 "curve scaling off at num_functions={num_functions}: \
595 expected log_2({}) = {expected_loss:.1} bits, got {loss:.6}",
596 num_functions - 1
597 );
598 }
599 }
600
601 const TABLE_FIELD_BITS: usize = 155;
603
604 #[test]
605 fn fixed_eta_formulas_match_their_recorded_values() {
606 #[allow(clippy::type_complexity)]
615 let table: [(SecurityAssumption, usize, usize, [f64; 5]); 45] = [
616 (
617 SecurityAssumption::JohnsonBound,
618 1,
619 10,
620 [
621 4.321928094887362,
622 127.4066006621302,
623 282.35614381022526,
624 149.67807190511263,
625 144.28575448233389,
626 ],
627 ),
628 (
629 SecurityAssumption::JohnsonBound,
630 1,
631 20,
632 [
633 4.321928094887362,
634 117.40800885652301,
635 262.35614381022526,
636 149.67807190511263,
637 144.28575448233389,
638 ],
639 ),
640 (
641 SecurityAssumption::JohnsonBound,
642 1,
643 24,
644 [
645 4.321928094887362,
646 113.40801014639354,
647 254.35614381022526,
648 149.67807190511263,
649 144.28575448233389,
650 ],
651 ),
652 (
653 SecurityAssumption::JohnsonBound,
654 2,
655 10,
656 [
657 5.321928094887362,
658 125.4066006621302,
659 280.35614381022526,
660 148.67807190511263,
661 143.28575448233389,
662 ],
663 ),
664 (
665 SecurityAssumption::JohnsonBound,
666 2,
667 20,
668 [
669 5.321928094887362,
670 115.40800885652301,
671 260.35614381022526,
672 148.67807190511263,
673 143.28575448233389,
674 ],
675 ),
676 (
677 SecurityAssumption::JohnsonBound,
678 2,
679 24,
680 [
681 5.321928094887362,
682 111.40801014639355,
683 252.35614381022526,
684 148.67807190511263,
685 143.28575448233389,
686 ],
687 ),
688 (
689 SecurityAssumption::JohnsonBound,
690 3,
691 10,
692 [
693 6.321928094887362,
694 123.4066006621302,
695 278.35614381022526,
696 147.67807190511263,
697 142.28575448233389,
698 ],
699 ),
700 (
701 SecurityAssumption::JohnsonBound,
702 3,
703 20,
704 [
705 6.321928094887362,
706 113.40800885652301,
707 258.35614381022526,
708 147.67807190511263,
709 142.28575448233389,
710 ],
711 ),
712 (
713 SecurityAssumption::JohnsonBound,
714 3,
715 24,
716 [
717 6.321928094887362,
718 109.40801014639355,
719 250.35614381022526,
720 147.67807190511263,
721 142.28575448233389,
722 ],
723 ),
724 (
725 SecurityAssumption::JohnsonBound,
726 4,
727 10,
728 [
729 7.321928094887362,
730 121.4066006621302,
731 276.35614381022526,
732 146.67807190511263,
733 141.28575448233389,
734 ],
735 ),
736 (
737 SecurityAssumption::JohnsonBound,
738 4,
739 20,
740 [
741 7.321928094887362,
742 111.40800885652301,
743 256.35614381022526,
744 146.67807190511263,
745 141.28575448233389,
746 ],
747 ),
748 (
749 SecurityAssumption::JohnsonBound,
750 4,
751 24,
752 [
753 7.321928094887362,
754 107.40801014639355,
755 248.35614381022526,
756 146.67807190511263,
757 141.28575448233389,
758 ],
759 ),
760 (
761 SecurityAssumption::JohnsonBound,
762 8,
763 10,
764 [
765 11.321928094887362,
766 113.4066006621302,
767 268.35614381022526,
768 142.67807190511263,
769 137.28575448233389,
770 ],
771 ),
772 (
773 SecurityAssumption::JohnsonBound,
774 8,
775 20,
776 [
777 11.321928094887362,
778 103.40800885652301,
779 248.35614381022526,
780 142.67807190511263,
781 137.28575448233389,
782 ],
783 ),
784 (
785 SecurityAssumption::JohnsonBound,
786 8,
787 24,
788 [
789 11.321928094887362,
790 99.40801014639355,
791 240.35614381022526,
792 142.67807190511263,
793 137.28575448233389,
794 ],
795 ),
796 (
797 SecurityAssumption::CapacityBound,
798 1,
799 10,
800 [
801 16.32192809488736,
802 133.67807190511263,
803 258.35614381022526,
804 137.67807190511263,
805 132.28575448233389,
806 ],
807 ),
808 (
809 SecurityAssumption::CapacityBound,
810 1,
811 20,
812 [
813 26.32192809488736,
814 123.67807190511263,
815 218.35614381022526,
816 127.67807190511263,
817 122.28575448233389,
818 ],
819 ),
820 (
821 SecurityAssumption::CapacityBound,
822 1,
823 24,
824 [
825 30.32192809488736,
826 119.67807190511263,
827 202.35614381022526,
828 123.67807190511263,
829 118.28575448233389,
830 ],
831 ),
832 (
833 SecurityAssumption::CapacityBound,
834 2,
835 10,
836 [
837 18.32192809488736,
838 130.67807190511263,
839 254.35614381022526,
840 135.67807190511263,
841 130.28575448233389,
842 ],
843 ),
844 (
845 SecurityAssumption::CapacityBound,
846 2,
847 20,
848 [
849 28.32192809488736,
850 120.67807190511263,
851 214.35614381022526,
852 125.67807190511263,
853 120.28575448233389,
854 ],
855 ),
856 (
857 SecurityAssumption::CapacityBound,
858 2,
859 24,
860 [
861 32.32192809488736,
862 116.67807190511263,
863 198.35614381022526,
864 121.67807190511263,
865 116.28575448233389,
866 ],
867 ),
868 (
869 SecurityAssumption::CapacityBound,
870 3,
871 10,
872 [
873 20.32192809488736,
874 127.67807190511263,
875 250.35614381022526,
876 133.67807190511263,
877 128.28575448233389,
878 ],
879 ),
880 (
881 SecurityAssumption::CapacityBound,
882 3,
883 20,
884 [
885 30.32192809488736,
886 117.67807190511263,
887 210.35614381022526,
888 123.67807190511263,
889 118.28575448233389,
890 ],
891 ),
892 (
893 SecurityAssumption::CapacityBound,
894 3,
895 24,
896 [
897 34.32192809488736,
898 113.67807190511263,
899 194.35614381022526,
900 119.67807190511263,
901 114.28575448233389,
902 ],
903 ),
904 (
905 SecurityAssumption::CapacityBound,
906 4,
907 10,
908 [
909 22.32192809488736,
910 124.67807190511263,
911 246.35614381022526,
912 131.67807190511263,
913 126.28575448233389,
914 ],
915 ),
916 (
917 SecurityAssumption::CapacityBound,
918 4,
919 20,
920 [
921 32.32192809488736,
922 114.67807190511263,
923 206.35614381022526,
924 121.67807190511263,
925 116.28575448233389,
926 ],
927 ),
928 (
929 SecurityAssumption::CapacityBound,
930 4,
931 24,
932 [
933 36.32192809488736,
934 110.67807190511263,
935 190.35614381022526,
936 117.67807190511263,
937 112.28575448233389,
938 ],
939 ),
940 (
941 SecurityAssumption::CapacityBound,
942 8,
943 10,
944 [
945 30.32192809488736,
946 112.67807190511263,
947 230.35614381022526,
948 123.67807190511263,
949 118.28575448233389,
950 ],
951 ),
952 (
953 SecurityAssumption::CapacityBound,
954 8,
955 20,
956 [
957 40.32192809488736,
958 102.67807190511263,
959 190.35614381022526,
960 113.67807190511263,
961 108.28575448233389,
962 ],
963 ),
964 (
965 SecurityAssumption::CapacityBound,
966 8,
967 24,
968 [
969 44.32192809488736,
970 98.67807190511263,
971 174.35614381022526,
972 109.67807190511263,
973 104.28575448233389,
974 ],
975 ),
976 (
977 SecurityAssumption::UniqueDecoding,
978 1,
979 10,
980 [0.0, 140.0, 0.0, 154.0, 148.60768257722123],
981 ),
982 (
983 SecurityAssumption::UniqueDecoding,
984 1,
985 20,
986 [0.0, 130.0, 0.0, 154.0, 148.60768257722123],
987 ),
988 (
989 SecurityAssumption::UniqueDecoding,
990 1,
991 24,
992 [0.0, 126.0, 0.0, 154.0, 148.60768257722123],
993 ),
994 (
995 SecurityAssumption::UniqueDecoding,
996 2,
997 10,
998 [0.0, 139.0, 0.0, 154.0, 148.60768257722123],
999 ),
1000 (
1001 SecurityAssumption::UniqueDecoding,
1002 2,
1003 20,
1004 [0.0, 129.0, 0.0, 154.0, 148.60768257722123],
1005 ),
1006 (
1007 SecurityAssumption::UniqueDecoding,
1008 2,
1009 24,
1010 [0.0, 125.0, 0.0, 154.0, 148.60768257722123],
1011 ),
1012 (
1013 SecurityAssumption::UniqueDecoding,
1014 3,
1015 10,
1016 [0.0, 138.0, 0.0, 154.0, 148.60768257722123],
1017 ),
1018 (
1019 SecurityAssumption::UniqueDecoding,
1020 3,
1021 20,
1022 [0.0, 128.0, 0.0, 154.0, 148.60768257722123],
1023 ),
1024 (
1025 SecurityAssumption::UniqueDecoding,
1026 3,
1027 24,
1028 [0.0, 124.0, 0.0, 154.0, 148.60768257722123],
1029 ),
1030 (
1031 SecurityAssumption::UniqueDecoding,
1032 4,
1033 10,
1034 [0.0, 137.0, 0.0, 154.0, 148.60768257722123],
1035 ),
1036 (
1037 SecurityAssumption::UniqueDecoding,
1038 4,
1039 20,
1040 [0.0, 127.0, 0.0, 154.0, 148.60768257722123],
1041 ),
1042 (
1043 SecurityAssumption::UniqueDecoding,
1044 4,
1045 24,
1046 [0.0, 123.0, 0.0, 154.0, 148.60768257722123],
1047 ),
1048 (
1049 SecurityAssumption::UniqueDecoding,
1050 8,
1051 10,
1052 [0.0, 133.0, 0.0, 154.0, 148.60768257722123],
1053 ),
1054 (
1055 SecurityAssumption::UniqueDecoding,
1056 8,
1057 20,
1058 [0.0, 123.0, 0.0, 154.0, 148.60768257722123],
1059 ),
1060 (
1061 SecurityAssumption::UniqueDecoding,
1062 8,
1063 24,
1064 [0.0, 119.0, 0.0, 154.0, 148.60768257722123],
1065 ),
1066 ];
1067
1068 for (assumption, log_inv_rate, log_degree, expected) in table {
1069 let actual = [
1070 assumption.list_size_bits(log_degree, log_inv_rate),
1071 assumption.prox_gaps_error(log_degree, log_inv_rate, TABLE_FIELD_BITS, 17),
1072 assumption.ood_error(log_degree, log_inv_rate, TABLE_FIELD_BITS, 2),
1073 assumption.fold_sumcheck_error(TABLE_FIELD_BITS, log_degree, log_inv_rate),
1074 assumption.queries_combination_error(
1075 TABLE_FIELD_BITS,
1076 log_degree,
1077 log_inv_rate,
1078 2,
1079 40,
1080 ),
1081 ];
1082 assert_eq!(
1083 actual, expected,
1084 "{assumption:?} log_inv_rate={log_inv_rate} log_degree={log_degree}"
1085 );
1086 }
1087 }
1088
1089 #[test]
1090 fn jb_prox_gaps_default_eta_is_m_10() {
1091 let jb = SecurityAssumption::JohnsonBound;
1097 for log_inv_rate in 0..=32 {
1098 for log_degree in [10, 20, 24] {
1099 for num_functions in [2, 3, 17] {
1100 assert_eq!(
1101 jb.prox_gaps_error(log_degree, log_inv_rate, 128, num_functions),
1102 SecurityAssumption::prox_gaps_error_jb_at_m(
1103 log_degree,
1104 log_inv_rate,
1105 128,
1106 num_functions,
1107 10,
1108 ),
1109 "log_inv_rate={log_inv_rate} log_degree={log_degree} \
1110 num_functions={num_functions}"
1111 );
1112 }
1113 }
1114 }
1115 }
1116}