stoffelcrypto 0.1.0

Asynchronous HoneyBadgerMPC protocols, preprocessing, and arithmetic for Stoffel.
Documentation
use crate::{
    common::{types::fixed::SecretFixedPoint, RBC},
    honeybadger::{
        fpmul::{truncpr::TruncPrNode, TruncPrError},
        mul::{multiplication::Multiply, MulError},
        robust_interpolate::robust_interpolate::RobustShare,
        triple_gen::ShamirBeaverTriple,
        SessionId,
    },
};
use ark_ff::PrimeField;
use std::sync::Arc;
use stoffelnet::network_utils::Network;
use thiserror::Error;
use tokio::{sync::mpsc::error::SendError, time::Duration};

#[derive(Error, Debug)]
pub enum FPError {
    #[error("error in the secure multiplication protocol: {0:?}")]
    MulError(#[from] MulError),
    #[error("error in the truncation protocol: {0:?}")]
    TruncPrError(#[from] TruncPrError),
    #[error("FpMul failed")]
    Failed,
    #[error("Incompatible precision")]
    IncompatiblePrecision,
    #[error("error sending the thread asynchronously")]
    SendError(#[from] SendError<SessionId>),
}

#[derive(Clone, Debug)]
pub struct FPMulNode<F, R>
where
    F: PrimeField,
    R: RBC,
{
    pub id: usize,
    pub n_parties: usize,
    pub threshold: usize,
    pub mult_node: Multiply<F, R>,
    pub trunc_node: TruncPrNode<F, R>,
}

impl<F, R> FPMulNode<F, R>
where
    F: PrimeField,
    R: RBC<Id = SessionId>,
{
    pub fn new(id: usize, n_parties: usize, threshold: usize) -> Result<Self, FPError> {
        let trunc_node = TruncPrNode::new(id, n_parties, threshold)?;
        let mult_node = Multiply::new(id, n_parties, threshold)?;
        Ok(Self {
            id,
            n_parties,
            threshold,
            mult_node,
            trunc_node,
        })
    }

    pub async fn init<N: Network + Send + Sync + 'static>(
        &mut self,
        a: SecretFixedPoint<F, RobustShare<F>>,
        b: SecretFixedPoint<F, RobustShare<F>>,
        triple: ShamirBeaverTriple<F>,
        r_bits: Vec<RobustShare<F>>,
        r_int: RobustShare<F>,
        duration: Duration,
        session_id: SessionId,
        network: Arc<N>,
    ) -> Result<SecretFixedPoint<F, RobustShare<F>>, FPError> {
        let p = if a.precision() == b.precision() {
            a.precision()
        } else {
            return Err(FPError::IncompatiblePrecision);
        };

        self.mult_node
            .init(
                session_id,
                vec![a.value().clone()],
                vec![b.value().clone()],
                vec![triple],
                network.clone(),
            )
            .await?;

        let trunc_input = self.mult_node.wait_for_result(session_id, duration).await?;

        self.mult_node.clear_store(session_id).await?;
        self.trunc_node
            .init(
                trunc_input[0].clone(),
                2 * p.k(),
                p.f(),
                r_bits,
                r_int,
                session_id,
                network,
            )
            .await?;

        let trunc_output = self
            .trunc_node
            .wait_for_result(session_id, duration)
            .await?;

        self.trunc_node.clear_store(session_id).await?;
        Ok(SecretFixedPoint::new(trunc_output))
    }
}