tfhe/high_level_api/booleans/
compressed.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::backward_compatibility::booleans::{
    CompressedFheBoolVersions, InnerCompressedFheBoolVersions,
};
use crate::conformance::ParameterSetConformant;
use crate::high_level_api::global_state::with_cpu_internal_keys;
use crate::high_level_api::traits::Tagged;
use crate::integer::BooleanBlock;
use crate::named::Named;
use crate::prelude::FheTryEncrypt;
use crate::shortint::ciphertext::{CompressedModulusSwitchedCiphertext, Degree};
use crate::shortint::CompressedCiphertext;
use crate::{ClientKey, FheBool, FheBoolConformanceParams, Tag};
use serde::{Deserialize, Serialize};
use tfhe_versionable::Versionize;

#[derive(Clone, Serialize, Deserialize, Versionize)]
#[versionize(InnerCompressedFheBoolVersions)]
pub enum InnerCompressedFheBool {
    Seeded(CompressedCiphertext),
    ModulusSwitched(CompressedModulusSwitchedCiphertext),
}

/// Compressed [FheBool]
///
/// Meant to save in storage space / transfer.
///
/// - A Compressed type must be decompressed before it can be used.
/// - It is not possible to compress an existing [FheBool], compression can only be achieved at
///   encryption time
///
/// # Example
///
/// ```rust
/// use tfhe::prelude::*;
/// use tfhe::{generate_keys, CompressedFheBool, ConfigBuilder};
///
/// let (client_key, _) = generate_keys(ConfigBuilder::default());
/// let compressed = CompressedFheBool::encrypt(true, &client_key);
///
/// let decompressed = compressed.decompress();
/// let decrypted: bool = decompressed.decrypt(&client_key);
/// assert!(decrypted);
/// ```
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[versionize(CompressedFheBoolVersions)]
pub struct CompressedFheBool {
    pub(in crate::high_level_api) inner: InnerCompressedFheBool,
    pub(crate) tag: Tag,
}

impl Tagged for CompressedFheBool {
    fn tag(&self) -> &Tag {
        &self.tag
    }

    fn tag_mut(&mut self) -> &mut Tag {
        &mut self.tag
    }
}

impl CompressedFheBool {
    pub(in crate::high_level_api) fn new(ciphertext: CompressedCiphertext, tag: Tag) -> Self {
        Self {
            inner: InnerCompressedFheBool::Seeded(ciphertext),
            tag,
        }
    }

    /// Decompresses itself into a [FheBool]
    ///
    /// See [CompressedFheBool] example.
    pub fn decompress(&self) -> FheBool {
        let ciphertext = BooleanBlock::new_unchecked(match &self.inner {
            InnerCompressedFheBool::Seeded(seeded) => seeded.decompress(),
            InnerCompressedFheBool::ModulusSwitched(modulus_switched) => {
                with_cpu_internal_keys(|sk| sk.pbs_key().key.decompress(modulus_switched))
            }
        });
        let mut ciphertext = FheBool::new(ciphertext, self.tag.clone());

        ciphertext.ciphertext.move_to_device_of_server_key_if_set();

        ciphertext
    }
}

impl FheTryEncrypt<bool, ClientKey> for CompressedFheBool {
    type Error = crate::Error;

    /// Creates a compressed encryption of a boolean value
    fn try_encrypt(value: bool, key: &ClientKey) -> Result<Self, Self::Error> {
        let mut ciphertext = key.key.key.key.encrypt_compressed(u64::from(value));
        ciphertext.degree = Degree::new(1);
        Ok(Self::new(ciphertext, key.tag.clone()))
    }
}

impl ParameterSetConformant for CompressedFheBool {
    type ParameterSet = FheBoolConformanceParams;

    fn is_conformant(&self, params: &FheBoolConformanceParams) -> bool {
        match &self.inner {
            InnerCompressedFheBool::Seeded(seeded) => seeded.is_conformant(&params.0),
            InnerCompressedFheBool::ModulusSwitched(ct) => ct.is_conformant(&params.0),
        }
    }
}

impl Named for CompressedFheBool {
    const NAME: &'static str = "high_level_api::CompressedFheBool";
}

impl FheBool {
    pub fn compress(&self) -> CompressedFheBool {
        with_cpu_internal_keys(|sk| {
            let inner = InnerCompressedFheBool::ModulusSwitched(
                sk.pbs_key()
                    .key
                    .switch_modulus_and_compress(&self.ciphertext.on_cpu().0),
            );

            CompressedFheBool {
                inner,
                tag: sk.tag.clone(),
            }
        })
    }
}