1pub mod authenticated;
3pub mod unauthenticated;
4
5use std::borrow::Borrow;
6
7pub use authenticated::*;
8use itertools::enumerate;
9use serde::{de::DeserializeOwned, Serialize};
10
11use crate::{
12 algebra::{field::FieldExtension, ops::transpose::transpose},
13 errors::{PrimitiveError, VerificationError},
14 random::{CryptoRngCore, RandomWith},
15 types::PeerIndex,
16 utils::TakeExact,
17};
18
19pub trait Reconstructible: Sized {
24 type Opening: Serialize + Clone + DeserializeOwned + Send + Sync;
26 type Secret: Serialize + DeserializeOwned + PartialEq + Send + Sync;
28
29 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError>;
31
32 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening>;
35
36 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError>;
38
39 fn reconstruct_all<T: Borrow<Self>>(shares: &[T]) -> Result<Self::Secret, PrimitiveError> {
43 let n_parties = shares.len();
44 if n_parties < 2 {
45 return Err(PrimitiveError::InvalidParameters(
46 "At least two shares are required for reconstruction.".to_string(),
47 ));
48 }
49 let mut all_openings = shares
51 .iter()
52 .map(|share| share.borrow().open_to_all_others())
53 .collect::<Vec<_>>();
54 enumerate(shares.iter())
56 .map(|(i, share)| {
57 let my_openings = enumerate(all_openings.iter_mut())
58 .take_exact(n_parties)
59 .filter(|(j, _)| i != *j)
60 .map(|(_, opening)| opening.next())
61 .collect::<Option<Vec<_>>>()
62 .ok_or(VerificationError::MissingOpening(i))?;
63 share.borrow().reconstruct(my_openings.as_slice())
64 })
65 .reduce(|previous, current| match (previous, current) {
67 (Ok(prev), Ok(curr)) => match prev == curr {
68 true => Ok(prev),
69 false => Err(VerificationError::OpeningMismatch(
70 serde_json::to_string(&prev).unwrap(),
71 serde_json::to_string(&curr).unwrap(),
72 )
73 .into()),
74 },
75 (Err(e), _) | (_, Err(e)) => Err(e),
76 })
77 .unwrap() }
79}
80
81impl<T: Reconstructible<Opening: Clone>> Reconstructible for Vec<T> {
82 type Opening = Vec<T::Opening>;
83 type Secret = Vec<T::Secret>;
84
85 fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
86 self.iter().map(|share| share.open_to(peer_index)).collect()
87 }
88
89 fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
90 let all_openings: Vec<Vec<_>> = self
91 .iter()
92 .map(|share| share.open_to_all_others().collect())
93 .collect();
94
95 transpose(all_openings).into_iter()
96 }
97
98 fn reconstruct(&self, openings: &[Self::Opening]) -> Result<Self::Secret, PrimitiveError> {
99 if openings.len() != self.len() {
100 return Err(PrimitiveError::InvalidParameters(
101 "Number of openings must match number of shares.".to_string(),
102 ));
103 }
104
105 let mut reconstructed = Vec::with_capacity(self.len());
107 for (i, share) in self.iter().enumerate() {
108 let my_openings: Vec<_> = openings
109 .iter()
110 .map(|opening| opening.get(i).cloned())
111 .collect::<Option<Vec<_>>>()
112 .ok_or(PrimitiveError::InvalidParameters(
113 "Opening is missing for some share.".to_string(),
114 ))?;
115 reconstructed.push(share.reconstruct(my_openings.as_slice())?);
116 }
117 Ok(reconstructed)
118 }
119}
120
121pub trait RandomAuthenticatedForNPeers<F: FieldExtension>:
125 RandomWith<Vec<Vec<GlobalFieldKey<F>>>>
126{
127 fn random_for_n_peers_with_alphas<Container: FromIterator<Self>>(
128 mut rng: impl CryptoRngCore,
129 n_parties: usize,
130 all_alphas: Vec<Vec<GlobalFieldKey<F>>>,
131 ) -> Container {
132 Self::random_n_with(&mut rng, n_parties, all_alphas)
133 }
134}
135
136impl<F: FieldExtension, S: RandomWith<Vec<Vec<GlobalFieldKey<F>>>>> RandomAuthenticatedForNPeers<F>
137 for S
138{
139}
140
141pub trait RandomAuthenticatedForNPeersWith<F: FieldExtension, T: Clone>:
142 RandomWith<(T, Vec<Vec<GlobalFieldKey<F>>>)>
143{
144 fn random_authenticated_for_n_peers_with<Container: FromIterator<Self>>(
145 mut rng: impl CryptoRngCore,
146 n_parties: usize,
147 value: T,
148 all_alphas: Vec<Vec<GlobalFieldKey<F>>>,
149 ) -> Container {
150 Self::random_n_with(&mut rng, n_parties, (value, all_alphas))
151 }
152}
153
154impl<F: FieldExtension, T: Clone, S: RandomWith<(T, Vec<Vec<GlobalFieldKey<F>>>)>>
155 RandomAuthenticatedForNPeersWith<F, T> for S
156{
157}
158
159pub trait AddPlaintext: Reconstructible {
161 type AssociatedInformation: Clone + Send + Sync;
164 fn add_plaintext(&self, plaintext: &Self::Secret, assoc: Self::AssociatedInformation) -> Self;
166
167 fn add_plaintext_owned(
169 self,
170 plaintext: &Self::Secret,
171 assoc: Self::AssociatedInformation,
172 ) -> Self {
173 self.add_plaintext(plaintext, assoc)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_transpose_empty_matrix() {
183 let matrix: Vec<Vec<i32>> = vec![];
184 let result = transpose(matrix.clone());
185 assert_eq!(result, matrix);
186 }
187
188 #[test]
189 fn test_transpose_empty_rows() {
190 let matrix: Vec<Vec<i32>> = vec![];
191 let result = transpose(matrix.clone());
192 assert_eq!(result, matrix);
193 }
194
195 #[test]
196 fn test_transpose_single_element() {
197 let matrix = vec![vec![1]];
198 let result = transpose(matrix);
199 assert_eq!(result, vec![vec![1]]);
200 }
201
202 #[test]
203 fn test_transpose_single_row() {
204 let matrix = vec![vec![1, 2, 3]];
205 let result = transpose(matrix);
206 assert_eq!(result, vec![vec![1], vec![2], vec![3]]);
207 }
208
209 #[test]
210 fn test_transpose_single_column() {
211 let matrix = vec![vec![1], vec![2], vec![3]];
212 let result = transpose(matrix);
213 assert_eq!(result, vec![vec![1, 2, 3]]);
214 }
215
216 #[test]
217 fn test_transpose_square_matrix() {
218 let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
219 let result = transpose(matrix);
220 let expected = vec![vec![1, 4, 7], vec![2, 5, 8], vec![3, 6, 9]];
221 assert_eq!(result, expected);
222 }
223
224 #[test]
225 fn test_transpose_rectangular_matrix() {
226 let matrix = vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8]];
227 let result = transpose(matrix);
228 let expected = vec![vec![1, 5], vec![2, 6], vec![3, 7], vec![4, 8]];
229 assert_eq!(result, expected);
230 }
231
232 #[test]
233 fn test_transpose_with_strings() {
234 let matrix = vec![vec!["a", "b"], vec!["c", "d"], vec!["e", "f"]];
235 let result = transpose(matrix);
236 let expected = vec![vec!["a", "c", "e"], vec!["b", "d", "f"]];
237 assert_eq!(result, expected);
238 }
239
240 #[test]
241 fn test_transpose_double_transpose() {
242 let matrix = vec![vec![1, 2, 3], vec![4, 5, 6]];
243 let result = transpose(transpose(matrix.clone()));
244 assert_eq!(result, matrix);
245 }
246}