commonware_cryptography/bls12381/dkg/
ops.rs1use crate::bls12381::{
4 dkg::Error,
5 primitives::{
6 group::Share,
7 ops::msm_interpolate,
8 poly::{self, compute_weights},
9 variant::Variant,
10 },
11};
12use rand_core::CryptoRngCore;
13use rayon::{prelude::*, ThreadPoolBuilder};
14use std::collections::BTreeMap;
15
16pub fn generate_shares<R: CryptoRngCore, V: Variant>(
18 rng: &mut R,
19 share: Option<Share>,
20 n: u32,
21 t: u32,
22) -> (poly::Public<V>, Vec<Share>) {
23 let mut secret = poly::new_from(t - 1, rng);
25 if let Some(share) = share {
26 secret.set(0, share.private);
29 }
30
31 let commitment = poly::Public::<V>::commit(secret.clone());
33 let shares = (0..n)
34 .map(|i| {
35 let eval = secret.evaluate(i);
36 Share {
37 index: eval.index,
38 private: eval.value,
39 }
40 })
41 .collect::<Vec<_>>();
42 (commitment, shares)
43}
44
45pub fn evaluate_all<V: Variant>(polynomial: &poly::Public<V>, n: u32) -> Vec<V::Public> {
47 let mut evals = Vec::with_capacity(n as usize);
48 for index in 0..n {
49 evals.push(polynomial.evaluate(index).value);
50 }
51 evals
52}
53
54pub fn verify_commitment<V: Variant>(
57 previous: Option<&poly::Public<V>>,
58 commitment: &poly::Public<V>,
59 dealer: u32,
60 t: u32,
61) -> Result<(), Error> {
62 if let Some(previous) = previous {
63 let expected = previous.evaluate(dealer).value;
64 if expected != *commitment.constant() {
65 return Err(Error::UnexpectedPolynomial);
66 }
67 }
68 if commitment.degree() != t - 1 {
69 return Err(Error::CommitmentWrongDegree);
70 }
71 Ok(())
72}
73
74pub fn verify_share<V: Variant>(
80 commitment: &poly::Public<V>,
81 recipient: u32,
82 share: &Share,
83) -> Result<(), Error> {
84 if share.index != recipient {
86 return Err(Error::MisdirectedShare);
87 }
88 let expected = share.public::<V>();
89 let given = commitment.evaluate(share.index);
90 if given.value != expected {
91 return Err(Error::ShareWrongCommitment);
92 }
93 Ok(())
94}
95
96pub fn construct_public<'a, V: Variant>(
98 commitments: impl IntoIterator<Item = &'a poly::Public<V>>,
99 required: u32,
100) -> Result<poly::Public<V>, Error> {
101 let mut count = 0;
103 let mut public = poly::Public::<V>::zero();
104 for commitment in commitments.into_iter() {
105 public.add(commitment);
106 count += 1;
107 }
108
109 if count < required {
111 return Err(Error::InsufficientDealings);
112 }
113 Ok(public)
114}
115
116pub fn recover_public_with_weights<V: Variant>(
121 previous: &poly::Public<V>,
122 commitments: &BTreeMap<u32, poly::Public<V>>,
123 weights: &BTreeMap<u32, poly::Weight>,
124 threshold: u32,
125 concurrency: usize,
126) -> Result<poly::Public<V>, Error> {
127 let required = previous.required();
129 if commitments.len() < required as usize {
130 return Err(Error::InsufficientDealings);
131 }
132
133 let pool = ThreadPoolBuilder::new()
135 .num_threads(concurrency)
136 .build()
137 .expect("unable to build thread pool");
138
139 let new = match pool.install(|| {
141 (0..threshold)
142 .into_par_iter()
143 .map(|coeff| {
144 let evals = commitments
146 .iter()
147 .map(|(dealer, commitment)| poly::Eval {
148 index: *dealer,
149 value: commitment.get(coeff),
150 })
151 .collect::<Vec<_>>();
152
153 msm_interpolate(weights, &evals).map_err(|_| Error::PublicKeyInterpolationFailed)
155 })
156 .collect::<Result<Vec<_>, _>>()
157 }) {
158 Ok(points) => poly::Public::<V>::from(points),
159 Err(e) => return Err(e),
160 };
161
162 if previous.constant() != new.constant() {
164 return Err(Error::ReshareMismatch);
165 }
166 Ok(new)
167}
168
169pub fn recover_public<V: Variant>(
174 previous: &poly::Public<V>,
175 commitments: &BTreeMap<u32, poly::Public<V>>,
176 threshold: u32,
177 concurrency: usize,
178) -> Result<poly::Public<V>, Error> {
179 let required = previous.required();
181 if commitments.len() < required as usize {
182 return Err(Error::InsufficientDealings);
183 }
184
185 let indices: Vec<u32> = commitments.keys().cloned().collect();
187 let weights = compute_weights(indices).map_err(|_| Error::PublicKeyInterpolationFailed)?;
188
189 recover_public_with_weights::<V>(previous, commitments, &weights, threshold, concurrency)
191}