-
Notifications
You must be signed in to change notification settings - Fork 203
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
Add point compression + canonical serialization for AffineCurve
elements
#51
Comments
We have an implementation of point compression/decompression for G1/G2 in circuits as well. It requires some new comparison gadgets though, that's why I didn't make a PR yet. Let me see about that! |
Awesome! Would love to see that =) |
Just want to ask would it be better to implement serialization and deserialization in serde? Not only it is the rust de facto standard, it also has good support on no_std. Similarly, the |
I think adding
|
Just want to mention serde is format agnostic.
Maybe use something like https://docs.rs/scroll/0.10.1/scroll/ |
I think we also need a couple more knobs than are provided by serde (example: generically packing the y-coordinate bit into the x-coordinate during compression), so that's why I'd like our own traits. But I'll admit that I haven't tried to hash out a design in detail yet, so I'm open to brainstorming =)
That looks almost exactly like what I had in mind, thanks! |
Just FYI, I don't see why this cannot be done in serde. For example, there is the serde implementation with point compression: https://github.com/filecoin-project/pairing/blob/master/src/bls12_381/serde_impl.rs |
But that delegates to this trait impl: https://github.com/filecoin-project/pairing/blob/12528ea6f399922ca7202e67f12883264d6fc2b4/src/bls12_381/ec.rs#L966 |
Ok expanding on my initial design, I was thinking of creating the following traits: pub trait CanonicalSerialize {
type Error;
fn serialize(&self, extra_info: &[bool], output_buf: &mut [u8]) -> Result<(), Self::Error>;
}
pub trait CanonicalDeserialize: CanonicalSerialize {
fn deserialize(bytes: &[u8], extra_info_buf: &mut [bool]) -> Result<Self, Self::Error> ;
} For field elements, this could be implemented as follows: impl<P: Fp256Parameters> CanonicalSerialize for Fp256<P> {
type Error = Something;
fn serialize(&self, extra_info: &[bool], output_buf: &mut [u8]) {
let bytes = [0u8; 32];
self.write(&mut bytes); // From the ToBytes impl
if extra_info.len() > (256 - P::MODULUS_BITS) {
return Err(Error::NotEnoughSpace);
} else {
// Write bits in `extra_info` to empty space in
// last byte of `bytes`.
// Write `bytes` to `output_buf`.
}
}
}
pub trait CanonicalDeserialize: CanonicalSerialize {
fn deserialize(input: &[u8], extra_info_buf: &mut [bool]) -> Result<Self, Self::Error> {
// 1. Read 32 bytes from `input` into `bytes`.
// 2. if extra_info_buf.len() > (256 - P::MODULUS_BITS), return Err(Error::NotEnoughSpace);
// 3. Extract top `extra_info_buf.len()` bits from `bytes`, and then zero out the corresponding bits in the last byte of `bytes`.
// 4. Invoke `FromBytes::read` on the remaining bytes to get a field element.
}
} This impl can be used by impl<P: SWParameters> CanonicalSerialize for SWAffine<P> {
type Error = Something;
fn serialize(&self, extra_info: &[bool], output_buf: &mut [u8]) {
// 1. If `self.is_zero()`, output `Self::BaseField::zero().serialize(&[0, 0])`.
// 2. Else, check if y-coordinate is lexicographically larger.
// If yes, then output `self.x.serialize(&[1, 0])`.
// If no, then output `self.x.serialize(&[0, 0])`.
}
}
pub trait CanonicalDeserialize: CanonicalSerialize {
fn deserialize(input: &[u8], extra_info_buf: &mut [bool]) -> Result<Self, Self::Error> {
// Inverse of above.
}
} This serialization scheme requires |
Thanks! Some questions:
|
Sure, we could do that, I was trying to avoid introducing
|
Both considerations sound good to me. |
@kobigurk If you'd like to take a stab at this let me know; otherwise I'll try to push an initial branch over the next few days |
Just my two cents. I think that it would be better to eliminate unnecessary copies. In your example above, there are three rounds of copies: (1) copy in My second issue is about |
This is one of the critical missing pieces for this library. A sketch of the design I have in mind is to make
CanonicalSerialize
andCanonicalDeserialize
traits:The idea would then be to implement these directly for the final instantiated curves, e.g. for
Bls12_381_G1
. (I don't see an easy way to have a generic implementation that works for all base fields.)The text was updated successfully, but these errors were encountered: