use itertools::izip;
use num_traits::identities::{One, Zero};
use crate::{
algebra::field::{binary::Gf2_128, Bit, FieldExtension, SubfieldElement},
correlated_randomness::dabits::{DaBit, DaBits, OpenDaBit, OpenDaBits},
errors::PrimitiveError,
sharing::{Reconstructible, VerifiableWith},
types::{HeapArray, PeerIndex, Positive},
};
impl<F: FieldExtension> Reconstructible for DaBit<F> {
type Value = (Bit, SubfieldElement<F>);
type Opening = OpenDaBit<F>;
fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
let opened_bit = self.bit.open_to(peer_index)?;
Ok(OpenDaBit {
opened_bit,
opened_field: self.field.open_to(peer_index)?,
})
}
fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
(0..self.field.get_macs().len())
.map(|peer_index| self.open_to(peer_index).expect("Opening should not fail"))
}
fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
let (bit_openings, field_openings): (Vec<_>, Vec<_>) = openings
.iter()
.map(|dabit_opening| (dabit_opening.bit(), dabit_opening.field()))
.unzip();
if field_openings.len() != self.field.get_macs().len() {
return Err(PrimitiveError::InvalidSize(
self.field.get_macs().len(),
field_openings.len(),
));
}
let field = self.field.reconstruct(field_openings)?;
let bit = self.bit.reconstruct(bit_openings)?;
Ok((bit, field))
}
}
impl<F: FieldExtension> VerifiableWith for DaBit<F> {
type VerificationData = ();
fn verify_with(&self, openings: Vec<Self::Opening>, _data: ()) -> Result<(), PrimitiveError> {
let (bit, field) = self.reconstruct(openings)?;
if field == SubfieldElement::<F>::one() {
if bit != SubfieldElement::<Gf2_128>::one() {
return Err(PrimitiveError::WrongCorrelation(
"daBit bit does not match the field element.".to_string(),
));
}
} else if field == SubfieldElement::<F>::zero() {
if bit != SubfieldElement::<Gf2_128>::zero() {
return Err(PrimitiveError::WrongCorrelation(
"daBit bit does not match the field element.".to_string(),
));
}
} else {
return Err(PrimitiveError::WrongCorrelation(
"daBit field element is not 0 or 1.".to_string(),
));
}
Ok(())
}
}
impl<F: FieldExtension, N: Positive> Reconstructible for DaBits<F, N> {
type Opening = OpenDaBits<F, N>;
type Value = HeapArray<(Bit, SubfieldElement<F>), N>;
fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
Ok(OpenDaBits {
opened_bits: self.bits.open_to(peer_index)?,
opened_field_shares: self.field_shares.open_to(peer_index)?,
})
}
fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
izip!(
self.bits.open_to_all_others(),
self.field_shares.open_to_all_others()
)
.map(|(opened_bits, opened_field_shares)| OpenDaBits {
opened_bits,
opened_field_shares,
})
}
fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
let (bit_openings, field_openings): (Vec<_>, Vec<_>) = openings
.into_iter()
.map(|dabit_opening| (dabit_opening.opened_bits, dabit_opening.opened_field_shares))
.unzip();
let bits = self.bits.reconstruct(bit_openings)?;
let field_shares = self.field_shares.reconstruct(field_openings)?;
Ok(HeapArray::from_iter(izip!(
bits.into_iter(),
field_shares.into_iter()
)))
}
}
impl<F: FieldExtension, N: Positive> VerifiableWith for DaBits<F, N> {
type VerificationData = ();
fn verify_with(&self, openings: Vec<Self::Opening>, _data: ()) -> Result<(), PrimitiveError> {
let openings = self.reconstruct(openings)?;
for (bit, field) in openings {
if field == SubfieldElement::<F>::one() {
if bit != SubfieldElement::<Gf2_128>::one() {
return Err(PrimitiveError::WrongCorrelation(
"daBit bit does not match the field element.".to_string(),
));
}
} else if field == SubfieldElement::<F>::zero() {
if bit != SubfieldElement::<Gf2_128>::zero() {
return Err(PrimitiveError::WrongCorrelation(
"daBit bit does not match the field element.".to_string(),
));
}
} else {
return Err(PrimitiveError::WrongCorrelation(
"daBit field element is not 0 or 1.".to_string(),
));
}
}
Ok(())
}
}