fancy_garbling/circuits/binary/
binary_to_unary.rs1use crate::{BinaryBundle, FancyBinary, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6#[derive(Default)]
11pub struct BinaryToUnary<'a>(PhantomData<&'a ()>);
12
13impl<'a> BinaryToUnary<'a> {
14 pub fn new() -> Self {
16 Default::default()
17 }
18}
19
20impl<'a, F: FancyBinary> Circuit<F> for BinaryToUnary<'a>
21where
22 F::Item: 'a,
23{
24 type Input = &'a BinaryBundle<F::Item>;
25 type Output = Vec<F::Item>;
26
27 fn execute(
28 &self,
29 backend: &mut F,
30 inputs: Self::Input,
31 channel: &mut Channel,
32 ) -> Result<Self::Output> {
33 let wires = inputs.wires();
34 let nbits = wires.len();
35 assert!(nbits <= 8, "wire bitlength is too large");
36
37 let mut outs = Vec::with_capacity(1 << nbits);
38
39 for ix in 0..1 << nbits {
40 let mut acc = wires[0].clone();
41 if (ix & 1) == 0 {
42 acc = backend.negate(&acc);
43 }
44 for (i, w) in wires.iter().enumerate().skip(1) {
45 if ((ix >> i) & 1) > 0 {
46 acc = backend.and(&acc, w, channel)?;
47 } else {
48 let not_w = backend.negate(w);
49 acc = backend.and(&acc, ¬_w, channel)?;
50 }
51 }
52 outs.push(acc);
53 }
54
55 Ok(outs)
56 }
57}
58
59#[cfg(test)]
60mod test {
61 use crate::{
62 circuits::binary::BinaryToUnary,
63 dummy::{Dummy, DummyVal},
64 };
65 use rand::{Rng, thread_rng};
66
67 #[test]
68 fn binary_to_unary() {
69 let mut rng = thread_rng();
70 let nbits = 8;
71 let q = 1 << nbits;
72
73 for _ in 0..16 {
74 let x = rng.r#gen::<u128>() % q;
75 let x_input = DummyVal::to_binary(x, nbits);
76 let output = Dummy::eval(&BinaryToUnary::new(), &x_input).unwrap();
77 for (i, y) in output.into_iter().enumerate() {
78 if i as u128 == x {
79 assert_eq!(y.val(), 1);
80 } else {
81 assert_eq!(y.val(), 0);
82 }
83 }
84 }
85 }
86}