1use crate::{FancyBinary, circuit::CircuitExecutor};
2use swanky_channel::Channel;
3
4#[derive(Clone, Debug, PartialEq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct BinaryCircuit {
8 pub(crate) gates: Vec<BinaryGate>,
9 pub(crate) input_refs: Vec<usize>,
10 pub(crate) const_refs: Vec<usize>,
11 pub(crate) output_refs: Vec<usize>,
12 pub(crate) num_nonfree_gates: usize,
13}
14
15impl<F: FancyBinary> CircuitExecutor<F> for BinaryCircuit {
16 fn execute(
17 &self,
18 backend: &mut F,
19 inputs: &[<F as crate::Fancy>::Item],
20 channel: &mut Channel,
21 ) -> swanky_error::Result<Vec<<F as crate::Fancy>::Item>> {
22 assert_eq!(
23 inputs.len(),
24 <BinaryCircuit as CircuitExecutor<F>>::ninputs(self)
25 );
26 self.eval_to_wirelabels(backend, inputs, channel)
27 }
28
29 fn ninputs(&self) -> usize {
30 self.input_refs.len()
31 }
32
33 fn modulus(&self, _: usize) -> u16 {
34 2
35 }
36}
37
38#[derive(Clone, Debug, PartialEq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44pub enum BinaryGate {
45 Input {
47 id: usize,
49 },
50 Constant {
52 val: u16,
54 },
55
56 Xor {
58 xref: usize,
60
61 yref: usize,
63
64 out: Option<usize>,
66 },
67 And {
69 xref: usize,
71
72 yref: usize,
74
75 id: usize,
77
78 out: Option<usize>,
80 },
81 Inv {
83 xref: usize,
85
86 out: Option<usize>,
88 },
89}
90
91impl std::fmt::Display for BinaryGate {
92 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
93 match self {
94 Self::Input { id } => write!(f, "Input {}", id),
95 Self::Constant { val } => write!(f, "Constant {}", val),
96 Self::Xor { xref, yref, out } => write!(f, "Xor ( {}, {}, {:?} )", xref, yref, out),
97 Self::And {
98 xref,
99 yref,
100 id,
101 out,
102 } => write!(f, "And ( {}, {}, {}, {:?} )", xref, yref, id, out),
103 Self::Inv { xref, out } => write!(f, "Inv ( {}, {:?} )", xref, out),
104 }
105 }
106}
107
108impl BinaryCircuit {
109 pub fn new(ngates: Option<usize>) -> Self {
112 let gates = if let Some(n) = ngates {
113 Vec::with_capacity(n)
114 } else {
115 Vec::new()
116 };
117 Self {
118 gates,
119 input_refs: Vec::new(),
120 const_refs: Vec::new(),
121 output_refs: Vec::new(),
122 num_nonfree_gates: 0,
123 }
124 }
125
126 fn eval_to_wirelabels<F: FancyBinary>(
127 &self,
128 f: &mut F,
129 inputs: &[F::Item],
130 channel: &mut Channel,
131 ) -> swanky_error::Result<Vec<F::Item>> {
132 let mut cache: Vec<Option<F::Item>> = vec![None; self.gates.len()];
133 for (i, gate) in self.gates.iter().enumerate() {
134 let q = 2;
135 let (zref_, val) = match *gate {
136 BinaryGate::Input { id } => (None, inputs[id].clone()),
137 BinaryGate::Constant { val } => (None, f.constant(val, q, channel)?),
138 BinaryGate::Inv { xref, out } => (out, f.negate(cache[xref].as_ref().unwrap())),
139 BinaryGate::Xor { xref, yref, out } => (
140 out,
141 f.xor(cache[xref].as_ref().unwrap(), cache[yref].as_ref().unwrap()),
142 ),
143 BinaryGate::And {
144 xref, yref, out, ..
145 } => (
146 out,
147 f.and(
148 cache[xref].as_ref().unwrap(),
149 cache[yref].as_ref().unwrap(),
150 channel,
151 )?,
152 ),
153 };
154 cache[zref_.unwrap_or(i)] = Some(val);
155 }
156 let mut outputs = Vec::with_capacity(self.output_refs.len());
157 for r in self.output_refs.iter() {
158 let wirelabel = cache[*r].as_ref().unwrap();
159 outputs.push(wirelabel.clone());
160 }
161 Ok(outputs)
162 }
163}