use std::{
fmt::Debug,
iter::Sum as IterSum,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use serde::{Deserialize, Serialize};
use subtle::{Choice, ConstantTimeEq};
use typenum::{Prod, Sum, U1, U2, U3};
use wincode::{SchemaRead, SchemaWrite};
use crate::{
algebra::field::{FieldElement, FieldExtension, SubfieldElement},
errors::PrimitiveError,
izip_eq,
random::{CryptoRngCore, Random, RandomWith},
sharing::{FieldShareKey, GlobalFieldKey, OpenFieldShares},
types::{
heap_array::{FieldElements, SubfieldElements},
ConditionallySelectable,
HeapArray,
Positive,
},
};
#[derive(Clone, Default, PartialEq, Eq, Serialize, Deserialize, SchemaRead, SchemaWrite)]
#[serde(bound = "F: FieldExtension, M: Positive")]
#[repr(C)]
pub struct FieldShareKeys<F: FieldExtension, M: Positive> {
pub(crate) alpha: GlobalFieldKey<F>, pub(crate) betas: FieldElements<F, M>, }
impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
#[inline]
pub fn new(alpha: GlobalFieldKey<F>, betas: FieldElements<F, M>) -> Self {
FieldShareKeys { alpha, betas }
}
#[inline]
pub fn get_alpha(&self) -> GlobalFieldKey<F> {
self.alpha.clone()
}
#[inline]
pub fn get_alpha_value(&self) -> FieldElement<F> {
*self.alpha
}
#[inline]
pub fn get_betas(&self) -> &FieldElements<F, M> {
&self.betas
}
#[inline]
pub fn compute_mac(&self, values: &SubfieldElements<F, M>) -> FieldElements<F, M> {
izip_eq!(&self.betas, values)
.map(|(beta, value)| (*self.alpha * value) + beta)
.collect()
}
#[inline]
pub fn verify_mac(&self, open_share: &OpenFieldShares<F, M>) -> Result<(), PrimitiveError> {
let computed_macs = self.compute_mac(&open_share.value);
bool::from(computed_macs.ct_eq(&open_share.mac))
.then_some(())
.ok_or_else(|| {
PrimitiveError::WrongMAC(serde_json::to_string(&open_share.mac).unwrap())
})
}
}
impl<T: FieldExtension, M: Positive> Debug for FieldShareKeys<T, M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(format!("FieldShareKeys<{}>", M::SIZE).as_str())
.field("alpha", &self.alpha)
.field("betas", &self.betas)
.finish()
}
}
impl<F: FieldExtension, M: Positive> Add for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn add(self, other: FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: self.alpha,
betas: self.betas + other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Add<&FieldShareKeys<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn add(self, other: &FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: self.alpha,
betas: self.betas + &other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Add<FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn add(self, other: FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: other.alpha,
betas: other.betas + &self.betas,
}
}
}
impl<F: FieldExtension, M: Positive> AddAssign for FieldShareKeys<F, M> {
#[inline]
fn add_assign(&mut self, other: Self) {
assert_eq!(self.alpha, other.alpha);
self.betas += other.betas;
}
}
impl<'a, F: FieldExtension, M: Positive> AddAssign<&'a FieldShareKeys<F, M>>
for FieldShareKeys<F, M>
{
#[inline]
fn add_assign(&mut self, other: &'a FieldShareKeys<F, M>) {
assert_eq!(self.alpha, other.alpha);
self.betas += &other.betas;
}
}
impl<F: FieldExtension, M: Positive> Sub for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn sub(self, other: FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: self.alpha,
betas: self.betas - other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Sub<&FieldShareKeys<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn sub(self, other: &FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: self.alpha,
betas: self.betas - &other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Sub<FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn sub(self, other: FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: other.alpha,
betas: &self.betas - other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Sub<&FieldShareKeys<F, M>> for &FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn sub(self, other: &FieldShareKeys<F, M>) -> Self::Output {
assert_eq!(self.alpha, other.alpha);
FieldShareKeys {
alpha: self.alpha.clone(),
betas: &self.betas - &other.betas,
}
}
}
impl<F: FieldExtension, M: Positive> SubAssign for FieldShareKeys<F, M> {
#[inline]
fn sub_assign(&mut self, other: Self) {
assert_eq!(self.alpha, other.alpha);
self.betas -= other.betas;
}
}
impl<'a, F: FieldExtension, M: Positive> SubAssign<&'a FieldShareKeys<F, M>>
for FieldShareKeys<F, M>
{
#[inline]
fn sub_assign(&mut self, other: &'a FieldShareKeys<F, M>) {
assert_eq!(self.alpha, other.alpha);
self.betas -= &other.betas;
}
}
impl<F: FieldExtension, M: Positive> Mul<FieldElements<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(mut self, other: FieldElements<F, M>) -> Self::Output {
izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
self
}
}
impl<'a, F: FieldExtension, M: Positive> Mul<&'a FieldElements<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(mut self, other: &'a FieldElements<F, M>) -> Self::Output {
izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
self
}
}
impl<F: FieldExtension, M: Positive> Mul<SubfieldElements<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(mut self, other: SubfieldElements<F, M>) -> Self::Output {
izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
self
}
}
impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElements<F, M>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(mut self, other: &'a SubfieldElements<F, M>) -> Self::Output {
izip_eq!(&mut self.betas, other).for_each(|(beta, value)| *beta *= value);
self
}
}
impl<F: FieldExtension, M: Positive> Mul<FieldElement<F>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(self, other: FieldElement<F>) -> Self::Output {
FieldShareKeys {
betas: self.betas * other,
..self
}
}
}
impl<'a, F: FieldExtension, M: Positive> Mul<&'a FieldElement<F>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(self, other: &'a FieldElement<F>) -> Self::Output {
FieldShareKeys {
betas: self.betas * other,
..self
}
}
}
impl<F: FieldExtension, M: Positive> Mul<SubfieldElement<F>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(self, other: SubfieldElement<F>) -> Self::Output {
FieldShareKeys {
betas: self.betas * other,
..self
}
}
}
impl<'a, F: FieldExtension, M: Positive> Mul<&'a SubfieldElement<F>> for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn mul(self, other: &'a SubfieldElement<F>) -> Self::Output {
FieldShareKeys {
betas: self.betas * other,
..self
}
}
}
impl<F: FieldExtension, M: Positive> MulAssign for FieldShareKeys<F, M> {
#[inline]
fn mul_assign(&mut self, other: Self) {
self.betas *= other.betas;
}
}
impl<F: FieldExtension, M: Positive> MulAssign<FieldElement<F>> for FieldShareKeys<F, M> {
#[inline]
fn mul_assign(&mut self, other: FieldElement<F>) {
izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
}
}
impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a FieldElement<F>> for FieldShareKeys<F, M> {
#[inline]
fn mul_assign(&mut self, other: &'a FieldElement<F>) {
izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
}
}
impl<F: FieldExtension, M: Positive> MulAssign<SubfieldElement<F>> for FieldShareKeys<F, M> {
#[inline]
fn mul_assign(&mut self, other: SubfieldElement<F>) {
izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
}
}
impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElement<F>>
for FieldShareKeys<F, M>
{
#[inline]
fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
izip_eq!(&mut self.betas).for_each(|beta| *beta *= other)
}
}
impl<'a, F: FieldExtension, M: Positive> MulAssign<&'a SubfieldElements<F, M>>
for FieldShareKeys<F, M>
{
#[inline]
fn mul_assign(&mut self, other: &'a SubfieldElements<F, M>) {
izip_eq!(&mut self.betas, other).for_each(|(beta, other)| *beta *= other);
}
}
impl<F: FieldExtension, M: Positive> Neg for FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn neg(self) -> Self::Output {
FieldShareKeys {
alpha: self.alpha,
betas: -self.betas,
}
}
}
impl<F: FieldExtension, M: Positive> Neg for &FieldShareKeys<F, M> {
type Output = FieldShareKeys<F, M>;
#[inline]
fn neg(self) -> Self::Output {
FieldShareKeys {
alpha: self.alpha.clone(),
betas: -self.betas.clone(),
}
}
}
impl<F: FieldExtension, M: Positive> IterSum for FieldShareKeys<F, M> {
fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
let first = iter.next().unwrap_or_default();
iter.fold(first, |acc, x| acc + x)
}
}
impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
#[inline]
pub fn add_secret_owned(mut self, constant: SubfieldElement<F>) -> Self {
self.betas -= *self.alpha * constant;
self
}
#[inline]
pub fn add_secret(&self, constant: SubfieldElement<F>) -> Self {
let mut result = self.clone();
result.betas -= *result.alpha * constant;
result
}
#[inline]
pub fn add_constant_array(&self, constant: SubfieldElements<F, M>) -> Self {
let mut result = self.clone();
result.betas -= constant
.iter()
.map(|c| *result.alpha * c)
.collect::<FieldElements<F, M>>();
result
}
#[inline]
pub fn add_constant_array_owned(&mut self, constant: &SubfieldElements<F, M>) {
izip_eq!(&mut self.betas, constant).for_each(|(beta, c)| *beta -= *self.alpha * c);
}
}
impl<F: FieldExtension, M: Positive> Random for FieldShareKeys<F, M> {
fn random(mut rng: impl CryptoRngCore) -> Self {
FieldShareKeys {
alpha: GlobalFieldKey::random(&mut rng),
betas: FieldElements::random(&mut rng),
}
}
}
impl<F: FieldExtension, M: Positive> RandomWith<GlobalFieldKey<F>> for FieldShareKeys<F, M> {
fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalFieldKey<F>) -> Self {
FieldShareKeys {
alpha,
betas: FieldElements::random(&mut rng),
}
}
}
impl<F: FieldExtension, M: Positive> FieldShareKeys<F, M> {
pub fn split<M1, M2>(self) -> (FieldShareKeys<F, M1>, FieldShareKeys<F, M2>)
where
M1: Positive,
M2: Positive + Add<M1, Output = M>,
{
let FieldShareKeys { alpha, betas } = self;
let (betas1, betas2) = betas.split::<M1, M2>();
(
FieldShareKeys::new(alpha.clone(), betas1),
FieldShareKeys::new(alpha, betas2),
)
}
pub fn split_halves<MDiv2>(self) -> (FieldShareKeys<F, MDiv2>, FieldShareKeys<F, MDiv2>)
where
MDiv2: Positive + Mul<U2, Output = M>,
{
let FieldShareKeys { alpha, betas } = self;
let (betas1, betas2) = betas.split_halves::<MDiv2>();
(
FieldShareKeys::new(alpha.clone(), betas1),
FieldShareKeys::new(alpha, betas2),
)
}
pub fn merge_halves(this: Self, other: Self) -> FieldShareKeys<F, Prod<M, U2>>
where
M: Positive + Mul<U2, Output: Positive>,
{
assert_eq!(this.alpha, other.alpha);
FieldShareKeys {
alpha: this.alpha,
betas: FieldElements::merge_halves(this.betas, other.betas),
}
}
pub fn split3<M1, M2, M3>(
self,
) -> (
FieldShareKeys<F, M1>,
FieldShareKeys<F, M2>,
FieldShareKeys<F, M3>,
)
where
M1: Positive,
M2: Positive + Add<M1>,
M3: Positive + Add<Sum<M2, M1>, Output = M>,
{
let FieldShareKeys { alpha, betas } = self;
let (betas1, betas2, betas3) = betas.split3::<M1, M2, M3>();
(
FieldShareKeys::new(alpha.clone(), betas1),
FieldShareKeys::new(alpha.clone(), betas2),
FieldShareKeys::new(alpha, betas3),
)
}
pub fn split_thirds<MDiv3>(
self,
) -> (
FieldShareKeys<F, MDiv3>,
FieldShareKeys<F, MDiv3>,
FieldShareKeys<F, MDiv3>,
)
where
MDiv3: Positive + Mul<U3, Output = M>,
{
let FieldShareKeys { alpha, betas } = self;
let (betas1, betas2, betas3) = betas.split_thirds::<MDiv3>();
(
FieldShareKeys::new(alpha.clone(), betas1),
FieldShareKeys::new(alpha.clone(), betas2),
FieldShareKeys::new(alpha, betas3),
)
}
pub fn merge_thirds(first: Self, second: Self, third: Self) -> FieldShareKeys<F, Prod<M, U3>>
where
M: Positive + Mul<U3, Output: Positive>,
{
assert_eq!(first.alpha, second.alpha);
assert_eq!(first.alpha, third.alpha);
FieldShareKeys {
alpha: first.alpha,
betas: FieldElements::merge_thirds(first.betas, second.betas, third.betas),
}
}
}
impl<F: FieldExtension, M: Positive> ConstantTimeEq for FieldShareKeys<F, M> {
#[inline]
fn ct_eq(&self, other: &Self) -> Choice {
self.alpha.ct_eq(&other.alpha) & self.betas.ct_eq(&other.betas)
}
}
impl<F: FieldExtension, M: Positive> ConditionallySelectable for FieldShareKeys<F, M> {
#[inline]
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
FieldShareKeys {
alpha: GlobalFieldKey::conditional_select(&a.alpha, &b.alpha, choice),
betas: HeapArray::conditional_select(&a.betas, &b.betas, choice),
}
}
}
impl<F: FieldExtension> From<FieldShareKey<F>> for FieldShareKeys<F, U1> {
fn from(key: FieldShareKey<F>) -> Self {
FieldShareKeys {
alpha: key.alpha,
betas: HeapArray::from(key.beta),
}
}
}
pub struct FieldShareKeysIterator<F, M>
where
F: FieldExtension,
M: Positive,
{
keys: FieldShareKeys<F, M>,
index: usize,
}
impl<F: FieldExtension, M: Positive> Iterator for FieldShareKeysIterator<F, M> {
type Item = FieldShareKey<F>;
fn next(&mut self) -> Option<Self::Item> {
if self.index < M::to_usize() {
let key = FieldShareKey {
alpha: self.keys.alpha.clone(),
beta: self.keys.betas[self.index],
};
self.index += 1;
Some(key)
} else {
None
}
}
}
impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysIterator<F, M> {
fn len(&self) -> usize {
M::to_usize()
}
}
impl<F: FieldExtension, M: Positive> IntoIterator for FieldShareKeys<F, M> {
type Item = FieldShareKey<F>;
type IntoIter = FieldShareKeysIterator<F, M>;
fn into_iter(self) -> Self::IntoIter {
FieldShareKeysIterator::<F, M> {
keys: self,
index: 0,
}
}
}
pub struct FieldShareKeyRef<'a, F>
where
F: FieldExtension,
{
pub alpha: GlobalFieldKey<F>,
pub beta: &'a FieldElement<F>,
}
impl<'a, F> From<FieldShareKeyRef<'a, F>> for FieldShareKey<F>
where
F: FieldExtension,
{
fn from(val: FieldShareKeyRef<'a, F>) -> Self {
FieldShareKey {
alpha: val.alpha,
beta: *val.beta,
}
}
}
pub struct FieldShareKeysRefIterator<'a, F, M>
where
F: FieldExtension,
M: Positive,
{
keys: &'a FieldShareKeys<F, M>,
index: usize,
}
impl<F: FieldExtension, M: Positive> ExactSizeIterator for FieldShareKeysRefIterator<'_, F, M> {
fn len(&self) -> usize {
M::to_usize()
}
}
impl<'a, F: FieldExtension, M: Positive> Iterator for FieldShareKeysRefIterator<'a, F, M> {
type Item = FieldShareKeyRef<'a, F>;
fn next(&mut self) -> Option<Self::Item> {
if self.index < M::to_usize() {
let key = FieldShareKeyRef {
alpha: self.keys.alpha.clone(),
beta: &self.keys.betas[self.index],
};
self.index += 1;
Some(key)
} else {
None
}
}
}
impl<'a, F: FieldExtension, M: Positive> IntoIterator for &'a FieldShareKeys<F, M> {
type Item = FieldShareKeyRef<'a, F>;
type IntoIter = FieldShareKeysRefIterator<'a, F, M>;
fn into_iter(self) -> Self::IntoIter {
FieldShareKeysRefIterator {
keys: self,
index: 0,
}
}
}
#[cfg(test)]
mod tests {
use typenum::U10;
use super::*;
use crate::algebra::elliptic_curve::{Curve25519Ristretto as C, ScalarAsExtension};
pub type FrExt = ScalarAsExtension<C>;
#[test]
fn test_addition() {
let alpha = GlobalFieldKey::new(FrExt::from(3u32));
let key1 = FieldShareKeys {
alpha: alpha.clone(),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
};
let key2 = FieldShareKeys {
alpha: alpha.clone(),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(7u32)),
};
let expected_result = FieldShareKeys {
alpha,
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(17u32)),
};
assert_eq!(key1 + key2, expected_result);
}
#[test]
fn test_subtraction() {
let alpha = GlobalFieldKey::new(FrExt::from(3u32));
let key1 = FieldShareKeys {
alpha: alpha.clone(),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
};
let key2 = FieldShareKeys {
alpha: alpha.clone(),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(7u32)),
};
let expected_result = FieldShareKeys {
alpha,
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(3u32)),
};
assert_eq!(key1 - key2, expected_result);
}
#[test]
fn test_multiplication() {
let alpha = GlobalFieldKey::new(FrExt::from(3u32));
let key = FieldShareKeys {
alpha: alpha.clone(),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
};
let scalar = FrExt::from(3u32);
let expected_result = FieldShareKeys {
alpha,
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(30u32)),
};
assert_eq!(key * scalar, expected_result);
}
#[test]
fn test_negation() {
let key = FieldShareKeys {
alpha: GlobalFieldKey::new(FrExt::from(5u32)),
betas: HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
};
let expected_result = FieldShareKeys {
alpha: GlobalFieldKey::new(FrExt::from(5u32)),
betas: -HeapArray::<_, U10>::from_fn(|_| FrExt::from(10u32)),
};
assert_eq!(-key, expected_result);
}
}