Commented code of a PBS doubling a 2-bits encrypted message using TFHE-rs C API.
The steps required to perform the multiplication by 2 of a 2-bits ciphertext using a PBS are detailed. This is NOT the most efficient way of doing this operation, but it can help to show the management required to run a PBS manually using the C API.
WARNING: The following example does not have proper memory management in the error case to make it easier to fit the code on this page.
To run the example below, the above CMakeLists.txt and main.c files need to be in the same directory. The commands to run are:
# /!\ Be sure to update CMakeLists.txt to give the absolute path to the compiled tfhe library$lsCMakeLists.txtmain.c$mkdirbuild&&cdbuild$cmake..-DCMAKE_BUILD_TYPE=RELEASE...$make...$./my-executableResult:2$
#include"tfhe.h"#include<assert.h>#include<inttypes.h>#include<stdio.h>uint64_tdouble_accumulator_2_bits_message(uint64_t in) { return (in *2) %4; }uint64_tget_max_value_of_accumulator_generator(uint64_t (*accumulator_func)(uint64_t),size_t message_bits){uint64_t max_value =0;for (size_t idx =0; idx < (1<< message_bits); ++idx) {uint64_t acc_value =accumulator_func((uint64_t)idx); max_value = acc_value > max_value ? acc_value : max_value; }return max_value;}intmain(void){ ShortintPBSLookupTable *accumulator =NULL; ShortintClientKey *cks =NULL; ShortintServerKey *sks =NULL; ShortintParameters *params =NULL;// Get the parameters for 2 bits messages with 2 bits of carryint get_params_ok =shortint_get_parameters(2,2,¶ms);assert(get_params_ok ==0);// Generate the keys with the parametersint gen_keys_ok =shortint_gen_keys_with_parameters(params,&cks,&sks);assert(gen_keys_ok ==0);// Generate the accumulator for the PBSint gen_acc_ok =shortint_server_key_generate_pbs_accumulator( sks, double_accumulator_2_bits_message,&accumulator);assert(gen_acc_ok ==0); ShortintCiphertext *ct =NULL; ShortintCiphertext *ct_out =NULL;// We will compute 1 * 2 using a PBS, it's not the recommended way to perform a multiplication,// but it shows how to manage a PBS manually in the C APIuint64_t in_val =1;// Encrypt the input valueint encrypt_ok =shortint_client_key_encrypt(cks, in_val,&ct);assert(encrypt_ok ==0);// Check the degree is set to the maximum value that can be encrypted on 2 bits, i.e. 3// This check is not required and is just added to show, the degree information can be retrieved// in the C APisize_t degree =-1;int get_degree_ok =shortint_ciphertext_get_degree(ct,°ree);assert(get_degree_ok ==0);assert(degree ==3);// Apply the PBS on our encrypted inputint pbs_ok =shortint_server_key_programmable_bootstrap(sks, accumulator, ct,&ct_out);assert(pbs_ok ==0);// Set the degree to keep consistency for potential further computations// Note: This is only required for the PBSsize_t degree_to_set = (size_t)get_max_value_of_accumulator_generator(double_accumulator_2_bits_message,2);int set_degree_ok =shortint_ciphertext_set_degree(ct_out, degree_to_set);assert(set_degree_ok ==0);// Decrypt the resultuint64_t result =-1;int decrypt_non_assign_ok =shortint_client_key_decrypt(cks, ct_out,&result);assert(decrypt_non_assign_ok ==0);// Check the result is what we expect i.e. 2assert(result == double_accumulator_2_bits_message(in_val));printf("Result: %ld\n", result);// Destroy entities from the C APIdestroy_shortint_ciphertext(ct);destroy_shortint_ciphertext(ct_out);destroy_shortint_pbs_accumulator(accumulator);destroy_shortint_client_key(cks);destroy_shortint_server_key(sks);destroy_shortint_parameters(params);return EXIT_SUCCESS;}