distributedgen.rs
1 use std::collections::{BTreeMap, HashMap}; 2 use std::fmt::Debug; 3 use std::hash::Hash; 4 use std::io::Write; 5 6 use anyhow::{ensure, format_err}; 7 use async_trait::async_trait; 8 use bitcoin::secp256k1; 9 use bitcoin_hashes::sha256::{Hash as Sha256, HashEngine}; 10 use bls12_381::Scalar; 11 use fedimint_core::config::{ 12 DkgError, DkgGroup, DkgMessage, DkgPeerMsg, DkgResult, ISupportedDkgMessage, 13 }; 14 use fedimint_core::core::{Decoder, ModuleInstanceId, ModuleKind}; 15 use fedimint_core::encoding::{Decodable, Encodable}; 16 use fedimint_core::module::registry::ModuleDecoderRegistry; 17 use fedimint_core::module::PeerHandle; 18 use fedimint_core::net::peers::MuxPeerConnections; 19 use fedimint_core::runtime::spawn; 20 use fedimint_core::{BitcoinHash, NumPeersExt, PeerId}; 21 use rand::rngs::OsRng; 22 use rand::{RngCore, SeedableRng}; 23 use rand_chacha::ChaChaRng; 24 use serde::de::DeserializeOwned; 25 use serde::Serialize; 26 use sha3::Digest; 27 use threshold_crypto::ff::Field; 28 use threshold_crypto::group::Curve; 29 use threshold_crypto::poly::Commitment; 30 use threshold_crypto::serde_impl::SerdeSecret; 31 use threshold_crypto::{ 32 G1Affine, G1Projective, G2Affine, G2Projective, PublicKeySet, SecretKeyShare, 33 }; 34 35 struct Dkg<G> { 36 gen_g: G, 37 peers: Vec<PeerId>, 38 our_id: PeerId, 39 threshold: usize, 40 f1_poly: Vec<Scalar>, 41 f2_poly: Vec<Scalar>, 42 hashed_commits: BTreeMap<PeerId, Sha256>, 43 commitments: BTreeMap<PeerId, Vec<G>>, 44 sk_shares: BTreeMap<PeerId, Scalar>, 45 pk_shares: BTreeMap<PeerId, Vec<G>>, 46 } 47 48 /// Implementation of "Secure Distributed Key Generation for Discrete-Log Based 49 /// Cryptosystems" by Rosario Gennaro and Stanislaw Jarecki and Hugo Krawczyk 50 /// and Tal Rabin 51 /// 52 /// Prevents any manipulation of the secret key, but fails with any 53 /// non-cooperative peers 54 impl<G: DkgGroup> Dkg<G> { 55 /// Creates the DKG and the first step of the algorithm 56 pub fn new( 57 group: G, 58 our_id: PeerId, 59 peers: Vec<PeerId>, 60 threshold: usize, 61 rng: &mut impl rand::RngCore, 62 ) -> (Self, DkgStep<G>) { 63 let f1_poly = random_scalar_coefficients(threshold - 1, rng); 64 let f2_poly = random_scalar_coefficients(threshold - 1, rng); 65 66 let mut dkg = Dkg { 67 gen_g: group, 68 peers, 69 our_id, 70 threshold, 71 f1_poly, 72 f2_poly, 73 hashed_commits: Default::default(), 74 commitments: Default::default(), 75 sk_shares: Default::default(), 76 pk_shares: Default::default(), 77 }; 78 79 // broadcast our commitment to the polynomials 80 let commit: Vec<G> = dkg 81 .f1_poly 82 .iter() 83 .map(|c| dkg.gen_g * *c) 84 .zip(dkg.f2_poly.iter().map(|c| dkg.gen_h() * *c)) 85 .map(|(g, h)| g + h) 86 .collect(); 87 88 let hashed = dkg.hash(commit.clone()); 89 dkg.commitments.insert(our_id, commit); 90 dkg.hashed_commits.insert(our_id, hashed); 91 let step = dkg.broadcast(DkgMessage::HashedCommit(hashed)); 92 93 (dkg, step) 94 } 95 96 /// Runs a single step of the DKG algorithm, processing a `msg` from `peer` 97 pub fn step(&mut self, peer: PeerId, msg: DkgMessage<G>) -> anyhow::Result<DkgStep<G>> { 98 match msg { 99 DkgMessage::HashedCommit(hashed) => { 100 match self.hashed_commits.get(&peer) { 101 Some(old) if *old != hashed => { 102 return Err(format_err!("{peer} sent us two hashes!")) 103 } 104 _ => self.hashed_commits.insert(peer, hashed), 105 }; 106 107 if self.hashed_commits.len() == self.peers.len() { 108 let our_commit = self.commitments[&self.our_id].clone(); 109 return Ok(self.broadcast(DkgMessage::Commit(our_commit))); 110 } 111 } 112 DkgMessage::Commit(commit) => { 113 let hash = self.hash(commit.clone()); 114 ensure!(self.threshold == commit.len(), "wrong degree from {peer}"); 115 ensure!(hash == self.hashed_commits[&peer], "wrong hash from {peer}"); 116 117 match self.commitments.get(&peer) { 118 Some(old) if *old != commit => { 119 return Err(format_err!("{peer} sent us two commitments!")) 120 } 121 _ => self.commitments.insert(peer, commit), 122 }; 123 124 // once everyone has made commitments, send out shares 125 if self.commitments.len() == self.peers.len() { 126 let mut messages = vec![]; 127 for peer in &self.peers { 128 let s1 = evaluate_polynomial_scalar(&self.f1_poly, &scalar(peer)); 129 let s2 = evaluate_polynomial_scalar(&self.f2_poly, &scalar(peer)); 130 131 if *peer == self.our_id { 132 self.sk_shares.insert(self.our_id, s1); 133 } else { 134 messages.push((*peer, DkgMessage::Share(s1, s2))); 135 } 136 } 137 return Ok(DkgStep::Messages(messages)); 138 } 139 } 140 // Pedersen-VSS verifies the shares match the commitments 141 DkgMessage::Share(s1, s2) => { 142 let share_product = (self.gen_g * s1) + (self.gen_h() * s2); 143 let commitment = self 144 .commitments 145 .get(&peer) 146 .ok_or_else(|| format_err!("{peer} sent share before commit"))?; 147 let commit_product: G = commitment 148 .iter() 149 .enumerate() 150 .map(|(idx, commit)| *commit * scalar(&self.our_id).pow(&[idx as u64, 0, 0, 0])) 151 .reduce(|a, b| a + b) 152 .expect("sums"); 153 154 ensure!(share_product == commit_product, "bad commit from {peer}"); 155 match self.sk_shares.get(&peer) { 156 Some(old) if *old != s1 => { 157 return Err(format_err!("{peer} sent us two shares!")) 158 } 159 _ => self.sk_shares.insert(peer, s1), 160 }; 161 162 if self.sk_shares.len() == self.peers.len() { 163 let extract: Vec<G> = self.f1_poly.iter().map(|c| self.gen_g * *c).collect(); 164 165 self.pk_shares.insert(self.our_id, extract.clone()); 166 return Ok(self.broadcast(DkgMessage::Extract(extract))); 167 } 168 } 169 // Feldman-VSS exposes the public key shares 170 DkgMessage::Extract(extract) => { 171 let share = self 172 .sk_shares 173 .get(&peer) 174 .ok_or_else(|| format_err!("{peer} sent extract before share"))?; 175 let share_product = self.gen_g * *share; 176 let extract_product: G = extract 177 .iter() 178 .enumerate() 179 .map(|(idx, commit)| *commit * scalar(&self.our_id).pow(&[idx as u64, 0, 0, 0])) 180 .reduce(|a, b| a + b) 181 .expect("sums"); 182 183 ensure!(share_product == extract_product, "bad extract from {peer}"); 184 ensure!(self.threshold == extract.len(), "wrong degree from {peer}"); 185 match self.pk_shares.get(&peer) { 186 Some(old) if *old != extract => { 187 return Err(format_err!("{peer} sent us two extracts!")) 188 } 189 _ => self.pk_shares.insert(peer, extract), 190 }; 191 192 if self.pk_shares.len() == self.peers.len() { 193 let sks = self.sk_shares.values().sum(); 194 195 let pks: Vec<G> = (0..self.threshold) 196 .map(|idx| { 197 self.pk_shares 198 .values() 199 .map(|shares| *shares.get(idx).unwrap()) 200 .reduce(|a, b| a + b) 201 .expect("sums") 202 }) 203 .collect(); 204 205 return Ok(DkgStep::Result(DkgKeys { 206 public_key_set: pks, 207 secret_key_share: sks, 208 })); 209 } 210 } 211 } 212 213 Ok(DkgStep::Messages(vec![])) 214 } 215 216 fn hash(&self, poly: Vec<G>) -> Sha256 { 217 let mut engine = HashEngine::default(); 218 for element in poly.iter() { 219 engine 220 .write_all(element.to_bytes().as_ref()) 221 .expect("hashes"); 222 } 223 Sha256::from_engine(engine) 224 } 225 226 fn broadcast(&self, msg: DkgMessage<G>) -> DkgStep<G> { 227 let others = self.peers.iter().filter(|p| **p != self.our_id); 228 DkgStep::Messages(others.map(|peer| (*peer, msg.clone())).collect()) 229 } 230 231 /// Get a second generator by hashing the first one to the curve 232 fn gen_h(&self) -> G { 233 let mut hash_engine = sha3::Sha3_256::new(); 234 235 hash_engine.update(self.gen_g.clone().to_bytes().as_ref()); 236 237 G::random(&mut ChaChaRng::from_seed(hash_engine.finalize().into())) 238 } 239 } 240 241 /// PeerIds are offset by 1, since evaluating a poly at 0 reveals the secret 242 pub fn scalar(peer: &PeerId) -> Scalar { 243 Scalar::from(peer.to_usize() as u64 + 1) 244 } 245 246 pub struct DkgRunner<T> { 247 peers: Vec<PeerId>, 248 our_id: PeerId, 249 dkg_config: HashMap<T, usize>, 250 } 251 252 /// Helper for running multiple DKGs over the same peer connections 253 /// 254 /// Messages are `(T, DkgMessage)` for creating a DKG for every `T` 255 impl<T> DkgRunner<T> 256 where 257 T: Serialize + DeserializeOwned + Unpin + Send + Clone + Eq + Hash, 258 { 259 /// Create multiple DKGs with the same `threshold` signatures required 260 pub fn multi(keys: Vec<T>, threshold: usize, our_id: &PeerId, peers: &[PeerId]) -> Self { 261 let dkg_config = keys.into_iter().map(|key| (key, threshold)).collect(); 262 263 Self { 264 our_id: *our_id, 265 peers: peers.to_vec(), 266 dkg_config, 267 } 268 } 269 270 /// Create a single DKG with `threshold` signatures required 271 pub fn new(key: T, threshold: usize, our_id: &PeerId, peers: &[PeerId]) -> Self { 272 Self::multi(vec![key], threshold, our_id, peers) 273 } 274 275 /// Create another DKG with `threshold` signatures required 276 pub fn add(&mut self, key: T, threshold: usize) { 277 self.dkg_config.insert(key, threshold); 278 } 279 280 /// Create keys from G2 (96B keys, 48B messages) used in `tbs` 281 pub async fn run_g2( 282 &mut self, 283 module_id: ModuleInstanceId, 284 connections: &MuxPeerConnections<(ModuleInstanceId, String), DkgPeerMsg>, 285 ) -> DkgResult<HashMap<T, DkgKeys<G2Projective>>> { 286 self.run(module_id, G2Projective::generator(), connections) 287 .await 288 } 289 290 /// Create keys from G1 (48B keys, 96B messages) used in `threshold_crypto` 291 pub async fn run_g1( 292 &mut self, 293 module_id: ModuleInstanceId, 294 connections: &MuxPeerConnections<(ModuleInstanceId, String), DkgPeerMsg>, 295 ) -> DkgResult<HashMap<T, DkgKeys<G1Projective>>> { 296 self.run(module_id, G1Projective::generator(), connections) 297 .await 298 } 299 300 /// Runs the DKG algorithms with our peers 301 /// 302 /// WARNING: Currently we do not handle any unexpected messages, all peers 303 /// are expected to be cooperative 304 pub async fn run<G: DkgGroup>( 305 &mut self, 306 module_id: ModuleInstanceId, 307 group: G, 308 connections: &MuxPeerConnections<(ModuleInstanceId, String), DkgPeerMsg>, 309 ) -> DkgResult<HashMap<T, DkgKeys<G>>> 310 where 311 DkgMessage<G>: ISupportedDkgMessage, 312 { 313 // Use tokio channel to await on `recv` or we might block 314 let (send, mut receive) = tokio::sync::mpsc::channel(10_000); 315 316 // For every `key` we run DKG in a new tokio task 317 self.dkg_config 318 .clone() 319 .into_iter() 320 .for_each(|(key, threshold)| { 321 let our_id = self.our_id; 322 let peers = self.peers.clone(); 323 let connections = connections.clone(); 324 let key = serde_json::to_string(&key).expect("serialization can't fail"); 325 let send = send.clone(); 326 327 spawn("dkg runner", async move { 328 let (dkg, step) = Dkg::new(group, our_id, peers, threshold, &mut OsRng); 329 let result = 330 Self::run_dkg_key((module_id, key.clone()), connections, dkg, step).await; 331 send.send((key, result)).await.expect("channel open"); 332 }); 333 }); 334 335 // Collect every key, returning an error if any fails 336 let mut results: HashMap<T, DkgKeys<G>> = HashMap::new(); 337 while results.len() < self.dkg_config.len() { 338 let (key, result) = receive.recv().await.expect("channel open"); 339 let key = serde_json::from_str(&key).expect("serialization can't fail"); 340 results.insert(key, result?); 341 } 342 Ok(results) 343 } 344 345 /// Runs the DKG algorithms for a given key and module id 346 async fn run_dkg_key<G: DkgGroup>( 347 key_id: (ModuleInstanceId, String), 348 connections: MuxPeerConnections<(ModuleInstanceId, String), DkgPeerMsg>, 349 mut dkg: Dkg<G>, 350 initial_step: DkgStep<G>, 351 ) -> DkgResult<DkgKeys<G>> 352 where 353 DkgMessage<G>: ISupportedDkgMessage, 354 { 355 if let DkgStep::Messages(messages) = initial_step { 356 for (peer, msg) in messages { 357 let send_msg = DkgPeerMsg::DistributedGen(msg.to_msg()); 358 connections.send(&[peer], key_id.clone(), send_msg).await?; 359 } 360 } 361 362 // process steps for each key 363 loop { 364 let (peer, msg) = connections.receive(key_id.clone()).await?; 365 366 let message = match msg { 367 DkgPeerMsg::DistributedGen(v) => Ok(v), 368 _ => Err(format_err!( 369 "Key {key_id:?} wrong message received: {msg:?}" 370 )), 371 }?; 372 373 let message = ISupportedDkgMessage::from_msg(message)?; 374 let step = dkg.step(peer, message)?; 375 376 match step { 377 DkgStep::Messages(messages) => { 378 for (peer, msg) in messages { 379 let send_msg = DkgPeerMsg::DistributedGen(msg.to_msg()); 380 connections.send(&[peer], key_id.clone(), send_msg).await?; 381 } 382 } 383 DkgStep::Result(result) => { 384 return Ok(result); 385 } 386 } 387 } 388 } 389 } 390 391 pub fn random_scalar_coefficients(degree: usize, rng: &mut impl RngCore) -> Vec<Scalar> { 392 (0..=degree).map(|_| random_scalar(rng)).collect() 393 } 394 395 fn random_scalar(rng: &mut impl RngCore) -> Scalar { 396 Scalar::random(rng) 397 } 398 399 pub fn evaluate_polynomial_scalar(coefficients: &[Scalar], x: &Scalar) -> Scalar { 400 coefficients 401 .iter() 402 .cloned() 403 .rev() 404 .reduce(|acc, coefficient| acc * x + coefficient) 405 .expect("We have at least one coefficient") 406 } 407 408 #[derive(Debug, Clone)] 409 pub enum DkgStep<G: DkgGroup> { 410 Messages(Vec<(PeerId, DkgMessage<G>)>), 411 Result(DkgKeys<G>), 412 } 413 414 #[derive(Debug, Clone)] 415 pub struct DkgKeys<G> { 416 pub public_key_set: Vec<G>, 417 pub secret_key_share: Scalar, 418 } 419 420 /// Our secret key share of a threshold key 421 #[derive(Debug, Clone)] 422 pub struct ThresholdKeys { 423 pub public_key_set: PublicKeySet, 424 pub secret_key_share: SerdeSecret<SecretKeyShare>, 425 } 426 427 impl DkgKeys<G2Projective> { 428 pub fn tbs(self) -> (Vec<G2Projective>, tbs::SecretKeyShare) { 429 ( 430 self.public_key_set, 431 tbs::SecretKeyShare(self.secret_key_share), 432 ) 433 } 434 } 435 436 impl DkgKeys<G1Projective> { 437 pub fn threshold_crypto(&self) -> ThresholdKeys { 438 ThresholdKeys { 439 public_key_set: PublicKeySet::from(Commitment::from(self.public_key_set.clone())), 440 secret_key_share: SerdeSecret(SecretKeyShare::from_mut( 441 &mut self.secret_key_share.clone(), 442 )), 443 } 444 } 445 446 pub fn tpe(self) -> (Vec<G1Projective>, Scalar) { 447 (self.public_key_set, self.secret_key_share) 448 } 449 } 450 451 pub fn evaluate_polynomial_g1(coefficients: &[G1Projective], x: &Scalar) -> G1Affine { 452 coefficients 453 .iter() 454 .cloned() 455 .rev() 456 .reduce(|acc, coefficient| acc * x + coefficient) 457 .expect("We have at least one coefficient") 458 .to_affine() 459 } 460 461 pub fn evaluate_polynomial_g2(coefficients: &[G2Projective], x: &Scalar) -> G2Affine { 462 coefficients 463 .iter() 464 .cloned() 465 .rev() 466 .reduce(|acc, coefficient| acc * x + coefficient) 467 .expect("We have at least one coefficient") 468 .to_affine() 469 } 470 471 // TODO: this trait is only needed to break the `DkgHandle` impl 472 // from it's definition that is still in `fedimint-core` 473 #[async_trait] 474 pub trait PeerHandleOps { 475 async fn run_dkg_g1<T>(&self, v: T) -> DkgResult<HashMap<T, DkgKeys<G1Projective>>> 476 where 477 T: Serialize + DeserializeOwned + Unpin + Send + Clone + Eq + Hash + Sync; 478 479 async fn run_dkg_multi_g2<T>(&self, v: Vec<T>) -> DkgResult<HashMap<T, DkgKeys<G2Projective>>> 480 where 481 T: Serialize + DeserializeOwned + Unpin + Send + Clone + Eq + Hash + Sync; 482 483 /// Exchanges a `DkgPeerMsg::PublicKey(key)` with all peers. Used by the 484 /// wallet module to setup the multisig wallet during DKG. 485 async fn exchange_pubkeys( 486 &self, 487 dkg_key: String, 488 key: secp256k1::PublicKey, 489 ) -> DkgResult<BTreeMap<PeerId, secp256k1::PublicKey>>; 490 491 /// Exchanges a `DkgPeerMsg::Module(Vec<u8>)` with all peers. All peers are 492 /// required to be online and submit a response for this to return 493 /// properly. The caller's message will be included in the returned 494 /// `BTreeMap` under the `PeerId` of this peer. This allows modules to 495 /// exchange arbitrary data during distributed key generation. 496 async fn exchange_with_peers<T: Encodable + Decodable + Send + Sync>( 497 &self, 498 dkg_key: String, 499 data: T, 500 kind: ModuleKind, 501 decoder: Decoder, 502 ) -> DkgResult<BTreeMap<PeerId, T>>; 503 } 504 505 #[async_trait] 506 impl<'a> PeerHandleOps for PeerHandle<'a> { 507 async fn run_dkg_g1<T>(&self, v: T) -> DkgResult<HashMap<T, DkgKeys<G1Projective>>> 508 where 509 T: Serialize + DeserializeOwned + Unpin + Send + Clone + Eq + Hash + Sync, 510 { 511 let mut dkg = DkgRunner::new(v, self.peers.threshold(), &self.our_id, &self.peers); 512 dkg.run_g1(self.module_instance_id, self.connections).await 513 } 514 515 async fn run_dkg_multi_g2<T>(&self, v: Vec<T>) -> DkgResult<HashMap<T, DkgKeys<G2Projective>>> 516 where 517 T: Serialize + DeserializeOwned + Unpin + Send + Clone + Eq + Hash + Sync, 518 { 519 let mut dkg = DkgRunner::multi(v, self.peers.threshold(), &self.our_id, &self.peers); 520 521 dkg.run_g2(self.module_instance_id, self.connections).await 522 } 523 524 async fn exchange_pubkeys( 525 &self, 526 dkg_key: String, 527 key: secp256k1::PublicKey, 528 ) -> DkgResult<BTreeMap<PeerId, secp256k1::PublicKey>> { 529 let mut peer_peg_in_keys: BTreeMap<PeerId, secp256k1::PublicKey> = BTreeMap::new(); 530 531 self.connections 532 .send( 533 &self.peers, 534 (self.module_instance_id, dkg_key.clone()), 535 DkgPeerMsg::PublicKey(key), 536 ) 537 .await?; 538 539 peer_peg_in_keys.insert(self.our_id, key); 540 while peer_peg_in_keys.len() < self.peers.len() { 541 match self 542 .connections 543 .receive((self.module_instance_id, dkg_key.clone())) 544 .await? 545 { 546 (peer, DkgPeerMsg::PublicKey(key)) => { 547 peer_peg_in_keys.insert(peer, key); 548 } 549 (peer, msg) => { 550 return Err( 551 format_err!("Invalid message received from: {peer}: {msg:?}").into(), 552 ); 553 } 554 } 555 } 556 557 Ok(peer_peg_in_keys) 558 } 559 560 async fn exchange_with_peers<T: Encodable + Decodable + Send + Sync>( 561 &self, 562 dkg_key: String, 563 data: T, 564 kind: ModuleKind, 565 decoder: Decoder, 566 ) -> DkgResult<BTreeMap<PeerId, T>> { 567 let mut peer_data: BTreeMap<PeerId, T> = BTreeMap::new(); 568 let msg = DkgPeerMsg::Module(data.consensus_encode_to_vec()); 569 570 self.connections 571 .send(&self.peers, (self.module_instance_id, dkg_key.clone()), msg) 572 .await?; 573 peer_data.insert(self.our_id, data); 574 575 let modules = 576 ModuleDecoderRegistry::new([(self.module_instance_id, kind.clone(), decoder)]); 577 while peer_data.len() < self.peers.len() { 578 match self 579 .connections 580 .receive((self.module_instance_id, dkg_key.clone())) 581 .await? 582 { 583 (peer, DkgPeerMsg::Module(bytes)) => { 584 let received_data: T = T::consensus_decode_vec(bytes, &modules) 585 .map_err(|_| DkgError::ModuleDecodeError(kind.clone()))?; 586 peer_data.insert(peer, received_data); 587 } 588 (peer, msg) => { 589 return Err(format_err!("Invalid message received from {peer}: {msg:?}").into()); 590 } 591 } 592 } 593 594 Ok(peer_data) 595 } 596 } 597 598 #[cfg(test)] 599 mod tests { 600 use std::collections::{HashMap, VecDeque}; 601 602 use fedimint_core::PeerId; 603 use rand::rngs::OsRng; 604 use threshold_crypto::{G1Projective, G2Projective}; 605 606 use crate::config::distributedgen::{ 607 evaluate_polynomial_g2, scalar, Dkg, DkgGroup, DkgKeys, DkgStep, ThresholdKeys, 608 }; 609 610 #[test_log::test] 611 fn test_dkg() { 612 for (peer, keys) in run(G1Projective::generator()) { 613 let ThresholdKeys { 614 public_key_set, 615 secret_key_share, 616 } = keys.threshold_crypto(); 617 assert_eq!(public_key_set.threshold(), 2); 618 assert_eq!( 619 public_key_set.public_key_share(peer.to_usize()), 620 secret_key_share.public_key_share() 621 ); 622 } 623 624 for (peer, keys) in run(G2Projective::generator()) { 625 let (pk, sk) = keys.tbs(); 626 assert_eq!(pk.len(), 3); 627 assert_eq!( 628 evaluate_polynomial_g2(&pk, &scalar(&peer)), 629 sk.to_pub_key_share().0 630 ); 631 } 632 } 633 634 fn run<G: DkgGroup>(group: G) -> HashMap<PeerId, DkgKeys<G>> { 635 let mut rng = OsRng; 636 let num_peers = 4; 637 let threshold = 3; 638 let peers = (0..num_peers as u16).map(PeerId::from).collect::<Vec<_>>(); 639 640 let mut steps: VecDeque<(PeerId, DkgStep<G>)> = VecDeque::new(); 641 let mut dkgs: HashMap<PeerId, Dkg<G>> = HashMap::new(); 642 let mut keys: HashMap<PeerId, DkgKeys<G>> = HashMap::new(); 643 644 for peer in &peers { 645 let (dkg, step) = Dkg::new(group, *peer, peers.clone(), threshold, &mut rng); 646 dkgs.insert(*peer, dkg); 647 steps.push_back((*peer, step)); 648 } 649 650 while keys.len() < peers.len() { 651 match steps.pop_front() { 652 Some((peer, DkgStep::Messages(messages))) => { 653 for (receive_peer, msg) in messages { 654 let receive_dkg = dkgs.get_mut(&receive_peer).unwrap(); 655 let step = receive_dkg.step(peer, msg); 656 steps.push_back((receive_peer, step.unwrap())); 657 } 658 } 659 Some((peer, DkgStep::Result(step_keys))) => { 660 keys.insert(peer, step_keys); 661 } 662 _ => {} 663 } 664 } 665 666 keys 667 } 668 }