1use std::{iter, marker::PhantomData};
26
27use generic_ec::{Curve, NonZero, SecretScalar};
28use rand_core::{CryptoRng, RngCore};
29use thiserror::Error;
30
31use crate::{
32 key_share::{AuxInfo, DirtyAuxInfo, IncompleteKeyShare, InvalidKeyShare, KeyShare, Validate},
33 security_level::SecurityLevel,
34 utils, PregeneratedPrimes,
35};
36
37pub fn builder<E: Curve, L: SecurityLevel>(n: u16) -> TrustedDealerBuilder<E, L> {
43 TrustedDealerBuilder::new(n)
44}
45
46type CoreBuilder<E> = cggmp24_keygen::key_share::trusted_dealer::TrustedDealerBuilder<E>;
47
48pub struct TrustedDealerBuilder<E: Curve, L: SecurityLevel> {
50 inner: CoreBuilder<E>,
51 n: u16,
52 pregenerated_primes: Option<Vec<PregeneratedPrimes<L>>>,
53 enable_mulitexp: bool,
54 _ph: PhantomData<L>,
55}
56
57impl<E: Curve, L: SecurityLevel> TrustedDealerBuilder<E, L> {
58 pub fn new(n: u16) -> Self {
62 TrustedDealerBuilder {
63 inner: CoreBuilder::new(n),
64 n,
65 pregenerated_primes: None,
66 enable_mulitexp: false,
67 _ph: PhantomData,
68 }
69 }
70
71 pub fn set_threshold(self, t: Option<u16>) -> Self {
84 Self {
85 inner: self.inner.set_threshold(t),
86 ..self
87 }
88 }
89
90 pub fn set_shared_secret_key(self, sk: NonZero<SecretScalar<E>>) -> Self {
94 Self {
95 inner: self.inner.set_shared_secret_key(sk),
96 ..self
97 }
98 }
99
100 pub fn set_pregenerated_primes(self, primes: Vec<PregeneratedPrimes<L>>) -> Self {
104 Self {
105 pregenerated_primes: Some(primes),
106 ..self
107 }
108 }
109
110 pub fn enable_multiexp(self, v: bool) -> Self {
115 Self {
116 enable_mulitexp: v,
117 ..self
118 }
119 }
120
121 #[cfg(feature = "hd-wallet")]
123 pub fn hd_wallet(self, v: bool) -> Self {
124 Self {
125 inner: self.inner.hd_wallet(v),
126 ..self
127 }
128 }
129
130 pub fn generate_core_shares(
135 self,
136 rng: &mut (impl RngCore + CryptoRng),
137 ) -> Result<Vec<IncompleteKeyShare<E>>, TrustedDealerError> {
138 self.inner
139 .generate_shares(rng)
140 .map_err(Reason::CoreError)
141 .map_err(TrustedDealerError)
142 }
143
144 pub fn generate_shares(
149 mut self,
150 rng: &mut (impl RngCore + CryptoRng),
151 ) -> Result<Vec<KeyShare<E, L>>, TrustedDealerError> {
152 let n = self.n;
153 let enable_multiexp = self.enable_mulitexp;
154
155 let primes = self.pregenerated_primes.take();
156 let core_key_shares = self.inner.generate_shares(rng).map_err(Reason::CoreError)?;
157 let aux_data = if let Some(primes) = primes {
158 generate_aux_data_with_primes(rng, primes, enable_multiexp)?
159 } else {
160 generate_aux_data(rng, n, enable_multiexp)?
161 };
162
163 let key_shares = core_key_shares
164 .into_iter()
165 .zip(aux_data)
166 .map(|(core, aux)| KeyShare::from_parts((core, aux)).map_err(|err| err.into_error()))
167 .collect::<Result<Vec<_>, _>>()
168 .map_err(Reason::InvalidKeyShare)?;
169
170 Ok(key_shares)
171 }
172}
173
174pub fn generate_aux_data<L: SecurityLevel, R: RngCore + CryptoRng>(
181 rng: &mut R,
182 n: u16,
183 enable_multiexp: bool,
184) -> Result<Vec<AuxInfo<L>>, TrustedDealerError> {
185 let primes = iter::repeat_with(|| crate::key_refresh::PregeneratedPrimes::<L>::generate(rng))
186 .take(n.into())
187 .collect::<Vec<_>>();
188
189 generate_aux_data_with_primes(rng, primes, enable_multiexp)
190}
191
192pub fn generate_aux_data_with_primes<L: SecurityLevel, R: RngCore + CryptoRng>(
199 rng: &mut R,
200 pregenerated_primes: Vec<crate::PregeneratedPrimes<L>>,
201 enable_multiexp: bool,
202) -> Result<Vec<AuxInfo<L>>, TrustedDealerError> {
203 let (N, pedersen_params) = pregenerated_primes
204 .iter()
205 .map(|primes| {
206 let [p, q, hat_p, hat_q] = primes.primes_ref();
207 let N = p * q;
208
209 let (mut params, _phi, _lambda) =
210 utils::generate_pedersen_params(rng, hat_p.clone(), hat_q.clone())?;
211
212 if enable_multiexp {
213 params
214 .precompute_multiexp_table::<L>()
215 .map_err(Reason::BuildMultiexp)?;
216 }
217 Ok((N, params))
218 })
219 .collect::<Result<(Vec<_>, Vec<_>), Reason>>()?;
220
221 pregenerated_primes
222 .into_iter()
223 .enumerate()
224 .map(|(i, primes)| {
225 let mut pedersen_params = pedersen_params.clone();
226 for (j, params) in pedersen_params.iter_mut().enumerate() {
227 if i != j {
228 params.crt = None;
229 }
230 }
231
232 let [p, q, _, _] = primes.into_primes();
233
234 DirtyAuxInfo {
235 p,
236 q,
237 N: N.clone(),
238 pedersen_params,
239 security_level: PhantomData,
240 }
241 .validate()
242 .map_err(|err| Reason::InvalidKeyShare(err.into_error()))
243 })
244 .collect::<Result<Vec<_>, _>>()
245 .map_err(TrustedDealerError)
246}
247
248#[derive(Debug, Error)]
250#[error(transparent)]
251pub struct TrustedDealerError(#[from] Reason);
252
253#[derive(Debug, Error)]
254enum Reason {
255 #[error("trusted dealer failed to generate shares due to internal error")]
256 InvalidKeyShare(#[source] InvalidKeyShare),
257 #[error("couldn't build multiexp tables")]
258 BuildMultiexp(#[source] InvalidKeyShare),
259 #[error(transparent)]
260 CoreError(#[from] cggmp24_keygen::key_share::trusted_dealer::TrustedDealerError),
261 #[error("generate pedersen params")]
262 GenPedersen(#[from] utils::GenPedersenError),
263}