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

Chore: ed25519 dalek update in next #4382

Merged
merged 1 commit into from Feb 15, 2024
Merged

Conversation

kantai
Copy link
Member

@kantai kantai commented Feb 15, 2024

Description

As part of Brice working to unify the TestSigners and SelfSigner structs, etc., it became clear that having multiple versions of the various rand libraries was going to create headaches. This PR sets workspace versions for rand, rand_core, and rand_chacha, as well as updates ed25519-dalek to facilate some unification here.

The biggest interface changes were: gen_range accepting a range argument rather than two low, high args, and changes to the ed25519-dalek interfaces. As part of this, I removed the Deref impls for VRFPublicKey and VRFPrivateKey -- those were only used to invoke the as_bytes and to_bytes, so I just added those explicitly. The problem with having Deref impls here is that it meant functions like from_bytes were overloaded, which I think can make it unclear which function is actually being invoked.

Copy link
Member

@jcnelson jcnelson left a comment

Choose a reason for hiding this comment

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

LGTM as long as CI passes. Maybe add @xoloki as a reviewer?

Copy link

codecov bot commented Feb 15, 2024

Codecov Report

Attention: 14 lines in your changes are missing coverage. Please review.

Comparison is base (2dca32f) 55.87% compared to head (41df072) 66.10%.

Files Patch % Lines
stacks-common/src/util/vrf.rs 87.09% 4 Missing ⚠️
stackslib/src/burnchains/tests/burnchain.rs 0.00% 4 Missing ⚠️
...ckslib/src/cost_estimates/tests/fee_rate_fuzzer.rs 70.00% 3 Missing ⚠️
stacks-common/src/address/c32.rs 0.00% 1 Missing ⚠️
stackslib/src/burnchains/bitcoin/network.rs 50.00% 1 Missing ⚠️
stackslib/src/net/prune.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             next    #4382       +/-   ##
===========================================
+ Coverage   55.87%   66.10%   +10.23%     
===========================================
  Files         447      447               
  Lines      320060   320041       -19     
===========================================
+ Hits       178820   211551    +32731     
+ Misses     141240   108490    -32750     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@jbencin jbencin left a comment

Choose a reason for hiding this comment

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

Looks good, a couple minor style comments. We should really be moving most, if not all, shared crates under [workspace.dependencies]

}

/// Verify that a given byte string is a well-formed EdDSA public
/// key (i.e. it's a compressed Edwards point that is valid), and return
/// a VRFPublicKey if so
pub fn from_bytes(pubkey_bytes: &[u8]) -> Option<VRFPublicKey> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know you didn't introduce this function in this PR, but this really should be try_from_bytes(), or even better, impl TryFrom<&[u8]> for VRFPublicKey, and return a Result

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I agree, but I don't want to do too much refactoring in this PR (and this would mean a pretty fair amount of refactoring).

Comment on lines +167 to +168
let key = ed25519_dalek::VerifyingKey::from_bytes(&pubkey_slice).ok()?;
Some(VRFPublicKey(key))
Copy link
Contributor

Choose a reason for hiding this comment

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

Simpler way to write this:

Suggested change
let key = ed25519_dalek::VerifyingKey::from_bytes(&pubkey_slice).ok()?;
Some(VRFPublicKey(key))
ed25519_dalek::VerifyingKey::from_bytes(&pubkey_slice).map(VRFPublicKey).ok()

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'm a little conflicted about this kind of thing -- it's actually not obvious to me which of the above is simpler. Sometimes the functional chaining in option and result can be hard to decipher (especially because it often means that the Err type survives to the end of the chain).

Comment on lines +172 to +173
let bytes = hex_bytes(h).ok()?;
Self::from_bytes(bytes.as_slice())
Copy link
Contributor

Choose a reason for hiding this comment

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

Slightly simpler:

Suggested change
let bytes = hex_bytes(h).ok()?;
Self::from_bytes(bytes.as_slice())
hex_bytes(h).ok().as_deref().and_then(Self::from_bytes)

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'm a little conflicted about this kind of thing -- it's actually not obvious to me which of the above is simpler. Sometimes the functional chaining in option and result can be hard to decipher (especially because it often means that the None type survives to the end of the chain).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree with @kantai , I find this kind of chaining to be less clear than the two line version.

Copy link
Contributor

Choose a reason for hiding this comment

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

Am I the only one who finds chaining easier to read? It just seems like extra steps to take a value out of an Option/Result and then reconstruct another one, rather than using map()/and_then()

Copy link
Member Author

Choose a reason for hiding this comment

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

For me, it depends on the situation. Sometimes I think it is much clearer to chain, other times less so. When there's multiple fallible steps, I think I usually prefer the non-chained version, because with chaining it can be hard to reason about how the error cases are being handled. Conversely, iteration is often much clearer to me when chained rather than manually looped (in particular things like finding an element or folding a sum).

Copy link
Collaborator

@xoloki xoloki left a comment

Choose a reason for hiding this comment

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

A few minor changes if not too difficult, otherwise LGTM

stacks-common/Cargo.toml Show resolved Hide resolved
stacks-common/Cargo.toml Show resolved Hide resolved
stacks-common/src/util/vrf.rs Show resolved Hide resolved
stackslib/Cargo.toml Show resolved Hide resolved
@kantai kantai merged commit 4227deb into next Feb 15, 2024
2 checks passed
@kantai kantai deleted the chore/ed25519-dalek-update branch February 15, 2024 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants