@@ -176,7 +176,7 @@ impl<C: CurveGroup> ShoupVess<C> {
176
176
aad : & [ u8 ] ,
177
177
) -> Result < ( ) , VessError >
178
178
where
179
- I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone ,
179
+ I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone + Sync ,
180
180
I :: IntoIter : ExactSizeIterator ,
181
181
{
182
182
self . verify_internal ( committee, recipients, ct, comm, aad, Mode :: Dkg )
@@ -194,7 +194,7 @@ impl<C: CurveGroup> ShoupVess<C> {
194
194
pub_share : C ,
195
195
) -> Result < ( ) , VessError >
196
196
where
197
- I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone ,
197
+ I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone + Sync ,
198
198
I :: IntoIter : ExactSizeIterator ,
199
199
{
200
200
self . verify_internal (
@@ -490,7 +490,7 @@ impl<C: CurveGroup> ShoupVess<C> {
490
490
mode : Mode < C > ,
491
491
) -> Result < ( ) , VessError >
492
492
where
493
- I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone ,
493
+ I : IntoIterator < Item = & ' a mre:: EncryptionKey < C > > + Clone + Sync ,
494
494
I :: IntoIter : ExactSizeIterator ,
495
495
{
496
496
let vss_pp = FeldmanVssPublicParam :: from ( committee) . with_lookup_table ( ) ;
@@ -499,7 +499,7 @@ impl<C: CurveGroup> ShoupVess<C> {
499
499
. to_verifier_state ( & ct. transcript ) ;
500
500
501
501
// verifier logic
502
- let ( expected_comm, h, subset_seed, mut shifted_polys, mut mre_cts, mut seeds) =
502
+ let ( expected_comm, h, subset_seed, shifted_polys, mre_cts, seeds) =
503
503
self . verify_core ( & vss_pp, & mut verifier_state, & mode) ?;
504
504
if & expected_comm != comm {
505
505
return Err ( VessError :: WrongCommitment ) ;
@@ -511,49 +511,72 @@ impl<C: CurveGroup> ShoupVess<C> {
511
511
512
512
// k in S, then homomorphically shift commitment; k notin S, reproduce dealing from seed
513
513
let subset_indices = self . map_subset_seed ( subset_seed) ;
514
- let mut subset_iter = subset_indices. iter ( ) . peekable ( ) ;
515
- let mut next_subset_idx = subset_iter. next ( ) ;
516
- for i in 0 ..self . num_repetition {
517
- match next_subset_idx {
518
- Some ( j) if i == * j => {
514
+
515
+ // Convert subset_indices to a HashSet for O(1) lookup
516
+ let subset_set: std:: collections:: HashSet < usize > = subset_indices. iter ( ) . copied ( ) . collect ( ) ;
517
+
518
+ // Create vectors to store the shifted polys and mre_cts data in the correct order
519
+ let mut shifted_polys_vec = Vec :: new ( ) ;
520
+ let mut mre_cts_vec = Vec :: new ( ) ;
521
+ let mut seeds_vec = Vec :: new ( ) ;
522
+
523
+ // Convert VecDeque to Vec to preserve order for subset items
524
+ for poly in shifted_polys. iter ( ) {
525
+ shifted_polys_vec. push ( poly. clone ( ) ) ;
526
+ }
527
+ for ct in mre_cts. iter ( ) {
528
+ mre_cts_vec. push ( ct. clone ( ) ) ;
529
+ }
530
+ for seed in seeds. iter ( ) {
531
+ seeds_vec. push ( * seed) ;
532
+ }
533
+
534
+ // Compute all hash data in parallel
535
+ let hash_data = ( 0 ..self . num_repetition )
536
+ . into_par_iter ( )
537
+ . map ( |i| {
538
+ if subset_set. contains ( & i) {
519
539
// k in S, shift the commitment
520
- let shifted_comm = vss_pp. commit (
521
- & shifted_polys
522
- . pop_front ( )
523
- . expect ( "subset_size > 0, so is shifted_polys.len()" ) ,
524
- ) ;
540
+ // Find the position of i in subset_indices to get the correct poly/ct
541
+ let subset_pos = subset_indices
542
+ . iter ( )
543
+ . position ( |& x| x == i)
544
+ . expect ( "i should be in subset_indices" ) ;
545
+
546
+ let shifted_comm = vss_pp. commit ( & shifted_polys_vec[ subset_pos] ) ;
525
547
526
548
let mut unshifted_comm = vec ! [ ] ;
527
549
for ( shifted, delta) in shifted_comm. into_iter ( ) . zip ( comm. iter ( ) ) {
528
550
// g^omega'' / C in paper
529
551
unshifted_comm. push ( shifted - delta) ;
530
552
}
531
553
let unshifted_comm = C :: normalize_batch ( & unshifted_comm) ;
532
- hasher. update ( serialize_to_vec ! [ unshifted_comm] ?) ;
533
-
534
- let mre_ct = mre_cts
535
- . pop_front ( )
536
- . expect ( "subset_size > 0, so is mre_cts.len()" ) ;
537
- hasher. update ( mre_ct. to_bytes ( ) ) ;
554
+ let unshifted_comm_bytes = serialize_to_vec ! [ unshifted_comm] ?;
555
+ let mre_ct_bytes = mre_cts_vec[ subset_pos] . to_bytes ( ) ;
538
556
539
- next_subset_idx = subset_iter. next ( ) ;
540
- }
541
- _ => {
557
+ Ok ( ( unshifted_comm_bytes, mre_ct_bytes) )
558
+ } else {
542
559
// k notin S, reproduce the dealing deterministically from seed
543
- let seed = seeds
544
- . pop_front ( )
545
- . expect ( "subset_size < num_repetitions, so seeds.len() > 0" ) ;
560
+ // Find the position of i among non-subset indices
561
+ let non_subset_pos = ( 0 ..i) . filter ( |& j| !subset_set. contains ( & j) ) . count ( ) ;
562
+ let seed = seeds_vec[ non_subset_pos] ;
563
+
546
564
let ( _poly, cm, mre_ct) =
547
565
self . new_dealing ( & vss_pp, i, & seed, recipients. clone ( ) , aad) ?;
548
566
549
- hasher. update ( serialize_to_vec ! [ cm] ?) ;
550
- hasher. update ( mre_ct. to_bytes ( ) ) ;
567
+ let cm_bytes = serialize_to_vec ! [ cm] ?;
568
+ let mre_ct_bytes = mre_ct. to_bytes ( ) ;
569
+
570
+ Ok ( ( cm_bytes, mre_ct_bytes) )
551
571
}
552
- }
572
+ } )
573
+ . collect :: < Result < Vec < _ > , VessError > > ( ) ?;
574
+
575
+ // Apply all hash updates in the correct sequential order
576
+ for ( cm_bytes, mre_ct_bytes) in hash_data {
577
+ hasher. update ( & cm_bytes) ;
578
+ hasher. update ( & mre_ct_bytes) ;
553
579
}
554
- debug_assert ! ( shifted_polys. is_empty( ) ) ;
555
- debug_assert ! ( mre_cts. is_empty( ) ) ;
556
- debug_assert ! ( seeds. is_empty( ) ) ;
557
580
558
581
if h == hasher. finalize ( ) . as_slice ( ) {
559
582
Ok ( ( ) )
0 commit comments