diff --git a/src/common.rs b/src/common.rs index 14e6989d..391de944 100644 --- a/src/common.rs +++ b/src/common.rs @@ -171,7 +171,7 @@ pub mod test_helpers { /// These evaluations take the form of s * G == \Sum{k=0}{T+1}(a_k * x^k) where the a vals are the coeffs of the polys /// There is 1 share per poly, N polys, and each poly is degree T-1 (so T coeffs) /// First we evaluate each poly, then we subtract each s * G -pub struct CheckPrivateShares<'a> { +pub struct CheckPrivateShares { /// number of keys n: u32, /// threshold, where the degree of each poly is (t-1) @@ -181,16 +181,25 @@ pub struct CheckPrivateShares<'a> { /// Negated DKG private shares for the receiving key ID, indexed by sending key ID pub neg_shares: HashMap, /// Polynomial commitments for each key ID - polys: &'a [PolyCommitment], + polys: HashMap, } -impl<'a> CheckPrivateShares<'a> { +impl CheckPrivateShares { /// Construct a new CheckPrivateShares object - pub fn new(id: Scalar, shares: &HashMap, polys: &'a [PolyCommitment]) -> Self { + pub fn new( + id: Scalar, + shares: &HashMap, + polys: HashMap, + ) -> Self { + let mut l: usize = 0; + for (_id, comm) in &polys { + l = comm.poly.len(); + break; + } let n: u32 = shares.len().try_into().unwrap(); - let t: u32 = polys[0].poly.len().try_into().unwrap(); + let t: u32 = l.try_into().unwrap(); let x = id; - let mut powers = Vec::with_capacity(polys[0].poly.len()); + let mut powers = Vec::with_capacity(l); let mut pow = Scalar::one(); for _ in 0..t { @@ -213,27 +222,29 @@ impl<'a> CheckPrivateShares<'a> { } } -impl<'a> MultiMult for CheckPrivateShares<'a> { +impl MultiMult for CheckPrivateShares { /// The first n*t scalars will be powers, the last n will be the negation of shares fn get_scalar(&self, i: usize) -> &Scalar { + println!("get_scalar({})", i); let h: u32 = i.try_into().unwrap(); let u: usize = self.t.try_into().unwrap(); if h < self.n * self.t { &self.powers[i % u] } else { - &self.neg_shares[&(h - (self.t * self.n))] + &self.neg_shares[&(h - (self.t * self.n) + 1)] } } /// The first n*t points will be poly coeffs, the last n will be G fn get_point(&self, i: usize) -> &Point { + println!("get_point({})", i); let h: u32 = i.try_into().unwrap(); let u: usize = self.t.try_into().unwrap(); if h < self.n * self.t { let j = i / u; let k = i % u; - &self.polys[j].poly[k] + &self.polys[&((j + 1) as u32)].poly[k] } else { &G } diff --git a/src/compute.rs b/src/compute.rs index 6cf2a750..9d015cb8 100644 --- a/src/compute.rs +++ b/src/compute.rs @@ -114,7 +114,7 @@ pub fn aggregate_nonce( /// Compute a one-based Scalar from a zero-based integer pub fn id(i: u32) -> Scalar { - Scalar::from(i + 1) + Scalar::from(i) } /// Evaluate the public polynomial `f` at scalar `x` using multi-exponentiation diff --git a/src/main.rs b/src/main.rs index d36ddd5e..08d6acce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,12 +37,12 @@ fn main() { .collect(); let dkg_start = time::Instant::now(); - let A = v1::test_helpers::dkg(&mut signers, &mut rng).expect("v1 dkg failed"); + let polys = v1::test_helpers::dkg(&mut signers, &mut rng).expect("v1 dkg failed"); let dkg_time = dkg_start.elapsed(); let mut signers = signers[..(K * 3 / 4).try_into().unwrap()].to_vec(); let mut aggregator = v1::Aggregator::new(N, T); - aggregator.init(A).expect("aggregator init failed"); + aggregator.init(&polys).expect("aggregator init failed"); let party_sign_start = time::Instant::now(); let (nonces, sig_shares) = v1::test_helpers::sign(msg, &mut signers, &mut rng); @@ -73,12 +73,12 @@ fn main() { .collect(); let dkg_start = time::Instant::now(); - let A = v2::test_helpers::dkg(&mut signers, &mut rng).expect("v2 dkg failed"); + let polys = v2::test_helpers::dkg(&mut signers, &mut rng).expect("v2 dkg failed"); let dkg_time = dkg_start.elapsed(); let mut signers = signers[..(K * 3 / 4).try_into().unwrap()].to_vec(); let mut aggregator = v2::Aggregator::new(N, T); - aggregator.init(A).expect("aggregator init failed"); + aggregator.init(&polys).expect("aggregator init failed"); let party_sign_start = time::Instant::now(); let (nonces, sig_shares, key_ids) = v2::test_helpers::sign(msg, &mut signers, &mut rng); diff --git a/src/net.rs b/src/net.rs index 44488726..593f2e1b 100644 --- a/src/net.rs +++ b/src/net.rs @@ -121,6 +121,8 @@ impl Signable for DkgPublicShares { pub struct DkgPrivateBegin { /// DKG round ID pub dkg_id: u64, + /// Signer IDs who responded in time for this DKG round + pub signer_ids: Vec, /// Key IDs who responded in time for this DKG round pub key_ids: Vec, } @@ -132,6 +134,9 @@ impl Signable for DkgPrivateBegin { for key_id in &self.key_ids { hasher.update(key_id.to_be_bytes()); } + for signer_id in &self.signer_ids { + hasher.update(signer_id.to_be_bytes()); + } } } @@ -167,6 +172,8 @@ impl Signable for DkgPrivateShares { pub struct DkgEndBegin { /// DKG round ID pub dkg_id: u64, + /// Signer IDs who responded in time for this DKG round + pub signer_ids: Vec, /// Key IDs who responded in time for this DKG round pub key_ids: Vec, } @@ -178,6 +185,9 @@ impl Signable for DkgEndBegin { for key_id in &self.key_ids { hasher.update(key_id.to_be_bytes()); } + for signer_id in &self.signer_ids { + hasher.update(signer_id.to_be_bytes()); + } } } @@ -510,6 +520,7 @@ mod test { let dkg_private_begin = DkgPrivateBegin { dkg_id: 0, key_ids: Default::default(), + signer_ids: Default::default(), }; let msg = Message::DkgBegin(dkg_begin.clone()); let coordinator_packet_dkg_begin = Packet { diff --git a/src/state_machine/coordinator/fire.rs b/src/state_machine/coordinator/fire.rs index 2bac1589..aa376b94 100644 --- a/src/state_machine/coordinator/fire.rs +++ b/src/state_machine/coordinator/fire.rs @@ -1,4 +1,4 @@ -use hashbrown::HashSet; +use hashbrown::{HashMap, HashSet}; use std::{collections::BTreeMap, time::Instant}; use tracing::{debug, error, info, warn}; @@ -32,7 +32,7 @@ pub struct Coordinator { dkg_public_shares: BTreeMap, dkg_private_shares: BTreeMap, dkg_end_messages: BTreeMap, - party_polynomials: BTreeMap, + party_polynomials: HashMap, public_nonces: BTreeMap, signature_shares: BTreeMap>, /// aggregate public key @@ -353,6 +353,7 @@ impl Coordinator { let dkg_begin = DkgPrivateBegin { dkg_id: self.current_dkg_id, key_ids: active_key_ids, + signer_ids: self.dkg_public_shares.keys().cloned().collect(), }; let dkg_private_begin_msg = Packet { sig: dkg_begin @@ -378,7 +379,7 @@ impl Coordinator { self.current_dkg_id ); let active_key_ids = self - .dkg_public_shares + .dkg_private_shares .keys() .flat_map(|signer_id| self.config.signer_key_ids[signer_id].clone()) .collect::>(); @@ -386,6 +387,7 @@ impl Coordinator { let dkg_end_begin = DkgEndBegin { dkg_id: self.current_dkg_id, key_ids: active_key_ids, + signer_ids: self.dkg_private_shares.keys().cloned().collect(), }; let dkg_end_begin_msg = Packet { sig: dkg_end_begin @@ -695,8 +697,6 @@ impl Coordinator { } if self.sign_wait_signer_ids.is_empty() { // Calculate the aggregate signature - let polys: Vec = self.party_polynomials.values().cloned().collect(); - let nonce_responses = self .public_nonces .values() @@ -726,7 +726,7 @@ impl Coordinator { shares.len() ); - self.aggregator.init(polys)?; + self.aggregator.init(&self.party_polynomials)?; if is_taproot { let schnorr_proof = self.aggregator.sign_taproot( @@ -1052,7 +1052,7 @@ pub mod test { let message = coordinator.start_private_shares().unwrap(); assert!(matches!(message.msg, Message::DkgPrivateBegin(_))); - assert_eq!(coordinator.get_state(), State::DkgEndGather); + assert_eq!(coordinator.get_state(), State::DkgPrivateGather); assert_eq!(coordinator.current_dkg_id, 0); } diff --git a/src/state_machine/coordinator/frost.rs b/src/state_machine/coordinator/frost.rs index 986d30cb..2662c9ef 100644 --- a/src/state_machine/coordinator/frost.rs +++ b/src/state_machine/coordinator/frost.rs @@ -1,4 +1,4 @@ -use hashbrown::HashSet; +use hashbrown::{HashMap, HashSet}; use std::collections::BTreeMap; use tracing::{debug, info}; @@ -31,7 +31,7 @@ pub struct Coordinator { current_sign_iter_id: u64, dkg_public_shares: BTreeMap, dkg_private_shares: BTreeMap, - party_polynomials: BTreeMap, + party_polynomials: HashMap, public_nonces: BTreeMap, signature_shares: BTreeMap>, /// aggregate public key @@ -204,6 +204,7 @@ impl Coordinator { let dkg_begin = DkgPrivateBegin { dkg_id: self.current_dkg_id, key_ids: (0..self.config.num_keys).collect(), + signer_ids: (0..self.config.num_signers).collect(), }; let dkg_private_begin_msg = Packet { sig: dkg_begin.sign(&self.config.message_private_key).expect(""), @@ -223,6 +224,7 @@ impl Coordinator { let dkg_begin = DkgEndBegin { dkg_id: self.current_dkg_id, key_ids: (0..self.config.num_keys).collect(), + signer_ids: (0..self.config.num_signers).collect(), }; let dkg_end_begin_msg = Packet { sig: dkg_begin.sign(&self.config.message_private_key).expect(""), @@ -453,8 +455,6 @@ impl Coordinator { } if self.ids_to_await.is_empty() { // Calculate the aggregate signature - let polys: Vec = self.party_polynomials.values().cloned().collect(); - let nonce_responses = (0..self.config.num_signers) .map(|i| self.public_nonces[&i].clone()) .collect::>(); @@ -482,7 +482,7 @@ impl Coordinator { shares.len() ); - self.aggregator.init(polys)?; + self.aggregator.init(&self.party_polynomials)?; if is_taproot { let schnorr_proof = self.aggregator.sign_taproot( @@ -764,7 +764,7 @@ pub mod test { let message = coordinator.start_private_shares().unwrap(); assert!(matches!(message.msg, Message::DkgPrivateBegin(_))); - assert_eq!(coordinator.get_state(), State::DkgEndGather); + assert_eq!(coordinator.get_state(), State::DkgPrivateGather); assert_eq!(coordinator.current_dkg_id, 0); } diff --git a/src/state_machine/coordinator/mod.rs b/src/state_machine/coordinator/mod.rs index e36badac..784c15f5 100644 --- a/src/state_machine/coordinator/mod.rs +++ b/src/state_machine/coordinator/mod.rs @@ -485,10 +485,9 @@ pub mod test { feedback_messages(&mut coordinators, &mut signers, &[message]); assert!(operation_results.is_empty()); for coordinator in coordinators.iter() { - assert_eq!(coordinator.get_state(), State::DkgEndGather); + assert_eq!(coordinator.get_state(), State::DkgPrivateGather); } - // Successfully got an Aggregate Public Key... assert_eq!(outbound_messages.len(), 1); match &outbound_messages[0].msg { Message::DkgPrivateBegin(_) => {} @@ -499,7 +498,13 @@ pub mod test { // Send the DKG Private Begin message to all signers and share their responses with the coordinator and signers let (outbound_messages, operation_results) = feedback_messages(&mut coordinators, &mut signers, &outbound_messages); - assert!(outbound_messages.is_empty()); + assert_eq!(outbound_messages.len(), 1); + match &outbound_messages[0].msg { + Message::DkgEndBegin(_) => {} + _ => { + panic!("Expected DkgEndBegin message"); + } + } assert_eq!(operation_results.len(), 1); match operation_results[0] { OperationResult::Dkg(point) => { diff --git a/src/state_machine/signer/mod.rs b/src/state_machine/signer/mod.rs index a5ed4112..f14b3589 100644 --- a/src/state_machine/signer/mod.rs +++ b/src/state_machine/signer/mod.rs @@ -10,8 +10,8 @@ use crate::{ scalar::Scalar, }, net::{ - DkgBegin, DkgEnd, DkgPrivateBegin, DkgPrivateShares, DkgPublicShares, DkgStatus, Message, - NonceRequest, NonceResponse, Packet, Signable, SignatureShareRequest, + DkgBegin, DkgEnd, DkgEndBegin, DkgPrivateBegin, DkgPrivateShares, DkgPublicShares, + DkgStatus, Message, NonceRequest, NonceResponse, Packet, Signable, SignatureShareRequest, SignatureShareResponse, }, state_machine::{PublicKeys, StateMachine}, @@ -83,7 +83,7 @@ pub struct Signer { /// the current state pub state: State, /// map of party_id to the polynomial commitment for that party - pub commitments: BTreeMap, + pub commitments: HashMap, /// map of decrypted DKG private shares pub decrypted_shares: HashMap>, /// invalid private shares @@ -94,6 +94,10 @@ pub struct Signer { pub network_private_key: Scalar, /// the public keys for all signers and coordinator pub public_keys: PublicKeys, + dkg_public_shares: BTreeMap, + dkg_private_shares: BTreeMap, + dkg_private_begin_msg: Option, + dkg_end_begin_msg: Option, } impl Signer { @@ -131,12 +135,16 @@ impl Signer { signer, signer_id, state: State::Idle, - commitments: BTreeMap::new(), + commitments: Default::default(), decrypted_shares: HashMap::new(), invalid_private_shares: Vec::new(), public_nonces: vec![], network_private_key, public_keys, + dkg_public_shares: Default::default(), + dkg_private_shares: Default::default(), + dkg_private_begin_msg: Default::default(), + dkg_end_begin_msg: Default::default(), } } @@ -147,6 +155,10 @@ impl Signer { self.invalid_private_shares.clear(); self.public_nonces.clear(); self.signer.reset_polys(rng); + self.dkg_public_shares.clear(); + self.dkg_private_shares.clear(); + self.dkg_private_begin_msg = None; + self.dkg_end_begin_msg = None; } /// @@ -215,6 +227,7 @@ impl Signer { Message::DkgPrivateBegin(dkg_private_begin) => { self.dkg_private_begin(dkg_private_begin) } + Message::DkgEndBegin(dkg_end_begin) => self.dkg_end_begin(dkg_end_begin), Message::DkgPublicShares(dkg_public_shares) => self.dkg_public_share(dkg_public_shares), Message::DkgPrivateShares(dkg_private_shares) => { self.dkg_private_shares(dkg_private_shares) @@ -228,13 +241,7 @@ impl Signer { match out_msgs { Ok(mut out) => { - if self.public_shares_done() { - debug!( - "public_shares_done==true. commitments {}", - self.commitments.len() - ); - self.move_to(State::DkgPrivateDistribute)?; - } else if self.can_dkg_end() { + if self.can_dkg_end() { debug!( "can_dkg_end==true. shares {} commitments {}", self.decrypted_shares.len(), @@ -252,10 +259,17 @@ impl Signer { /// DKG is done so compute secrets pub fn dkg_ended(&mut self) -> Result { - let polys: Vec = self.commitments.clone().into_values().collect(); + for (_signer_id, shares) in &self.dkg_public_shares { + for (party_id, comm) in shares.comms.iter() { + self.commitments.insert(*party_id, comm.clone()); + } + } let dkg_end = if self.invalid_private_shares.is_empty() { - match self.signer.compute_secrets(&self.decrypted_shares, &polys) { + match self + .signer + .compute_secrets(&self.decrypted_shares, &self.commitments) + { Ok(()) => DkgEnd { dkg_id: self.dkg_id, signer_id: self.signer_id, @@ -304,7 +318,7 @@ impl Signer { self.decrypted_shares.len() ); self.state == State::DkgPrivateGather - && self.commitments.len() == usize::try_from(self.signer.get_num_parties()).unwrap() + //&& self.commitments.len() == usize::try_from(self.signer.get_num_parties()).unwrap() && self.decrypted_shares.len() == usize::try_from(self.signer.get_num_parties()).unwrap() } @@ -455,6 +469,10 @@ impl Signer { .iter() .cloned() .collect::>(); + + self.dkg_private_begin_msg = Some(dkg_private_begin.clone()); + self.move_to(State::DkgPrivateDistribute)?; + info!( "Signer {} sending DkgPrivateShares for round {}", self.signer.get_id(), @@ -499,14 +517,25 @@ impl Signer { Ok(msgs) } + fn dkg_end_begin(&mut self, dkg_end_begin: &DkgEndBegin) -> Result, Error> { + let msgs = vec![]; + + self.dkg_end_begin_msg = Some(dkg_end_begin.clone()); + + info!( + "Signer {} received DkgEndBegin for round {}", + self.signer.get_id(), + self.dkg_id, + ); + + Ok(msgs) + } + /// handle incoming DkgPublicShares pub fn dkg_public_share( &mut self, dkg_public_shares: &DkgPublicShares, ) -> Result, Error> { - for (party_id, comm) in &dkg_public_shares.comms { - self.commitments.insert(*party_id, comm.clone()); - } debug!( "received DkgPublicShares from signer {} {}/{}", dkg_public_shares.signer_id, diff --git a/src/taproot.rs b/src/taproot.rs index c52b680d..8882a570 100644 --- a/src/taproot.rs +++ b/src/taproot.rs @@ -86,10 +86,11 @@ pub mod test_helpers { pub fn dkg( signers: &mut [Signer], rng: &mut RNG, - ) -> Result, HashMap> { - let A: Vec = signers + ) -> Result, HashMap> { + let polys: HashMap = signers .iter() .flat_map(|s| s.get_poly_commitments(rng)) + .map(|comm| (comm.id.id.get_u32(), comm)) .collect(); let mut private_shares = HashMap::new(); @@ -101,13 +102,13 @@ pub mod test_helpers { let mut secret_errors = HashMap::new(); for signer in signers.iter_mut() { - if let Err(signer_secret_errors) = signer.compute_secrets(&private_shares, &A) { + if let Err(signer_secret_errors) = signer.compute_secrets(&private_shares, &polys) { secret_errors.extend(signer_secret_errors.into_iter()); } } if secret_errors.is_empty() { - Ok(A) + Ok(polys) } else { Err(secret_errors) } @@ -186,8 +187,8 @@ mod test { .map(|(id, ids)| v1::Signer::new(id.try_into().unwrap(), ids, N, T, &mut rng)) .collect(); - let A = match test_helpers::dkg(&mut signers, &mut rng) { - Ok(A) => A, + let polys = match test_helpers::dkg(&mut signers, &mut rng) { + Ok(polys) => polys, Err(secret_errors) => { panic!("Got secret errors from DKG: {:?}", secret_errors); } @@ -195,7 +196,7 @@ mod test { let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec(); let mut sig_agg = v1::Aggregator::new(N, T); - sig_agg.init(A.clone()).expect("aggregator init failed"); + sig_agg.init(&polys).expect("aggregator init failed"); let tweaked_public_key = compute::tweaked_public_key(&sig_agg.poly[0], merkle_root); let (nonces, sig_shares) = test_helpers::sign(msg, &mut S, &mut rng, merkle_root); let proof = match sig_agg.sign_taproot(msg, &nonces, &sig_shares, &[], merkle_root) { @@ -248,8 +249,8 @@ mod test { .map(|(id, ids)| v2::Signer::new(id.try_into().unwrap(), ids, Np, Nk, T, &mut rng)) .collect(); - let A = match test_helpers::dkg(&mut signers, &mut rng) { - Ok(A) => A, + let polys = match test_helpers::dkg(&mut signers, &mut rng) { + Ok(polys) => polys, Err(secret_errors) => { panic!("Got secret errors from DKG: {:?}", secret_errors); } @@ -258,7 +259,7 @@ mod test { let mut S = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec(); let key_ids = S.iter().flat_map(|s| s.get_key_ids()).collect::>(); let mut sig_agg = v2::Aggregator::new(Nk, T); - sig_agg.init(A.clone()).expect("aggregator init failed"); + sig_agg.init(&polys).expect("aggregator init failed"); let tweaked_public_key = compute::tweaked_public_key(&sig_agg.poly[0], merkle_root); let (nonces, sig_shares) = test_helpers::sign(msg, &mut S, &mut rng, merkle_root); let proof = match sig_agg.sign_taproot(msg, &nonces, &sig_shares, &key_ids, merkle_root) { diff --git a/src/traits.rs b/src/traits.rs index 762ffb4f..a7055da5 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -42,7 +42,7 @@ pub trait Signer: Clone { fn compute_secrets( &mut self, shares: &HashMap>, - polys: &[PolyCommitment], + polys: &HashMap, ) -> Result<(), HashMap>; /// Generate all nonces for this signer @@ -82,7 +82,7 @@ pub trait Aggregator: Clone { fn new(num_keys: u32, threshold: u32) -> Self; /// Initialize an Aggregator with the passed polynomial commitments - fn init(&mut self, poly_comms: Vec) -> Result<(), AggregatorError>; + fn init(&mut self, poly_comms: &HashMap) -> Result<(), AggregatorError>; /// Check and aggregate the signature shares into a `Signature` fn sign( diff --git a/src/v1.rs b/src/v1.rs index 21bbb577..bfd0fb3e 100644 --- a/src/v1.rs +++ b/src/v1.rs @@ -3,6 +3,7 @@ use num_traits::{One, Zero}; use polynomial::Polynomial; use rand_core::{CryptoRng, RngCore}; use serde::{Deserialize, Serialize}; +use tracing::info; use crate::{ common::{CheckPrivateShares, Nonce, PolyCommitment, PublicNonce, Signature, SignatureShare}, @@ -104,7 +105,7 @@ impl Party { /// Get the shares of this party's private polynomial for all parties pub fn get_shares(&self) -> HashMap { let mut shares = HashMap::new(); - for i in 0..self.n { + for i in 1..self.n + 1 { shares.insert(i, self.f.eval(compute::id(i))); } shares @@ -114,12 +115,12 @@ impl Party { pub fn compute_secret( &mut self, shares: HashMap, - comms: &[PolyCommitment], + polys: &HashMap, ) -> Result<(), DkgError> { let mut missing_shares = Vec::new(); - for i in 0..self.n { - if shares.get(&i).is_none() { - missing_shares.push(i); + for i in polys.keys() { + if shares.get(i).is_none() { + missing_shares.push(*i); } } if !missing_shares.is_empty() { @@ -132,7 +133,7 @@ impl Party { let bad_ids: Vec = shares .keys() .cloned() - .filter(|i| !comms[usize::try_from(*i).unwrap()].verify()) + .filter(|i| !polys[i].verify()) .collect(); if !bad_ids.is_empty() { return Err(DkgError::BadIds(bad_ids)); @@ -141,13 +142,13 @@ impl Party { // building a vector of scalars and points from public poly evaluations and expected values takes too much memory // instead make an object which implements p256k1 MultiMult trait, using the existing powers of x and shares - let mut check_shares = CheckPrivateShares::new(self.id(), &shares, comms); + let mut check_shares = CheckPrivateShares::new(self.id(), &shares, polys.clone()); // if the batch verify fails then check them one by one and find the bad ones if Point::multimult_trait(&mut check_shares)? != Point::zero() { let mut bad_shares = Vec::new(); for (i, s) in shares.iter() { - let comm = &comms[usize::try_from(*i).unwrap()]; + let comm = &polys[i]; if s * G != compute::poly(&self.id(), &comm.poly)? { bad_shares.push(*i); } @@ -156,7 +157,7 @@ impl Party { } for (i, s) in shares.iter() { - let comm = &comms[usize::try_from(*i).unwrap()]; + let comm = &polys[i]; self.private_key += s; self.group_key += comm.poly[0]; @@ -322,14 +323,14 @@ impl traits::Aggregator for Aggregator { } /// Initialize the Aggregator polynomial - fn init(&mut self, comms: Vec) -> Result<(), AggregatorError> { + fn init(&mut self, comms: &HashMap) -> Result<(), AggregatorError> { let len = self.num_keys.try_into().unwrap(); if comms.len() != len { return Err(AggregatorError::BadPolyCommitmentLen(len, comms.len())); } let mut bad_poly_commitments = Vec::new(); - for comm in &comms { + for (_id, comm) in comms { if !comm.verify() { bad_poly_commitments.push(comm.id.id); } @@ -342,7 +343,7 @@ impl traits::Aggregator for Aggregator { for i in 0..poly.capacity() { poly.push(Point::zero()); - for p in &comms { + for (_, p) in comms { poly[i] += &p.poly[i]; } } @@ -518,13 +519,15 @@ impl traits::Signer for Signer { fn compute_secrets( &mut self, private_shares: &HashMap>, - polys: &[PolyCommitment], + polys: &HashMap, ) -> Result<(), HashMap> { + println!("compute_secrets {}", self.get_id()); let mut dkg_errors = HashMap::new(); for party in &mut self.parties { // go through the shares, looking for this party's let mut key_shares = HashMap::with_capacity(polys.len()); for (signer_id, signer_shares) in private_shares.iter() { + println!("{signer_id} {}", party.id); key_shares.insert(*signer_id, signer_shares[&party.id]); } if let Err(e) = party.compute_secret(key_shares, polys) { @@ -597,10 +600,11 @@ pub mod test_helpers { pub fn dkg( signers: &mut [v1::Signer], rng: &mut RNG, - ) -> Result, HashMap> { - let comms: Vec = signers + ) -> Result, HashMap> { + let comms: HashMap = signers .iter() .flat_map(|s| s.get_poly_commitments(rng)) + .map(|comm| (comm.id.id.get_u32(), comm)) .collect(); let mut private_shares = HashMap::new(); @@ -709,10 +713,10 @@ mod tests { let N: u32 = 10; let T: u32 = 7; let signer_ids: Vec> = [ - [0, 1, 2].to_vec(), - [3, 4].to_vec(), - [5, 6, 7].to_vec(), - [8, 9].to_vec(), + [1, 2, 3].to_vec(), + [4, 5].to_vec(), + [6, 7, 8].to_vec(), + [9, 10].to_vec(), ] .to_vec(); let mut signers: Vec = signer_ids @@ -732,7 +736,7 @@ mod tests { { let mut signers = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec(); let mut sig_agg = v1::Aggregator::new(N, T); - sig_agg.init(comms.clone()).expect("aggregator init failed"); + sig_agg.init(&comms).expect("aggregator init failed"); let (nonces, sig_shares) = v1::test_helpers::sign(msg, &mut signers, &mut rng); if let Err(e) = sig_agg.sign(msg, &nonces, &sig_shares, &[]) { diff --git a/src/v2.rs b/src/v2.rs index fe483311..a72cf545 100644 --- a/src/v2.rs +++ b/src/v2.rs @@ -143,7 +143,7 @@ impl Party { pub fn compute_secret( &mut self, shares: &HashMap>, - comms: &[PolyCommitment], + comms: &HashMap, ) -> Result<(), DkgError> { let mut missing_shares = Vec::new(); for key_id in &self.key_ids { @@ -156,9 +156,9 @@ impl Party { } let mut bad_ids = Vec::new(); - for (i, comm) in comms.iter().enumerate() { + for (i, comm) in comms.iter() { if !comm.verify() { - bad_ids.push(i.try_into().unwrap()); + bad_ids.push(*i); } self.group_key += comm.poly[0]; } @@ -180,7 +180,7 @@ impl Party { let mut bad_shares = Vec::new(); for key_id in &self.key_ids { for (sender, s) in &shares[key_id] { - let comm = &comms[usize::try_from(*sender).unwrap()]; + let comm = &comms[sender]; if s * G != compute::poly(&compute::id(*key_id), &comm.poly)? { bad_shares.push(*sender); } @@ -348,9 +348,9 @@ impl traits::Aggregator for Aggregator { } /// Initialize the Aggregator polynomial - fn init(&mut self, comms: Vec) -> Result<(), AggregatorError> { + fn init(&mut self, comms: &HashMap) -> Result<(), AggregatorError> { let mut bad_poly_commitments = Vec::new(); - for comm in &comms { + for (_id, comm) in comms { if !comm.verify() { bad_poly_commitments.push(comm.id.id); } @@ -363,7 +363,7 @@ impl traits::Aggregator for Aggregator { for i in 0..poly.capacity() { poly.push(Point::zero()); - for comm in &comms { + for (_, comm) in comms { poly[i] += &comm.poly[i]; } } @@ -459,7 +459,7 @@ impl traits::Signer for Party { fn compute_secrets( &mut self, private_shares: &HashMap>, - polys: &[PolyCommitment], + polys: &HashMap, ) -> Result<(), HashMap> { // go through the shares, looking for this party's let mut key_shares = HashMap::new(); @@ -521,6 +521,7 @@ impl traits::Signer for Party { pub mod test_helpers { use crate::common::{PolyCommitment, PublicNonce}; use crate::errors::DkgError; + use crate::traits::Signer; use crate::v2; use crate::v2::SignatureShare; @@ -531,9 +532,11 @@ pub mod test_helpers { pub fn dkg( signers: &mut [v2::Party], rng: &mut RNG, - ) -> Result, HashMap> { - let polys: Vec = - signers.iter().map(|s| s.get_poly_commitment(rng)).collect(); + ) -> Result, HashMap> { + let polys: HashMap = signers + .iter() + .map(|s| (s.get_id(), s.get_poly_commitment(rng))) + .collect(); // each party broadcasts their commitments let mut broadcast_shares = Vec::new(); @@ -640,7 +643,7 @@ mod tests { let mut signers = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec(); let mut sig_agg = v2::Aggregator::new(Nk, T); - sig_agg.init(comms.clone()).expect("aggregator init failed"); + sig_agg.init(&comms).expect("aggregator init failed"); let (nonces, sig_shares, key_ids) = v2::test_helpers::sign(msg, &mut signers, &mut rng); if let Err(e) = sig_agg.sign(msg, &nonces, &sig_shares, &key_ids) {