commonware_cryptography/bls12381/dkg/
ops.rsuse crate::bls12381::{
dkg::Error,
primitives::{group::Share, poly},
};
use rayon::{prelude::*, ThreadPoolBuilder};
use std::collections::BTreeMap;
pub fn generate_shares(share: Option<Share>, n: u32, t: u32) -> (poly::Public, Vec<Share>) {
let mut secret = poly::new(t - 1);
if let Some(share) = share {
secret.set(0, share.private);
}
let commitment = poly::Public::commit(secret.clone());
let shares = (0..n)
.map(|i| {
let eval = secret.evaluate(i);
Share {
index: eval.index,
private: eval.value,
}
})
.collect::<Vec<_>>();
(commitment, shares)
}
pub fn verify_commitment(
previous: Option<&poly::Public>,
dealer: u32,
commitment: &poly::Public,
t: u32,
) -> Result<(), Error> {
if let Some(previous) = previous {
let expected = previous.evaluate(dealer).value;
if expected != *commitment.constant() {
return Err(Error::UnexpectedPolynomial);
}
}
if commitment.degree() != t - 1 {
return Err(Error::CommitmentWrongDegree);
}
Ok(())
}
pub fn verify_share(
previous: Option<&poly::Public>,
dealer: u32,
commitment: &poly::Public,
t: u32,
recipient: u32,
share: &Share,
) -> Result<(), Error> {
verify_commitment(previous, dealer, commitment, t)?;
if share.index != recipient {
return Err(Error::MisdirectedShare);
}
let expected = share.public();
let given = commitment.evaluate(share.index);
if given.value != expected {
return Err(Error::ShareWrongCommitment);
}
Ok(())
}
pub fn construct_public(
commitments: Vec<poly::Public>,
required: u32,
) -> Result<poly::Public, Error> {
if commitments.len() < required as usize {
return Err(Error::InsufficientDealings);
}
let mut public = poly::Public::zero();
for commitment in commitments {
public.add(&commitment);
}
Ok(public)
}
pub fn recover_public(
previous: &poly::Public,
commitments: BTreeMap<u32, poly::Public>,
threshold: u32,
concurrency: usize,
) -> Result<poly::Public, Error> {
let required = previous.required();
if commitments.len() < required as usize {
return Err(Error::InsufficientDealings);
}
let pool = ThreadPoolBuilder::new()
.num_threads(concurrency)
.build()
.expect("unable to build thread pool");
let new = match pool.install(|| {
(0..threshold)
.into_par_iter()
.map(|coeff| {
let evals: Vec<_> = commitments
.iter()
.map(|(dealer, commitment)| poly::Eval {
index: *dealer,
value: commitment.get(coeff),
})
.collect();
match poly::Public::recover(required, evals) {
Ok(point) => Ok(point),
Err(_) => Err(Error::PublicKeyInterpolationFailed),
}
})
.collect::<Result<Vec<_>, _>>()
}) {
Ok(points) => poly::Public::from(points),
Err(e) => return Err(e),
};
if previous.constant() != new.constant() {
return Err(Error::ReshareMismatch);
}
Ok(new)
}