Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversion between TFHErs fheint and Concrete ciphertexts/keys #945

Merged
merged 16 commits into from
Sep 3, 2024

Conversation

youben11
Copy link
Member

No description provided.

@cla-bot cla-bot bot added the cla-signed label Jul 18, 2024
@youben11 youben11 requested a review from aPere3 July 18, 2024 10:00
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 278def1 Previous: 0060f01 Ratio
v0 PBS table generation 60839502 ns/iter (± 1588090) 60865468 ns/iter (± 3212038) 1.00
v0 PBS simulate dag table generation 38096598 ns/iter (± 393959) 37760545 ns/iter (± 342103) 1.01
v0 WoP-PBS table generation 50395693 ns/iter (± 1820335) 50040680 ns/iter (± 4218342) 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Copy link
Collaborator

@aPere3 aPere3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

backends/concrete-cpu/implementation/src/c_api/fheint.rs Outdated Show resolved Hide resolved
Comment on lines 37 to 45
Result<TransportValue>
importTfhersFheUint8(llvm::ArrayRef<uint8_t> serializedFheUint8);
Result<std::vector<uint8_t>> exportTfhersFheUint8(TransportValue value,
TfhersFheIntDescription info);
Result<TfhersFheIntDescription>
getTfhersFheUint8Description(llvm::ArrayRef<uint8_t> serializedFheUint8);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be better put into Commons. If ever we need to use that in the ServerLib as well.

@youben11 youben11 changed the title Conversion between TFHErs fheint and Concrete ciphertexts Conversion between TFHErs fheint and Concrete ciphertexts/keys Aug 28, 2024
@youben11 youben11 force-pushed the feat/import-export-fheuint branch 2 times, most recently from 651d11b to 6bc67fe Compare August 28, 2024 14:39
Copy link
Member

@BourgerieQuentin BourgerieQuentin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First review (test not yet reviewed)

backends/concrete-cpu/implementation/src/c_api/fheint.rs Outdated Show resolved Hide resolved
serialized_data_len: usize,
) -> TfhersFheIntDescription {
nounwind(|| {
// deserialize fheuint8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: We should see if we can have a generic code

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IceTDrinker any thoughts on this? In short: can we have a generic function which serialize/deserialize FheUint/Int of different widths?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it generic over the FheUintId and FheIntId traits

Copy link
Member

@IceTDrinker IceTDrinker Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FheUint and FheInt are built like so:

FheUint<Id: FheUintId>
FheInt<Id: FheIntId>

the FheUint8 is just an instantiation of the type with a dedicated ID for 8 bits

}

#[no_mangle]
pub unsafe extern "C" fn concrete_cpu_tfhers_uint8_to_lwe_array(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we merge both function to deserialize just once?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand you mean with the get description function. This could be done, but the two functions are actually unrelated. With recent changes, the get description function is no longer necessary, but it could be used to get some information for debugging for example. So I don't think we should merge them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see how it's used in my following push

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok but should be used at least to verify that the imported ciphertext parameters are equals to ones given by the developer, wdyt?

# pylint: enable=protected-access


def new_context(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this wrapper around the constructor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a matter of taste 😛

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that python idomatic?

frontends/concrete-python/concrete/fhe/tfhers/context.py Outdated Show resolved Hide resolved
frontends/concrete-python/tests/dtypes/test_tfhers.py Outdated Show resolved Hide resolved
serialized_data_ptr,
serialized_data_len,
));
let fheuint: FheUint8 = match bincode::deserialize_from(&mut serialized_data) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make sure that the bincode version we use here is compatible with the version used on tfhe-rs side ? Maybe I am wrong, but if a new version of bincode changes the binary format, it may break the serialization doesn't it ? Could it be a security issue ?

Maybe I am way over my head here so feel free to ignore 😆

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be future proof and benefit from the data compatibility you would want to use the versionize primitives before serializing, then you are free to use whichever serde-compatible serialization backend

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see e.g. here https://github.com/zama-ai/tfhe-rs/tree/main/utils/tfhe-versionable Nicolas is the one who worked on the design of this if support is needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's TFHErs vs Concrete versions. It's the user of TFHErs which will be doing serialization, so he should make sure he uses the same version as in Concrete. I don't think TFHErs has something to do in here. For example, you can see the tool I'm using for testing (tfhers-utils). It's using bincode for serialization and doesn't rely on TFHErs for that. Unless serialization of TFHErs struct would rely on something implemeneted in TFHErs that I'm not aware of.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IceTDrinker I was not worried by the versionning of TFHE-rs structures, but more in the compatibility of the serialization format implemented by bincode.

@youben11 you are right, but Concrete is delivered as a binary (with a fixed version for bincode), but we don't know what users will do in their rust code, nor if they will be aware that the version of bincode is important.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IceTDrinker Not sure ! I did not go into many details but it seems they changed their spec since last major release (https://github.com/bincode-org/bincode/commits/trunk/docs/spec.md).

@youben11 what do you mean by follow the framework ? The basic user (me) won't look at the repo tree at the commit of the concrete binary to extract the bincode version. He will just do Cargo.toml bincode="2" and call it a day 🤣

I any case, I am not overly worried about that 😉 Though it may be interesting to think about adding bincode version in the serialization if they are not reliable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean we should document that. Otherwise, we should provide ser/deser functions maybe? I'm no expert in Rust serialization, but I would always think how to serialize something before sending it to another package for deserialization. Or is bincode what everyone uses? Think of when we will be using versionize: we will have to document how someone is expected to serialize a ciphertext before using it in Concrete.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually ciphertexts will come from tfhe-rs users (blockchain as example). So we should use the same serialization framework than casual tfhe-rs user will use, if I well understand the versionable framework is something generic, but is that will be used for tfhe-rs integers @IceTDrinker ? From my understanding you should implement versioning on tfhe-rs side for thf-rs integers and we should use that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have versioning for ciphertexts, Nicolas will be back on thursday so if Ayoub needs a quick tour it can likely be done then

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok great 👍

}
let fheuint = match FheUint8::from_expanded_blocks(
blocks,
tfhe::integer::ciphertext::DataKind::Unsigned(4),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it mean we only support 4bits ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like the number of bits of the DataKind is not really used to check anything in the function afterwards 🤔 only the fact that it's unsigned matters

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend matching the numebr of bits in the Unsigned to the type being reconstructed so here 8 bits

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Looking into this, and why it was working for other values, I found that in reality, the 4 was never used underneath as it was recomputed from blocks. I made a fix by computing the datakind based sign and width

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just saw Arthur's comment as it wasn't appearing initially)

frontends/concrete-python/concrete/fhe/tfhers/context.py Outdated Show resolved Hide resolved
This is useful for it to be used in TFHErs
this is done to have the same format as tfhers
this will be used to test Concrete <> TFHErs compatibility
Concrete doing the keygen, while TFHErs doing enc/dec
we were doing a deserialization previously to get the fheint
description, but we will now construct it from the type instead. It's
still possible for the user to get the description from the buffer and
use it for import (using the Compiler API).
@youben11
Copy link
Member Author

youben11 commented Sep 3, 2024

@slab-ci concrete-python-tests-linux

@youben11 youben11 merged commit a951789 into main Sep 3, 2024
31 of 44 checks passed
@youben11 youben11 deleted the feat/import-export-fheuint branch September 3, 2024 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants