Skip to main content

primitives/correlated_randomness/triples/
sharing.rs

1use itertools::enumerate;
2
3use crate::{
4    algebra::field::FieldExtension,
5    correlated_randomness::triples::{
6        OpenTriple,
7        OpenTriples,
8        Triple,
9        Triples,
10        UnauthenticatedTriple,
11        UnauthenticatedTriples,
12    },
13    errors::PrimitiveError,
14    izip_eq,
15    sharing::{PairwiseAuthShare, Reconstructible, Verifiable, VerifiableWith},
16    types::{PeerIndex, Positive, TryFoldAll},
17};
18
19// ---------------
20// |   Opening   |
21// ---------------
22
23impl<F: FieldExtension, M: Positive> Reconstructible for Triples<F, M> {
24    type Opening = OpenTriples<F, M>;
25    type Value = UnauthenticatedTriples<F, M>;
26
27    fn open_to(&self, peer_index: PeerIndex) -> Result<OpenTriples<F, M>, PrimitiveError> {
28        Ok(OpenTriples {
29            a: self.a.open_to(peer_index)?,
30            b: self.b.open_to(peer_index)?,
31            c: self.c.open_to(peer_index)?,
32        })
33    }
34
35    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenTriples<F, M>> {
36        (0..self.a.n_parties() - 1)
37            .map(|peer_index| self.open_to(peer_index).unwrap())
38            .collect::<Vec<_>>()
39            .into_iter()
40    }
41
42    fn reconstruct(&self, openings: Vec<OpenTriples<F, M>>) -> Result<Self::Value, PrimitiveError> {
43        enumerate(izip_eq!(
44            self.a.get_keys(),
45            self.b.get_keys(),
46            self.c.get_keys(),
47            openings
48        ))
49        .try_fold_all(
50            self.get_value(),
51            |mut acc: UnauthenticatedTriples<F, M>,
52             (peer_index, (a_key, b_key, c_key, opening))| {
53                // Reconstruct shares (borrow before moving into verify_mac)
54                acc.a += opening.a.get_value();
55                acc.b += opening.b.get_value();
56                acc.c += opening.c.get_value();
57                // Verify MACs
58                let a_ok = bool::from(PairwiseAuthShare::verify_mac(a_key, opening.a));
59                let b_ok = bool::from(PairwiseAuthShare::verify_mac(b_key, opening.b));
60                let c_ok = bool::from(PairwiseAuthShare::verify_mac(c_key, opening.c));
61                let error = if a_ok && b_ok && c_ok {
62                    None
63                } else {
64                    Some(PrimitiveError::WrongMAC(format!(
65                        "triple MAC mismatch at peer {peer_index}"
66                    )))
67                };
68                (acc, error)
69            },
70        )
71    }
72}
73
74impl<F: FieldExtension> Reconstructible for Triple<F> {
75    type Opening = OpenTriple<F>;
76    type Value = UnauthenticatedTriple<F>;
77
78    fn open_to(&self, peer_index: PeerIndex) -> Result<OpenTriple<F>, PrimitiveError> {
79        Ok(OpenTriple {
80            a: self.a.open_to(peer_index)?,
81            b: self.b.open_to(peer_index)?,
82            c: self.c.open_to(peer_index)?,
83        })
84    }
85
86    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenTriple<F>> {
87        (0..self.a.n_parties() - 1)
88            .map(|peer_index| self.open_to(peer_index).unwrap())
89            .collect::<Vec<_>>()
90            .into_iter()
91    }
92
93    fn reconstruct(&self, openings: Vec<OpenTriple<F>>) -> Result<Self::Value, PrimitiveError> {
94        enumerate(izip_eq!(
95            self.a.get_keys(),
96            self.b.get_keys(),
97            self.c.get_keys(),
98            openings
99        ))
100        .try_fold_all(
101            self.get_value(),
102            |mut acc: UnauthenticatedTriple<F>, (peer_index, (a_key, b_key, c_key, opening))| {
103                // Reconstruct shares (borrow before moving into verify_mac)
104                acc.a += opening.a.get_value();
105                acc.b += opening.b.get_value();
106                acc.c += opening.c.get_value();
107                // Verify MACs
108                let a_ok = bool::from(PairwiseAuthShare::verify_mac(a_key, opening.a));
109                let b_ok = bool::from(PairwiseAuthShare::verify_mac(b_key, opening.b));
110                let c_ok = bool::from(PairwiseAuthShare::verify_mac(c_key, opening.c));
111                let error = if a_ok && b_ok && c_ok {
112                    None
113                } else {
114                    Some(PrimitiveError::WrongMAC(format!(
115                        "triple MAC mismatch at peer {peer_index}"
116                    )))
117                };
118                (acc, error)
119            },
120        )
121    }
122}
123
124// --------------------
125// |   Verification   |
126// --------------------
127
128impl<F: FieldExtension, M: Positive> VerifiableWith for Triples<F, M> {
129    type VerificationData = ();
130    fn verify_with(
131        &self,
132        openings: Vec<OpenTriples<F, M>>,
133        _verification_data: (),
134    ) -> Result<(), PrimitiveError> {
135        let UnauthenticatedTriples { a, b, c } = self.reconstruct(openings)?;
136        if a * &b != c {
137            return Err(PrimitiveError::WrongCorrelation(
138                "Reconstructed Triples do not satisfy a * b = c".to_string(),
139            ));
140        }
141        Ok(())
142    }
143
144    fn verify_from_peer_with(
145        &self,
146        opening: OpenTriples<F, M>,
147        peer_index: PeerIndex,
148        _verification_data: (),
149    ) -> Result<(), PrimitiveError> {
150        self.a.verify_from(opening.a, peer_index)?;
151        self.b.verify_from(opening.b, peer_index)?;
152        self.c.verify_from(opening.c, peer_index)?;
153        Ok(())
154    }
155}
156
157impl<F: FieldExtension> VerifiableWith for Triple<F> {
158    type VerificationData = ();
159    fn verify_with(
160        &self,
161        openings: Vec<OpenTriple<F>>,
162        _verification_data: (),
163    ) -> Result<(), PrimitiveError> {
164        let UnauthenticatedTriple { a, b, c } = self.reconstruct(openings)?;
165        if a * b != c {
166            return Err(PrimitiveError::WrongCorrelation(
167                "Reconstructed Triple does not satisfy a * b = c".to_string(),
168            ));
169        }
170        Ok(())
171    }
172
173    fn verify_from_peer_with(
174        &self,
175        opening: OpenTriple<F>,
176        peer_index: PeerIndex,
177        _verification_data: (),
178    ) -> Result<(), PrimitiveError> {
179        self.a.verify_from(opening.a, peer_index)?;
180        self.b.verify_from(opening.b, peer_index)?;
181        self.c.verify_from(opening.c, peer_index)?;
182        Ok(())
183    }
184}
185
186impl<F: FieldExtension> VerifiableWith for UnauthenticatedTriple<F> {
187    type VerificationData = ();
188    fn verify_with(
189        &self,
190        openings: Vec<UnauthenticatedTriple<F>>,
191        _verification_data: (),
192    ) -> Result<(), PrimitiveError> {
193        let reconstructed = self.reconstruct(openings)?;
194        if reconstructed.a * reconstructed.b != reconstructed.c {
195            return Err(PrimitiveError::WrongCorrelation(
196                "Reconstructed UnauthenticatedTriple does not satisfy a * b = c".to_string(),
197            ));
198        }
199        Ok(())
200    }
201
202    fn verify_all_with(shares: Vec<Self>, _verification_data: ()) -> Result<(), PrimitiveError> {
203        let reconstructed = Self::reconstruct_all(shares)?;
204        if reconstructed.a * reconstructed.b != reconstructed.c {
205            return Err(PrimitiveError::WrongCorrelation(
206                "Reconstructed UnauthenticatedTriple does not satisfy a * b = c".to_string(),
207            ));
208        }
209        Ok(())
210    }
211}
212
213impl<F: FieldExtension, M: Positive> VerifiableWith for UnauthenticatedTriples<F, M> {
214    type VerificationData = ();
215    fn verify_with(
216        &self,
217        openings: Vec<UnauthenticatedTriples<F, M>>,
218        _verification_data: (),
219    ) -> Result<(), PrimitiveError> {
220        let reconstructed = self.reconstruct(openings)?;
221        if reconstructed.a * &reconstructed.b != reconstructed.c {
222            return Err(PrimitiveError::WrongCorrelation(
223                "Reconstructed UnauthenticatedTriples does not satisfy a * b = c".to_string(),
224            ));
225        }
226        Ok(())
227    }
228
229    fn verify_all_with(shares: Vec<Self>, _verification_data: ()) -> Result<(), PrimitiveError> {
230        let reconstructed = Self::reconstruct_all(shares)?;
231        if reconstructed.a * &reconstructed.b != reconstructed.c {
232            return Err(PrimitiveError::WrongCorrelation(
233                "Reconstructed UnauthenticatedTriples does not satisfy a * b = c".to_string(),
234            ));
235        }
236        Ok(())
237    }
238}