use itertools::enumerate;
use crate::{
algebra::field::FieldExtension,
correlated_randomness::triples::{
OpenTriple,
OpenTriples,
Triple,
Triples,
UnauthenticatedTriple,
UnauthenticatedTriples,
},
errors::PrimitiveError,
izip_eq,
sharing::{PairwiseAuthShare, Reconstructible, Verifiable, VerifiableWith},
types::{PeerIndex, Positive, TryFoldAll},
};
impl<F: FieldExtension, M: Positive> Reconstructible for Triples<F, M> {
type Opening = OpenTriples<F, M>;
type Value = UnauthenticatedTriples<F, M>;
fn open_to(&self, peer_index: PeerIndex) -> Result<OpenTriples<F, M>, PrimitiveError> {
Ok(OpenTriples {
a: self.a.open_to(peer_index)?,
b: self.b.open_to(peer_index)?,
c: self.c.open_to(peer_index)?,
})
}
fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenTriples<F, M>> {
(0..self.a.n_parties() - 1)
.map(|peer_index| self.open_to(peer_index).unwrap())
.collect::<Vec<_>>()
.into_iter()
}
fn reconstruct(&self, openings: Vec<OpenTriples<F, M>>) -> Result<Self::Value, PrimitiveError> {
enumerate(izip_eq!(
self.a.get_keys(),
self.b.get_keys(),
self.c.get_keys(),
openings
))
.try_fold_all(
self.get_value(),
|mut acc: UnauthenticatedTriples<F, M>,
(peer_index, (a_key, b_key, c_key, opening))| {
acc.a += opening.a.get_value();
acc.b += opening.b.get_value();
acc.c += opening.c.get_value();
let a_ok = bool::from(PairwiseAuthShare::verify_mac(a_key, opening.a));
let b_ok = bool::from(PairwiseAuthShare::verify_mac(b_key, opening.b));
let c_ok = bool::from(PairwiseAuthShare::verify_mac(c_key, opening.c));
let error = if a_ok && b_ok && c_ok {
None
} else {
Some(PrimitiveError::WrongMAC(format!(
"triple MAC mismatch at peer {peer_index}"
)))
};
(acc, error)
},
)
}
}
impl<F: FieldExtension> Reconstructible for Triple<F> {
type Opening = OpenTriple<F>;
type Value = UnauthenticatedTriple<F>;
fn open_to(&self, peer_index: PeerIndex) -> Result<OpenTriple<F>, PrimitiveError> {
Ok(OpenTriple {
a: self.a.open_to(peer_index)?,
b: self.b.open_to(peer_index)?,
c: self.c.open_to(peer_index)?,
})
}
fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = OpenTriple<F>> {
(0..self.a.n_parties() - 1)
.map(|peer_index| self.open_to(peer_index).unwrap())
.collect::<Vec<_>>()
.into_iter()
}
fn reconstruct(&self, openings: Vec<OpenTriple<F>>) -> Result<Self::Value, PrimitiveError> {
enumerate(izip_eq!(
self.a.get_keys(),
self.b.get_keys(),
self.c.get_keys(),
openings
))
.try_fold_all(
self.get_value(),
|mut acc: UnauthenticatedTriple<F>, (peer_index, (a_key, b_key, c_key, opening))| {
acc.a += opening.a.get_value();
acc.b += opening.b.get_value();
acc.c += opening.c.get_value();
let a_ok = bool::from(PairwiseAuthShare::verify_mac(a_key, opening.a));
let b_ok = bool::from(PairwiseAuthShare::verify_mac(b_key, opening.b));
let c_ok = bool::from(PairwiseAuthShare::verify_mac(c_key, opening.c));
let error = if a_ok && b_ok && c_ok {
None
} else {
Some(PrimitiveError::WrongMAC(format!(
"triple MAC mismatch at peer {peer_index}"
)))
};
(acc, error)
},
)
}
}
impl<F: FieldExtension, M: Positive> VerifiableWith for Triples<F, M> {
type VerificationData = ();
fn verify_with(
&self,
openings: Vec<OpenTriples<F, M>>,
_verification_data: (),
) -> Result<(), PrimitiveError> {
let UnauthenticatedTriples { a, b, c } = self.reconstruct(openings)?;
if a * &b != c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed Triples do not satisfy a * b = c".to_string(),
));
}
Ok(())
}
fn verify_from_peer_with(
&self,
opening: OpenTriples<F, M>,
peer_index: PeerIndex,
_verification_data: (),
) -> Result<(), PrimitiveError> {
self.a.verify_from(opening.a, peer_index)?;
self.b.verify_from(opening.b, peer_index)?;
self.c.verify_from(opening.c, peer_index)?;
Ok(())
}
}
impl<F: FieldExtension> VerifiableWith for Triple<F> {
type VerificationData = ();
fn verify_with(
&self,
openings: Vec<OpenTriple<F>>,
_verification_data: (),
) -> Result<(), PrimitiveError> {
let UnauthenticatedTriple { a, b, c } = self.reconstruct(openings)?;
if a * b != c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed Triple does not satisfy a * b = c".to_string(),
));
}
Ok(())
}
fn verify_from_peer_with(
&self,
opening: OpenTriple<F>,
peer_index: PeerIndex,
_verification_data: (),
) -> Result<(), PrimitiveError> {
self.a.verify_from(opening.a, peer_index)?;
self.b.verify_from(opening.b, peer_index)?;
self.c.verify_from(opening.c, peer_index)?;
Ok(())
}
}
impl<F: FieldExtension> VerifiableWith for UnauthenticatedTriple<F> {
type VerificationData = ();
fn verify_with(
&self,
openings: Vec<UnauthenticatedTriple<F>>,
_verification_data: (),
) -> Result<(), PrimitiveError> {
let reconstructed = self.reconstruct(openings)?;
if reconstructed.a * reconstructed.b != reconstructed.c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed UnauthenticatedTriple does not satisfy a * b = c".to_string(),
));
}
Ok(())
}
fn verify_all_with(shares: Vec<Self>, _verification_data: ()) -> Result<(), PrimitiveError> {
let reconstructed = Self::reconstruct_all(shares)?;
if reconstructed.a * reconstructed.b != reconstructed.c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed UnauthenticatedTriple does not satisfy a * b = c".to_string(),
));
}
Ok(())
}
}
impl<F: FieldExtension, M: Positive> VerifiableWith for UnauthenticatedTriples<F, M> {
type VerificationData = ();
fn verify_with(
&self,
openings: Vec<UnauthenticatedTriples<F, M>>,
_verification_data: (),
) -> Result<(), PrimitiveError> {
let reconstructed = self.reconstruct(openings)?;
if reconstructed.a * &reconstructed.b != reconstructed.c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed UnauthenticatedTriples does not satisfy a * b = c".to_string(),
));
}
Ok(())
}
fn verify_all_with(shares: Vec<Self>, _verification_data: ()) -> Result<(), PrimitiveError> {
let reconstructed = Self::reconstruct_all(shares)?;
if reconstructed.a * &reconstructed.b != reconstructed.c {
return Err(PrimitiveError::WrongCorrelation(
"Reconstructed UnauthenticatedTriples does not satisfy a * b = c".to_string(),
));
}
Ok(())
}
}