use crate::shamir::create_shares_with_participant_generator;
use crate::*;
use core::{
marker::PhantomData,
ops::{Add, Sub},
};
use generic_array::{
ArrayLength, GenericArray,
typenum::{Add1, B1, Sub1},
};
use hybrid_array::{Array, ArraySize};
use rand_core::{CryptoRng, RngCore};
pub trait Feldman<S, V>: Shamir<S>
where
S: Share,
V: ShareVerifier<S>,
{
type VerifierSet: FeldmanVerifierSet<S, V>;
fn split_secret_with_verifier(
threshold: usize,
limit: usize,
secret: &S::Value,
generator: Option<V>,
rng: impl RngCore + CryptoRng,
) -> VsssResult<(Self::ShareSet, Self::VerifierSet)> {
Self::split_secret_with_participant_generator_and_verifiers(
threshold,
limit,
secret,
generator,
rng,
&[ParticipantIdGeneratorType::<S::Identifier>::default()],
)
}
fn split_secret_with_participant_generator_and_verifiers(
threshold: usize,
limit: usize,
secret: &S::Value,
generator: Option<V>,
rng: impl RngCore + CryptoRng,
participant_generators: &[ParticipantIdGeneratorType<S::Identifier>],
) -> VsssResult<(Self::ShareSet, Self::VerifierSet)> {
check_params(threshold, limit)?;
let g = generator.unwrap_or_else(V::one);
if g.is_zero().into() {
return Err(Error::InvalidGenerator(
"Generator cannot be the identity element",
));
}
let mut polynomial = Self::InnerPolynomial::create(threshold);
polynomial.fill(secret, rng, threshold)?;
let mut verifier_set = Self::VerifierSet::empty_feldman_set_with_capacity(threshold, g);
let coefficients = polynomial.coefficients();
let verifiers = verifier_set.verifiers_mut();
verifiers[0] = g * coefficients[0].value();
for i in 1..threshold {
verifiers[i] = g * coefficients[i].identifier();
}
let shares = create_shares_with_participant_generator(
&polynomial,
threshold,
limit,
participant_generators,
)?;
Ok((shares, verifier_set))
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct GenericArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
{
pub marker: PhantomData<(S, V, Add1<THRESHOLD>, SHARES)>,
}
impl<S, V, THRESHOLD, SHARES> Shamir<S> for GenericArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
{
type InnerPolynomial = GenericArray<S, THRESHOLD>;
type ShareSet = GenericArray<S, SHARES>;
}
impl<S, V, THRESHOLD, SHARES> Feldman<S, V> for GenericArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
{
type VerifierSet = GenericArray<V, Add1<THRESHOLD>>;
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct HybridArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
{
pub marker: PhantomData<(S, V, Add1<THRESHOLD>, SHARES)>,
}
impl<S, V, THRESHOLD, SHARES> Shamir<S> for HybridArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
{
type InnerPolynomial = Array<S, THRESHOLD>;
type ShareSet = Array<S, SHARES>;
}
impl<S, V, THRESHOLD, SHARES> Feldman<S, V> for HybridArrayFeldmanVsss<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
{
type VerifierSet = Array<V, Add1<THRESHOLD>>;
}
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn split_secret<S, V>(
threshold: usize,
limit: usize,
secret: &S::Value,
generator: Option<V>,
rng: impl RngCore + CryptoRng,
) -> VsssResult<(Vec<S>, Vec<V>)>
where
S: Share,
V: ShareVerifier<S>,
{
StdVsss::split_secret_with_verifier(threshold, limit, secret, generator, rng)
}
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn split_secret_with_participant_generator<S, V>(
threshold: usize,
limit: usize,
secret: &S::Value,
generator: Option<V>,
rng: impl RngCore + CryptoRng,
participant_generators: &[ParticipantIdGeneratorType<S::Identifier>],
) -> VsssResult<(Vec<S>, Vec<V>)>
where
S: Share,
V: ShareVerifier<S>,
{
StdVsss::split_secret_with_participant_generator_and_verifiers(
threshold,
limit,
secret,
generator,
rng,
participant_generators,
)
}