use crate::bootstrap::Bootstrap;
use crate::key::CloudKey;
use crate::trgsw::{blind_rotate, identity_key_switching};
use crate::trlwe::{sample_extract_index, sample_extract_index_2};
use crate::utils::Ciphertext;
#[derive(Debug, Clone)]
pub struct VanillaBootstrap {
_private: (),
}
impl VanillaBootstrap {
pub fn new() -> Self {
VanillaBootstrap { _private: () }
}
}
impl Default for VanillaBootstrap {
fn default() -> Self {
Self::new()
}
}
impl Bootstrap for VanillaBootstrap {
fn bootstrap(&self, ctxt: &Ciphertext, cloud_key: &CloudKey) -> Ciphertext {
let trlwe = blind_rotate(ctxt, cloud_key);
let tlwe_lv1 = sample_extract_index(&trlwe, 0);
identity_key_switching(&tlwe_lv1, &cloud_key.key_switching_key)
}
fn bootstrap_without_key_switch(&self, ctxt: &Ciphertext, cloud_key: &CloudKey) -> Ciphertext {
let trlwe = blind_rotate(ctxt, cloud_key);
sample_extract_index_2(&trlwe, 0)
}
fn name(&self) -> &str {
"vanilla"
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::key;
use crate::params;
use rand::Rng;
#[test]
fn test_vanilla_bootstrap() {
let mut rng = rand::thread_rng();
let key = key::SecretKey::new();
let cloud_key = key::CloudKey::new(&key);
let bootstrap = VanillaBootstrap::new();
let try_num = 10;
for _i in 0..try_num {
let plain = rng.gen::<bool>();
let encrypted = Ciphertext::encrypt_bool(plain, params::tlwe_lv0::ALPHA, &key.key_lv0);
let bootstrapped = bootstrap.bootstrap(&encrypted, &cloud_key);
let decrypted = bootstrapped.decrypt_bool(&key.key_lv0);
assert_eq!(
plain, decrypted,
"Bootstrap failed: expected {}, got {}",
plain, decrypted
);
}
}
#[test]
fn test_vanilla_bootstrap_without_key_switch() {
let mut rng = rand::thread_rng();
let key = key::SecretKey::new();
let cloud_key = key::CloudKey::new(&key);
let bootstrap = VanillaBootstrap::new();
for _ in 0..3 {
let plain = rng.gen::<bool>();
let encrypted = Ciphertext::encrypt_bool(plain, params::tlwe_lv0::ALPHA, &key.key_lv0);
let _intermediate = bootstrap.bootstrap_without_key_switch(&encrypted, &cloud_key);
}
}
#[test]
fn test_bootstrap_trait() {
let bootstrap: Box<dyn Bootstrap> = Box::new(VanillaBootstrap::new());
assert_eq!(bootstrap.name(), "vanilla");
let mut rng = rand::thread_rng();
let key = key::SecretKey::new();
let cloud_key = key::CloudKey::new(&key);
let plain = rng.gen::<bool>();
let encrypted = Ciphertext::encrypt_bool(plain, params::tlwe_lv0::ALPHA, &key.key_lv0);
let bootstrapped = bootstrap.bootstrap(&encrypted, &cloud_key);
let decrypted = bootstrapped.decrypt_bool(&key.key_lv0);
assert_eq!(plain, decrypted);
}
}