1use alloc::collections::BTreeMap;
27use alloc::vec::Vec;
28
29use crate::{
30 keys::dkg::{compute_proof_of_knowledge, round1, round2},
31 keys::{
32 evaluate_polynomial, generate_coefficients, generate_secret_polynomial,
33 generate_secret_shares, validate_num_of_signers, CoefficientCommitment, PublicKeyPackage,
34 SigningKey, SigningShare, VerifyingShare,
35 },
36 Ciphersuite, CryptoRng, Error, Field, Group, Header, Identifier, RngCore,
37};
38
39use core::iter;
40
41use super::{dkg::round1::Package, KeyPackage, SecretShare, VerifiableSecretSharingCommitment};
42
43pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
58 pub_key_package: PublicKeyPackage<C>,
59 max_signers: u16,
60 min_signers: u16,
61 identifiers: &[Identifier<C>],
62 rng: &mut R,
63) -> Result<(Vec<SecretShare<C>>, PublicKeyPackage<C>), Error<C>> {
64 if identifiers.len() != max_signers as usize {
66 return Err(Error::IncorrectNumberOfIdentifiers);
67 }
68 validate_num_of_signers(min_signers, max_signers)?;
69
70 let refreshing_key = SigningKey {
72 scalar: <<C::Group as Group>::Field>::zero(),
73 };
74
75 let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, rng);
76 let refreshing_shares = generate_secret_shares(
77 &refreshing_key,
78 max_signers,
79 min_signers,
80 coefficients,
81 identifiers,
82 )?;
83
84 let mut refreshed_verifying_shares: BTreeMap<Identifier<C>, VerifyingShare<C>> =
85 BTreeMap::new();
86 let mut refreshing_shares_minus_identity: Vec<SecretShare<C>> = Vec::new();
87
88 for mut share in refreshing_shares {
89 let refreshing_verifying_share: VerifyingShare<C> = SigningShare::into(share.signing_share);
90
91 let verifying_share = pub_key_package.verifying_shares.get(&share.identifier);
92
93 match verifying_share {
94 Some(verifying_share) => {
95 let refreshed_verifying_share =
96 refreshing_verifying_share.to_element() + verifying_share.to_element();
97 refreshed_verifying_shares.insert(
98 share.identifier,
99 VerifyingShare::new(refreshed_verifying_share),
100 );
101 }
102 None => return Err(Error::UnknownIdentifier),
103 };
104
105 share.commitment.0.remove(0);
106 refreshing_shares_minus_identity.push(share);
107 }
108
109 let refreshed_pub_key_package = PublicKeyPackage::<C> {
110 header: pub_key_package.header,
111 verifying_shares: refreshed_verifying_shares,
112 verifying_key: pub_key_package.verifying_key,
113 };
114
115 Ok((refreshing_shares_minus_identity, refreshed_pub_key_package))
116}
117
118pub fn refresh_share<C: Ciphersuite>(
124 mut refreshing_share: SecretShare<C>,
125 current_key_package: &KeyPackage<C>,
126) -> Result<KeyPackage<C>, Error<C>> {
127 let identity_commitment: Vec<CoefficientCommitment<C>> =
129 vec![CoefficientCommitment::new(C::Group::identity())];
130
131 let refreshing_share_commitments: Vec<CoefficientCommitment<C>> = identity_commitment
132 .into_iter()
133 .chain(refreshing_share.commitment.0.clone())
134 .collect();
135
136 refreshing_share.commitment =
137 VerifiableSecretSharingCommitment::<C>::new(refreshing_share_commitments);
138
139 let refreshed_share_package = KeyPackage::<C>::try_from(refreshing_share)?;
141
142 if refreshed_share_package.min_signers() != current_key_package.min_signers() {
143 return Err(Error::InvalidMinSigners);
144 }
145
146 let signing_share: SigningShare<C> = SigningShare::new(
147 refreshed_share_package.signing_share.to_scalar()
148 + current_key_package.signing_share.to_scalar(),
149 );
150
151 let mut new_key_package = current_key_package.clone();
152 new_key_package.signing_share = signing_share;
153
154 Ok(new_key_package)
155}
156
157pub fn refresh_dkg_part_1<C: Ciphersuite, R: RngCore + CryptoRng>(
172 identifier: Identifier<C>,
173 max_signers: u16,
174 min_signers: u16,
175 mut rng: R,
176) -> Result<(round1::SecretPackage<C>, round1::Package<C>), Error<C>> {
177 validate_num_of_signers::<C>(min_signers, max_signers)?;
178
179 let refreshing_key = SigningKey {
181 scalar: <<C::Group as Group>::Field>::zero(),
182 };
183
184 let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, &mut rng);
186
187 let (coefficients, commitment) =
188 generate_secret_polynomial(&refreshing_key, max_signers, min_signers, coefficients)?;
189
190 let mut coeff_comms = commitment.0;
192 coeff_comms.remove(0);
193 let commitment = VerifiableSecretSharingCommitment::new(coeff_comms.clone());
194
195 let proof_of_knowledge =
196 compute_proof_of_knowledge(identifier, &coefficients, &commitment, &mut rng)?;
197
198 let secret_package = round1::SecretPackage::new(
199 identifier,
200 coefficients.clone(),
201 commitment.clone(),
202 min_signers,
203 max_signers,
204 );
205 let package = round1::Package {
206 header: Header::default(),
207 commitment,
208 proof_of_knowledge,
209 };
210
211 Ok((secret_package, package))
212}
213
214pub fn refresh_dkg_part2<C: Ciphersuite>(
230 mut secret_package: round1::SecretPackage<C>,
231 round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
232) -> Result<
233 (
234 round2::SecretPackage<C>,
235 BTreeMap<Identifier<C>, round2::Package<C>>,
236 ),
237 Error<C>,
238> {
239 if round1_packages.len() != (secret_package.max_signers - 1) as usize {
240 return Err(Error::IncorrectNumberOfPackages);
241 }
242
243 let identity_commitment: Vec<CoefficientCommitment<C>> =
245 vec![CoefficientCommitment::new(C::Group::identity())];
246
247 let refreshing_secret_share_commitments: Vec<CoefficientCommitment<C>> = identity_commitment
248 .into_iter()
249 .chain(secret_package.commitment.0.clone())
250 .collect();
251
252 secret_package.commitment =
253 VerifiableSecretSharingCommitment::<C>::new(refreshing_secret_share_commitments);
254
255 let mut round2_packages = BTreeMap::new();
256
257 for (sender_identifier, round1_package) in round1_packages {
258 let identity_commitment: Vec<CoefficientCommitment<C>> =
260 vec![CoefficientCommitment::new(C::Group::identity())];
261
262 let refreshing_share_commitments: Vec<CoefficientCommitment<C>> = identity_commitment
263 .into_iter()
264 .chain(round1_package.commitment.0.clone())
265 .collect();
266
267 if refreshing_share_commitments.clone().len() != secret_package.min_signers as usize {
268 return Err(Error::IncorrectNumberOfCommitments);
269 }
270
271 let ell = *sender_identifier;
272
273 let signing_share = SigningShare::from_coefficients(&secret_package.coefficients(), ell);
282
283 round2_packages.insert(
284 ell,
285 round2::Package {
286 header: Header::default(),
287 signing_share,
288 },
289 );
290 }
291 let fii = evaluate_polynomial(secret_package.identifier, &secret_package.coefficients());
292
293 Ok((
294 round2::SecretPackage::new(
295 secret_package.identifier,
296 secret_package.commitment,
297 fii,
298 secret_package.min_signers,
299 secret_package.max_signers,
300 ),
301 round2_packages,
302 ))
303}
304
305pub fn refresh_dkg_shares<C: Ciphersuite>(
328 round2_secret_package: &round2::SecretPackage<C>,
329 round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
330 round2_packages: &BTreeMap<Identifier<C>, round2::Package<C>>,
331 old_pub_key_package: PublicKeyPackage<C>,
332 old_key_package: KeyPackage<C>,
333) -> Result<(KeyPackage<C>, PublicKeyPackage<C>), Error<C>> {
334 if round2_secret_package.min_signers() != old_key_package.min_signers() {
335 return Err(Error::InvalidMinSigners);
336 }
337
338 let mut new_round_1_packages = BTreeMap::new();
340 for (sender_identifier, round1_package) in round1_packages {
341 let identity_commitment: Vec<CoefficientCommitment<C>> =
343 vec![CoefficientCommitment::new(C::Group::identity())];
344
345 let refreshing_share_commitments: Vec<CoefficientCommitment<C>> = identity_commitment
346 .into_iter()
347 .chain(round1_package.commitment.0.clone())
348 .collect();
349
350 let new_commitments =
351 VerifiableSecretSharingCommitment::<C>::new(refreshing_share_commitments);
352
353 let new_round_1_package = Package {
354 header: round1_package.header,
355 commitment: new_commitments,
356 proof_of_knowledge: round1_package.proof_of_knowledge,
357 };
358
359 new_round_1_packages.insert(*sender_identifier, new_round_1_package);
360 }
361
362 if new_round_1_packages.len() != (round2_secret_package.max_signers - 1) as usize {
363 return Err(Error::IncorrectNumberOfPackages);
364 }
365 if new_round_1_packages.len() != round2_packages.len() {
366 return Err(Error::IncorrectNumberOfPackages);
367 }
368 if new_round_1_packages
369 .keys()
370 .any(|id| !round2_packages.contains_key(id))
371 {
372 return Err(Error::IncorrectPackage);
373 }
374
375 let mut signing_share = <<C::Group as Group>::Field>::zero();
376
377 for (sender_identifier, round2_package) in round2_packages {
378 let ell = *sender_identifier;
384 let f_ell_i = round2_package.signing_share;
385
386 let commitment = &new_round_1_packages
387 .get(&ell)
388 .ok_or(Error::PackageNotFound)?
389 .commitment;
390
391 let secret_share = SecretShare {
395 header: Header::default(),
396 identifier: round2_secret_package.identifier,
397 signing_share: f_ell_i,
398 commitment: commitment.clone(),
399 };
400
401 let _ = secret_share.verify()?;
403
404 signing_share = signing_share + f_ell_i.to_scalar();
409 }
410
411 signing_share = signing_share + round2_secret_package.secret_share();
412
413 let old_signing_share = old_key_package.signing_share.to_scalar();
415 signing_share = signing_share + old_signing_share;
416 let signing_share = SigningShare::new(signing_share);
417
418 let verifying_share = signing_share.into();
422
423 let commitments: BTreeMap<_, _> = new_round_1_packages
424 .iter()
425 .map(|(id, package)| (*id, &package.commitment))
426 .chain(iter::once((
427 round2_secret_package.identifier,
428 &round2_secret_package.commitment,
429 )))
430 .collect();
431
432 let zero_shares_public_key_package = PublicKeyPackage::from_dkg_commitments(&commitments)?;
433
434 let mut new_verifying_shares = BTreeMap::new();
435
436 for (identifier, verifying_share) in zero_shares_public_key_package.verifying_shares {
437 let new_verifying_share = verifying_share.to_element()
438 + old_pub_key_package
439 .verifying_shares
440 .get(&identifier)
441 .ok_or(Error::UnknownIdentifier)?
442 .to_element();
443 new_verifying_shares.insert(identifier, VerifyingShare::new(new_verifying_share));
444 }
445
446 let public_key_package = PublicKeyPackage {
447 header: old_pub_key_package.header,
448 verifying_shares: new_verifying_shares,
449 verifying_key: old_pub_key_package.verifying_key,
450 };
451
452 let key_package = KeyPackage {
453 header: Header::default(),
454 identifier: round2_secret_package.identifier,
455 signing_share,
456 verifying_share,
457 verifying_key: public_key_package.verifying_key,
458 min_signers: round2_secret_package.min_signers,
459 };
460
461 Ok((key_package, public_key_package))
462}