Skip to main content

fancy_garbling/circuits/binary/
binary_greater_than_or_equal.rs

1use crate::{BinaryBundle, FancyBinary, circuit::Circuit, circuits::binary::BinaryLessThan};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6/// Binary greater than or equal.
7///
8/// For [`BinaryBundle`]s `x` and `y`, return `x >= y`.
9#[derive(Default)]
10pub struct BinaryGreaterThanOrEqual<'a>(PhantomData<&'a ()>);
11
12impl<'a> BinaryGreaterThanOrEqual<'a> {
13    /// Create a new [`BinaryGreaterThanOrEqual`] circuit.
14    pub fn new() -> Self {
15        Default::default()
16    }
17}
18
19impl<'a, F: FancyBinary> Circuit<F> for BinaryGreaterThanOrEqual<'a>
20where
21    F::Item: 'a,
22{
23    type Input = (&'a BinaryBundle<F::Item>, &'a BinaryBundle<F::Item>);
24    type Output = F::Item;
25
26    fn execute(
27        &self,
28        backend: &mut F,
29        inputs: Self::Input,
30        channel: &mut Channel,
31    ) -> Result<Self::Output> {
32        let z = BinaryLessThan::new().execute(backend, inputs, channel)?;
33        Ok(backend.negate(&z))
34    }
35}
36
37pub mod test {
38    use super::*;
39    use crate::circuit::CircuitInputMapper;
40
41    /// Circuit for testing [`BinaryGreaterThanOrEqual`].
42    pub struct TestBinaryGreaterThanOrEqual(pub usize);
43    impl<F: FancyBinary> Circuit<F> for TestBinaryGreaterThanOrEqual {
44        type Input = (BinaryBundle<F::Item>, BinaryBundle<F::Item>);
45        type Output = F::Item;
46
47        fn execute(
48            &self,
49            backend: &mut F,
50            inputs: Self::Input,
51            channel: &mut Channel,
52        ) -> Result<Self::Output> {
53            BinaryGreaterThanOrEqual::new().execute(backend, (&inputs.0, &inputs.1), channel)
54        }
55    }
56
57    impl<F: FancyBinary> CircuitInputMapper<F> for TestBinaryGreaterThanOrEqual {
58        fn map(&self, inputs: Vec<<F as crate::Fancy>::Item>) -> Self::Input {
59            assert_eq!(inputs.len(), self.0 * 2);
60            let (x, y) = inputs.split_at(self.0);
61            (BinaryBundle::new(x.to_vec()), BinaryBundle::new(y.to_vec()))
62        }
63
64        fn ninputs(&self) -> usize {
65            self.0 * 2
66        }
67
68        fn modulus(&self, _: usize) -> u16 {
69            2
70        }
71    }
72
73    #[test]
74    fn binary_greater_than_or_equal() {
75        use crate::dummy::{Dummy, DummyVal};
76        use rand::Rng;
77
78        let mut rng = rand::thread_rng();
79        let nbits = 64;
80        let q = 1 << nbits;
81        let c = TestBinaryGreaterThanOrEqual(nbits);
82
83        for _ in 0..16 {
84            let x = rng.r#gen::<u128>() % q;
85            let y = rng.r#gen::<u128>() % q;
86            let x_input = DummyVal::to_binary(x, nbits);
87            let y_input = DummyVal::to_binary(y, nbits);
88            let output = Dummy::eval(&c, (x_input, y_input)).unwrap();
89            assert_eq!(output.val() > 0, x >= y);
90        }
91    }
92}