1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! Multiplication triples and providers.

use crate::circuit::ExecutableCircuit;
use crate::executor::GateOutputs;
use crate::protocols::{FunctionDependentSetup, Protocol};
use crate::utils::{BoxError, ErasedError};
use async_trait::async_trait;
use std::error::Error;

pub mod arithmetic;
pub mod boolean;
pub mod storage;

/// Provides a source of multiplication triples.
#[async_trait]
pub trait MTProvider {
    type Output;
    type Error;

    async fn precompute_mts(&mut self, amount: usize) -> Result<(), Self::Error>;

    async fn request_mts(&mut self, amount: usize) -> Result<Self::Output, Self::Error>;

    fn into_dyn(
        self,
    ) -> Box<dyn MTProvider<Output = Self::Output, Error = BoxError> + Send + 'static>
    where
        Self: Sized + Send + 'static,
        Self::Error: Error + Send + Sync + 'static,
    {
        Box::new(ErasedError(self))
    }
}

#[async_trait]
impl<Mtp: MTProvider + Send> MTProvider for &mut Mtp {
    type Output = Mtp::Output;
    type Error = Mtp::Error;

    async fn precompute_mts(&mut self, amount: usize) -> Result<(), Self::Error> {
        (**self).precompute_mts(amount).await
    }

    async fn request_mts(&mut self, amount: usize) -> Result<Self::Output, Self::Error> {
        (**self).request_mts(amount).await
    }
}

#[async_trait]
impl<Out, Err> MTProvider for Box<dyn MTProvider<Output = Out, Error = Err> + Send> {
    type Output = Out;
    type Error = Err;

    async fn precompute_mts(&mut self, amount: usize) -> Result<(), Self::Error> {
        (**self).precompute_mts(amount).await
    }

    async fn request_mts(&mut self, amount: usize) -> Result<Self::Output, Self::Error> {
        (**self).request_mts(amount).await
    }
}

// TODO I think this impl would disallow downstream crates to impl FunctionDependentSetup
//  on second thought, this might not be the case
#[async_trait]
impl<P, Idx, Mtp> FunctionDependentSetup<P, Idx> for Mtp
where
    P: Protocol,
    Idx: Send + Sync,
    Mtp: MTProvider<Output = P::SetupStorage> + Send,
{
    type Error = Mtp::Error;

    async fn setup(
        &mut self,
        _shares: &GateOutputs<P::ShareStorage>,
        _circuit: &ExecutableCircuit<P::Plain, P::Gate, Idx>,
    ) -> Result<(), Self::Error> {
        // TODO, should this call precompute_mts ? Mhh, currently I call it explicitly
        //  when I want to perform FIP
        Ok(())
    }

    async fn request_setup_output(&mut self, count: usize) -> Result<P::SetupStorage, Self::Error> {
        self.request_mts(count).await
    }
}

#[async_trait]
impl<MTP> MTProvider for ErasedError<MTP>
where
    MTP: MTProvider + Send,
    <MTP as MTProvider>::Error: Error + Send + Sync + 'static,
{
    type Output = MTP::Output;
    type Error = BoxError;

    async fn precompute_mts(&mut self, amount: usize) -> Result<(), Self::Error> {
        self.0
            .precompute_mts(amount)
            .await
            .map_err(BoxError::from_err)
    }

    async fn request_mts(&mut self, amount: usize) -> Result<Self::Output, Self::Error> {
        self.0.request_mts(amount).await.map_err(BoxError::from_err)
    }
}