use std::collections::BTreeMap;
use frost::keys::{KeyPackage, PublicKeyPackage};
use frost::Identifier;
use frost_ed25519 as frost;
use crate::threshold::ThresholdError;
pub fn proactive_refresh(
current_key_packages: &BTreeMap<Identifier, KeyPackage>,
requested_threshold: u16,
) -> Result<BTreeMap<Identifier, KeyPackage>, ThresholdError> {
if current_key_packages.is_empty() {
return Err(ThresholdError::InvalidParams("empty key package set"));
}
let first_kp = current_key_packages.values().next().unwrap();
if requested_threshold != *first_kp.min_signers() {
return Err(ThresholdError::InvalidParams(
"requested threshold does not match active key package threshold (CVE-2025-58359 guard)",
));
}
let identifiers: Vec<Identifier> = current_key_packages.keys().copied().collect();
let mut verifying_shares = BTreeMap::new();
for (id, kp) in current_key_packages {
verifying_shares.insert(*id, *kp.verifying_share());
}
let pub_key_package = PublicKeyPackage::new(
verifying_shares,
*first_kp.verifying_key(),
Some(requested_threshold),
);
let mut rng = rand::rngs::OsRng;
let (refreshing_shares, _) =
frost::keys::refresh::compute_refreshing_shares(pub_key_package, &identifiers, &mut rng)?;
let mut refreshed_key_packages = BTreeMap::new();
for (id, secret_share) in identifiers.into_iter().zip(refreshing_shares) {
let current_kp = ¤t_key_packages[&id];
let refreshed_kp = frost::keys::refresh::refresh_share(secret_share, current_kp)?;
refreshed_key_packages.insert(id, refreshed_kp);
}
Ok(refreshed_key_packages)
}
pub fn repair_lost_share(
lost_participant: Identifier,
helpers: &[(Identifier, KeyPackage)],
pubkey_package: &PublicKeyPackage,
) -> Result<KeyPackage, ThresholdError> {
let helper_ids: Vec<Identifier> = helpers.iter().map(|(id, _)| *id).collect();
let mut rng = rand::rngs::OsRng;
let mut deltas_by_recipient: BTreeMap<Identifier, Vec<frost::keys::repairable::Delta>> =
BTreeMap::new();
for (_id, kp) in helpers {
let deltas = frost::keys::repairable::repair_share_part1::<frost_ed25519::Ed25519Sha512, _>(
&helper_ids,
kp,
&mut rng,
lost_participant,
)?;
for (recipient, delta) in deltas {
deltas_by_recipient
.entry(recipient)
.or_default()
.push(delta);
}
}
let mut sigmas = Vec::new();
for id in &helper_ids {
let deltas = deltas_by_recipient
.remove(id)
.ok_or(ThresholdError::InvalidParams("missing helper delta"))?;
let sigma = frost::keys::repairable::repair_share_part2(&deltas);
sigmas.push(sigma);
}
let repaired_kp =
frost::keys::repairable::repair_share_part3(&sigmas, lost_participant, pubkey_package)?;
Ok(repaired_kp)
}