foundry-mpc-rs 0.1.2

shamir-secret-sharing implementation forked from Lúcás C. Meier's cait_sith protocol and ZcashFoundation's frost
Documentation
use elliptic_curve::bigint::Encoding;
use elliptic_curve::ScalarPrimitive;
use rand_core::OsRng;

use crate::compat::CSCurve;
use crate::math::Polynomial;
use crate::point::Point256;

pub fn split<C: CSCurve>(
    secret: [u8; 32],
    point_xs: Vec<[u8; 32]>,
    t: u32,
) -> Result<Vec<Point256>, String> {
    if secret.len() != 32 {
        return Err("Secret must be 32 bytes".to_string());
    }

    if (point_xs.len() as u32) < t {
        return Err("KS node hashes must be greater than t".to_string());
    }

    if t < 2 {
        return Err("T must be greater than 2".to_string());
    }

    let secret_scalar = ScalarPrimitive::<C>::from_slice(&secret)
        .map_err(|err| format!("Failed to convert secret to scalar, err: {}", err))?;
    let constant = C::Scalar::from(secret_scalar);

    let mut rng = OsRng;

    let polynomial = Polynomial::<C>::extend_random(&mut rng, t as usize, &constant);

    let x_vec = point_xs.iter().collect::<Vec<_>>();

    let ks_node_hash_scalars = x_vec
        .iter()
        .map(|&hash| {
            let sp = ScalarPrimitive::<C>::from_slice(hash)
                .map_err(|err| format!("Failed to convert hash to scalar, err: {}", err))?;
            Ok(C::Scalar::from(sp))
        })
        .collect::<Result<Vec<C::Scalar>, String>>()?;

    let points = ks_node_hash_scalars
        .iter()
        .map(|x_scalar| {
            let x_bytes = Into::<C::Uint>::into(*x_scalar).to_be_bytes();

            let y_scalar = polynomial.evaluate(x_scalar);
            {}
            let y_bytes = Into::<C::Uint>::into(y_scalar).to_be_bytes();

            let x: Result<[u8; 32], String> = x_bytes
                .as_ref()
                .try_into()
                .map_err(|_| "Failed to convert x to [u8; 32]".to_string());
            let y: Result<[u8; 32], String> = y_bytes
                .as_ref()
                .try_into()
                .map_err(|_| "Failed to convert y to [u8; 32]".to_string());

            let x = match x {
                Ok(val) => val,
                Err(_) => return Err("Failed to convert x to [u8; 32]".to_string()),
            };
            let y = match y {
                Ok(val) => val,
                Err(_) => return Err("Failed to convert y to [u8; 32]".to_string()),
            };

            let point = Point256 { x, y };

            Ok(point)
        })
        .collect::<Result<Vec<Point256>, String>>()?;

    Ok(points)
}