1use k256::{
9 elliptic_curve::{
10 group::GroupEncoding,
11 subtle::{Choice, ConstantTimeEq},
12 Group,
13 },
14 NonZeroScalar, ProjectivePoint, Scalar,
15};
16use merlin::Transcript;
17use rand::prelude::*;
18use rand_chacha::ChaCha20Rng;
19use sha2::{Digest, Sha256};
20
21use sl_mpc_mate::{
22 coord::*,
23 math::{
24 feldman_verify, polynomial_coeff_multipliers, GroupPolynomial,
25 Polynomial,
26 },
27 message::*,
28 SessionId,
29};
30
31use sl_oblivious::{
32 endemic_ot::{EndemicOTMsg1, EndemicOTReceiver, EndemicOTSender},
33 soft_spoken::{build_pprf, eval_pprf},
34 utils::TranscriptProtocol,
35 zkproofs::DLogProof,
36};
37
38use crate::{
39 keygen::{
40 constants::*, messages::*, utils::check_secret_recovery, KeygenError,
41 Keyshare,
42 },
43 proto::{tags::*, *},
44 setup::{KeygenSetupMessage, ProtocolParticipant, ABORT_MESSAGE_TAG},
45};
46
47#[cfg(feature = "multi-thread")]
48use tokio::task::block_in_place;
49
50#[cfg(not(feature = "multi-thread"))]
51fn block_in_place<F, R>(f: F) -> R
52where
53 F: FnOnce() -> R,
54{
55 f()
56}
57
58pub type Seed = <ChaCha20Rng as SeedableRng>::Seed;
60
61use crate::pairs::Pairs;
62
63pub(crate) struct KeyRefreshData {
68 pub(crate) s_i_0: Scalar,
73
74 pub(crate) lost_keyshare_party_ids: Vec<u8>,
77
78 pub(crate) expected_public_key: ProjectivePoint,
80
81 pub(crate) root_chain_code: [u8; 32],
83}
84
85pub async fn run<T, R>(
113 setup: T,
114 seed: Seed,
115 relay: R,
116) -> Result<Keyshare, KeygenError>
117where
118 T: KeygenSetupMessage,
119 R: Relay,
120{
121 let abort_msg = create_abort_message(&setup);
122 let mut relay = FilteredMsgRelay::new(relay);
123
124 let result = match run_inner(setup, seed, &mut relay, None).await {
125 Ok(share) => Ok(share),
126 Err(KeygenError::AbortProtocol(p)) => {
127 Err(KeygenError::AbortProtocol(p))
128 }
129 Err(KeygenError::SendMessage) => Err(KeygenError::SendMessage),
130 Err(err) => {
131 let _ = relay.send(abort_msg).await;
133 Err(err)
134 }
135 };
136
137 let _ = relay.close().await;
138
139 result
140}
141
142#[allow(non_snake_case)]
171pub(crate) async fn run_inner<T, R>(
172 setup: T,
173 seed: Seed,
174 relay: &mut FilteredMsgRelay<R>,
175 key_refresh_data: Option<&KeyRefreshData>,
176) -> Result<Keyshare, KeygenError>
177where
178 T: KeygenSetupMessage,
179 R: Relay,
180{
181 let mut rng = ChaCha20Rng::from_seed(seed);
182
183 let mut scheme = crate::proto::Scheme::new(&mut rng);
184
185 let T = setup.threshold() as usize;
186 let N = setup.total_participants();
187
188 let my_party_id = setup.participant_index() as u8;
189 let my_rank = setup.participant_rank(my_party_id as usize);
190
191 if let Some(v) = key_refresh_data {
192 let cond1 = v.expected_public_key == ProjectivePoint::IDENTITY;
193 let cond2 = v.lost_keyshare_party_ids.len() > (N - T);
194 let cond3 = (v.s_i_0 == Scalar::ZERO)
195 && (!v.lost_keyshare_party_ids.contains(&my_party_id));
196 if cond1 || cond2 || cond3 {
197 return Err(KeygenError::InvalidKeyRefresh);
198 }
199 }
200
201 let mut keyshare =
202 Keyshare::new(N as u8, T as u8, my_party_id, setup.keyshare_extra());
203
204 let session_id = SessionId::new(rng.gen());
205 let r_i = rng.gen();
206
207 let mut polynomial = Polynomial::random(&mut rng, T - 1);
209 if let Some(v) = key_refresh_data {
210 polynomial.set_constant(v.s_i_0);
211 }
212
213 let x_i = NonZeroScalar::random(&mut rng);
214
215 let big_f_i_vec = polynomial.commit(); let commitment = hash_commitment(
218 &session_id,
219 my_party_id as usize,
220 setup.participant_rank(my_party_id as usize) as usize,
221 &x_i,
222 &big_f_i_vec,
223 &r_i,
224 );
225
226 let mut d_i_list = vec![Scalar::ZERO; N];
227 d_i_list[my_party_id as usize] =
228 block_in_place(|| polynomial.derivative_at(my_rank as usize, &x_i));
229
230 relay.ask_messages(&setup, ABORT_MESSAGE_TAG, false).await?;
231 relay.ask_messages(&setup, DKG_MSG_R1, false).await?;
232 relay.ask_messages(&setup, DKG_MSG_R2, false).await?;
233 relay.ask_messages(&setup, DKG_MSG_OT1, true).await?;
234 relay.ask_messages(&setup, DKG_MSG_R3, true).await?;
235 relay.ask_messages(&setup, DKG_MSG_R4, false).await?;
236
237 let (sid_i_list, commitment_list, x_i_list, enc_pub_key) = broadcast_4(
238 &setup,
239 relay,
240 DKG_MSG_R1,
241 (session_id, commitment, x_i, scheme.public_key().to_vec()),
242 )
243 .await?;
244
245 for (receiver, pub_key) in enc_pub_key.into_iter().enumerate() {
246 if receiver != setup.participant_index() {
247 scheme
248 .receiver_public_key(receiver, &pub_key)
249 .map_err(|_| KeygenError::InvalidMessage)?;
250 }
251 }
252
253 for i in 0..x_i_list.len() - 1 {
256 let x = &x_i_list[i];
257 for s in &x_i_list[i + 1..] {
258 if x.ct_eq(s).into() {
259 return Err(KeygenError::NotUniqueXiValues);
260 }
261 }
262 }
263
264 keyshare.info_mut().final_session_id = sid_i_list
266 .iter()
267 .fold(Sha256::new(), |hash, sid| hash.chain_update(sid))
268 .finalize()
269 .into();
270
271 let dlog_proofs = {
272 let mut dlog_transcript = Transcript::new_dlog_proof(
274 &keyshare.final_session_id,
275 my_party_id as usize,
276 &DLOG_PROOF1_LABEL,
277 &DKG_LABEL,
278 );
279
280 polynomial
281 .iter()
282 .map(|f_i| {
283 DLogProof::prove(
284 f_i,
285 &ProjectivePoint::GENERATOR,
286 &mut dlog_transcript,
287 &mut rng,
288 )
289 })
290 .collect::<Vec<_>>()
291 };
292
293 let mut base_ot_receivers: Pairs<EndemicOTReceiver> = Pairs::new();
294
295 for receiver_id in setup.all_other_parties() {
296 let sid = get_base_ot_session_id(
297 my_party_id,
298 receiver_id as u8,
299 &keyshare.final_session_id,
300 );
301
302 let mut enc_msg1 = EncryptedMessage::<EndemicOTMsg1>::new(
303 &setup.msg_id(Some(receiver_id), DKG_MSG_OT1),
304 setup.message_ttl().as_secs() as u32,
305 0,
306 0,
307 &scheme,
308 );
309
310 let (msg1, _) = enc_msg1.payload(&scheme);
311
312 let receiver = EndemicOTReceiver::new(&sid, msg1, &mut rng);
313
314 base_ot_receivers.push(receiver_id as u8, receiver);
315
316 relay
320 .feed(
321 enc_msg1
322 .encrypt(&mut scheme, receiver_id)
323 .ok_or(KeygenError::SendMessage)?,
324 )
325 .await
326 .map_err(|_| KeygenError::SendMessage)?;
327 }
328
329 #[cfg(feature = "tracing")]
330 tracing::debug!("feed all OT1");
331
332 let chain_code_sid = if let Some(v) = key_refresh_data {
334 v.root_chain_code
335 } else {
336 SessionId::new(rng.gen()).into()
337 };
338 let r_i_2 = rng.gen();
339
340 let (big_f_i_vecs, r_i_list, commitment_list_2, dlog_proofs_i_list) =
341 broadcast_4(
342 &setup,
343 relay,
344 DKG_MSG_R2,
345 (
346 big_f_i_vec,
347 r_i,
348 hash_commitment_2(
349 &keyshare.final_session_id,
350 &chain_code_sid,
351 &r_i_2,
352 ),
353 dlog_proofs,
354 ),
355 )
356 .await?;
357
358 for party_id in 0..N {
359 let r_i = &r_i_list[party_id];
360 let x_i = &x_i_list[party_id];
361 let sid = &sid_i_list[party_id];
362 let commitment = &commitment_list[party_id];
363 let big_f_i_vector = &big_f_i_vecs[party_id];
364 let dlog_proofs_i = &dlog_proofs_i_list[party_id];
365
366 if big_f_i_vector.coeffs.len() != T {
367 return Err(KeygenError::InvalidMessage);
368 }
369 if dlog_proofs_i.len() != T {
370 return Err(KeygenError::InvalidMessage);
371 }
372
373 let commit_hash = hash_commitment(
374 sid,
375 party_id,
376 setup.participant_rank(party_id) as usize,
377 x_i,
378 big_f_i_vector,
379 r_i,
380 );
381
382 if commit_hash.ct_ne(commitment).into() {
383 return Err(KeygenError::InvalidCommitmentHash);
384 }
385
386 {
387 let mut points = big_f_i_vector.points();
388 if let Some(v) = key_refresh_data {
389 if v.lost_keyshare_party_ids.contains(&(party_id as u8)) {
390 if points.next() != Some(&ProjectivePoint::IDENTITY) {
392 return Err(KeygenError::InvalidPolynomialPoint);
393 }
394 }
395 }
396 if points.any(|p| p.is_identity().into()) {
397 return Err(KeygenError::InvalidPolynomialPoint);
398 }
399 }
400
401 verify_dlog_proofs(
402 &keyshare.final_session_id,
403 party_id,
404 dlog_proofs_i,
405 &big_f_i_vector.coeffs,
406 )?;
407 }
408
409 let mut big_f_vec = GroupPolynomial::identity(T);
411 for v in big_f_i_vecs.iter() {
412 big_f_vec.add_mut(v); }
414
415 let public_key = big_f_vec.get_constant();
416
417 if let Some(v) = key_refresh_data {
418 if public_key != v.expected_public_key {
419 return Err(KeygenError::InvalidKeyRefresh);
420 }
421 }
422
423 Round::new(setup.total_participants() - 1, DKG_MSG_OT1, relay)
424 .of_encrypted_messages(
425 &setup,
426 &mut scheme,
427 0,
428 KeygenError::AbortProtocol,
429 |base_ot_msg1: &EndemicOTMsg1, receiver_index, _, scheme| {
430 let receiver_id = receiver_index as u8;
431 let rank = setup.participant_rank(receiver_id as usize);
432
433 let trailer = big_f_vec.external_size();
434
435 let mut enc_buf = EncryptedMessage::<KeygenMsg3>::new(
436 &setup.msg_id(Some(receiver_id as usize), DKG_MSG_R3),
437 setup.message_ttl().as_secs() as _,
438 0,
439 trailer,
440 scheme,
441 );
442
443 let (msg3, trailer) = enc_buf.payload(scheme);
444
445 let sender_ot_seed = {
446 let sid = get_base_ot_session_id(
447 receiver_id,
448 my_party_id,
449 &keyshare.final_session_id,
450 );
451
452 block_in_place(|| {
453 EndemicOTSender::process(
454 &sid,
455 base_ot_msg1,
456 &mut msg3.base_ot_msg2,
457 &mut rng,
458 )
459 })
460 .map_err(|_| KeygenError::InvalidMessage)?
461 };
462
463 let all_but_one_session_id = get_all_but_one_session_id(
464 my_party_id as usize,
465 receiver_id as usize,
466 &keyshare.final_session_id,
467 );
468
469 build_pprf(
470 &all_but_one_session_id,
471 &sender_ot_seed,
472 &mut keyshare.other_mut(receiver_id).send_ot_seed,
473 &mut msg3.pprf_output,
474 );
475
476 if receiver_id > my_party_id {
477 rng.fill_bytes(&mut msg3.seed_i_j);
478 keyshare.each_mut(receiver_id - 1).zeta_seed =
479 msg3.seed_i_j;
480 };
481
482 let x_i = &x_i_list[receiver_id as usize];
483 let d_i = block_in_place(|| {
484 polynomial.derivative_at(rank as usize, x_i)
485 });
486
487 msg3.d_i = encode_scalar(&d_i);
488 msg3.chain_code_sid = chain_code_sid;
489 msg3.r_i_2 = r_i_2;
490
491 big_f_vec.write(trailer);
492
493 Ok(Some(
494 enc_buf
495 .encrypt(scheme, receiver_id as usize)
496 .ok_or(KeygenError::SendMessage)?,
497 ))
498 },
499 )
500 .await?;
501
502 let mut chain_code_sids =
503 Pairs::new_with_item(my_party_id, chain_code_sid);
504
505 if let Some(v) = key_refresh_data {
506 if v.lost_keyshare_party_ids.contains(&my_party_id) {
507 chain_code_sids = Pairs::new();
508 }
509 }
510
511 Round::new(setup.total_participants() - 1, DKG_MSG_R3, relay)
512 .of_encrypted_messages(
513 &setup,
514 &mut scheme,
515 big_f_vec.external_size(),
516 KeygenError::AbortProtocol,
517 |msg3: &KeygenMsg3, party_index, trailer, _| {
518 let party_id = party_index as u8;
519 let msg3_big_f_vec =
520 <GroupPolynomial<ProjectivePoint> as Wrap>::read(trailer)
521 .ok_or(KeygenError::InvalidMessage)?;
522
523 if msg3_big_f_vec != big_f_vec {
525 return Err(KeygenError::BigFVecMismatch);
526 }
527
528 d_i_list[party_id as usize] = decode_scalar(&msg3.d_i)
529 .ok_or(KeygenError::InvalidMessage)?;
530
531 let receiver = base_ot_receivers.pop_pair(party_id);
532 let receiver_output =
533 block_in_place(|| receiver.process(&msg3.base_ot_msg2))
534 .map_err(|_| KeygenError::InvalidMessage)?;
535 let all_but_one_session_id = get_all_but_one_session_id(
536 party_id as usize,
537 my_party_id as usize,
538 &keyshare.final_session_id,
539 );
540
541 block_in_place(|| {
542 eval_pprf(
543 &all_but_one_session_id,
544 &receiver_output,
545 &msg3.pprf_output,
546 &mut keyshare.other_mut(party_id).recv_ot_seed,
547 )
548 })
549 .map_err(KeygenError::PPRFError)?;
550
551 if party_id < my_party_id {
552 keyshare.each_mut(party_id).zeta_seed = msg3.seed_i_j;
553 }
554
555 let commitment_2 = &commitment_list_2[party_id as usize];
557 let commit_hash = hash_commitment_2(
558 &keyshare.final_session_id,
559 &msg3.chain_code_sid,
560 &msg3.r_i_2,
561 );
562
563 bool::from(commit_hash.ct_eq(commitment_2))
564 .then_some(())
565 .ok_or(KeygenError::InvalidCommitmentHash)?;
566
567 if let Some(v) = key_refresh_data {
568 if !v.lost_keyshare_party_ids.contains(&party_id) {
569 chain_code_sids.push(party_id, msg3.chain_code_sid);
570 }
571 } else {
572 chain_code_sids.push(party_id, msg3.chain_code_sid);
573 }
574
575 Ok(None)
576 },
577 )
578 .await?;
579
580 if key_refresh_data.is_some() {
581 let chain_code_sids = chain_code_sids.remove_ids();
582 if chain_code_sids.is_empty() {
583 return Err(KeygenError::InvalidKeyRefresh);
584 }
585 let root_chain_code = chain_code_sids[0];
586 if !chain_code_sids.iter().all(|&item| item == root_chain_code) {
587 return Err(KeygenError::InvalidKeyRefresh);
588 }
589 keyshare.info_mut().root_chain_code = root_chain_code;
591 } else {
592 keyshare.info_mut().root_chain_code = chain_code_sids
594 .iter()
595 .fold(Sha256::new(), |hash, (_, sid)| hash.chain_update(sid))
596 .finalize()
597 .into();
598 }
599
600 if big_f_i_vecs.len() != d_i_list.len() {
601 return Err(KeygenError::FailedFelmanVerify);
602 }
603
604 for (big_f_i_vec, f_i_val) in big_f_i_vecs.into_iter().zip(&d_i_list) {
605 let coeffs = block_in_place(|| {
606 big_f_i_vec.derivative_coeffs(my_rank as usize)
607 });
608 let valid = feldman_verify(
609 coeffs,
610 &x_i_list[my_party_id as usize],
611 f_i_val,
612 &ProjectivePoint::GENERATOR,
613 );
614 if !valid {
615 return Err(KeygenError::FailedFelmanVerify);
616 }
617 }
618
619 let s_i: Scalar = d_i_list.iter().sum();
620 let big_s_i = ProjectivePoint::GENERATOR * s_i;
621
622 let final_session_id_with_root_chain_code = {
625 let mut buf = [0u8; 32];
626 let mut transcript = Transcript::new(&DKG_LABEL);
627 transcript
628 .append_message(b"final_session_id", &keyshare.final_session_id);
629 transcript
630 .append_message(b"root_chain_code", &keyshare.root_chain_code);
631 transcript
632 .challenge_bytes(&DLOG_SESSION_ID_WITH_CHAIN_CODE, &mut buf);
633 SessionId::new(buf)
634 };
635
636 let proof = {
637 let mut transcript = Transcript::new_dlog_proof(
638 &final_session_id_with_root_chain_code,
639 my_party_id as usize,
640 &DLOG_PROOF2_LABEL,
641 &DKG_LABEL,
642 );
643
644 DLogProof::prove(
645 &s_i,
646 &ProjectivePoint::GENERATOR,
647 &mut transcript,
648 &mut rng,
649 )
650 };
651
652 let (public_key_list, big_s_list, proof_list, _) = broadcast_4(
653 &setup,
654 relay,
655 DKG_MSG_R4,
656 (public_key, big_s_i, proof, ()),
657 )
658 .await?;
659
660 if public_key_list.into_iter().any(|pk| pk != public_key) {
661 return Err(KeygenError::PublicKeyMismatch);
662 }
663
664 if big_s_list.len() != proof_list.len() {
665 return Err(KeygenError::InvalidDLogProof);
666 }
667
668 for (party_id, (big_s_i, dlog_proof)) in
669 big_s_list.iter().zip(proof_list.into_iter()).enumerate()
670 {
671 if party_id == my_party_id as usize {
672 continue;
673 }
674
675 let mut transcript = Transcript::new_dlog_proof(
676 &final_session_id_with_root_chain_code,
677 party_id,
678 &DLOG_PROOF2_LABEL,
679 &DKG_LABEL,
680 );
681
682 if dlog_proof
683 .verify(big_s_i, &ProjectivePoint::GENERATOR, &mut transcript)
684 .unwrap_u8()
685 == 0
686 {
687 return Err(KeygenError::InvalidDLogProof);
688 }
689 }
690
691 for (party_id, x_i) in x_i_list.iter().enumerate() {
692 let party_rank = setup.participant_rank(party_id);
693
694 let coeff_multipliers =
695 polynomial_coeff_multipliers(x_i, party_rank as usize, N);
696
697 let expected_point: ProjectivePoint = big_f_vec
698 .points()
699 .zip(coeff_multipliers)
700 .map(|(point, coeff)| point * &coeff)
701 .sum();
702
703 if expected_point != big_s_list[party_id] {
704 return Err(KeygenError::BigSMismatch);
705 }
706 }
707
708 let rank_list = (0..setup.total_participants())
710 .map(|p| setup.participant_rank(p))
711 .collect::<Vec<_>>();
712
713 check_secret_recovery(&x_i_list, &rank_list, &big_s_list, &public_key)?;
715
716 keyshare.info_mut().public_key = encode_point(&public_key);
717 keyshare.info_mut().s_i = encode_scalar(&s_i);
718 keyshare.info_mut().key_id = setup.derive_key_id(&public_key.to_bytes());
719
720 for p in 0..N {
721 let each = keyshare.each_mut(p as u8);
722
723 each.x_i = encode_scalar(&x_i_list[p]);
724 each.big_s = encode_point(&big_s_list[p]);
725 each.rank = rank_list[p];
726 }
727
728 Ok(keyshare)
729}
730
731fn hash_commitment(
749 session_id: &SessionId,
750 party_id: usize,
751 rank: usize,
752 x_i: &NonZeroScalar,
753 big_f_i_vec: &GroupPolynomial<ProjectivePoint>,
754 r_i: &[u8; 32],
755) -> [u8; 32] {
756 let mut hasher = Sha256::new();
757 hasher.update(DKG_LABEL);
758 hasher.update(session_id);
759 hasher.update((party_id as u64).to_be_bytes());
760 hasher.update((rank as u64).to_be_bytes());
761 hasher.update(x_i.to_bytes());
762 for point in big_f_i_vec.points() {
763 hasher.update(point.to_bytes());
764 }
765 hasher.update(r_i);
766 hasher.update(COMMITMENT_1_LABEL);
767
768 hasher.finalize().into()
769}
770
771fn hash_commitment_2(
785 session_id: &[u8],
786 chain_code_sid: &[u8; 32],
787 r_i: &[u8; 32],
788) -> [u8; 32] {
789 let mut hasher = Sha256::new();
790 hasher.update(DKG_LABEL);
791 hasher.update(session_id);
792 hasher.update(chain_code_sid);
793 hasher.update(r_i);
794 hasher.update(COMMITMENT_2_LABEL);
795
796 hasher.finalize().into()
797}
798
799pub(crate) fn get_base_ot_session_id(
814 sender_id: u8,
815 receiver_id: u8,
816 session_id: &[u8],
817) -> SessionId {
818 SessionId::new(
819 Sha256::new()
820 .chain_update(DKG_LABEL)
821 .chain_update(session_id)
822 .chain_update(b"sender_id")
823 .chain_update((sender_id as u64).to_be_bytes())
824 .chain_update(b"receiver_id")
825 .chain_update((receiver_id as u64).to_be_bytes())
826 .chain_update(b"base_ot_session_id")
827 .finalize()
828 .into(),
829 )
830}
831
832pub(crate) fn get_all_but_one_session_id(
847 sender_id: usize,
848 receiver_id: usize,
849 session_id: &[u8],
850) -> SessionId {
851 SessionId::new(
852 Sha256::new()
853 .chain_update(DKG_LABEL)
854 .chain_update(session_id)
855 .chain_update(b"sender_id")
856 .chain_update((sender_id as u64).to_be_bytes())
857 .chain_update(b"receiver_id")
858 .chain_update((receiver_id as u64).to_be_bytes())
859 .chain_update(b"all_but_one_session_id")
860 .finalize()
861 .into(),
862 )
863}
864
865fn verify_dlog_proofs(
882 final_session_id: &[u8],
883 party_id: usize,
884 proofs: &[DLogProof],
885 points: &[ProjectivePoint],
886) -> Result<(), KeygenError> {
887 let mut dlog_transcript = Transcript::new_dlog_proof(
888 final_session_id,
889 party_id,
890 &DLOG_PROOF1_LABEL,
891 &DKG_LABEL,
892 );
893
894 let mut ok = Choice::from(1);
895 for (proof, point) in proofs.iter().zip(points) {
896 ok &= proof.verify(
897 point,
898 &ProjectivePoint::GENERATOR,
899 &mut dlog_transcript,
900 );
901 }
902
903 if ok.unwrap_u8() == 0 {
904 return Err(KeygenError::InvalidDLogProof);
905 }
906
907 Ok(())
908}
909
910pub(crate) async fn broadcast_4<P, R, T1, T2, T3, T4>(
936 setup: &P,
937 relay: &mut FilteredMsgRelay<R>,
938 tag: MessageTag,
939 msg: (T1, T2, T3, T4),
940) -> Result<(Vec<T1>, Vec<T2>, Vec<T3>, Vec<T4>), KeygenError>
941where
942 P: ProtocolParticipant,
943 R: Relay,
944 T1: Wrap,
945 T2: Wrap,
946 T3: Wrap,
947 T4: Wrap,
948{
949 let (v0, v1, v2, v3) =
950 Round::new(setup.total_participants() - 1, tag, relay)
951 .broadcast_4(setup, msg)
952 .await?;
953
954 Ok((v0.into(), v1.into(), v2.into(), v3.into()))
955}
956
957#[cfg(test)]
958mod tests {
959 use super::*;
960
961 use tokio::task::JoinSet;
962
963 use sl_mpc_mate::coord::{
964 adversary::{EvilMessageRelay, EvilPlay},
965 {MessageRelayService, SimpleMessageRelay},
966 };
967
968 use crate::{keygen::utils::setup_keygen, setup::keygen::SetupMessage};
969
970 async fn sim<S, R>(t: u8, ranks: &[u8], coord: S) -> Vec<Keyshare>
971 where
972 S: MessageRelayService<MessageRelay = R>,
973 R: Relay + Send + 'static,
974 {
975 let parties = setup_keygen(None, t, ranks.len() as u8, Some(ranks));
976 sim_parties(parties, coord).await
977 }
978
979 async fn sim_parties<S, R>(
980 parties: Vec<(SetupMessage, [u8; 32])>,
981 coord: S,
982 ) -> Vec<Keyshare>
983 where
984 S: MessageRelayService<MessageRelay = R>,
985 R: Send + Relay + 'static,
986 {
987 let mut jset = JoinSet::new();
988 for (setup, seed) in parties {
989 let relay = coord.connect().await.unwrap();
990
991 jset.spawn(run(setup, seed, relay));
992 }
993
994 let mut shares = vec![];
995
996 while let Some(fini) = jset.join_next().await {
997 let fini = fini.unwrap();
998
999 if let Err(ref err) = fini {
1000 println!("error {}", err);
1001 }
1002
1003 let share = fini.unwrap();
1004
1005 println!(
1006 "PK {}",
1007 share
1008 .public_key()
1009 .to_bytes()
1010 .iter()
1011 .map(|v| format!("{:02X}", v))
1012 .collect::<Vec<_>>()
1013 .join(".")
1014 );
1015
1016 shares.push(share);
1017 }
1018
1019 shares
1020 }
1021
1022 #[tokio::test(flavor = "multi_thread")]
1023 async fn dkg_r1() {
1024 sim(2, &[0, 1, 1], SimpleMessageRelay::new()).await;
1025 }
1026
1027 #[tokio::test(flavor = "multi_thread")]
1028 async fn keyshares() {
1029 let shares = sim(2, &[0, 1, 1], SimpleMessageRelay::new()).await;
1030
1031 for s in &shares {
1032 let bytes = s.as_slice().to_vec();
1033
1034 let _reloaded = Keyshare::from_vec(bytes).unwrap();
1035 }
1036 }
1037
1038 #[tokio::test(flavor = "multi_thread")]
1039 async fn n1() {
1040 let parties = setup_keygen(None, 2, 3, None);
1041
1042 let play = EvilPlay::new().drop_message(MsgId::ZERO_ID, None);
1043
1044 sim_parties(parties, EvilMessageRelay::new(play)).await;
1045 }
1046
1047 #[tokio::test(flavor = "multi_thread")]
1048 async fn inject_random_messages() {
1049 let parties = setup_keygen(None, 2, 3, None);
1050
1051 let _intance = parties[0].0.instance_id();
1055
1056 let mut rng = rand::thread_rng();
1057
1058 let mut play = EvilPlay::new().drop_message(MsgId::ZERO_ID, None);
1059
1060 for _ in 0..3 {
1061 let mut bytes = [0u8; 2000];
1062 rng.fill_bytes(&mut bytes);
1063 play = play.inject_message(bytes.into(), |_, _| true);
1064 }
1065
1066 let msg_id = parties[0].0.msg_id_from(
1067 0, None, DKG_MSG_R1,
1069 );
1070
1071 let mut bad_msg = vec![]; bad_msg.extend(msg_id.as_slice());
1075 bad_msg.extend(10u32.to_le_bytes());
1076 bad_msg.extend(0u64.to_le_bytes()); bad_msg.extend([0u8; 32]); let play = play.inject_message(bad_msg, |_, p| p == 1);
1080
1081 sim_parties(parties, EvilMessageRelay::new(play)).await;
1082 }
1083}