## ----echo=F-------------------------------------------------------------------
knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE,
  error = FALSE,
  tidy = FALSE,
  cache = FALSE
)

## -----------------------------------------------------------------------------
library(openfhe.R)

set.seed(42)
site_data <- lapply(c(1000, 500, 1500), function(n) {
    data.frame(
        age       = sample(40:70, n, replace = TRUE),
        sex       = sample(c("M", "F"), n, replace = TRUE),
        biomarker = runif(n, 0, 1)
    )
})

## -----------------------------------------------------------------------------
## BFV: exact integer arithmetic mod plaintext_modulus.
cc   <- fhe_context("BFV",
                    plaintext_modulus    = 65537L,
                    multiplicative_depth = 1L)
keys <- key_gen(cc)

pk <- keys@public
sk <- keys@secret

## -----------------------------------------------------------------------------
site_encrypt <- function(site_df, cc, pk) {
    count <- sum(site_df$age < 50 &
                 site_df$sex == "F" &
                 site_df$biomarker < 0.2)
    pt    <- make_packed_plaintext(cc, as.integer(count))
    encrypt(pk, pt, cc = cc)
}

ct_site1 <- site_encrypt(site_data[[1]], cc, pk)
ct_site2 <- site_encrypt(site_data[[2]], cc, pk)
ct_site3 <- site_encrypt(site_data[[3]], cc, pk)

## -----------------------------------------------------------------------------
## Homomorphic addition: the aggregator never decrypts intermediate values.
ct_total <- ct_site1 + ct_site2 + ct_site3

## Only the aggregator holds the secret key.
result      <- decrypt(ct_total, sk, cc = cc)
total_count <- get_packed_value(result)[1]
total_count

## -----------------------------------------------------------------------------
true_count <- sum(sapply(site_data, function(df) {
    sum(df$age < 50 & df$sex == "F" & df$biomarker < 0.2)
}))
true_count

stopifnot(total_count == true_count)

## -----------------------------------------------------------------------------
tdir <- tempdir()
fhe_serialize(cc, file.path(tdir, "context.bin"))
fhe_serialize(pk, file.path(tdir, "pubkey.bin"))

cc_remote <- fhe_deserialize(file.path(tdir, "context.bin"), "CryptoContext")
pk_remote <- fhe_deserialize(file.path(tdir, "pubkey.bin"), "PublicKey")

ct <- encrypt(pk_remote,
              make_packed_plaintext(cc_remote, 42L),
              cc = cc_remote)

fhe_serialize(ct, file.path(tdir, "site_count.bin"))
ct_received <- fhe_deserialize(file.path(tdir, "site_count.bin"), "Ciphertext")
result      <- decrypt(ct_received, sk, cc = cc)
get_packed_value(result)[1]

