1use crate::{
2 FancyBinary, HasModulus,
3 circuit::{CircuitBuilder, CircuitRef, CircuitType, EvaluableCircuit, GateType},
4};
5use swanky_channel::Channel;
6
7#[derive(Clone, Debug, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct BinaryCircuit {
11 pub(crate) gates: Vec<BinaryGate>,
12 pub(crate) garbler_input_refs: Vec<CircuitRef>,
13 pub(crate) evaluator_input_refs: Vec<CircuitRef>,
14 pub(crate) const_refs: Vec<CircuitRef>,
15 pub(crate) output_refs: Vec<CircuitRef>,
16 pub(crate) num_nonfree_gates: usize,
17}
18
19#[derive(Clone, Debug, PartialEq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub enum BinaryGate {
26 GarblerInput {
28 id: usize,
30 },
31 EvaluatorInput {
33 id: usize,
35 },
36 Constant {
38 val: u16,
40 },
41
42 Xor {
44 xref: CircuitRef,
46
47 yref: CircuitRef,
49
50 out: Option<usize>,
52 },
53 And {
55 xref: CircuitRef,
57
58 yref: CircuitRef,
60
61 id: usize,
63
64 out: Option<usize>,
66 },
67 Inv {
69 xref: CircuitRef,
71
72 out: Option<usize>,
74 },
75}
76
77impl std::fmt::Display for BinaryGate {
78 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
79 match self {
80 Self::GarblerInput { id } => write!(f, "GarblerInput {}", id),
81 Self::EvaluatorInput { id } => write!(f, "EvaluatorInput {}", id),
82 Self::Constant { val } => write!(f, "Constant {}", val),
83 Self::Xor { xref, yref, out } => write!(f, "Xor ( {}, {}, {:?} )", xref, yref, out),
84 Self::And {
85 xref,
86 yref,
87 id,
88 out,
89 } => write!(f, "And ( {}, {}, {}, {:?} )", xref, yref, id, out),
90 Self::Inv { xref, out } => write!(f, "Inv ( {}, {:?} )", xref, out),
91 }
92 }
93}
94
95impl<F: FancyBinary> EvaluableCircuit<F> for BinaryCircuit {
96 fn eval_to_wirelabels(
97 &self,
98 f: &mut F,
99 garbler_inputs: &[F::Item],
100 evaluator_inputs: &[F::Item],
101 channel: &mut Channel,
102 ) -> swanky_error::Result<Vec<F::Item>> {
103 let mut cache: Vec<Option<F::Item>> = vec![None; self.gates.len()];
104 for (i, gate) in self.gates.iter().enumerate() {
105 let q = 2;
106 let (zref_, val) = match *gate {
107 BinaryGate::GarblerInput { id } => (None, garbler_inputs[id].clone()),
108 BinaryGate::EvaluatorInput { id } => {
109 assert!(
110 id < evaluator_inputs.len(),
111 "id={} ev_inps.len()={}",
112 id,
113 evaluator_inputs.len()
114 );
115 (None, evaluator_inputs[id].clone())
116 }
117 BinaryGate::Constant { val } => (None, f.constant(val, q, channel)?),
118 BinaryGate::Inv { xref, out } => (out, f.negate(cache[xref.ix].as_ref().unwrap())),
119 BinaryGate::Xor { xref, yref, out } => (
120 out,
121 f.xor(
122 cache[xref.ix].as_ref().unwrap(),
123 cache[yref.ix].as_ref().unwrap(),
124 ),
125 ),
126 BinaryGate::And {
127 xref, yref, out, ..
128 } => (
129 out,
130 f.and(
131 cache[xref.ix].as_ref().unwrap(),
132 cache[yref.ix].as_ref().unwrap(),
133 channel,
134 )?,
135 ),
136 };
137 cache[zref_.unwrap_or(i)] = Some(val);
138 }
139 let mut outputs = Vec::with_capacity(self.noutputs());
140 for r in self.get_output_refs().iter() {
141 let wirelabel = cache[r.ix].as_ref().unwrap();
142 outputs.push(wirelabel.clone());
143 }
144 Ok(outputs)
145 }
146}
147
148impl GateType for BinaryGate {
149 fn make_constant(val: u16) -> Self {
150 Self::Constant { val }
151 }
152
153 fn make_garbler_input(id: usize) -> Self {
154 Self::GarblerInput { id }
155 }
156
157 fn make_evaluator_input(id: usize) -> Self {
158 Self::EvaluatorInput { id }
159 }
160}
161
162impl CircuitType for BinaryCircuit {
163 type Gate = BinaryGate;
164
165 fn new(ngates: Option<usize>) -> Self {
166 let gates = Vec::with_capacity(ngates.unwrap_or(0));
167 Self {
168 gates,
169 garbler_input_refs: Vec::new(),
170 evaluator_input_refs: Vec::new(),
171 const_refs: Vec::new(),
172 output_refs: Vec::new(),
173 num_nonfree_gates: 0,
174 }
175 }
176
177 fn push_gates(&mut self, gate: Self::Gate) {
178 self.gates.push(gate)
179 }
180
181 fn push_const_ref(&mut self, xref: CircuitRef) {
182 self.const_refs.push(xref)
183 }
184
185 fn push_output_ref(&mut self, xref: CircuitRef) {
186 self.output_refs.push(xref)
187 }
188
189 fn push_garbler_input_ref(&mut self, xref: CircuitRef) {
190 self.garbler_input_refs.push(xref)
191 }
192
193 fn push_modulus(&mut self, modulus: u16) {
194 assert_eq!(modulus, 2);
195 }
196
197 fn push_evaluator_input_ref(&mut self, xref: CircuitRef) {
198 self.evaluator_input_refs.push(xref)
199 }
200
201 fn increment_nonfree_gates(&mut self) {
202 self.num_nonfree_gates += 1;
203 }
204
205 fn get_num_nonfree_gates(&self) -> usize {
206 self.num_nonfree_gates
207 }
208
209 fn get_output_refs(&self) -> &[CircuitRef] {
210 &self.output_refs
211 }
212
213 fn get_garbler_input_refs(&self) -> &[CircuitRef] {
214 &self.garbler_input_refs
215 }
216
217 fn get_evaluator_input_refs(&self) -> &[CircuitRef] {
218 &self.evaluator_input_refs
219 }
220
221 fn garbler_input_mod(&self, _: usize) -> u16 {
222 2
223 }
224
225 fn evaluator_input_mod(&self, _: usize) -> u16 {
226 2
227 }
228}
229
230impl FancyBinary for CircuitBuilder<BinaryCircuit> {
231 fn xor(&mut self, xref: &Self::Item, yref: &Self::Item) -> Self::Item {
232 let gate = BinaryGate::Xor {
233 xref: *xref,
234 yref: *yref,
235 out: None,
236 };
237
238 self.gate(gate, xref.modulus())
239 }
240
241 fn negate(&mut self, xref: &Self::Item) -> Self::Item {
242 let gate = BinaryGate::Inv {
243 xref: *xref,
244 out: None,
245 };
246 self.gate(gate, xref.modulus())
247 }
248
249 fn and(
250 &mut self,
251 xref: &Self::Item,
252 yref: &Self::Item,
253 _: &mut Channel,
254 ) -> swanky_error::Result<Self::Item> {
255 let gate = BinaryGate::And {
256 xref: *xref,
257 yref: *yref,
258 id: self.get_next_ciphertext_id(),
259 out: None,
260 };
261
262 Ok(self.gate(gate, xref.modulus()))
263 }
264}