Skip to main content

fancy_garbling/circuits/binary/
or_many.rs

1use crate::{FancyBinary, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6/// Returns `true` if any input is `true`.
7///
8/// # Panics
9/// Panics if no inputs are provided.
10#[derive(Default)]
11pub struct OrMany<'a>(PhantomData<&'a ()>);
12
13impl<'a> OrMany<'a> {
14    /// Create a new [`OrMany`] circuit.
15    pub fn new() -> Self {
16        Default::default()
17    }
18}
19
20impl<'a, F: FancyBinary> Circuit<F> for OrMany<'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.or(&acc, x, channel))
38    }
39}
40
41#[cfg(test)]
42pub mod test {
43    use super::OrMany;
44
45    #[test]
46    fn or_many() {
47        use crate::dummy::{Dummy, DummyVal};
48        use rand::Rng;
49
50        let mut rng = rand::thread_rng();
51        for _ in 0..16 {
52            let n = 2 + (rng.r#gen::<usize>() % 200);
53            let inputs = (0..n)
54                .map(|_| DummyVal::rand_bool(&mut rng))
55                .collect::<Vec<_>>();
56            let expected = inputs.iter().fold(0, |acc, &x| x.val() | acc);
57            let circuit = OrMany::new();
58            let output = Dummy::eval(&circuit, inputs.as_slice()).unwrap();
59            assert_eq!(output.val(), expected);
60        }
61    }
62}