use std::ops::{Add, SubAssign};
use serde::{de::DeserializeOwned, Serialize};
use wincode::{SchemaRead, SchemaWrite};
use crate::{
errors::PrimitiveError,
random::{CryptoRngCore, Random},
sharing::Reconstructible,
types::{Element, HeapArray, PeerIndex, Positive},
};
pub trait AdditiveShares:
Sized + Clone + Random + for<'a> Add<&'a Self, Output = Self> + for<'s> SubAssign<&'s Self>
{
fn to_additive_shares(&self, n_parties: usize, mut rng: impl CryptoRngCore) -> Vec<Self> {
let mut last_share = self.clone();
let mut shares = (0..n_parties - 1)
.map(|_| {
let share = Self::random(&mut rng);
last_share -= &share;
share
})
.collect::<Vec<_>>();
shares.push(last_share);
shares
}
fn from_additive_shares<S: std::borrow::Borrow<Self>>(shares: &[S]) -> Self {
let mut shares_iter = shares.iter();
let first = shares_iter
.next()
.expect("At least one share is required for reconstruction.");
shares_iter.fold(first.borrow().clone(), |acc, share| acc + share.borrow())
}
}
impl<
T: AdditiveShares
+ Serialize
+ DeserializeOwned
+ SchemaWrite<Src = T>
+ for<'de> SchemaRead<'de, Dst = T>
+ PartialEq
+ Send
+ Sync
+ 'static,
> Reconstructible for T
{
type Opening = T;
type Value = T;
fn open_to(&self, _peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
Ok(self.to_owned())
}
fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
if true {
unimplemented!("No info about number of parties to open to");
} else {
std::iter::empty()
}
}
fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
Ok(openings
.iter()
.fold(self.to_owned(), |acc, opening| acc + opening))
}
fn reconstruct_all<S: std::borrow::Borrow<Self>>(
shares: Vec<S>,
) -> Result<Self::Value, PrimitiveError> {
Ok(Self::from_additive_shares(&shares))
}
}
impl<
T: Element
+ Clone
+ Random
+ for<'b> derive_more::SubAssign<&'b T>
+ for<'b> derive_more::Add<&'b T, Output = T>,
M: Positive,
> AdditiveShares for HeapArray<T, M>
{
}