1use crate::{
2 AllWire, ArithmeticWireLabel, BinaryWireLabel, WireMod2,
3 util::{output_tweak, tweak2},
4 wire::{WireLabel, hash_wires},
5};
6use fancy_traits::{
7 Fancy, FancyArithmetic, FancyBinary, FancyBinaryConstant, FancyConstant, FancyEncode,
8 FancyOutput, HasModulus, is_binary,
9};
10use swanky_channel::Channel;
11use swanky_error::ErrorKind;
12use swanky_field_binary::F2;
13use vectoreyes::U8x16;
14
15pub struct Evaluator<Wire> {
20 one: Wire,
21 current_gate: usize,
22 current_output: usize,
23}
24
25impl<Wire: WireLabel> Evaluator<Wire> {
26 pub fn new() -> Self {
28 let one = Wire::from_repr(U8x16::from(1u128), 2);
30 Evaluator {
31 one,
32 current_gate: 0,
33 current_output: 0,
34 }
35 }
36
37 fn current_gate(&mut self) -> usize {
39 let current = self.current_gate;
40 self.current_gate += 1;
41 current
42 }
43
44 fn current_output(&mut self) -> usize {
46 let current = self.current_output;
47 self.current_output += 1;
48 current
49 }
50}
51
52impl<Wire: WireLabel> Default for Evaluator<Wire> {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl<W: BinaryWireLabel> FancyBinary for Evaluator<W> {
59 fn negate(&mut self, x: &Self::Item) -> Self::Item {
60 *x + self.one
61 }
62
63 fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item {
64 *x + *y
65 }
66
67 fn and(
68 &mut self,
69 A: &Self::Item,
70 B: &Self::Item,
71 channel: &mut Channel,
72 ) -> swanky_error::Result<Self::Item> {
73 let gate_num = self.current_gate();
74 let gate0 = channel.read()?;
75 let gate1 = channel.read()?;
76 Ok(W::evaluate_and_gate(gate_num, A, B, &gate0, &gate1))
77 }
78}
79
80impl FancyBinary for Evaluator<AllWire> {
81 fn negate(&mut self, x: &Self::Item) -> Self::Item {
83 is_binary!(x);
84
85 x.clone() + self.one.clone()
86 }
87
88 fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item {
89 is_binary!(x);
90 is_binary!(y);
91
92 self.add(x, y)
93 }
94
95 fn and(
96 &mut self,
97 x: &Self::Item,
98 y: &Self::Item,
99 channel: &mut Channel,
100 ) -> swanky_error::Result<Self::Item> {
101 if let (AllWire::Mod2(A), AllWire::Mod2(B)) = (x, y) {
102 let gate_num = self.current_gate();
103 let gate0 = channel.read()?;
104 let gate1 = channel.read()?;
105 return Ok(AllWire::Mod2(WireMod2::evaluate_and_gate(
106 gate_num, A, B, &gate0, &gate1,
107 )));
108 }
109
110 is_binary!(x);
112 is_binary!(y);
113
114 unreachable!()
116 }
117}
118
119impl<Wire: WireLabel + ArithmeticWireLabel> FancyArithmetic for Evaluator<Wire> {
120 fn add(&mut self, x: &Wire, y: &Wire) -> Wire {
121 assert_eq!(x.modulus(), y.modulus());
122 x.clone() + y.clone()
123 }
124
125 fn sub(&mut self, x: &Wire, y: &Wire) -> Wire {
126 assert_eq!(x.modulus(), y.modulus());
127 x.clone() - y.clone()
128 }
129
130 fn cmul(&mut self, x: &Wire, c: u16) -> Wire {
131 x.clone() * c
132 }
133
134 fn mul(&mut self, A: &Wire, B: &Wire, channel: &mut Channel) -> swanky_error::Result<Wire> {
135 if A.modulus() < B.modulus() {
136 return self.mul(B, A, channel);
137 }
138 let q = A.modulus();
139 let qb = B.modulus();
140 let unequal = q != qb;
141 let ngates = q as usize + qb as usize - 2 + unequal as usize;
142 let mut gate = Vec::with_capacity(ngates);
143 {
144 for _ in 0..ngates {
145 let block = channel.read::<U8x16>()?;
146 gate.push(block);
147 }
148 }
149 let gate_num = self.current_gate();
150 let g = tweak2(gate_num as u64, 0);
151
152 let [hashA, hashB] = hash_wires([A, B], g);
153
154 let L = if A.color() == 0 {
156 Wire::hash_to_mod(hashA, q)
157 } else {
158 let ct_left = gate[A.color() as usize - 1];
159 Wire::from_repr(ct_left ^ hashA, q)
160 };
161
162 let R = if B.color() == 0 {
164 Wire::hash_to_mod(hashB, q)
165 } else {
166 let ct_right = gate[(q + B.color()) as usize - 2];
167 Wire::from_repr(ct_right ^ hashB, q)
168 };
169
170 let new_b_color = if unequal {
173 let minitable = *gate.last().unwrap();
174 let ct = u128::from(minitable) >> (B.color() * 16);
175 let pt = u128::from(B.hash(tweak2(gate_num as u64, 1))) ^ ct;
176 pt as u16
177 } else {
178 B.color()
179 };
180
181 let res = L + R + A.clone() * new_b_color;
182 Ok(res)
183 }
184}
185
186impl<Wire: WireLabel> Fancy for Evaluator<Wire> {
187 type Item = Wire;
188}
189
190impl<Wire: WireLabel> FancyConstant for Evaluator<Wire> {
191 fn constant(&mut self, _: u16, q: u16, channel: &mut Channel) -> swanky_error::Result<Wire> {
192 Ok(Wire::from_repr(channel.read()?, q))
193 }
194}
195
196impl<Wire: WireLabel> FancyBinaryConstant for Evaluator<Wire> {
197 fn constant(&mut self, x: F2) -> Self::Item {
198 if x.into() {
199 self.one.clone()
200 } else {
201 Default::default()
203 }
204 }
205}
206
207impl<Wire: WireLabel> FancyEncode for Evaluator<Wire> {
208 fn encode_many(
209 &mut self,
210 _values: &[u16],
211 _moduli: &[u16],
212 _: &mut Channel,
213 ) -> swanky_error::Result<Vec<Self::Item>> {
214 unimplemented!("Evaluator cannot encode values")
215 }
216
217 fn receive_many(
218 &mut self,
219 moduli: &[u16],
220 channel: &mut Channel,
221 ) -> swanky_error::Result<Vec<Self::Item>> {
222 moduli
223 .iter()
224 .map(|q| {
225 let block = channel.read()?;
226 Ok(Wire::from_repr(block, *q))
227 })
228 .collect()
229 }
230}
231
232impl<Wire: WireLabel> FancyOutput for Evaluator<Wire> {
233 fn output(&mut self, x: &Wire, channel: &mut Channel) -> swanky_error::Result<Option<u16>> {
234 let q = x.modulus();
235 let i = self.current_output();
236
237 let mut ct = Vec::with_capacity(q as usize);
239 for _ in 0..q {
240 let block = channel.read()?;
241 ct.push(block);
242 }
243
244 let mut decoded = None;
246 for k in 0..q {
247 let hashed_wire = x.hash(output_tweak(i, k));
248 if hashed_wire == ct[k as usize] {
249 decoded = Some(k);
250 break;
251 }
252 }
253
254 if let Some(output) = decoded {
255 Ok(Some(output))
256 } else {
257 swanky_error::bail!(ErrorKind::OtherError, "Decoding failed");
258 }
259 }
260}