Skip to main content

fancy_garbling/circuits/binary/
and_many.rs

1use crate::{FancyBinary, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6/// Returns `true` if all inputs are `true`.
7///
8/// # Panics
9/// Panics if no inputs are provided.
10#[derive(Default)]
11pub struct AndMany<'a>(PhantomData<&'a ()>);
12
13impl<'a> AndMany<'a> {
14    /// Create a new [`AndMany`] circuit.
15    pub fn new() -> Self {
16        Default::default()
17    }
18}
19
20impl<'a, F: FancyBinary> Circuit<F> for AndMany<'a>
21where
22    F::Item: 'a,
23{
24    type Input = &'a [F::Item];
25    type Output = 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        assert!(!inputs.is_empty(), "`args` cannot be empty");
34        inputs
35            .iter()
36            .skip(1)
37            .try_fold(inputs[0].clone(), |acc, x| backend.and(&acc, x, channel))
38    }
39}
40
41#[cfg(test)]
42pub mod test {
43    use super::AndMany;
44
45    #[test]
46    fn and_many() {
47        use crate::dummy::{Dummy, DummyVal};
48        use rand::Rng;
49
50        let mut rng = rand::thread_rng();
51
52        for _ in 0..100 {
53            let n = 2 + (rng.r#gen::<usize>() % 200);
54            let inputs = (0..n)
55                .map(|_| DummyVal::rand_bool(&mut rng))
56                .collect::<Vec<_>>();
57            let expected = inputs.iter().fold(1, |acc, &x| x.val() & acc);
58            let circuit = AndMany::new();
59            let output = Dummy::eval(&circuit, inputs.as_slice()).unwrap();
60            assert_eq!(output.val(), expected);
61        }
62    }
63}