Skip to main content

amaters_sdk_rust/
fhe_ops.rs

1//! FHE value type with arithmetic, comparison, and boolean operations
2//!
3//! This module exposes client-side homomorphic operations on encrypted values.
4//! All operations require the `fhe` feature and a server key set via
5//! [`FheKeys::set_as_global_server_key`].
6
7use crate::error::{Result, SdkError};
8
9#[cfg(feature = "fhe")]
10use crate::fhe::FheKeys;
11
12/// The kind of value held inside an [`FheValue`]
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum FheValueKind {
15    Bool,
16    U8,
17    U16,
18    U32,
19    U64,
20}
21
22impl std::fmt::Display for FheValueKind {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        match self {
25            FheValueKind::Bool => write!(f, "Bool"),
26            FheValueKind::U8 => write!(f, "U8"),
27            FheValueKind::U16 => write!(f, "U16"),
28            FheValueKind::U32 => write!(f, "U32"),
29            FheValueKind::U64 => write!(f, "U64"),
30        }
31    }
32}
33
34/// Inner encrypted value variants (only present when `fhe` feature is enabled)
35#[cfg(feature = "fhe")]
36enum FheValueInner {
37    Bool(tfhe::FheBool),
38    U8(tfhe::FheUint8),
39    U16(tfhe::FheUint16),
40    U32(tfhe::FheUint32),
41    U64(tfhe::FheUint64),
42}
43
44/// An encrypted value that supports homomorphic operations
45///
46/// Wrap plaintext with `encrypt_*` constructors, then use `add`/`sub`/`mul`,
47/// comparison methods (`eq`/`ne`/`lt`/`le`/`gt`/`ge`), and boolean methods
48/// (`and`/`or`/`xor`/`not`) — all without decrypting.
49///
50/// # Requirements
51///
52/// Before calling any operation, you must call [`FheKeys::set_as_global_server_key`].
53/// The `fhe` feature must be enabled.
54pub struct FheValue {
55    #[cfg(feature = "fhe")]
56    inner: FheValueInner,
57    #[cfg(not(feature = "fhe"))]
58    _placeholder: (),
59}
60
61impl FheValue {
62    /// Return the type of this encrypted value
63    pub fn kind(&self) -> FheValueKind {
64        #[cfg(feature = "fhe")]
65        {
66            match &self.inner {
67                FheValueInner::Bool(_) => FheValueKind::Bool,
68                FheValueInner::U8(_) => FheValueKind::U8,
69                FheValueInner::U16(_) => FheValueKind::U16,
70                FheValueInner::U32(_) => FheValueKind::U32,
71                FheValueInner::U64(_) => FheValueKind::U64,
72            }
73        }
74        #[cfg(not(feature = "fhe"))]
75        {
76            FheValueKind::Bool
77        }
78    }
79}
80
81#[cfg(not(feature = "fhe"))]
82impl FheValue {
83    /// Stub: encrypt a boolean (requires `fhe` feature)
84    pub fn encrypt_bool(_val: bool, _keys: &crate::fhe::FheKeys) -> Result<Self> {
85        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
86    }
87
88    /// Stub: encrypt a u8 (requires `fhe` feature)
89    pub fn encrypt_u8(_val: u8, _keys: &crate::fhe::FheKeys) -> Result<Self> {
90        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
91    }
92
93    /// Stub: encrypt a u16 (requires `fhe` feature)
94    pub fn encrypt_u16(_val: u16, _keys: &crate::fhe::FheKeys) -> Result<Self> {
95        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
96    }
97
98    /// Stub: encrypt a u32 (requires `fhe` feature)
99    pub fn encrypt_u32(_val: u32, _keys: &crate::fhe::FheKeys) -> Result<Self> {
100        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
101    }
102
103    /// Stub: encrypt a u64 (requires `fhe` feature)
104    pub fn encrypt_u64(_val: u64, _keys: &crate::fhe::FheKeys) -> Result<Self> {
105        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
106    }
107
108    /// Stub: add two values (requires `fhe` feature)
109    pub fn add(&self, _other: &Self) -> Result<Self> {
110        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
111    }
112
113    /// Stub: subtract two values (requires `fhe` feature)
114    pub fn sub(&self, _other: &Self) -> Result<Self> {
115        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
116    }
117
118    /// Stub: multiply two values (requires `fhe` feature)
119    pub fn mul(&self, _other: &Self) -> Result<Self> {
120        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
121    }
122
123    /// Stub: compare equality (requires `fhe` feature)
124    pub fn eq(&self, _other: &Self) -> Result<Self> {
125        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
126    }
127
128    /// Stub: compare not-equal (requires `fhe` feature)
129    pub fn ne(&self, _other: &Self) -> Result<Self> {
130        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
131    }
132
133    /// Stub: compare less-than (requires `fhe` feature)
134    pub fn lt(&self, _other: &Self) -> Result<Self> {
135        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
136    }
137
138    /// Stub: compare less-than-or-equal (requires `fhe` feature)
139    pub fn le(&self, _other: &Self) -> Result<Self> {
140        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
141    }
142
143    /// Stub: compare greater-than (requires `fhe` feature)
144    pub fn gt(&self, _other: &Self) -> Result<Self> {
145        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
146    }
147
148    /// Stub: compare greater-than-or-equal (requires `fhe` feature)
149    pub fn ge(&self, _other: &Self) -> Result<Self> {
150        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
151    }
152
153    /// Stub: boolean AND (requires `fhe` feature)
154    pub fn and(&self, _other: &Self) -> Result<Self> {
155        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
156    }
157
158    /// Stub: boolean OR (requires `fhe` feature)
159    pub fn or(&self, _other: &Self) -> Result<Self> {
160        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
161    }
162
163    /// Stub: boolean XOR (requires `fhe` feature)
164    pub fn xor(&self, _other: &Self) -> Result<Self> {
165        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
166    }
167
168    /// Stub: boolean NOT (requires `fhe` feature)
169    pub fn not(&self) -> Result<Self> {
170        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
171    }
172
173    /// Stub: decrypt bool (requires `fhe` feature)
174    pub fn decrypt_bool(&self, _keys: &crate::fhe::FheKeys) -> Result<bool> {
175        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
176    }
177
178    /// Stub: decrypt u8 (requires `fhe` feature)
179    pub fn decrypt_u8(&self, _keys: &crate::fhe::FheKeys) -> Result<u8> {
180        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
181    }
182
183    /// Stub: decrypt u16 (requires `fhe` feature)
184    pub fn decrypt_u16(&self, _keys: &crate::fhe::FheKeys) -> Result<u16> {
185        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
186    }
187
188    /// Stub: decrypt u32 (requires `fhe` feature)
189    pub fn decrypt_u32(&self, _keys: &crate::fhe::FheKeys) -> Result<u32> {
190        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
191    }
192
193    /// Stub: decrypt u64 (requires `fhe` feature)
194    pub fn decrypt_u64(&self, _keys: &crate::fhe::FheKeys) -> Result<u64> {
195        Err(SdkError::Fhe("fhe feature not enabled".to_string()))
196    }
197}
198
199#[cfg(feature = "fhe")]
200impl FheValue {
201    /// Encrypt a boolean value
202    pub fn encrypt_bool(val: bool, keys: &FheKeys) -> Result<Self> {
203        use tfhe::prelude::FheEncrypt;
204        let encrypted = tfhe::FheBool::encrypt(val, keys.client_key());
205        Ok(Self {
206            inner: FheValueInner::Bool(encrypted),
207        })
208    }
209
210    /// Encrypt a u8 value
211    pub fn encrypt_u8(val: u8, keys: &FheKeys) -> Result<Self> {
212        use tfhe::prelude::FheEncrypt;
213        let encrypted = tfhe::FheUint8::encrypt(val, keys.client_key());
214        Ok(Self {
215            inner: FheValueInner::U8(encrypted),
216        })
217    }
218
219    /// Encrypt a u16 value
220    pub fn encrypt_u16(val: u16, keys: &FheKeys) -> Result<Self> {
221        use tfhe::prelude::FheEncrypt;
222        let encrypted = tfhe::FheUint16::encrypt(val, keys.client_key());
223        Ok(Self {
224            inner: FheValueInner::U16(encrypted),
225        })
226    }
227
228    /// Encrypt a u32 value
229    pub fn encrypt_u32(val: u32, keys: &FheKeys) -> Result<Self> {
230        use tfhe::prelude::FheEncrypt;
231        let encrypted = tfhe::FheUint32::encrypt(val, keys.client_key());
232        Ok(Self {
233            inner: FheValueInner::U32(encrypted),
234        })
235    }
236
237    /// Encrypt a u64 value
238    pub fn encrypt_u64(val: u64, keys: &FheKeys) -> Result<Self> {
239        use tfhe::prelude::FheEncrypt;
240        let encrypted = tfhe::FheUint64::encrypt(val, keys.client_key());
241        Ok(Self {
242            inner: FheValueInner::U64(encrypted),
243        })
244    }
245
246    /// Decrypt to bool (only valid for Bool variant)
247    pub fn decrypt_bool(&self, keys: &FheKeys) -> Result<bool> {
248        use tfhe::prelude::FheDecrypt;
249        match &self.inner {
250            FheValueInner::Bool(v) => Ok(v.decrypt(keys.client_key())),
251            _ => Err(SdkError::Fhe(format!(
252                "type mismatch: expected Bool, got {}",
253                self.kind()
254            ))),
255        }
256    }
257
258    /// Decrypt to u8 (only valid for U8 variant)
259    pub fn decrypt_u8(&self, keys: &FheKeys) -> Result<u8> {
260        use tfhe::prelude::FheDecrypt;
261        match &self.inner {
262            FheValueInner::U8(v) => Ok(v.decrypt(keys.client_key())),
263            _ => Err(SdkError::Fhe(format!(
264                "type mismatch: expected U8, got {}",
265                self.kind()
266            ))),
267        }
268    }
269
270    /// Decrypt to u16 (only valid for U16 variant)
271    pub fn decrypt_u16(&self, keys: &FheKeys) -> Result<u16> {
272        use tfhe::prelude::FheDecrypt;
273        match &self.inner {
274            FheValueInner::U16(v) => Ok(v.decrypt(keys.client_key())),
275            _ => Err(SdkError::Fhe(format!(
276                "type mismatch: expected U16, got {}",
277                self.kind()
278            ))),
279        }
280    }
281
282    /// Decrypt to u32 (only valid for U32 variant)
283    pub fn decrypt_u32(&self, keys: &FheKeys) -> Result<u32> {
284        use tfhe::prelude::FheDecrypt;
285        match &self.inner {
286            FheValueInner::U32(v) => Ok(v.decrypt(keys.client_key())),
287            _ => Err(SdkError::Fhe(format!(
288                "type mismatch: expected U32, got {}",
289                self.kind()
290            ))),
291        }
292    }
293
294    /// Decrypt to u64 (only valid for U64 variant)
295    pub fn decrypt_u64(&self, keys: &FheKeys) -> Result<u64> {
296        use tfhe::prelude::FheDecrypt;
297        match &self.inner {
298            FheValueInner::U64(v) => Ok(v.decrypt(keys.client_key())),
299            _ => Err(SdkError::Fhe(format!(
300                "type mismatch: expected U64, got {}",
301                self.kind()
302            ))),
303        }
304    }
305
306    /// Add two encrypted integers (same type required)
307    pub fn add(&self, other: &Self) -> Result<Self> {
308        match (&self.inner, &other.inner) {
309            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
310                inner: FheValueInner::U8(a + b),
311            }),
312            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
313                inner: FheValueInner::U16(a + b),
314            }),
315            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
316                inner: FheValueInner::U32(a + b),
317            }),
318            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
319                inner: FheValueInner::U64(a + b),
320            }),
321            _ => Err(SdkError::Fhe(format!(
322                "type mismatch in add: {} vs {}",
323                self.kind(),
324                other.kind()
325            ))),
326        }
327    }
328
329    /// Subtract two encrypted integers (same type required)
330    pub fn sub(&self, other: &Self) -> Result<Self> {
331        match (&self.inner, &other.inner) {
332            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
333                inner: FheValueInner::U8(a - b),
334            }),
335            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
336                inner: FheValueInner::U16(a - b),
337            }),
338            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
339                inner: FheValueInner::U32(a - b),
340            }),
341            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
342                inner: FheValueInner::U64(a - b),
343            }),
344            _ => Err(SdkError::Fhe(format!(
345                "type mismatch in sub: {} vs {}",
346                self.kind(),
347                other.kind()
348            ))),
349        }
350    }
351
352    /// Multiply two encrypted integers (same type required)
353    pub fn mul(&self, other: &Self) -> Result<Self> {
354        match (&self.inner, &other.inner) {
355            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
356                inner: FheValueInner::U8(a * b),
357            }),
358            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
359                inner: FheValueInner::U16(a * b),
360            }),
361            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
362                inner: FheValueInner::U32(a * b),
363            }),
364            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
365                inner: FheValueInner::U64(a * b),
366            }),
367            _ => Err(SdkError::Fhe(format!(
368                "type mismatch in mul: {} vs {}",
369                self.kind(),
370                other.kind()
371            ))),
372        }
373    }
374
375    /// Compare equality — returns a Bool-variant FheValue
376    pub fn eq(&self, other: &Self) -> Result<Self> {
377        use tfhe::prelude::FheEq;
378        match (&self.inner, &other.inner) {
379            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
380                inner: FheValueInner::Bool(a.eq(b)),
381            }),
382            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
383                inner: FheValueInner::Bool(a.eq(b)),
384            }),
385            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
386                inner: FheValueInner::Bool(a.eq(b)),
387            }),
388            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
389                inner: FheValueInner::Bool(a.eq(b)),
390            }),
391            _ => Err(SdkError::Fhe(format!(
392                "type mismatch in eq: {} vs {}",
393                self.kind(),
394                other.kind()
395            ))),
396        }
397    }
398
399    /// Compare not-equal — returns a Bool-variant FheValue
400    pub fn ne(&self, other: &Self) -> Result<Self> {
401        use tfhe::prelude::FheEq;
402        match (&self.inner, &other.inner) {
403            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
404                inner: FheValueInner::Bool(a.ne(b)),
405            }),
406            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
407                inner: FheValueInner::Bool(a.ne(b)),
408            }),
409            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
410                inner: FheValueInner::Bool(a.ne(b)),
411            }),
412            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
413                inner: FheValueInner::Bool(a.ne(b)),
414            }),
415            _ => Err(SdkError::Fhe(format!(
416                "type mismatch in ne: {} vs {}",
417                self.kind(),
418                other.kind()
419            ))),
420        }
421    }
422
423    /// Compare less-than — returns a Bool-variant FheValue
424    pub fn lt(&self, other: &Self) -> Result<Self> {
425        use tfhe::prelude::FheOrd;
426        match (&self.inner, &other.inner) {
427            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
428                inner: FheValueInner::Bool(a.lt(b)),
429            }),
430            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
431                inner: FheValueInner::Bool(a.lt(b)),
432            }),
433            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
434                inner: FheValueInner::Bool(a.lt(b)),
435            }),
436            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
437                inner: FheValueInner::Bool(a.lt(b)),
438            }),
439            _ => Err(SdkError::Fhe(format!(
440                "type mismatch in lt: {} vs {}",
441                self.kind(),
442                other.kind()
443            ))),
444        }
445    }
446
447    /// Compare less-than-or-equal — returns a Bool-variant FheValue
448    pub fn le(&self, other: &Self) -> Result<Self> {
449        use tfhe::prelude::FheOrd;
450        match (&self.inner, &other.inner) {
451            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
452                inner: FheValueInner::Bool(a.le(b)),
453            }),
454            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
455                inner: FheValueInner::Bool(a.le(b)),
456            }),
457            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
458                inner: FheValueInner::Bool(a.le(b)),
459            }),
460            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
461                inner: FheValueInner::Bool(a.le(b)),
462            }),
463            _ => Err(SdkError::Fhe(format!(
464                "type mismatch in le: {} vs {}",
465                self.kind(),
466                other.kind()
467            ))),
468        }
469    }
470
471    /// Compare greater-than — returns a Bool-variant FheValue
472    pub fn gt(&self, other: &Self) -> Result<Self> {
473        use tfhe::prelude::FheOrd;
474        match (&self.inner, &other.inner) {
475            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
476                inner: FheValueInner::Bool(a.gt(b)),
477            }),
478            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
479                inner: FheValueInner::Bool(a.gt(b)),
480            }),
481            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
482                inner: FheValueInner::Bool(a.gt(b)),
483            }),
484            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
485                inner: FheValueInner::Bool(a.gt(b)),
486            }),
487            _ => Err(SdkError::Fhe(format!(
488                "type mismatch in gt: {} vs {}",
489                self.kind(),
490                other.kind()
491            ))),
492        }
493    }
494
495    /// Compare greater-than-or-equal — returns a Bool-variant FheValue
496    pub fn ge(&self, other: &Self) -> Result<Self> {
497        use tfhe::prelude::FheOrd;
498        match (&self.inner, &other.inner) {
499            (FheValueInner::U8(a), FheValueInner::U8(b)) => Ok(Self {
500                inner: FheValueInner::Bool(a.ge(b)),
501            }),
502            (FheValueInner::U16(a), FheValueInner::U16(b)) => Ok(Self {
503                inner: FheValueInner::Bool(a.ge(b)),
504            }),
505            (FheValueInner::U32(a), FheValueInner::U32(b)) => Ok(Self {
506                inner: FheValueInner::Bool(a.ge(b)),
507            }),
508            (FheValueInner::U64(a), FheValueInner::U64(b)) => Ok(Self {
509                inner: FheValueInner::Bool(a.ge(b)),
510            }),
511            _ => Err(SdkError::Fhe(format!(
512                "type mismatch in ge: {} vs {}",
513                self.kind(),
514                other.kind()
515            ))),
516        }
517    }
518
519    /// Boolean AND (only valid for Bool variants)
520    pub fn and(&self, other: &Self) -> Result<Self> {
521        match (&self.inner, &other.inner) {
522            (FheValueInner::Bool(a), FheValueInner::Bool(b)) => Ok(Self {
523                inner: FheValueInner::Bool(a & b),
524            }),
525            _ => Err(SdkError::Fhe(format!(
526                "type mismatch in and: expected Bool, got {} and {}",
527                self.kind(),
528                other.kind()
529            ))),
530        }
531    }
532
533    /// Boolean OR (only valid for Bool variants)
534    pub fn or(&self, other: &Self) -> Result<Self> {
535        match (&self.inner, &other.inner) {
536            (FheValueInner::Bool(a), FheValueInner::Bool(b)) => Ok(Self {
537                inner: FheValueInner::Bool(a | b),
538            }),
539            _ => Err(SdkError::Fhe(format!(
540                "type mismatch in or: expected Bool, got {} and {}",
541                self.kind(),
542                other.kind()
543            ))),
544        }
545    }
546
547    /// Boolean XOR (only valid for Bool variants)
548    pub fn xor(&self, other: &Self) -> Result<Self> {
549        match (&self.inner, &other.inner) {
550            (FheValueInner::Bool(a), FheValueInner::Bool(b)) => Ok(Self {
551                inner: FheValueInner::Bool(a ^ b),
552            }),
553            _ => Err(SdkError::Fhe(format!(
554                "type mismatch in xor: expected Bool, got {} and {}",
555                self.kind(),
556                other.kind()
557            ))),
558        }
559    }
560
561    /// Boolean NOT (only valid for Bool variant)
562    pub fn not(&self) -> Result<Self> {
563        match &self.inner {
564            FheValueInner::Bool(v) => Ok(Self {
565                inner: FheValueInner::Bool(!v),
566            }),
567            _ => Err(SdkError::Fhe(format!(
568                "type mismatch in not: expected Bool, got {}",
569                self.kind()
570            ))),
571        }
572    }
573}
574
575#[cfg(all(test, feature = "fhe"))]
576mod tests {
577    use super::*;
578    use crate::fhe::FheKeys;
579
580    #[test]
581    fn test_fhe_value_arithmetic() {
582        let keys = FheKeys::generate().expect("generate keys");
583        keys.set_as_global_server_key();
584
585        let a = FheValue::encrypt_u8(10, &keys).expect("encrypt a");
586        let b = FheValue::encrypt_u8(5, &keys).expect("encrypt b");
587
588        let sum = a.add(&b).expect("add");
589        let result: u8 = sum.decrypt_u8(&keys).expect("decrypt sum");
590        assert_eq!(result, 15);
591
592        let diff = a.sub(&b).expect("sub");
593        let result: u8 = diff.decrypt_u8(&keys).expect("decrypt diff");
594        assert_eq!(result, 5);
595
596        let product = a.mul(&b).expect("mul");
597        let result: u8 = product.decrypt_u8(&keys).expect("decrypt product");
598        assert_eq!(result, 50);
599    }
600
601    #[test]
602    fn test_fhe_value_comparison() {
603        let keys = FheKeys::generate().expect("generate keys");
604        keys.set_as_global_server_key();
605
606        let a = FheValue::encrypt_u8(10, &keys).expect("encrypt a");
607        let b = FheValue::encrypt_u8(5, &keys).expect("encrypt b");
608        let c = FheValue::encrypt_u8(10, &keys).expect("encrypt c");
609
610        let gt = a.gt(&b).expect("gt");
611        assert!(gt.decrypt_bool(&keys).expect("decrypt gt"));
612
613        let lt = a.lt(&b).expect("lt");
614        assert!(!lt.decrypt_bool(&keys).expect("decrypt lt"));
615
616        let eq_result = a.eq(&c).expect("eq");
617        assert!(eq_result.decrypt_bool(&keys).expect("decrypt eq"));
618
619        let ne_result = a.ne(&b).expect("ne");
620        assert!(ne_result.decrypt_bool(&keys).expect("decrypt ne"));
621
622        let le = b.le(&a).expect("le");
623        assert!(le.decrypt_bool(&keys).expect("decrypt le"));
624
625        let ge = a.ge(&c).expect("ge");
626        assert!(ge.decrypt_bool(&keys).expect("decrypt ge"));
627    }
628
629    #[test]
630    fn test_fhe_value_boolean() {
631        let keys = FheKeys::generate().expect("generate keys");
632        keys.set_as_global_server_key();
633
634        let t = FheValue::encrypt_bool(true, &keys).expect("encrypt true");
635        let f = FheValue::encrypt_bool(false, &keys).expect("encrypt false");
636        let t2 = FheValue::encrypt_bool(true, &keys).expect("encrypt true2");
637
638        let and_result = t.and(&f).expect("and");
639        assert!(!and_result.decrypt_bool(&keys).expect("decrypt and"));
640
641        let or_result = t2.or(&f).expect("or");
642        assert!(or_result.decrypt_bool(&keys).expect("decrypt or"));
643
644        let xor_result = t.xor(&f).expect("xor");
645        assert!(xor_result.decrypt_bool(&keys).expect("decrypt xor"));
646
647        let not_t = t2.not().expect("not");
648        assert!(!not_t.decrypt_bool(&keys).expect("decrypt not"));
649    }
650
651    #[test]
652    fn test_fhe_value_type_mismatch() {
653        let keys = FheKeys::generate().expect("generate keys");
654        keys.set_as_global_server_key();
655
656        let a = FheValue::encrypt_u8(10, &keys).expect("encrypt u8");
657        let b = FheValue::encrypt_u16(5, &keys).expect("encrypt u16");
658
659        assert!(a.add(&b).is_err(), "should fail on type mismatch");
660        assert!(a.sub(&b).is_err(), "should fail on type mismatch");
661
662        let bool_val = FheValue::encrypt_bool(true, &keys).expect("encrypt bool");
663        assert!(bool_val.add(&a).is_err(), "bool + u8 should fail");
664        assert!(a.and(&b).is_err(), "u8 and u16 should fail on and");
665    }
666}