1pub mod authenticated;
3pub mod unauthenticated;
4
5use std::{borrow::Borrow, sync::Arc};
6
7pub use authenticated::*;
8use itertools::{enumerate, izip};
9use serde::{de::DeserializeOwned, Serialize};
10use wincode::{SchemaRead, SchemaWrite};
11
12use crate::{
13 algebra::{field::FieldExtension, ops::transpose::transpose},
14 errors::PrimitiveError,
15 random::{CryptoRngCore, RandomWith},
16 types::PeerIndex,
17 utils::TakeExact,
18};
19
20pub trait Reconstructible: Sized {
25 type Secret: Serialize
27 + DeserializeOwned
28 + for<'de> SchemaRead<'de, Dst = Self::Secret>
29 + SchemaWrite<Src = Self::Secret>
30 + Clone
31 + PartialEq
32 + Send
33 + Sync
34 + 'static;
35 type Opening: Serialize
37 + DeserializeOwned
38 + for<'de> SchemaRead<'de, Dst = Self::Opening>
39 + SchemaWrite<Src = Self::Opening>
40 + Clone
41 + Send
42 + Sync
43 + 'static;
44
45 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError>;
47
48 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening>;
51
52 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError>;
54
55 fn reconstruct_all<T: Borrow<Self>>(shares: &[T]) -> Result<Self::Secret, PrimitiveError> {
59 let n_parties = shares.len();
60 if n_parties < 2 {
61 return Err(PrimitiveError::MinimumLength(2, n_parties));
62 }
63 let mut all_openings = shares
65 .iter()
66 .map(|share| share.borrow().open_to_all_others())
67 .collect::<Vec<_>>();
68 enumerate(shares.iter())
70 .map(|(i, share)| {
71 let my_openings = enumerate(all_openings.iter_mut())
72 .take_exact(n_parties)
73 .filter(|(j, _)| i != *j)
74 .map(|(_, opening)| opening.next())
75 .collect::<Option<Vec<_>>>()
76 .ok_or_else(|| PrimitiveError::InvalidPeerIndex(i, shares.len() - 1))?;
77 share.borrow().reconstruct(my_openings.as_slice())
78 })
79 .reduce(|previous, current| match (previous, current) {
81 (Ok(prev), Ok(curr)) => match prev == curr {
82 true => Ok(prev),
83 false => Err(PrimitiveError::WrongOpening(
84 serde_json::to_string(&prev).unwrap(),
85 serde_json::to_string(&curr).unwrap(),
86 )),
87 },
88 (Err(e), _) | (_, Err(e)) => Err(e),
89 })
90 .unwrap() }
92}
93
94impl<T: Reconstructible<Opening: Clone>> Reconstructible for Vec<T> {
95 type Opening = Vec<T::Opening>;
96 type Secret = Vec<T::Secret>;
97
98 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
99 self.iter().map(|share| share.open_to(peer_index)).collect()
100 }
101
102 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
103 let all_openings: Vec<Vec<_>> = self
104 .iter()
105 .map(|share| share.open_to_all_others().collect())
106 .collect();
107
108 transpose(all_openings).into_iter()
109 }
110
111 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError> {
112 if openings.is_empty() {
113 return Err(PrimitiveError::MinimumLength(1, 0));
114 }
115
116 if openings[0].len() != self.len() {
117 return Err(PrimitiveError::InvalidParameters(
118 "Number of openings must match number of shares.".to_string(),
119 ));
120 }
121
122 let mut reconstructed = Vec::with_capacity(self.len());
124 for (i, share) in self.iter().enumerate() {
125 let my_openings: Vec<_> = openings
126 .iter()
127 .map(|opening| opening.get(i).cloned())
128 .collect::<Option<Vec<_>>>()
129 .ok_or_else(|| {
130 PrimitiveError::InvalidParameters(
131 "Opening is missing for some share.".to_string(),
132 )
133 })?;
134 reconstructed.push(share.reconstruct(my_openings.as_slice())?);
135 }
136 Ok(reconstructed)
137 }
138}
139
140impl<T: Reconstructible<Opening: Clone>> Reconstructible for Arc<[T]> {
141 type Opening = Arc<[T::Opening]>;
142 type Secret = Arc<[T::Secret]>;
143
144 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
145 self.iter().map(|share| share.open_to(peer_index)).collect()
146 }
147
148 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
149 let all_openings: Vec<Vec<_>> = self
150 .iter()
151 .map(|share| share.open_to_all_others().collect())
152 .collect();
153
154 transpose(all_openings)
155 .into_iter()
156 .map(Arc::from)
157 .collect::<Vec<_>>()
158 .into_iter()
159 }
160
161 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError> {
162 if openings.is_empty() {
163 return Err(PrimitiveError::MinimumLength(1, 0));
164 }
165
166 if openings[0].len() != self.len() {
167 return Err(PrimitiveError::InvalidParameters(
168 "Number of openings must match number of shares.".to_string(),
169 ));
170 }
171
172 let mut reconstructed = Vec::with_capacity(self.len());
174 for (i, share) in self.iter().enumerate() {
175 let my_openings: Vec<_> = openings
176 .iter()
177 .map(|opening| opening.get(i).cloned())
178 .collect::<Option<Vec<_>>>()
179 .ok_or_else(|| {
180 PrimitiveError::InvalidParameters(
181 "Opening is missing for some share.".to_string(),
182 )
183 })?;
184 reconstructed.push(share.reconstruct(my_openings.as_slice())?);
185 }
186
187 Ok(reconstructed.into())
188 }
189}
190
191impl<T: Reconstructible, S: Reconstructible> Reconstructible for (T, S) {
192 type Opening = (T::Opening, S::Opening);
193 type Secret = (T::Secret, S::Secret);
194
195 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
196 Ok((self.0.open_to(peer_index)?, self.1.open_to(peer_index)?))
197 }
198
199 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
200 let all_openings_t: Vec<_> = self.0.open_to_all_others().collect();
201 let all_openings_s: Vec<_> = self.1.open_to_all_others().collect();
202 izip!(all_openings_t, all_openings_s).map(|(o1, o2)| (o1, o2))
203 }
204
205 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError> {
206 let (openings_t, openings_s): (Vec<_>, Vec<_>) = openings.iter().cloned().unzip();
207 Ok((
208 self.0.reconstruct(&openings_t)?,
209 self.1.reconstruct(&openings_s)?,
210 ))
211 }
212}
213
214pub trait RandomAuthenticatedForNPeers<F: FieldExtension>:
218 RandomWith<Vec<Vec<GlobalFieldKey<F>>>>
219{
220 fn random_for_n_peers_with_alphas<Container: FromIterator<Self>>(
221 mut rng: impl CryptoRngCore,
222 n_parties: usize,
223 all_alphas: Vec<Vec<GlobalFieldKey<F>>>,
224 ) -> Container {
225 Self::random_n_with(&mut rng, n_parties, all_alphas)
226 }
227}
228
229impl<F: FieldExtension, S: RandomWith<Vec<Vec<GlobalFieldKey<F>>>>> RandomAuthenticatedForNPeers<F>
230 for S
231{
232}
233
234pub trait RandomAuthenticatedForNPeersWith<F: FieldExtension, T: Clone>:
235 RandomWith<(T, Vec<Vec<GlobalFieldKey<F>>>)>
236{
237 fn random_authenticated_for_n_peers_with<Container: FromIterator<Self>>(
238 mut rng: impl CryptoRngCore,
239 n_parties: usize,
240 value: T,
241 all_alphas: Vec<Vec<GlobalFieldKey<F>>>,
242 ) -> Container {
243 Self::random_n_with(&mut rng, n_parties, (value, all_alphas))
244 }
245}
246
247impl<F: FieldExtension, T: Clone, S: RandomWith<(T, Vec<Vec<GlobalFieldKey<F>>>)>>
248 RandomAuthenticatedForNPeersWith<F, T> for S
249{
250}
251
252pub trait AddPlaintext: Reconstructible {
255 type AssociatedInformation: Clone + Send + Sync;
256
257 fn add_plaintext(&self, ptx: &Self::Secret, assoc: Self::AssociatedInformation) -> Self;
259
260 fn add_plaintext_owned(self, ptx: &Self::Secret, assoc: Self::AssociatedInformation) -> Self {
262 self.add_plaintext(ptx, assoc)
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269 use crate::{
270 algebra::elliptic_curve::Curve25519Ristretto,
271 random::Random,
272 sharing::ScalarShares,
273 };
274
275 #[test]
276 fn test_transpose_empty_matrix() {
277 let matrix: Vec<Vec<i32>> = vec![];
278 let result = transpose(matrix.clone());
279 assert_eq!(result, matrix);
280 }
281
282 #[test]
283 fn test_transpose_empty_rows() {
284 let matrix: Vec<Vec<i32>> = vec![];
285 let result = transpose(matrix.clone());
286 assert_eq!(result, matrix);
287 }
288
289 #[test]
290 fn test_transpose_single_element() {
291 let matrix = vec![vec![1]];
292 let result = transpose(matrix);
293 assert_eq!(result, vec![vec![1]]);
294 }
295
296 #[test]
297 fn test_transpose_single_row() {
298 let matrix = vec![vec![1, 2, 3]];
299 let result = transpose(matrix);
300 assert_eq!(result, vec![vec![1], vec![2], vec![3]]);
301 }
302
303 #[test]
304 fn test_transpose_single_column() {
305 let matrix = vec![vec![1], vec![2], vec![3]];
306 let result = transpose(matrix);
307 assert_eq!(result, vec![vec![1, 2, 3]]);
308 }
309
310 #[test]
311 fn test_transpose_square_matrix() {
312 let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
313 let result = transpose(matrix);
314 let expected = vec![vec![1, 4, 7], vec![2, 5, 8], vec![3, 6, 9]];
315 assert_eq!(result, expected);
316 }
317
318 #[test]
319 fn test_transpose_rectangular_matrix() {
320 let matrix = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
321 let result = transpose(matrix);
322 let expected = vec![vec![1, 5], vec![2, 6], vec![3, 7], vec![4, 8]];
323 assert_eq!(result, expected);
324 }
325
326 #[test]
327 fn test_transpose_with_strings() {
328 let matrix = vec![vec!["a", "b"], vec!["c", "d"], vec!["e", "f"]];
329 let result = transpose(matrix);
330 let expected = vec![vec!["a", "c", "e"], vec!["b", "d", "f"]];
331 assert_eq!(result, expected);
332 }
333
334 #[test]
335 fn test_transpose_double_transpose() {
336 let matrix = vec![vec![1, 2, 3], vec![4, 5, 6]];
337 let result = transpose(transpose(matrix.clone()));
338 assert_eq!(result, matrix);
339 }
340
341 #[test]
342 fn test_reconstruct_vec() {
343 let n_parties = 3;
344 let mut rng = crate::random::test_rng();
345
346 let scalar_shares: Vec<_> =
347 ScalarShares::<Curve25519Ristretto, typenum::U5>::random_n(&mut rng, n_parties);
348 let scalar_shares = scalar_shares
349 .into_iter()
350 .map(|s| s.into_iter().collect::<Vec<_>>())
351 .collect::<Vec<_>>();
352
353 let reconstructed =
354 Vec::<ScalarShare<Curve25519Ristretto>>::reconstruct_all(&scalar_shares).unwrap();
355 let expected = (0..5)
356 .map(|i| {
357 ScalarShare::<Curve25519Ristretto>::reconstruct_all(
358 &scalar_shares.iter().map(|v| &v[i]).collect::<Vec<_>>(),
359 )
360 .unwrap()
361 })
362 .collect::<Vec<_>>();
363 assert_eq!(reconstructed, expected);
364 }
365
366 #[test]
367 fn test_reconstruct_tuple() {
368 let n_parties = 3;
369 let mut rng = crate::random::test_rng();
370
371 let scalar_shares: Vec<_> =
372 ScalarShare::<Curve25519Ristretto>::random_n(&mut rng, n_parties);
373 let base_field_shares: Vec<_> =
374 BaseFieldShare::<Curve25519Ristretto>::random_n(&mut rng, n_parties);
375
376 let shares: Vec<(
377 ScalarShare<Curve25519Ristretto>,
378 BaseFieldShare<Curve25519Ristretto>,
379 )> = izip!(&scalar_shares, &base_field_shares)
380 .map(|(s, b)| (s.clone(), b.clone()))
381 .collect();
382
383 let reconstructed = <(
384 ScalarShare<Curve25519Ristretto>,
385 BaseFieldShare<Curve25519Ristretto>,
386 )>::reconstruct_all(&shares)
387 .unwrap();
388
389 assert_eq!(
390 reconstructed.0,
391 ScalarShare::<Curve25519Ristretto>::reconstruct_all(&scalar_shares).unwrap()
392 );
393 assert_eq!(
394 reconstructed.1,
395 BaseFieldShare::<Curve25519Ristretto>::reconstruct_all(&base_field_shares).unwrap()
396 );
397 }
398}