-
Notifications
You must be signed in to change notification settings - Fork 150
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
feat(hlapi): add tag system #1468
Conversation
35efd30
to
bc4cd3d
Compare
tests are red at the moment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice API !
ec5fe0e
to
6bba729
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the SmallVec is too smart for what we are trying to do (there may even be issues depending on the wasm vec size) I think an Option for the tag should be enough, not bigger than a vec https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c0cf100d311d5780007cbf38a26f4515
and allows to have an empty tag that has smaller overhead than the SmallVec which needs to be initialized with 0s and then copied around even if it's morally empty
use crate::high_level_api::backward_compatibility::tag::TagVersions; | ||
use tfhe_versionable::{Unversionize, UnversionizeError, Versionize, VersionizeOwned}; | ||
|
||
const STACK_ARRAY_SIZE: usize = std::mem::size_of::<Vec<u8>>() - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this may not be constant across compiler versions and perhaps even platforms/hw ?
could be an issue with WASM as well ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would just mean that if for example sizeof::Vec is 3*32 = 96, then, a 128 bit number would be stored in a Vec rather than a the stack.
So when creating, no problem, when deserializing no problem either, and if a 64 bit CPU deserialize that, as it would fit on stack, the 128 bits would live on the stack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all right I need to check the details of the small vec stuff then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why it's important to convert it to a plain array before serialization (as you did)
|
||
const STACK_ARRAY_SIZE: usize = std::mem::size_of::<Vec<u8>>() - 1; | ||
|
||
/// Simple short optimized vec, where if the data is small enough |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like the SmallVec optimization might be premature and has other implications that cause more trouble at the moment than it solves
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other implications ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the size, compatibility of compiler versions, the fact the default case copies an array of 0s around
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just like with just a Vec, the compiler would copy the bytes of the internal data (ptr, size, capacity) of the vec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep my bad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SmallVec size is 8 bytes (likely sizeof::<usize>
) bigger than a plain Vec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do agree that the SmallVec thing might be premature, but the complexity of it is not that high I think
Also, the vec of the Tag which only gets and return bytes or simple u64/u128 and the fact that the serialization/versioning returns bytes protects us in a sense.
#[cfg(feature = "zk-pok")] | ||
#[derive(Clone, Serialize, Deserialize)] | ||
pub struct ProvenCompactCiphertextList(crate::integer::ciphertext::ProvenCompactCiphertextList); | ||
pub struct ProvenCompactCiphertextList { | ||
inner: crate::integer::ciphertext::ProvenCompactCiphertextList, | ||
tag: Tag, | ||
} | ||
|
||
#[cfg(feature = "zk-pok")] | ||
impl Tagged for ProvenCompactCiphertextList { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we create a zk mod here and have a feature gate on it + a pub re export ?
allows to limit the number of #cfg and I find it less error prone
6bba729
to
2dc3ede
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
last comments on small vec + tests
use crate::ProvenCompactCiphertextList; | ||
|
||
let config = | ||
ConfigBuilder::with_custom_parameters(PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M64).build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to mimich the blockchain case better could we use the dedicated PK params + casting params ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try to add it, but since the tag is for the whole key set it won't change how it behaves
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s to make sure it gets from the public key through the keyswitch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what I mean is for the BC use case we have
PKE -> KS -> PBS
and we want to make sure the tagging works well in that scenario
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok i see
tfhe/src/high_level_api/tag.rs
Outdated
bytes: r_bytes, | ||
len: r_len, | ||
}, | ||
) => l_vec == &r_bytes[..usize::from(*r_len)], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering if a short circuit by checking the l_vec.len() == r_len is worth it here and below
} | ||
} | ||
|
||
pub fn as_u64(&self) -> u64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as_le_u64 I would suggest then, or docstring that makes it clear how the data is interpreted and the truncating behavior of the as_u64
u64::from_le_bytes(le_bytes) | ||
} | ||
|
||
pub fn as_u128(&self) -> u128 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same thing for the endianness
tfhe/src/high_level_api/tag.rs
Outdated
pub fn set_u64(&mut self, value: u64) { | ||
let le_bytes = value.to_le_bytes(); | ||
self.set_data(le_bytes.as_slice()); | ||
} | ||
|
||
pub fn set_u128(&mut self, value: u128) { | ||
let le_bytes = value.to_le_bytes(); | ||
self.set_data(le_bytes.as_slice()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
info about endianness
tfhe/src/high_level_api/tag.rs
Outdated
|
||
/// Tag | ||
/// | ||
/// The `Tag` allows to store bytes alongside of entities (keys, and ciphertext) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alongside of -> alongside
keys, and ciphertexts
(missing s)
tfhe/src/high_level_api/tag.rs
Outdated
/// The `Tag` allows to store bytes alongside of entities (keys, and ciphertext) | ||
/// the main purpose of this system is to `tag` / identify ciphertext with their keys. | ||
/// | ||
/// tfhe-rs does not interpret or check this data, it only stores it and passes it around |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TFHE-rs I think is the accepted spelling for public resources
44c6291
to
cd89af4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor things, next one should be the one to merge
#[derive(VersionsDispatch)] | ||
pub(in crate::high_level_api) enum SmallVecVersions { | ||
#[allow(unused)] // Unused because V1 does not exists yet | ||
V0(SmallVec), | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no Versions for the SmallVec ?
tfhe/src/high_level_api/tag.rs
Outdated
/// the main purpose of this system is to `tag` / identify ciphertext with their keys. | ||
/// | ||
/// TFHE-RS does not interpret or check this data, it only stores it and passes it around |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TFHE-rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing only this I believe and go for merge
da069ad
to
c4228e5
Compare
Tag The `Tag` allows to store bytes alongside of entities (keys, and ciphertext) the main purpose of this system is to `tag` / identify ciphertext with their keys. * When encrypted, a ciphertext gets the tag of the key used to encrypt it. * Ciphertexts resulting from operations (add, sub, etc.) get the tag from the ServerKey used * PublicKey gets its tag from the ClientKey that was used to create it * ServerKey gets its tag from the ClientKey that was used to create it User can change the tag of any entities at any point. BREAKING CHANGE: Many of the into_raw_parts and from_raw_parts changed to accommodate the addition of the `tag``
c4228e5
to
44ec753
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot !
Tag
The
Tag
allows to store bytes alongside of entities (keys, and ciphertext) the main purpose of this system is totag
/ identify ciphertext with their keys.User can change the tag of any entities at any point.
BREAKING CHANGE: Many of the into_raw_parts and from_raw_parts changed to accommodate the addition of the `tag``
closes: please link all relevant issues
PR content/description
Check-list: