@@ -9,6 +9,7 @@ use crate::integer::encryption::{create_clear_radix_block_iterator, KnowsMessage
9
9
use crate :: integer:: parameters:: CompactCiphertextListConformanceParams ;
10
10
pub use crate :: integer:: parameters:: IntegerCompactCiphertextListExpansionMode ;
11
11
use crate :: integer:: { CompactPublicKey , ServerKey } ;
12
+ use crate :: shortint:: ciphertext:: Degree ;
12
13
#[ cfg( feature = "zk-pok" ) ]
13
14
use crate :: shortint:: ciphertext:: ProvenCompactCiphertextListConformanceParams ;
14
15
use crate :: shortint:: parameters:: {
@@ -545,6 +546,85 @@ impl IntegerUnpackingToShortintCastingModeHelper {
545
546
}
546
547
}
547
548
549
+ type ExpansionHelperCallback < ' a , ListType > = & ' a dyn Fn (
550
+ & ListType ,
551
+ ShortintCompactCiphertextListCastingMode < ' _ > ,
552
+ ) -> Result < Vec < Ciphertext > , crate :: Error > ;
553
+
554
+ fn expansion_helper < ListType > (
555
+ expansion_mode : IntegerCompactCiphertextListExpansionMode < ' _ > ,
556
+ ct_list : & ListType ,
557
+ list_degree : Degree ,
558
+ info : & [ DataKind ] ,
559
+ is_packed : bool ,
560
+ list_expansion_fn : ExpansionHelperCallback < ' _ , ListType > ,
561
+ ) -> Result < Vec < Ciphertext > , crate :: Error > {
562
+ if is_packed
563
+ && matches ! (
564
+ expansion_mode,
565
+ IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking
566
+ )
567
+ {
568
+ return Err ( crate :: Error :: new ( String :: from (
569
+ WRONG_UNPACKING_MODE_ERR_MSG ,
570
+ ) ) ) ;
571
+ }
572
+
573
+ match expansion_mode {
574
+ IntegerCompactCiphertextListExpansionMode :: CastAndUnpackIfNecessary (
575
+ key_switching_key_view,
576
+ ) => {
577
+ let dest_sks = & key_switching_key_view. key . dest_server_key ;
578
+ let function_helper = IntegerUnpackingToShortintCastingModeHelper :: new (
579
+ dest_sks. message_modulus ,
580
+ dest_sks. carry_modulus ,
581
+ ) ;
582
+ let functions = if is_packed {
583
+ function_helper. generate_unpack_and_sanitize_functions ( info)
584
+ } else {
585
+ function_helper. generate_sanitize_without_unpacking_functions ( info)
586
+ } ;
587
+
588
+ list_expansion_fn (
589
+ ct_list,
590
+ ShortintCompactCiphertextListCastingMode :: CastIfNecessary {
591
+ casting_key : key_switching_key_view. key ,
592
+ functions : Some ( functions. as_slice ( ) ) ,
593
+ } ,
594
+ )
595
+ }
596
+ IntegerCompactCiphertextListExpansionMode :: UnpackAndSanitizeIfNecessary ( sks) => {
597
+ let expanded_blocks =
598
+ list_expansion_fn ( ct_list, ShortintCompactCiphertextListCastingMode :: NoCasting ) ?;
599
+
600
+ if is_packed {
601
+ let mut conformance_params = sks. key . conformance_params ( ) ;
602
+ conformance_params. degree = list_degree;
603
+
604
+ for ct in expanded_blocks. iter ( ) {
605
+ if !ct. is_conformant ( & conformance_params) {
606
+ return Err ( crate :: Error :: new (
607
+ "This compact list is not conformant with the given server key"
608
+ . to_string ( ) ,
609
+ ) ) ;
610
+ }
611
+ }
612
+
613
+ Ok ( unpack_and_sanitize_message_and_carries (
614
+ expanded_blocks,
615
+ sks,
616
+ info,
617
+ ) )
618
+ } else {
619
+ Ok ( sanitize_boolean_blocks ( expanded_blocks, sks, info) )
620
+ }
621
+ }
622
+ IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking => {
623
+ list_expansion_fn ( ct_list, ShortintCompactCiphertextListCastingMode :: NoCasting )
624
+ }
625
+ }
626
+ }
627
+
548
628
impl CompactCiphertextList {
549
629
pub fn is_packed ( & self ) -> bool {
550
630
self . ct_list . degree . get ( )
@@ -694,66 +774,14 @@ impl CompactCiphertextList {
694
774
) -> crate :: Result < CompactCiphertextListExpander > {
695
775
let is_packed = self . is_packed ( ) ;
696
776
697
- if is_packed
698
- && matches ! (
699
- expansion_mode,
700
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking
701
- )
702
- {
703
- return Err ( crate :: Error :: new ( String :: from (
704
- WRONG_UNPACKING_MODE_ERR_MSG ,
705
- ) ) ) ;
706
- }
707
-
708
- let expanded_blocks = match expansion_mode {
709
- IntegerCompactCiphertextListExpansionMode :: CastAndUnpackIfNecessary (
710
- key_switching_key_view,
711
- ) => {
712
- let dest_sks = & key_switching_key_view. key . dest_server_key ;
713
- let function_helper = IntegerUnpackingToShortintCastingModeHelper :: new (
714
- dest_sks. message_modulus ,
715
- dest_sks. carry_modulus ,
716
- ) ;
717
- let functions = if is_packed {
718
- function_helper. generate_unpack_and_sanitize_functions ( & self . info )
719
- } else {
720
- function_helper. generate_sanitize_without_unpacking_functions ( & self . info )
721
- } ;
722
-
723
- self . ct_list
724
- . expand ( ShortintCompactCiphertextListCastingMode :: CastIfNecessary {
725
- casting_key : key_switching_key_view. key ,
726
- functions : Some ( functions. as_slice ( ) ) ,
727
- } ) ?
728
- }
729
- IntegerCompactCiphertextListExpansionMode :: UnpackAndSanitizeIfNecessary ( sks) => {
730
- let expanded_blocks = self
731
- . ct_list
732
- . expand ( ShortintCompactCiphertextListCastingMode :: NoCasting ) ?;
733
-
734
- if is_packed {
735
- let degree = self . ct_list . degree ;
736
- let mut conformance_params = sks. key . conformance_params ( ) ;
737
- conformance_params. degree = degree;
738
-
739
- for ct in expanded_blocks. iter ( ) {
740
- if !ct. is_conformant ( & conformance_params) {
741
- return Err ( crate :: Error :: new (
742
- "This compact list is not conformant with the given server key"
743
- . to_string ( ) ,
744
- ) ) ;
745
- }
746
- }
747
-
748
- unpack_and_sanitize_message_and_carries ( expanded_blocks, sks, & self . info )
749
- } else {
750
- sanitize_boolean_blocks ( expanded_blocks, sks, & self . info )
751
- }
752
- }
753
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking => self
754
- . ct_list
755
- . expand ( ShortintCompactCiphertextListCastingMode :: NoCasting ) ?,
756
- } ;
777
+ let expanded_blocks = expansion_helper (
778
+ expansion_mode,
779
+ & self . ct_list ,
780
+ self . ct_list . degree ,
781
+ & self . info ,
782
+ is_packed,
783
+ & crate :: shortint:: ciphertext:: CompactCiphertextList :: expand,
784
+ ) ?;
757
785
758
786
Ok ( CompactCiphertextListExpander :: new (
759
787
expanded_blocks,
@@ -822,78 +850,27 @@ impl ProvenCompactCiphertextList {
822
850
) -> crate :: Result < CompactCiphertextListExpander > {
823
851
let is_packed = self . is_packed ( ) ;
824
852
825
- if is_packed
826
- && matches ! (
853
+ // Type annotation needed rust is not able to coerce the type on its own, also forces us to
854
+ // use a trait object
855
+ let callback: ExpansionHelperCallback < ' _ , _ > = & |ct_list, expansion_mode| {
856
+ crate :: shortint:: ciphertext:: ProvenCompactCiphertextList :: verify_and_expand (
857
+ ct_list,
858
+ crs,
859
+ & public_key. key ,
860
+ metadata,
827
861
expansion_mode,
828
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking
829
862
)
830
- {
831
- return Err ( crate :: Error :: new ( String :: from (
832
- WRONG_UNPACKING_MODE_ERR_MSG ,
833
- ) ) ) ;
834
- }
835
-
836
- let expanded_blocks = match expansion_mode {
837
- IntegerCompactCiphertextListExpansionMode :: CastAndUnpackIfNecessary (
838
- key_switching_key_view,
839
- ) => {
840
- let dest_sks = & key_switching_key_view. key . dest_server_key ;
841
- let function_helper = IntegerUnpackingToShortintCastingModeHelper :: new (
842
- dest_sks. message_modulus ,
843
- dest_sks. carry_modulus ,
844
- ) ;
845
- let functions = if is_packed {
846
- function_helper. generate_unpack_and_sanitize_functions ( & self . info )
847
- } else {
848
- function_helper. generate_sanitize_without_unpacking_functions ( & self . info )
849
- } ;
850
- self . ct_list . verify_and_expand (
851
- crs,
852
- & public_key. key ,
853
- metadata,
854
- ShortintCompactCiphertextListCastingMode :: CastIfNecessary {
855
- casting_key : key_switching_key_view. key ,
856
- functions : Some ( functions. as_slice ( ) ) ,
857
- } ,
858
- ) ?
859
- }
860
- IntegerCompactCiphertextListExpansionMode :: UnpackAndSanitizeIfNecessary ( sks) => {
861
- let expanded_blocks = self . ct_list . verify_and_expand (
862
- crs,
863
- & public_key. key ,
864
- metadata,
865
- ShortintCompactCiphertextListCastingMode :: NoCasting ,
866
- ) ?;
867
-
868
- if is_packed {
869
- let degree = self . ct_list . proved_lists [ 0 ] . 0 . degree ;
870
- let mut conformance_params = sks. key . conformance_params ( ) ;
871
- conformance_params. degree = degree;
872
-
873
- for ct in expanded_blocks. iter ( ) {
874
- if !ct. is_conformant ( & conformance_params) {
875
- return Err ( crate :: Error :: new (
876
- "This compact list is not conformant with the given server key"
877
- . to_string ( ) ,
878
- ) ) ;
879
- }
880
- }
881
-
882
- unpack_and_sanitize_message_and_carries ( expanded_blocks, sks, & self . info )
883
- } else {
884
- sanitize_boolean_blocks ( expanded_blocks, sks, & self . info )
885
- }
886
- }
887
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking => {
888
- self . ct_list . verify_and_expand (
889
- crs,
890
- & public_key. key ,
891
- metadata,
892
- ShortintCompactCiphertextListCastingMode :: NoCasting ,
893
- ) ?
894
- }
895
863
} ;
896
864
865
+ let expanded_blocks = expansion_helper (
866
+ expansion_mode,
867
+ & self . ct_list ,
868
+ self . ct_list . proved_lists [ 0 ] . 0 . degree ,
869
+ & self . info ,
870
+ is_packed,
871
+ callback,
872
+ ) ?;
873
+
897
874
Ok ( CompactCiphertextListExpander :: new (
898
875
expanded_blocks,
899
876
self . info . clone ( ) ,
@@ -910,66 +887,14 @@ impl ProvenCompactCiphertextList {
910
887
) -> crate :: Result < CompactCiphertextListExpander > {
911
888
let is_packed = self . is_packed ( ) ;
912
889
913
- if is_packed
914
- && matches ! (
915
- expansion_mode,
916
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking
917
- )
918
- {
919
- return Err ( crate :: Error :: new ( String :: from (
920
- WRONG_UNPACKING_MODE_ERR_MSG ,
921
- ) ) ) ;
922
- }
923
-
924
- let expanded_blocks = match expansion_mode {
925
- IntegerCompactCiphertextListExpansionMode :: CastAndUnpackIfNecessary (
926
- key_switching_key_view,
927
- ) => {
928
- let dest_sks = & key_switching_key_view. key . dest_server_key ;
929
- let function_helper = IntegerUnpackingToShortintCastingModeHelper :: new (
930
- dest_sks. message_modulus ,
931
- dest_sks. carry_modulus ,
932
- ) ;
933
- let functions = if is_packed {
934
- function_helper. generate_unpack_and_sanitize_functions ( & self . info )
935
- } else {
936
- function_helper. generate_sanitize_without_unpacking_functions ( & self . info )
937
- } ;
938
- self . ct_list . expand_without_verification (
939
- ShortintCompactCiphertextListCastingMode :: CastIfNecessary {
940
- casting_key : key_switching_key_view. key ,
941
- functions : Some ( functions. as_slice ( ) ) ,
942
- } ,
943
- ) ?
944
- }
945
- IntegerCompactCiphertextListExpansionMode :: UnpackAndSanitizeIfNecessary ( sks) => {
946
- let expanded_blocks = self . ct_list . expand_without_verification (
947
- ShortintCompactCiphertextListCastingMode :: NoCasting ,
948
- ) ?;
949
-
950
- if is_packed {
951
- let degree = self . ct_list . proved_lists [ 0 ] . 0 . degree ;
952
- let mut conformance_params = sks. key . conformance_params ( ) ;
953
- conformance_params. degree = degree;
954
-
955
- for ct in expanded_blocks. iter ( ) {
956
- if !ct. is_conformant ( & conformance_params) {
957
- return Err ( crate :: Error :: new (
958
- "This compact list is not conformant with the given server key"
959
- . to_string ( ) ,
960
- ) ) ;
961
- }
962
- }
963
-
964
- unpack_and_sanitize_message_and_carries ( expanded_blocks, sks, & self . info )
965
- } else {
966
- sanitize_boolean_blocks ( expanded_blocks, sks, & self . info )
967
- }
968
- }
969
- IntegerCompactCiphertextListExpansionMode :: NoCastingAndNoUnpacking => self
970
- . ct_list
971
- . expand_without_verification ( ShortintCompactCiphertextListCastingMode :: NoCasting ) ?,
972
- } ;
890
+ let expanded_blocks = expansion_helper (
891
+ expansion_mode,
892
+ & self . ct_list ,
893
+ self . ct_list . proved_lists [ 0 ] . 0 . degree ,
894
+ & self . info ,
895
+ is_packed,
896
+ & crate :: shortint:: ciphertext:: ProvenCompactCiphertextList :: expand_without_verification,
897
+ ) ?;
973
898
974
899
Ok ( CompactCiphertextListExpander :: new (
975
900
expanded_blocks,
0 commit comments