fancy_garbling/
depth_informer.rs

1//! Fancy object to compute the multiplicative depth of a computation.
2
3use crate::{
4    FancyArithmetic, FancyBinary,
5    errors::FancyError,
6    fancy::{Fancy, FancyInput, FancyReveal, HasModulus},
7};
8use std::cmp::max;
9
10/// Carries the depth of the computation.
11#[derive(Clone, Debug)]
12pub struct DepthItem {
13    modulus: u16,
14    depth: usize,
15}
16
17impl HasModulus for DepthItem {
18    fn modulus(&self) -> u16 {
19        self.modulus
20    }
21}
22
23/// Errors thrown by the Fancy computation.
24#[derive(Debug)]
25pub enum DepthError {
26    /// Projection is unsupported by the depth informer
27    ProjUnsupported,
28    /// Error from Fancy library.
29    Underlying(FancyError),
30}
31
32impl From<FancyError> for DepthError {
33    fn from(e: FancyError) -> Self {
34        DepthError::Underlying(e)
35    }
36}
37
38impl std::fmt::Display for DepthError {
39    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40        match self {
41            Self::ProjUnsupported => writeln!(f, "Projection unsupported"),
42            Self::Underlying(e) => writeln!(f, "Fancy error: {}", e),
43        }
44    }
45}
46
47/// Fancy Object which computes information about the circuit of interest to FHE.
48#[derive(Clone, Debug)]
49pub struct DepthInformer {
50    ninputs: usize,
51    nconstants: usize,
52    nadds: usize,
53    nsubs: usize,
54    ncmuls: usize,
55    nmuls: usize,
56    mul_depth: usize,
57}
58
59impl std::fmt::Display for DepthInformer {
60    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
61        writeln!(f, "computation info:")?;
62        writeln!(f, "  inputs:             {:16}", self.ninputs)?;
63        writeln!(f, "  constants:          {:16}", self.nconstants)?;
64        writeln!(f, "  additions:          {:16}", self.nadds)?;
65        writeln!(f, "  subtractions:       {:16}", self.nsubs)?;
66        writeln!(f, "  cmuls:              {:16}", self.ncmuls)?;
67        writeln!(f, "  muls:               {:16}", self.nmuls)?;
68        writeln!(
69            f,
70            "  total gates:        {:16}",
71            self.nadds + self.nsubs + self.ncmuls + self.nmuls
72        )?;
73        writeln!(f, "  mul depth:          {:16}", self.mul_depth)?;
74        Ok(())
75    }
76}
77
78impl DepthInformer {
79    /// Create a new DepthInformer
80    pub fn new() -> DepthInformer {
81        DepthInformer {
82            ninputs: 0,
83            nconstants: 0,
84            nadds: 0,
85            nsubs: 0,
86            ncmuls: 0,
87            nmuls: 0,
88            mul_depth: 0,
89        }
90    }
91}
92
93impl FancyInput for DepthInformer {
94    type Item = DepthItem;
95    type Error = DepthError;
96
97    fn receive_many(&mut self, moduli: &[u16]) -> Result<Vec<Self::Item>, Self::Error> {
98        self.ninputs += moduli.len();
99        Ok(moduli
100            .iter()
101            .map(|q| DepthItem {
102                modulus: *q,
103                depth: 0,
104            })
105            .collect())
106    }
107
108    fn encode_many(
109        &mut self,
110        _values: &[u16],
111        moduli: &[u16],
112    ) -> Result<Vec<Self::Item>, Self::Error> {
113        self.receive_many(moduli)
114    }
115}
116
117impl FancyBinary for DepthInformer {
118    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
119        FancyArithmetic::add(self, x, y)
120    }
121
122    fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
123        FancyArithmetic::mul(self, x, y)
124    }
125
126    fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
127        self.nadds += 1;
128        Ok(DepthItem {
129            modulus: x.modulus,
130            depth: x.depth,
131        })
132    }
133}
134
135impl FancyArithmetic for DepthInformer {
136    fn add(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
137        self.nadds += 1;
138        Ok(DepthItem {
139            modulus: x.modulus,
140            depth: max(x.depth, y.depth),
141        })
142    }
143
144    fn sub(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
145        self.nsubs += 1;
146        Ok(DepthItem {
147            modulus: x.modulus,
148            depth: max(x.depth, y.depth),
149        })
150    }
151
152    fn cmul(&mut self, x: &Self::Item, _y: u16) -> Result<Self::Item, Self::Error> {
153        self.ncmuls += 1;
154        Ok(DepthItem {
155            modulus: x.modulus,
156            depth: x.depth + 1,
157        })
158    }
159
160    fn mul(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
161        self.nmuls += 1;
162        Ok(DepthItem {
163            modulus: x.modulus,
164            depth: max(x.depth, y.depth) + 1,
165        })
166    }
167
168    fn proj(
169        &mut self,
170        _x: &Self::Item,
171        _q: u16,
172        _tt: Option<Vec<u16>>,
173    ) -> Result<Self::Item, Self::Error> {
174        Err(DepthError::ProjUnsupported)
175    }
176}
177
178impl Fancy for DepthInformer {
179    type Item = DepthItem;
180    type Error = DepthError;
181
182    fn constant(&mut self, _val: u16, q: u16) -> Result<Self::Item, Self::Error> {
183        self.nconstants += 1;
184        Ok(DepthItem {
185            modulus: q,
186            depth: 0,
187        })
188    }
189
190    fn output(&mut self, x: &Self::Item) -> Result<Option<u16>, Self::Error> {
191        self.mul_depth = max(self.mul_depth, x.depth);
192        Ok(None)
193    }
194}
195
196impl FancyReveal for DepthInformer {
197    fn reveal(&mut self, _x: &Self::Item) -> Result<u16, Self::Error> {
198        Ok(0)
199    }
200}