-
Notifications
You must be signed in to change notification settings - Fork 31
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
Implement generic FF arithmetic #14
Conversation
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.
For what it's worth, I merged these changes into a wasm-compatible fork (link, rebasing was ugly...) and tried out a test web-app using the library (link). For an input of [1,1,0,1]
, I used to get [1,1,0,1]
out. After switching to the new branch, I get [2564090464,6858009185,4293918721,2564090464]
. I'm guessing that this might be caused by the new field representation of u128
vs u32
and wasm-bindgen only supporting 64-bit integers.
This likely has to do with the way the new code represents field elements internally. You need to cast field elements to their integer representation by doing UPDATE: I can confirm this is what's happening. The following:
prints:
Not sure why you're seeing the internal representations in your context. The Into and From traits do the conversion properly... |
This need to be enforced with the type system, thus, the external u128 is not mapped to the u128 used internally. |
Just to clarify, I'm using the default Serialize/Deserialize traits on the VerificationMessage struct. The above is serialized in a wrapper: pub fn generate_verification_message(&mut self, eval_at: u32, share: &[u8]) -> JsValue {
set_panic_hook();
let verification = self
.this
.generate_verification_message(eval_at.into(), share)
.unwrap();
JsValue::from_serde(&verification).unwrap()
} Serde doesn't use the Into and From traits afaik, so I may need to write a custom implementation of Serialize and Deserialize if I can't rely on serializing the Field elements directly. It sounds like I can just use |
To get from |
Aha, I see now. I'm using I was just showing the serialized form of this directly, but casting the elements into integers was what I needed.
Would this be considered an API compatible change from the perspective of https://github.com/abetterinternet/prio-server? I don't have much context from that perspective. |
Golly, I hope so. That's a question for @tgeoghegan maybe? |
re: Now, on the subject of primitive-> |
My main concern about breaking the API is its impact on prio-server, If you're not concerned about this, then I'm fine breaking the API. However, I think we should punt to a future PR for the following reason. The conversion between |
use modinverse::modinverse; | ||
use num_bigint::{BigInt, ToBigInt}; | ||
|
||
let err_modulus_too_large = "p > 2^126"; |
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.
nit: this is fine for now since the only caller of this method is only going to print any error they encounter, but if we end up with more errors from fp
, it'd be best to define an fp::Error
enum with variants for specific error cases (like finite_field does).
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.
Ack. Yeah, this seems like it will be handy. I'll keep this in mind for the future.
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 agree with your point about u32
<-> Field
being safe, even if Field
wraps u128
, because everything is modulo 4293918721, and that we can make this safer when we expand the Field
object model. LGTM, thank you for this contribution!
Squashed. |
This change swaps the existing implementation of GF(2^32 - 2^20 + 1) with a constant-time implementation suitable for any GF(p) for which p < 2^126. It is based on Montgomery multiplication.
Partially solves #10.
This change replaces the existing finite field (FF) arithmetic with a generic, constant time implementation that is suitable for any modulus p < 2^126. The code was designed by @armfazh and ported from Go into Rust by me.
The goal of this PR is to make no API changes. In particular, the same FF parameters are used for
Field
. The next step will be to rework the code to be compatible with any field, which may or may not involve breaking the API.On a personal note, I would appreciate all levels of feedback, as this is the first time I've ever tried to contribute to a real Rust project. Feel free to tear it apart :)