fancy_garbling/twopac/semihonest/
evaluator.rs

1use crate::{
2    AllWire, ArithmeticWire, Evaluator as Ev, Fancy, FancyArithmetic, FancyBinary, FancyInput,
3    FancyReveal, WireMod2, errors::TwopacError, wire::WireLabel,
4};
5use rand::{CryptoRng, Rng};
6use swanky_adversary::SemiHonest;
7use swanky_block::Block;
8use swanky_channel_legacy::AbstractChannel;
9use swanky_ot_traits::Receiver as OtReceiver;
10
11/// Semi-honest evaluator.
12pub struct Evaluator<C, RNG, OT, Wire> {
13    evaluator: Ev<C, Wire>,
14    ot: OT,
15    rng: RNG,
16}
17
18impl<C, RNG, OT, Wire> Evaluator<C, RNG, OT, Wire> {}
19
20impl<
21    C: AbstractChannel,
22    RNG: CryptoRng + Rng,
23    OT: OtReceiver<Msg = Block> + SemiHonest,
24    Wire: WireLabel,
25> Evaluator<C, RNG, OT, Wire>
26{
27    /// Make a new `Evaluator`.
28    pub fn new(mut channel: C, mut rng: RNG) -> Result<Self, TwopacError> {
29        let ot = OT::init(&mut channel, &mut rng)?;
30        let evaluator = Ev::new(channel);
31        Ok(Self { evaluator, ot, rng })
32    }
33
34    /// Get a reference to the internal channel.
35    pub fn get_channel(&mut self) -> &mut C {
36        &mut self.evaluator.channel
37    }
38
39    fn run_ot(&mut self, inputs: &[bool]) -> Result<Vec<Block>, TwopacError> {
40        self.ot
41            .receive(&mut self.evaluator.channel, inputs, &mut self.rng)
42            .map_err(TwopacError::from)
43    }
44}
45
46impl<
47    C: AbstractChannel,
48    RNG: CryptoRng + Rng,
49    OT: OtReceiver<Msg = Block> + SemiHonest,
50    Wire: WireLabel,
51> FancyInput for Evaluator<C, RNG, OT, Wire>
52{
53    type Item = Wire;
54    type Error = TwopacError;
55
56    /// Receive a garbler input wire.
57    fn receive(&mut self, modulus: u16) -> Result<Wire, TwopacError> {
58        let w = self.evaluator.read_wire(modulus)?;
59        Ok(w)
60    }
61
62    /// Receive garbler input wires.
63    fn receive_many(&mut self, moduli: &[u16]) -> Result<Vec<Wire>, TwopacError> {
64        moduli.iter().map(|q| self.receive(*q)).collect()
65    }
66
67    /// Perform OT and obtain wires for the evaluator's inputs.
68    fn encode_many(&mut self, inputs: &[u16], moduli: &[u16]) -> Result<Vec<Wire>, TwopacError> {
69        let mut lens = Vec::new();
70        let mut bs = Vec::new();
71        for (x, q) in inputs.iter().zip(moduli.iter()) {
72            let len = f32::from(*q).log(2.0).ceil() as usize;
73            for b in (0..len).map(|i| x & (1 << i) != 0) {
74                bs.push(b);
75            }
76            lens.push(len);
77        }
78        let wires = self.run_ot(&bs)?;
79        let mut start = 0;
80        Ok(lens
81            .into_iter()
82            .zip(moduli.iter())
83            .map(|(len, q)| {
84                let range = start..start + len;
85                let chunk = &wires[range];
86                start += len;
87                combine(chunk, *q)
88            })
89            .collect::<Vec<Wire>>())
90    }
91}
92
93fn combine<Wire: WireLabel>(wires: &[Block], q: u16) -> Wire {
94    wires.iter().enumerate().fold(Wire::zero(q), |acc, (i, w)| {
95        let w = Wire::from_block(*w, q);
96        acc.plus(&w.cmul(1 << i))
97    })
98}
99
100impl<C: AbstractChannel, RNG, OT> FancyBinary for Evaluator<C, RNG, OT, WireMod2> {
101    fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
102        self.evaluator.and(x, y).map_err(Self::Error::from)
103    }
104
105    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
106        self.evaluator.xor(x, y).map_err(Self::Error::from)
107    }
108
109    fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
110        self.evaluator.negate(x).map_err(Self::Error::from)
111    }
112}
113
114impl<C: AbstractChannel, RNG, OT> FancyBinary for Evaluator<C, RNG, OT, AllWire> {
115    fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
116        self.evaluator.and(x, y).map_err(Self::Error::from)
117    }
118
119    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
120        self.evaluator.xor(x, y).map_err(Self::Error::from)
121    }
122
123    fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
124        self.evaluator.negate(x).map_err(Self::Error::from)
125    }
126}
127
128impl<C: AbstractChannel, RNG, OT, Wire: WireLabel + ArithmeticWire> FancyArithmetic
129    for Evaluator<C, RNG, OT, Wire>
130{
131    fn add(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
132        self.evaluator.add(x, y).map_err(Self::Error::from)
133    }
134
135    fn sub(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
136        self.evaluator.sub(x, y).map_err(Self::Error::from)
137    }
138
139    fn cmul(&mut self, x: &Wire, c: u16) -> Result<Self::Item, Self::Error> {
140        self.evaluator.cmul(x, c).map_err(Self::Error::from)
141    }
142
143    fn mul(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
144        self.evaluator.mul(x, y).map_err(Self::Error::from)
145    }
146
147    fn proj(&mut self, x: &Wire, q: u16, tt: Option<Vec<u16>>) -> Result<Self::Item, Self::Error> {
148        self.evaluator.proj(x, q, tt).map_err(Self::Error::from)
149    }
150}
151
152impl<C: AbstractChannel, RNG, OT, Wire: WireLabel> Fancy for Evaluator<C, RNG, OT, Wire> {
153    type Item = Wire;
154    type Error = TwopacError;
155
156    fn constant(&mut self, x: u16, q: u16) -> Result<Self::Item, Self::Error> {
157        self.evaluator.constant(x, q).map_err(Self::Error::from)
158    }
159
160    fn output(&mut self, x: &Wire) -> Result<Option<u16>, Self::Error> {
161        self.evaluator.output(x).map_err(Self::Error::from)
162    }
163}
164
165impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT, Wire: WireLabel> FancyReveal
166    for Evaluator<C, RNG, OT, Wire>
167{
168    fn reveal(&mut self, x: &Self::Item) -> Result<u16, Self::Error> {
169        self.evaluator.reveal(x).map_err(Self::Error::from)
170    }
171}
172
173impl<C: AbstractChannel, RNG, OT, Wire> SemiHonest for Evaluator<C, RNG, OT, Wire> {}