-
Notifications
You must be signed in to change notification settings - Fork 476
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 ff
and group
traits
#473
Conversation
c51ba24
to
e665a4c
Compare
I'll rebase this. |
These are placed behind the new `ff` feature flag.
Rebased on |
Cc #373. |
I haven't added |
@str4d you could add |
If that's a strategy that the users of this crate (specifically the users of the |
@str4d if you had the full traits wired up, you could just have a I expect most users who care about the Re: making curve25519-dalek = ">= 5, < 5.1" ...which will still allow for patch-level updates, though users would need to keep an eye out for minor version updates. These ranges can also be expanded once it's been verified that a minor version bump doesn't affect functionality a given downstream dependent crate happens to be using, e.g. curve25519-dalek = ">= 5.1, < 5.4" |
Given that
If I understand you correctly, the recommended workflow for using these "breaking changes in minor version bumps" feature flags is:
It does require proactivity, but it seems fine as long as it is documented. So assuming my understanding is correct, I'm fine with adding |
What you're suggesting would work just fine with namespaced features in 1.60 if you did something like this: [dependencies]
ff = { version = "0.13", optional = true }
group = { version = "0.13", optional = true }
rand_core = { version = "0.6", optional = true }
[features]
ff = ["dep:ff", "rand_core"]
group = ["dep:group", "ff"] However prior to 1.60 you can't rely on feature unification to activate other features in the same crate by way of transitive dependencies, i.e. if you just have this: [dependencies]
ff = { version = "0.13", optional = true }
group = { version = "0.13", optional = true }
rand_core = { version = "0.6", optional = true } Activating the |
I know, which is why the current PR uses the crate renaming trick to change the name of the implicit feature, so we can instead add an explicit feature that does have the correct setup. I was just arguing that we may as well preserve this because we're going to have an |
Oh wait, I'm not tired now and see what you meant. Accessing |
This PR now includes implementations of the |
Force-pushed to fix test imports. |
Force-pushed to address most of @tarcieri's comments. I'll add a follow-up commit with the de-duplication of decompression. |
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.
Looks good, thank you! Left a few comments. Structurally, I think it also might be cleaner to put all the trait impls into a separate file. edwards.rs
has almost 1/4 of its non-test code spent on impls.
@@ -260,6 +267,27 @@ impl CompressedRistretto { | |||
/// | |||
/// - `None` if `self` was not the canonical encoding of a point. | |||
pub fn decompress(&self) -> Option<RistrettoPoint> { | |||
let (s_encoding_is_canonical, s_is_negative, s) = decompress::step_1(self); | |||
|
|||
if s_encoding_is_canonical.unwrap_u8() == 0u8 || s_is_negative.unwrap_u8() == 1u8 { |
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: unwrap_u8 -> bool::from
pub fn decompress(&self) -> Option<EdwardsPoint> { | ||
let Y = FieldElement::from_bytes(self.as_bytes()); | ||
let (is_valid_y_coord, X, Y, Z) = decompress::step_1(self); | ||
if is_valid_y_coord.unwrap_u8() != 1u8 { |
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'd use the bool::from
impl here rather than unwrap_u8()
group::ff::helpers::sqrt_tonelli_shanks( | ||
self, | ||
[ | ||
0xcb02_4c63_4b9e_ba7d, |
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 is this constant? Put a comment here
0, 0, 0, | ||
], | ||
}; | ||
const S: u32 = 2; |
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 is S?
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.
FWIW these constants are documented in the trait definition itself:
https://docs.rs/ff/latest/ff/trait.PrimeField.html#associatedconstant.S
0xef, 0x8c, 0xb5, 0x06, | ||
], | ||
}; | ||
const DELTA: Self = Self { |
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 is Delta?
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.
MULTIPLICATIVE_GENERATOR ^ (2^s) mod p
, i.e. s
squarings of MULTIPLICATIVE_GENERATOR
], | ||
}; | ||
const S: u32 = 2; | ||
const ROOT_OF_UNITY: Self = Self { |
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.
Which root of unity is this?
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 MULTIPLICATIVE_GENERATOR ^ t mod p
where t = (modulus - 1) >> s
} | ||
|
||
const MODULUS: &'static str = | ||
"0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"; |
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 cite this and/or add a test for it in the tests. This constant occurs in the l()
function on page 52 of RFC 8032.
// DELTA^{t} mod m == 1 | ||
assert_eq!( | ||
Scalar::DELTA.pow(&[ | ||
0x9604_98c6_973d_74fb, |
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 is t
?
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.
t = (modulus - 1) >> s
@@ -65,6 +66,7 @@ packed_simd = { version = "0.3.4", package = "packed_simd_2", features = ["into_ | |||
[features] | |||
default = ["alloc"] | |||
alloc = ["zeroize/alloc"] | |||
group = ["group_crate", "rand_core"] |
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.
With #485 landed this can now be:
group = ["group_crate", "rand_core"] | |
group = ["dep:group", "rand_core"] |
What is preventing the merge? |
This feature is taking a back seat to the other things we need before 4.0. This can likely come in 4.1. |
Thanks, and is there any rough estimation on when 4.1 will come? Also, is the code here already working or needs much more work? |
Would love to get this merged soon if possible. People are still asking me about it. |
Might just move this along: |
Superseded by #562 |
These are placed behind the new
group
feature flag.