fancy_garbling/twopac/semihonest/
evaluator.rs1use 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
11pub 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 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 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 fn receive(&mut self, modulus: u16) -> Result<Wire, TwopacError> {
58 let w = self.evaluator.read_wire(modulus)?;
59 Ok(w)
60 }
61
62 fn receive_many(&mut self, moduli: &[u16]) -> Result<Vec<Wire>, TwopacError> {
64 moduli.iter().map(|q| self.receive(*q)).collect()
65 }
66
67 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> {}