use crate::shamir::create_shares_with_participant_generator;
use crate::*;
use core::ops::{Add, Sub};
use generic_array::{
ArrayLength, GenericArray,
typenum::{Add1, B1, Sub1, U2},
};
use hybrid_array::{Array, ArraySize};
use rand_core::{CryptoRng, RngCore};
#[derive(Debug)]
pub struct PedersenOptions<'a, S: Share, V: ShareVerifier<S>> {
pub secret: S::Value,
pub blinder: Option<S::Value>,
pub secret_generator: Option<V>,
pub blinder_generator: Option<V>,
pub participant_generators: &'a [ParticipantIdGeneratorType<'a, S::Identifier>],
}
pub trait Pedersen<S, V>: Shamir<S>
where
S: Share,
V: ShareVerifier<S>,
{
type FeldmanVerifierSet: FeldmanVerifierSet<S, V>;
type PedersenVerifierSet: PedersenVerifierSet<S, V>;
type PedersenResult: PedersenResult<
S,
V,
ShareSet = <Self as Shamir<S>>::ShareSet,
FeldmanVerifierSet = Self::FeldmanVerifierSet,
PedersenVerifierSet = Self::PedersenVerifierSet,
>;
fn split_secret_with_blind_verifiers(
threshold: usize,
limit: usize,
options: &PedersenOptions<S, V>,
mut rng: impl RngCore + CryptoRng,
) -> VsssResult<Self::PedersenResult> {
check_params(threshold, limit)?;
let g = options.secret_generator.unwrap_or_else(V::one);
let h = options
.blinder_generator
.unwrap_or_else(|| V::random(&mut rng));
if (g.is_zero() | h.is_zero()).into() {
return Err(Error::InvalidGenerator(
"Pedersen generators cannot be zero",
));
}
if g == h {
return Err(Error::InvalidGenerator(
"Pedersen generators cannot be the same",
));
}
let blinder = options
.blinder
.clone()
.unwrap_or_else(|| S::Value::random(&mut rng));
let mut secret_polynomial = Self::InnerPolynomial::create(threshold);
let mut blinder_polynomial = Self::InnerPolynomial::create(threshold);
secret_polynomial.fill(&options.secret, &mut rng, threshold)?;
blinder_polynomial.fill(&blinder, &mut rng, threshold)?;
let mut feldman_verifier_set =
Self::FeldmanVerifierSet::empty_feldman_set_with_capacity(threshold, g);
let mut pedersen_verifier_set =
Self::PedersenVerifierSet::empty_pedersen_set_with_capacity(threshold, g, h);
let secret_coefficients = secret_polynomial.coefficients();
let blinder_coefficients = blinder_polynomial.coefficients();
let feldman_verifiers = feldman_verifier_set.verifiers_mut();
let pedersen_verifiers = pedersen_verifier_set.blind_verifiers_mut();
feldman_verifiers[0] = g * secret_coefficients[0].value();
pedersen_verifiers[0] = feldman_verifiers[0] + h * blinder_coefficients[0].value();
for i in 1..threshold {
feldman_verifiers[i] = g * secret_coefficients[i].identifier();
pedersen_verifiers[i] = feldman_verifiers[i] + h * blinder_coefficients[i].identifier();
}
let secret_shares = create_shares_with_participant_generator(
&secret_polynomial,
threshold,
limit,
options.participant_generators,
)?;
let blinder_shares = create_shares_with_participant_generator(
&blinder_polynomial,
threshold,
limit,
options.participant_generators,
)?;
Ok(Self::PedersenResult::new(
blinder,
secret_shares,
blinder_shares,
feldman_verifier_set,
pedersen_verifier_set,
))
}
}
pub trait PedersenResult<S, V>: Sized
where
S: Share,
V: ShareVerifier<S>,
{
type ShareSet: ReadableShareSet<S>;
type FeldmanVerifierSet: FeldmanVerifierSet<S, V>;
type PedersenVerifierSet: PedersenVerifierSet<S, V>;
fn new(
blinder: S::Value,
secret_shares: Self::ShareSet,
blinder_shares: Self::ShareSet,
feldman_verifier_set: Self::FeldmanVerifierSet,
pedersen_verifier_set: Self::PedersenVerifierSet,
) -> Self;
fn blinder(&self) -> &S::Value;
fn secret_shares(&self) -> &Self::ShareSet;
fn blinder_shares(&self) -> &Self::ShareSet;
fn feldman_verifier_set(&self) -> &Self::FeldmanVerifierSet;
fn pedersen_verifier_set(&self) -> &Self::PedersenVerifierSet;
}
type Add2<A> = <A as Add<U2>>::Output;
type Sub2<A> = <A as Sub<U2>>::Output;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct GenericArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + Add<U2> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArrayLength + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
Sub2<Add2<THRESHOLD>>: ArrayLength,
{
pub(crate) blinder: S::Value,
pub(crate) secret_shares: GenericArray<S, SHARES>,
pub(crate) blinder_shares: GenericArray<S, SHARES>,
pub(crate) feldman_verifier_set: GenericArray<V, Add1<THRESHOLD>>,
pub(crate) pedersen_verifier_set: GenericArray<V, Add2<THRESHOLD>>,
}
impl<S, V, THRESHOLD, SHARES> PedersenResult<S, V>
for GenericArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + Add<U2> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArrayLength + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
Sub2<Add2<THRESHOLD>>: ArrayLength,
{
type ShareSet = GenericArray<S, SHARES>;
type FeldmanVerifierSet = GenericArray<V, Add1<THRESHOLD>>;
type PedersenVerifierSet = GenericArray<V, Add2<THRESHOLD>>;
fn new(
blinder: S::Value,
secret_shares: Self::ShareSet,
blinder_shares: Self::ShareSet,
feldman_verifier_set: Self::FeldmanVerifierSet,
pedersen_verifier_set: Self::PedersenVerifierSet,
) -> Self {
Self {
blinder,
secret_shares,
blinder_shares,
feldman_verifier_set,
pedersen_verifier_set,
}
}
fn blinder(&self) -> &S::Value {
&self.blinder
}
fn secret_shares(&self) -> &Self::ShareSet {
&self.secret_shares
}
fn blinder_shares(&self) -> &Self::ShareSet {
&self.blinder_shares
}
fn feldman_verifier_set(&self) -> &Self::FeldmanVerifierSet {
&self.feldman_verifier_set
}
fn pedersen_verifier_set(&self) -> &Self::PedersenVerifierSet {
&self.pedersen_verifier_set
}
}
impl<S, V, THRESHOLD, SHARES> Shamir<S> for GenericArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + Add<U2> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArrayLength + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
Sub2<Add2<THRESHOLD>>: ArrayLength,
{
type InnerPolynomial = GenericArray<S, THRESHOLD>;
type ShareSet = GenericArray<S, SHARES>;
}
impl<S, V, THRESHOLD, SHARES> Pedersen<S, V> for GenericArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArrayLength,
THRESHOLD: Add<B1> + Add<U2> + ArrayLength,
Add1<THRESHOLD>: ArrayLength + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArrayLength + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArrayLength,
Sub2<Add2<THRESHOLD>>: ArrayLength,
{
type FeldmanVerifierSet = GenericArray<V, Add1<THRESHOLD>>;
type PedersenVerifierSet = GenericArray<V, Add2<THRESHOLD>>;
type PedersenResult = Self;
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub struct HybridArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + Add<U2> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArraySize + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
Sub2<Add2<THRESHOLD>>: ArraySize,
{
pub(crate) blinder: S::Value,
pub(crate) secret_shares: Array<S, SHARES>,
pub(crate) blinder_shares: Array<S, SHARES>,
pub(crate) feldman_verifier_set: Array<V, Add1<THRESHOLD>>,
pub(crate) pedersen_verifier_set: Array<V, Add2<THRESHOLD>>,
}
impl<S, V, THRESHOLD, SHARES> PedersenResult<S, V>
for HybridArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + Add<U2> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArraySize + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
Sub2<Add2<THRESHOLD>>: ArraySize,
{
type ShareSet = Array<S, SHARES>;
type FeldmanVerifierSet = Array<V, Add1<THRESHOLD>>;
type PedersenVerifierSet = Array<V, Add2<THRESHOLD>>;
fn new(
blinder: S::Value,
secret_shares: Self::ShareSet,
blinder_shares: Self::ShareSet,
feldman_verifier_set: Self::FeldmanVerifierSet,
pedersen_verifier_set: Self::PedersenVerifierSet,
) -> Self {
Self {
blinder,
secret_shares,
blinder_shares,
feldman_verifier_set,
pedersen_verifier_set,
}
}
fn blinder(&self) -> &S::Value {
&self.blinder
}
fn secret_shares(&self) -> &Self::ShareSet {
&self.secret_shares
}
fn blinder_shares(&self) -> &Self::ShareSet {
&self.blinder_shares
}
fn feldman_verifier_set(&self) -> &Self::FeldmanVerifierSet {
&self.feldman_verifier_set
}
fn pedersen_verifier_set(&self) -> &Self::PedersenVerifierSet {
&self.pedersen_verifier_set
}
}
impl<S, V, THRESHOLD, SHARES> Shamir<S> for HybridArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + Add<U2> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArraySize + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
Sub2<Add2<THRESHOLD>>: ArraySize,
{
type InnerPolynomial = Array<S, THRESHOLD>;
type ShareSet = Array<S, SHARES>;
}
impl<S, V, THRESHOLD, SHARES> Pedersen<S, V> for HybridArrayPedersenResult<S, V, THRESHOLD, SHARES>
where
S: Share,
V: ShareVerifier<S>,
SHARES: ArraySize,
THRESHOLD: Add<B1> + Add<U2> + ArraySize,
Add1<THRESHOLD>: ArraySize + Sub<B1, Output = THRESHOLD>,
Add2<THRESHOLD>: ArraySize + Sub<U2, Output = THRESHOLD>,
Sub1<Add1<THRESHOLD>>: ArraySize,
Sub2<Add2<THRESHOLD>>: ArraySize,
{
type FeldmanVerifierSet = Array<V, Add1<THRESHOLD>>;
type PedersenVerifierSet = Array<V, Add2<THRESHOLD>>;
type PedersenResult = Self;
}
#[cfg(any(feature = "alloc", feature = "std"))]
#[derive(Debug, Clone)]
pub struct StdPedersenResult<S, V>
where
S: Share,
V: ShareVerifier<S>,
{
pub(crate) blinder: S::Value,
pub(crate) secret_shares: Vec<S>,
pub(crate) blinder_shares: Vec<S>,
pub(crate) feldman_verifier_set: Vec<V>,
pub(crate) pedersen_verifier_set: Vec<V>,
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<S, V> Shamir<S> for StdPedersenResult<S, V>
where
S: Share,
V: ShareVerifier<S>,
{
type InnerPolynomial = Vec<S>;
type ShareSet = Vec<S>;
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<S, V> Pedersen<S, V> for StdPedersenResult<S, V>
where
S: Share,
V: ShareVerifier<S>,
{
type FeldmanVerifierSet = Vec<V>;
type PedersenVerifierSet = Vec<V>;
type PedersenResult = Self;
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<S, V> PedersenResult<S, V> for StdPedersenResult<S, V>
where
S: Share,
V: ShareVerifier<S>,
{
type ShareSet = Vec<S>;
type FeldmanVerifierSet = Vec<V>;
type PedersenVerifierSet = Vec<V>;
fn new(
blinder: S::Value,
secret_shares: Self::ShareSet,
blinder_shares: Self::ShareSet,
feldman_verifier_set: Self::FeldmanVerifierSet,
pedersen_verifier_set: Self::PedersenVerifierSet,
) -> Self {
Self {
blinder,
secret_shares,
blinder_shares,
feldman_verifier_set,
pedersen_verifier_set,
}
}
fn blinder(&self) -> &S::Value {
&self.blinder
}
fn secret_shares(&self) -> &Self::ShareSet {
&self.secret_shares
}
fn blinder_shares(&self) -> &Self::ShareSet {
&self.blinder_shares
}
fn feldman_verifier_set(&self) -> &Self::FeldmanVerifierSet {
&self.feldman_verifier_set
}
fn pedersen_verifier_set(&self) -> &Self::PedersenVerifierSet {
&self.pedersen_verifier_set
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn split_secret<S, V>(
threshold: usize,
limit: usize,
secret: &S::Value,
blinding: Option<S::Value>,
share_generator: Option<V>,
blind_factor_generator: Option<V>,
rng: impl RngCore + CryptoRng,
) -> VsssResult<StdPedersenResult<S, V>>
where
S: Share,
V: ShareVerifier<S>,
{
StdVsss::split_secret_with_blind_verifiers(
threshold,
limit,
&PedersenOptions {
secret: secret.clone(),
blinder: blinding,
secret_generator: share_generator,
blinder_generator: blind_factor_generator,
participant_generators: &[ParticipantIdGeneratorType::default()],
},
rng,
)
}