use ark_ec::AffineRepr;
use ark_ff::PrimeField;
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::{cfg_into_iter, cfg_iter, vec::Vec};
use digest::Digest;
use dock_crypto_utils::{affine_group_element_from_byte_slices, serde_utils::ArkObjectBytes};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
pub type ShareId = u16;
pub type ParticipantId = u16;
#[serde_as]
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Zeroize,
ZeroizeOnDrop,
CanonicalSerialize,
CanonicalDeserialize,
Serialize,
Deserialize,
)]
pub struct Share<F: PrimeField> {
#[zeroize(skip)]
pub id: ShareId,
#[zeroize(skip)]
pub threshold: ShareId,
#[serde_as(as = "ArkObjectBytes")]
pub share: F,
}
#[derive(
Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
)]
#[serde(bound = "")]
pub struct Shares<F: PrimeField>(pub Vec<Share<F>>);
#[serde_as]
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Zeroize,
ZeroizeOnDrop,
CanonicalSerialize,
CanonicalDeserialize,
Serialize,
Deserialize,
)]
pub struct VerifiableShare<F: PrimeField> {
#[zeroize(skip)]
pub id: ShareId,
#[zeroize(skip)]
pub threshold: ShareId,
#[serde_as(as = "ArkObjectBytes")]
pub secret_share: F,
#[serde_as(as = "ArkObjectBytes")]
pub blinding_share: F,
}
#[derive(
Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
)]
#[serde(bound = "")]
pub struct VerifiableShares<F: PrimeField>(pub Vec<VerifiableShare<F>>);
#[serde_as]
#[derive(
Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
)]
pub struct CommitmentToCoefficients<G: AffineRepr>(
#[serde_as(as = "Vec<ArkObjectBytes>")] pub Vec<G>,
);
impl<F: PrimeField> From<(ShareId, ShareId, F)> for Share<F> {
fn from((i, t, s): (ShareId, ShareId, F)) -> Self {
Share {
id: i,
threshold: t,
share: s,
}
}
}
impl<F: PrimeField> Shares<F> {
pub fn threshold(&self) -> ShareId {
self.0[0].threshold
}
}
impl<G: AffineRepr> From<Vec<G>> for CommitmentToCoefficients<G> {
fn from(coeffs: Vec<G>) -> Self {
CommitmentToCoefficients(coeffs)
}
}
impl<G: AffineRepr> CommitmentToCoefficients<G> {
pub fn commitment_to_secret(&self) -> &G {
&self.0[0]
}
pub fn poly_degree(&self) -> usize {
self.0.len() - 1
}
pub fn supports_threshold(&self, threshold: ShareId) -> bool {
threshold as usize - 1 == self.poly_degree()
}
}
#[serde_as]
#[derive(
Clone, Debug, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
)]
pub struct PublicKeyBase<G: AffineRepr>(#[serde_as(as = "ArkObjectBytes")] pub G);
impl<G: AffineRepr> PublicKeyBase<G> {
pub fn new<D: Digest>(label: &[u8]) -> Self {
Self(affine_group_element_from_byte_slices!(label))
}
}
pub fn lagrange_basis_at_0<F: PrimeField>(x_coords: &[ShareId], i: ShareId) -> F {
let mut numerator = F::one();
let mut denominator = F::one();
let i_f = F::from(i as u64);
for x in x_coords {
if *x == i {
continue;
}
let x = F::from(*x as u64);
numerator *= x;
denominator *= x - i_f;
}
denominator.inverse_in_place().unwrap();
numerator * denominator
}
pub fn lagrange_basis_at_0_for_all<F: PrimeField>(x_coords: Vec<ShareId>) -> Vec<F> {
let x = cfg_into_iter!(x_coords.as_slice())
.map(|x| F::from(*x as u64))
.collect::<Vec<_>>();
let product = cfg_iter!(x).product::<F>();
cfg_into_iter!(x.clone())
.map(move |i| {
let mut denominator = cfg_iter!(x)
.filter(|&j| &i != j)
.map(|&j| j - i)
.product::<F>();
denominator.inverse_in_place().unwrap();
let numerator = product * i.inverse().unwrap();
denominator * numerator
})
.collect::<Vec<_>>()
}
#[cfg(test)]
pub mod tests {
use super::*;
use ark_bls12_381::Bls12_381;
use ark_ec::pairing::Pairing;
use ark_std::{
rand::{prelude::StdRng, SeedableRng},
UniformRand,
};
use std::time::Instant;
type Fr = <Bls12_381 as Pairing>::ScalarField;
#[test]
fn compare_lagrange_basis_at_0() {
let mut rng = StdRng::seed_from_u64(0u64);
let count = 20;
let x = (0..count)
.map(|_| ShareId::rand(&mut rng))
.collect::<Vec<_>>();
let start = Instant::now();
let single = cfg_iter!(x)
.map(|i| lagrange_basis_at_0(&x, *i))
.collect::<Vec<Fr>>();
println!("For {} x, single took {:?}", count, start.elapsed());
let start = Instant::now();
let multiple = lagrange_basis_at_0_for_all(x);
println!("For {} x, multiple took {:?}", count, start.elapsed());
assert_eq!(single, multiple);
}
}