Dear Community,
How do I perform multiple functions using tfhe integer. I am using the code as below:
use tfhe::integer::ciphertext::RadixCiphertext;
use tfhe::integer::client_key::RadixClientKey;
use tfhe::integer::server_key::ServerKey;
fn analysis<PBSOder: tfhe::shortint::PBSOrderMarker>(array: &Vec<RadixCiphertext<PBSOder>>, ck: &RadixClientKey, sk: &ServerKey){
let enc = ck.encrypt(5 as u64);
for itr in 0..100{
let t = array[itr];
let c1 = sk.le_parallelized(&t, &enc);
}
}
I get the following error for c1, expected type parameter PBSOder, found KeySwitchBootstrap.
How to resolve this
The problem here, is that encrypt
returns a RadixCiphertext<KeySwitchBootstrap>
not a RadixCiphertext<PBSOder>
.
You could fix this by using RadixCiphertextBig
instead of RadixCiphertext<PBSOder>
.
fn analysis(array: &Vec<RadixCiphertextBig>, ck: &RadixClientKey, sk: &ServerKey){
let enc = ck.encrypt(5 as u64);
for itr in 0..100{
let t = array[itr];
let c1 = sk.le_parallelized(&t, &enc);
}
}
I see that your analysis function takes both the client key and the server key, this is not exactly how fhe code should be written, as the client key must stay private and not sent to the server.
What you may be looking for is a trivial encryption using the sks.
let trivial_5 = sks.create_trivial_radix(5, array[0].blocks().len());
use tfhe::integer::IntegerCiphertext;
fn analysis(array: &Vec<RadixCiphertextBig>, sk: &ServerKey){
let trivial_5 = sks.create_trivial_radix(5u64, array[0].blocks().len());
for ct in array.iter() {
let c1 = sk.le_parallelized(ct, &trivial_5);
}
}
(Normally, create_trivial_radix should also works if you really want to use RadixCiphertext<PBSOder>
use tfhe::integer::IntegerCiphertext;
fn analysis<PBSOder: tfhe::shortint::PBSOrderMarker>(array: &Vec<RadixCiphertext<PBSOder>>, sk: &ServerKey){
let trivial_5 = sks.create_trivial_radix(5u64, array[0].blocks().len());
for ct in array.iter() {
let c1 = sk.le_parallelized(ct, &trivial_5);
}
}
What is the difference between RadixCiphertext and RadixCiphertextBig?
Also when I sometimes do c1 = arrray[itr], I get an error cannot move out of index because it doesn’t implement Copy trait, so how do we such steps?
What is the difference between RadixCiphertext and RadixCiphertextBig?
RadixCiphertext is a generic type of ciphertext that uses radix representation.
RadixCiphertextBig is a concrete implementation of radix ciphertext type that uses the ‘big’ lwe for encryption. There also exists RadixCiphertextSmall.
You should not worry about them, in the next release it is going to be simplified
Also when I sometimes do c1 = arrray[itr], I get an error cannot move out of index because it doesn’t implement Copy trait, so how do we such steps?
You can either take a reference or clone
let c1 = &arrray[itr];
// or
let c1 = arrray[itr].clone();
Is it possible to access individual blocks of the radix ciphertexts and perform operations on those based like programmable bootstrap
Dear team, any update on this?
You probably want to check this trait
Cheers
Lets say I create a ciphertext
zero = sk.create_trivial_radix(5u64, num_blocks);
Now what I want to apply programmable bootstrapping on each bock of cipher
So I do something like this:
blocks = zero.blocks();
for i in 0..4{
blocks[i] = some_operation(blocks[i]);
}
I get error private field not a method
If I do
blocks = zero.blocks;
I still get error private field
You need to import the trait with
use tfhe::integer::IntegerCiphertext;
To be able to use the method in your first code snippet, use the blocks_mut method if you need to modify the underlying blocks.
Cheers
1 Like
Thank you this is working. Now I have extracted all the blocks, next step I want to convert the blocks back to IntegerCiphertext(RadixCiphertext), will it happen automatically because of the reference or will I have to apply some function on it to convert it?
Normally the blocks function directly references the blocks in the original Integer Ciphertext so you should be able to continue with the ciphertext you called blocks_mut on
If ever you may want to use some specific blocks you can use from_blocks IntegerCiphertext in tfhe::integer::ciphertext - Rust
1 Like
okay thank you. Sorry for being persistent with the questions, but I have one more.
The extracted blocks are of Ciphertext format, and to perform programmable bootstrapping on it, we require ClientKey to generate the wopbs_key, but initially we had the RadixClientkey, so how do we perform these steps? To simplify, how can I apply programmable bootstrapping on the blocks extracted from the Radixciphertext using wopbs_key generated by RadixClientKey and ServerKey?
Also if I have to create a trivial Ciphertext(not RadixCiphertext) for doing sum of the result obtained from above bootstrap code of a block, how to create this?!
Why do you want to use wopbs on the blocks ? There are wopbs primitives at the integer level
One example is to find out which are the positions/blocks that are non zero in the integer ciphertext, and then using this result to perform some other complex function.
You don’t need wopbs for that you should be able to perform per block operation using the classic PBS. At the moment we don’t have an accessor but there should be a way to convert the integer key to shortint with something like:
let sk = …; //integer server key
let shortint_sk: tfhe::shortint::ServerKey = sk.clone().into();
Then use the shortint_sk methods on the blocks you extracted
1 Like