@@ -65,65 +65,72 @@ pub fn get_index_in_commitments(
6565 ) ) )
6666}
6767
68- pub fn verify_seed_exchange_commitment < Setup > (
69- verification_hashes : & VerificationHashes ,
68+ # [ cfg ( feature = "auth_commitment" ) ]
69+ fn verify_commitment_details < Setup > (
7070 seed_exchange : & SeedExchangeCommitment < Setup > ,
71- initial_commitment : & InitialCommitment < Setup > ,
7271) -> Result < ( ) , Box < dyn std:: error:: Error > >
7372where
7473 Setup : DkgSetup + DkgSetupTypes < Setup > ,
7574{
76- #[ cfg( feature = "auth_commitment" ) ]
77- {
78- let commitment = & seed_exchange. commitment ;
75+ let commitment = & seed_exchange. commitment ;
7976
80- if !verify_commitment ( & seed_exchange. commitment ) {
81- return Err ( Box :: new ( VerificationErrors :: UnslashableError ( format ! (
82- "Invalid field seeds_exchange_commitment.commitment.signature {},
77+ if !verify_commitment ( & seed_exchange. commitment ) {
78+ return Err ( Box :: new ( VerificationErrors :: UnslashableError ( format ! (
79+ "Invalid field seeds_exchange_commitment.commitment.signature {},
8380 message: {}
8481 pubkey: {},
8582 \n " ,
86- commitment. signature, commitment. hash, commitment. pubkey
87- ) ) ) ) ;
88- }
83+ commitment. signature, commitment. hash, commitment. pubkey
84+ ) ) ) ) ;
8985 }
9086
91- let shared_secret = & seed_exchange. shared_secret ;
92- let sk = match Setup :: DkgSecretKey :: from_bytes ( & shared_secret. secret ) {
93- Ok ( sk) => sk,
94- Err ( e) => {
95- return Err ( Box :: new ( VerificationErrors :: SlashableError ( format ! (
96- "Invalid field seeds_exchange_commitment.shared_secret.secret: {e} \n "
97- ) ) ) ) ;
98- }
99- } ;
87+ let computed_commitment_hash = compute_seed_exchange_hash :: < Setup > ( seed_exchange) ;
10088
101- #[ cfg( feature = "auth_commitment" ) ]
102- {
103- let computed_commitment_hash = compute_seed_exchange_hash :: < Setup > ( seed_exchange) ;
104-
105- if computed_commitment_hash. to_vec ( ) != seed_exchange. commitment . hash . as_ref ( ) {
106- return Err ( Box :: new ( VerificationErrors :: SlashableError (
107- format ! (
108- "Invalid field seeds_exchange_commitment.commitment.hash. Expected: {:?}, got hash: {:?}\n " ,
109- seed_exchange. commitment. hash,
110- hex:: encode( computed_commitment_hash. to_vec( ) )
111- ) ,
112- ) ) ) ;
113- }
89+ if computed_commitment_hash. to_vec ( ) != seed_exchange. commitment . hash . as_ref ( ) {
90+ return Err ( Box :: new ( VerificationErrors :: SlashableError (
91+ format ! (
92+ "Invalid field seeds_exchange_commitment.commitment.hash. Expected: {:?}, got hash: {:?}\n " ,
93+ seed_exchange. commitment. hash,
94+ hex:: encode( computed_commitment_hash. to_vec( ) )
95+ ) ,
96+ ) ) ) ;
11497 }
11598
116- let dest_id = match get_index_in_commitments (
99+ Ok ( ( ) )
100+ }
101+
102+ fn validate_shared_secret < Setup > (
103+ seed_exchange : & SeedExchangeCommitment < Setup > ,
104+ ) -> Result < Setup :: DkgSecretKey , Box < dyn std:: error:: Error > >
105+ where
106+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
107+ {
108+ let shared_secret = & seed_exchange. shared_secret ;
109+ Setup :: DkgSecretKey :: from_bytes ( & shared_secret. secret ) . map_err ( |e| {
110+ Box :: new ( VerificationErrors :: SlashableError ( format ! (
111+ "Invalid field seeds_exchange_commitment.shared_secret.secret: {e} \n "
112+ ) ) ) as Box < dyn std:: error:: Error >
113+ } )
114+ }
115+
116+ fn verify_polynomial_evaluation_for_seed < Setup > (
117+ verification_hashes : & VerificationHashes ,
118+ seed_exchange : & SeedExchangeCommitment < Setup > ,
119+ initial_commitment : & InitialCommitment < Setup > ,
120+ sk : & Setup :: DkgSecretKey ,
121+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
122+ where
123+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
124+ {
125+ let dest_id = get_index_in_commitments (
117126 verification_hashes,
118127 & seed_exchange. shared_secret . dst_base_hash ,
119- ) {
120- Ok ( id) => id,
121- Err ( e) => {
122- return Err ( Box :: new ( VerificationErrors :: SlashableError ( format ! (
123- "Invalid field seeds_exchange_commitment.shared_secret.dst_base_hash: {e} \n "
124- ) ) ) ) ;
125- }
126- } ;
128+ )
129+ . map_err ( |e| {
130+ Box :: new ( VerificationErrors :: SlashableError ( format ! (
131+ "Invalid field seeds_exchange_commitment.shared_secret.dst_base_hash: {e} \n "
132+ ) ) ) as Box < dyn std:: error:: Error >
133+ } ) ?;
127134
128135 // F(0) is always reserved for the aggregated key so we need to start from 1
129136 let dest_id = dest_id + 1 ;
@@ -148,6 +155,31 @@ where
148155 Ok ( ( ) )
149156}
150157
158+ pub fn verify_seed_exchange_commitment < Setup > (
159+ verification_hashes : & VerificationHashes ,
160+ seed_exchange : & SeedExchangeCommitment < Setup > ,
161+ initial_commitment : & InitialCommitment < Setup > ,
162+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
163+ where
164+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
165+ {
166+ #[ cfg( feature = "auth_commitment" ) ]
167+ {
168+ verify_commitment_details ( seed_exchange) ?;
169+ }
170+
171+ let sk = validate_shared_secret ( seed_exchange) ?;
172+
173+ verify_polynomial_evaluation_for_seed (
174+ verification_hashes,
175+ seed_exchange,
176+ initial_commitment,
177+ & sk,
178+ ) ?;
179+
180+ Ok ( ( ) )
181+ }
182+
151183fn compute_base_hash < Setup > (
152184 settings : & GenerateSettings ,
153185 pubkeys : & [ RawBytes < Setup :: Point > ] ,
@@ -261,9 +293,8 @@ fn compute_agg_key_from_dkg<C: Curve>(
261293 Ok ( coefficients[ 0 ] )
262294}
263295
264- pub fn verify_generation_hashes < Setup > (
296+ fn verify_message_cleartext < Setup > (
265297 generations : & [ Generation < Setup > ] ,
266- settings : & GenerateSettings ,
267298) -> Result < ( ) , Box < dyn std:: error:: Error > >
268299where
269300 Setup : DkgSetup + DkgSetupTypes < Setup > ,
@@ -282,7 +313,16 @@ where
282313 ) ) ) ;
283314 }
284315 }
316+ Ok ( ( ) )
317+ }
285318
319+ fn verify_signatures_and_commitments < Setup > (
320+ generations : & [ Generation < Setup > ] ,
321+ settings : & GenerateSettings ,
322+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
323+ where
324+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
325+ {
286326 let message_mapping = Setup :: TargetCryptography :: precompute_message_mapping (
287327 generations[ 0 ] . message_cleartext . as_bytes ( ) ,
288328 ) ;
@@ -301,8 +341,7 @@ where
301341 }
302342
303343 let initial_commitment = generate_initial_commitment ( generation, settings) ;
304- let ok = verify_initial_commitment_hash :: < Setup > ( & initial_commitment) ;
305- if !ok {
344+ if !verify_initial_commitment_hash :: < Setup > ( & initial_commitment) {
306345 return Err ( Box :: new ( VerificationErrors :: UnslashableError ( format ! (
307346 "Invalid initial commitment hash {}" ,
308347 initial_commitment. hash
@@ -312,36 +351,38 @@ where
312351 Ok ( ( ) )
313352}
314353
315- pub fn verify_generations < Setup > (
354+ pub fn verify_generation_hashes < Setup > (
316355 generations : & [ Generation < Setup > ] ,
317356 settings : & GenerateSettings ,
318- agg_key : & Setup :: DkgPubkey ,
319357) -> Result < ( ) , Box < dyn std:: error:: Error > >
320358where
321359 Setup : DkgSetup + DkgSetupTypes < Setup > ,
322360{
323- if generations. len ( ) != settings. n as usize {
324- return Err ( Box :: new ( std:: io:: Error :: new (
325- std:: io:: ErrorKind :: InvalidData ,
326- "Invalid number of generations" ,
327- ) ) ) ;
328- }
329-
330- verify_generation_hashes ( generations, settings) ?;
361+ verify_message_cleartext ( generations) ?;
362+ verify_signatures_and_commitments ( generations, settings)
363+ }
331364
365+ fn sort_and_deserialize_vectors < Setup > (
366+ generations : & [ Generation < Setup > ] ,
367+ ) -> ( Vec < Generation < Setup > > , Vec < Vec < Setup :: Point > > )
368+ where
369+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
370+ {
332371 let mut sorted = generations. to_vec ( ) ;
333372 sorted. sort_by ( |a, b| a. base_hash . cmp ( & b. base_hash ) ) ;
334-
335373 let verification_vectors = deserialize_verification_vectors :: < Setup > ( & sorted) ;
374+ ( sorted, verification_vectors)
375+ }
336376
337- let ids: Vec < Setup :: Scalar > = sorted
338- . iter ( )
339- . enumerate ( )
340- . map ( |( i, _) | Setup :: Scalar :: from_u32 ( ( i + 1 ) as u32 ) )
341- . collect ( ) ;
342-
343- let computed_key = compute_agg_key_from_dkg :: < Setup :: Curve > ( & verification_vectors, & ids) ?;
344-
377+ fn verify_computed_agg_key < Setup > (
378+ verification_vectors : & [ Vec < Setup :: Point > ] ,
379+ ids : & [ Setup :: Scalar ] ,
380+ agg_key : & Setup :: DkgPubkey ,
381+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
382+ where
383+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
384+ {
385+ let computed_key = compute_agg_key_from_dkg :: < Setup :: Curve > ( verification_vectors, ids) ?;
345386 if agg_key. to_bytes ( ) != computed_key. to_bytes ( ) {
346387 return Err ( Box :: new ( std:: io:: Error :: new (
347388 std:: io:: ErrorKind :: InvalidData ,
@@ -351,15 +392,25 @@ where
351392 ) ,
352393 ) ) ) ;
353394 }
395+ Ok ( ( ) )
396+ }
354397
355- let partial_keys: Vec < Setup :: Point > = sorted
398+ fn verify_lagrange_interpolation_for_agg_key < Setup > (
399+ sorted_generations : & [ Generation < Setup > ] ,
400+ ids : & [ Setup :: Scalar ] ,
401+ agg_key : & Setup :: DkgPubkey ,
402+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
403+ where
404+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
405+ {
406+ let partial_keys: Vec < Setup :: Point > = sorted_generations
356407 . iter ( )
357408 . map ( |generation| {
358409 Setup :: Point :: from_bytes ( & generation. partial_pubkey ) . expect ( "Invalid g1 point" )
359410 } )
360411 . collect ( ) ;
361412
362- let computed_key = lagrange_interpolation :: < Setup :: Curve > ( & partial_keys, & ids) ?;
413+ let computed_key = lagrange_interpolation :: < Setup :: Curve > ( & partial_keys, ids) ?;
363414
364415 if computed_key. to_bytes ( ) != agg_key. to_bytes ( ) {
365416 return Err ( Box :: new ( std:: io:: Error :: new (
@@ -370,6 +421,34 @@ where
370421 ) ,
371422 ) ) ) ;
372423 }
424+ Ok ( ( ) )
425+ }
426+
427+ pub fn verify_generations < Setup > (
428+ generations : & [ Generation < Setup > ] ,
429+ settings : & GenerateSettings ,
430+ agg_key : & Setup :: DkgPubkey ,
431+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
432+ where
433+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
434+ {
435+ if generations. len ( ) != settings. n as usize {
436+ return Err ( Box :: new ( std:: io:: Error :: new (
437+ std:: io:: ErrorKind :: InvalidData ,
438+ "Invalid number of generations" ,
439+ ) ) ) ;
440+ }
441+
442+ verify_generation_hashes ( generations, settings) ?;
443+
444+ let ( sorted, verification_vectors) = sort_and_deserialize_vectors ( generations) ;
445+
446+ let ids: Vec < Setup :: Scalar > = ( 1 ..=sorted. len ( ) )
447+ . map ( |i| Setup :: Scalar :: from_u32 ( i as u32 ) )
448+ . collect ( ) ;
449+
450+ verify_computed_agg_key :: < Setup > ( & verification_vectors, & ids, agg_key) ?;
451+ verify_lagrange_interpolation_for_agg_key :: < Setup > ( & sorted, & ids, agg_key) ?;
373452
374453 Ok ( ( ) )
375454}
@@ -453,6 +532,44 @@ where
453532 Ok ( ( ) )
454533}
455534
535+ fn verify_partial_signature < Setup > (
536+ bad_partial : & BadPartialShare < Setup > ,
537+ key : & Setup :: DkgPubkey ,
538+ ) -> Result < ( ) , Box < dyn std:: error:: Error > >
539+ where
540+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
541+ {
542+ let sig =
543+ Setup :: DkgSignature :: from_bytes_safe ( & bad_partial. data . message_signature ) . map_err ( |e| {
544+ Box :: new ( VerificationErrors :: SlashableError ( format ! (
545+ "While uncompressing data.bad_partial.data.message_signature {}" ,
546+ e
547+ ) ) ) as Box < dyn std:: error:: Error >
548+ } ) ?;
549+
550+ if !key. verify_signature ( bad_partial. data . message_cleartext . as_bytes ( ) , & sig) {
551+ return Err ( Box :: new ( VerificationErrors :: SlashableError ( format ! (
552+ "Invalid partial signature {} from key {}" ,
553+ sig, key
554+ ) ) ) ) ;
555+ }
556+ Ok ( ( ) )
557+ }
558+
559+ fn get_perpetrator_key < Setup > (
560+ bad_partial : & BadPartialShare < Setup > ,
561+ ) -> Result < Setup :: DkgPubkey , Box < dyn std:: error:: Error > >
562+ where
563+ Setup : DkgSetup + DkgSetupTypes < Setup > ,
564+ {
565+ Setup :: DkgPubkey :: from_bytes_safe ( & bad_partial. data . partial_pubkey ) . map_err ( |e| {
566+ Box :: new ( VerificationErrors :: SlashableError ( format ! (
567+ "While uncompressing data.bad_partial.data.partial_pubkey {}" ,
568+ e
569+ ) ) ) as Box < dyn std:: error:: Error >
570+ } )
571+ }
572+
456573pub fn prove_wrong_final_key_generation < Setup > (
457574 data : & BadPartialShareData < Setup > ,
458575) -> Result < ( ) , Box < dyn std:: error:: Error > >
@@ -471,29 +588,9 @@ where
471588 let perpetrator_index =
472589 find_perpetrator_index ( & data. bad_partial . data . base_hash , & sorted_generation) ?;
473590
474- let key =
475- Setup :: DkgPubkey :: from_bytes_safe ( & data. bad_partial . data . partial_pubkey ) . map_err ( |e| {
476- VerificationErrors :: SlashableError ( format ! (
477- "While uncompressing data.bad_partial.data.partial_pubkey {}" ,
478- e
479- ) )
480- } ) ?;
481-
482- let sig = Setup :: DkgSignature :: from_bytes_safe ( & data. bad_partial . data . message_signature )
483- . map_err ( |e| {
484- VerificationErrors :: SlashableError ( format ! (
485- "While uncompressing data.bad_partial.data.message_signature {}" ,
486- e
487- ) )
488- } ) ?;
489-
490- if !key. verify_signature ( data. bad_partial . data . message_cleartext . as_bytes ( ) , & sig) {
491- return Err ( Box :: new ( VerificationErrors :: SlashableError ( format ! (
492- "Invalid partial signature {} from key {}" ,
493- sig, key
494- ) ) ) ) ;
495- }
591+ let key = get_perpetrator_key ( & data. bad_partial ) ?;
496592
593+ verify_partial_signature ( & data. bad_partial , & key) ?;
497594 verify_expected_key :: < Setup > ( & sorted_generation, perpetrator_index, & key) ?;
498595
499596 Ok ( ( ) )
0 commit comments