1use rand::{CryptoRng, Rng, RngCore};
7use swanky_channel::Channel;
8use swanky_error::{ErrorKind, Result};
9
10use crate::{
11 BinaryBundle, BinaryGadgets, Bundle, CrtBundle, CrtGadgets, FancyArithmetic, FancyBinary,
12 FancyEncode, FancyOutput, FancyProj, check_binary,
13 circuit::Circuit,
14 fancy::{Fancy, HasModulus},
15 util::{as_mixed_radix, crt_inv_factor, u128_from_bits},
16};
17
18pub struct Dummy;
20
21#[derive(Clone, Copy, Debug, PartialEq)]
23pub struct DummyVal {
24 val: u16,
25 modulus: u16,
26}
27
28impl HasModulus for DummyVal {
29 fn modulus(&self) -> u16 {
30 self.modulus
31 }
32}
33
34impl DummyVal {
35 pub fn new(val: u16, modulus: u16) -> Self {
37 Self {
38 val: val % modulus,
39 modulus,
40 }
41 }
42
43 pub fn new_bool(val: bool) -> Self {
45 Self {
46 val: val as u16,
47 modulus: 2,
48 }
49 }
50
51 pub fn val(&self) -> u16 {
53 self.val
54 }
55
56 pub fn rand_bool<RNG: CryptoRng + RngCore>(rng: &mut RNG) -> Self {
58 Self::rand(2, rng)
59 }
60
61 pub fn rand<RNG: CryptoRng + RngCore>(modulus: u16, rng: &mut RNG) -> Self {
63 Self::new(rng.r#gen::<u16>(), modulus)
64 }
65
66 pub fn to_crt(value: u128, modulus: u128) -> CrtBundle<Self> {
68 let mut dummy = Dummy::new();
69 Channel::with(std::io::empty(), |channel| {
70 dummy.crt_encode(value, modulus, channel)
71 })
72 .unwrap()
73 }
74
75 pub fn from_crt(crt: &Bundle<Self>, modulus: u128) -> u128 {
78 let crt = crt.wires().iter().map(|w| w.val()).collect::<Vec<_>>();
79 crt_inv_factor(&crt, modulus)
80 }
81
82 pub fn to_binary(value: u128, nbits: usize) -> BinaryBundle<Self> {
84 let mut dummy = Dummy::new();
85 Channel::with(std::io::empty(), |channel| {
86 dummy.bin_encode(value, nbits, channel)
87 })
88 .unwrap()
89 }
90
91 pub fn from_binary(bin: &Bundle<Self>) -> u128 {
94 let bin = bin.wires().iter().map(|w| w.val()).collect::<Vec<_>>();
95 u128_from_bits(&bin)
96 }
97
98 pub fn to_mixed_radix(value: u128, radii: &[u16]) -> CrtBundle<Self> {
101 let mixed = as_mixed_radix(value, radii);
102 let mixed = mixed
103 .into_iter()
104 .zip(radii)
105 .map(|(x, q)| DummyVal::new(x, *q))
106 .collect::<Vec<_>>();
107 CrtBundle::new(mixed)
108 }
109
110 pub fn from_mixed_radix(bundle: &CrtBundle<Self>) -> u128 {
113 let mut x: u128 = 0;
114 for wire in bundle.wires().iter().rev() {
115 let (xp, overflow) = x.overflowing_mul(wire.modulus as u128);
116 assert!(!overflow);
117 x = xp + wire.val as u128;
118 }
119 x
120 }
121}
122
123impl Dummy {
124 pub fn new() -> Dummy {
126 Dummy {}
127 }
128
129 pub fn eval<C: Circuit<Dummy>>(circuit: &C, inputs: C::Input) -> Result<C::Output> {
131 let mut dummy = Dummy::new();
132 Channel::with(std::io::empty(), |c| circuit.execute(&mut dummy, inputs, c))
133 }
134}
135
136impl Default for Dummy {
137 fn default() -> Self {
138 Self::new()
139 }
140}
141
142impl FancyBinary for Dummy {
143 fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item {
144 check_binary!(x);
145 check_binary!(y);
146
147 self.add(x, y)
148 }
149
150 fn and(
151 &mut self,
152 x: &Self::Item,
153 y: &Self::Item,
154 channel: &mut Channel,
155 ) -> swanky_error::Result<Self::Item> {
156 check_binary!(x);
157 check_binary!(y);
158
159 self.mul(x, y, channel)
160 }
161
162 fn negate(&mut self, x: &Self::Item) -> Self::Item {
163 check_binary!(x);
164
165 self.xor(x, &DummyVal::new(1, 2))
166 }
167}
168
169impl FancyArithmetic for Dummy {
170 fn add(&mut self, x: &DummyVal, y: &DummyVal) -> DummyVal {
171 assert_eq!(x.modulus(), y.modulus());
172 DummyVal {
173 val: (x.val + y.val) % x.modulus,
174 modulus: x.modulus,
175 }
176 }
177
178 fn sub(&mut self, x: &DummyVal, y: &DummyVal) -> DummyVal {
179 assert_eq!(x.modulus(), y.modulus());
180 DummyVal {
181 val: (x.modulus + x.val - y.val) % x.modulus,
182 modulus: x.modulus,
183 }
184 }
185
186 fn cmul(&mut self, x: &DummyVal, c: u16) -> DummyVal {
187 DummyVal {
188 val: (x.val * c) % x.modulus,
189 modulus: x.modulus,
190 }
191 }
192
193 fn mul(
194 &mut self,
195 x: &DummyVal,
196 y: &DummyVal,
197 _channel: &mut Channel,
198 ) -> swanky_error::Result<DummyVal> {
199 if x.modulus < y.modulus {
200 return self.mul(y, x, _channel);
201 }
202 Ok(DummyVal {
203 val: x.val * y.val % x.modulus,
204 modulus: x.modulus,
205 })
206 }
207}
208
209impl FancyProj for Dummy {
210 fn proj(
211 &mut self,
212 x: &DummyVal,
213 modulus: u16,
214 tt: Option<Vec<u16>>,
215 _: &mut Channel,
216 ) -> swanky_error::Result<DummyVal> {
217 assert!(tt.is_some(), "`tt` must not be `None`");
218 let tt = tt.unwrap();
219 assert!(
220 tt.len() >= x.modulus() as usize,
221 "`tt` not large enough for `x`s modulus"
222 );
223 assert!(
224 tt.iter().all(|&x| x < modulus),
225 "`tt` value larger than `q`"
226 );
227 let val = tt[x.val as usize];
228 Ok(DummyVal { val, modulus })
229 }
230}
231
232impl Fancy for Dummy {
233 type Item = DummyVal;
234
235 fn constant(
236 &mut self,
237 val: u16,
238 modulus: u16,
239 _: &mut Channel,
240 ) -> swanky_error::Result<DummyVal> {
241 Ok(DummyVal { val, modulus })
242 }
243}
244
245impl FancyEncode for Dummy {
246 fn encode_many(
247 &mut self,
248 xs: &[u16],
249 moduli: &[u16],
250 _: &mut Channel,
251 ) -> swanky_error::Result<Vec<DummyVal>> {
252 assert_eq!(xs.len(), moduli.len());
253 Ok(xs
254 .iter()
255 .zip(moduli.iter())
256 .map(|(x, q)| DummyVal::new(*x, *q))
257 .collect())
258 }
259
260 fn receive_many(
261 &mut self,
262 _moduli: &[u16],
263 _: &mut Channel,
264 ) -> swanky_error::Result<Vec<DummyVal>> {
265 swanky_error::bail!(
267 ErrorKind::UnsupportedError,
268 "`receive_many` is undefined for `Dummy`"
269 );
270 }
271}
272
273impl FancyOutput for Dummy {
274 fn output(&mut self, x: &DummyVal, _: &mut Channel) -> swanky_error::Result<Option<u16>> {
275 Ok(Some(x.val))
276 }
277}