-
Notifications
You must be signed in to change notification settings - Fork 90
Bump ed25519-dalek to 2.1.1, ed25519-dalek-bip32 to 0.3.0 #26
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
base: master
Are you sure you want to change the base?
Conversation
30b1850
to
4dce186
Compare
How does this affect performance (the bench should tell us that, I think). |
Looks like the new version is faster. Found this in the CI bench output https://github.com/anza-xyz/solana-sdk/actions/runs/13304474459/job/37152326064?pr=26:
Meanwhile in another unrelated PR: https://github.com/anza-xyz/solana-sdk/actions/runs/13344518453/job/37273344074?pr=40
|
@@ -76,12 +71,12 @@ impl Keypair { | |||
|
|||
/// Returns this `Keypair` as a base58-encoded string | |||
pub fn to_base58_string(&self) -> String { | |||
bs58::encode(&self.0.to_bytes()).into_string() | |||
bs58::encode(&self.to_bytes()).into_string() | |||
} | |||
|
|||
/// Gets this `Keypair`'s SecretKey | |||
pub fn secret(&self) -> &ed25519_dalek::SecretKey { |
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 this should just return [u8; 32]
directly, skip the type alias of ed25519-dalek.
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 function has been deprecated and will be removed anyway
keypair/src/lib.rs
Outdated
@@ -271,11 +262,9 @@ pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>> | |||
if seed.len() < ed25519_dalek::SECRET_KEY_LENGTH { | |||
return Err("Seed is too short".into()); | |||
} | |||
let secret = ed25519_dalek::SecretKey::from_bytes(&seed[..ed25519_dalek::SECRET_KEY_LENGTH]) | |||
let secret_key = ed25519_dalek::SecretKey::try_from(&seed[..ed25519_dalek::SECRET_KEY_LENGTH]) |
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 function never fail, should call unwrap here
24cb6ce
to
c15a222
Compare
We're ready to integrate this now! Do you mind rebasing your branch? Otherwise, I can take care of it. Just let me know |
c15a222
to
aabc669
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.
Looks great to me! Just some small things
@samkim-crypto can you also take a quick look and make sure it's all ok?
@@ -78,19 +75,19 @@ impl Keypair { | |||
/// Returns this `Keypair` as a base58-encoded string | |||
pub fn to_base58_string(&self) -> String { | |||
let mut out = [0u8; five8::BASE58_ENCODED_64_MAX_LEN]; | |||
let len = five8::encode_64(&self.0.to_bytes(), &mut out); | |||
let len = five8::encode_64(&self.to_bytes(), &mut out); |
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: to avoid the copy, this should be able to use as_bytes()
let len = five8::encode_64(&self.to_bytes(), &mut out); | |
let len = five8::encode_64(self.as_bytes(), &mut out); |
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.
self.0.as_bytes()
would give just the secret 32 bytes, not the full 64 bytes
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.
Ah you're right, sorry, I was looking at methods on SigningKey
@@ -76,12 +71,12 @@ impl Keypair { | |||
|
|||
/// Returns this `Keypair` as a base58-encoded string | |||
pub fn to_base58_string(&self) -> String { | |||
bs58::encode(&self.0.to_bytes()).into_string() | |||
bs58::encode(&self.to_bytes()).into_string() | |||
} | |||
|
|||
/// Gets this `Keypair`'s SecretKey | |||
pub fn secret(&self) -> &ed25519_dalek::SecretKey { |
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 function has been deprecated and will be removed anyway
@@ -158,8 +158,8 @@ curve25519-dalek = { version = "4.1.3", features = ["digest", "rand_core"] } | |||
dashmap = { version = "5.5.3", features = ["serde"] } | |||
derivation-path = { version = "0.2.0", default-features = false } | |||
digest = "0.10.7" | |||
ed25519-dalek = "=1.0.1" | |||
ed25519-dalek-bip32 = "0.2.0" | |||
ed25519-dalek = "=2.1.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.
note to self for later: 2.2.0 just got released, so we can bump to that after this lands
.map_err(SignatureError::from_source)?; | ||
let expected_public = ed25519_dalek::PublicKey::from(&secret); | ||
}; | ||
// compiler elides the second len check so try_into().unwrap() is as fast as unsafe code |
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.
cool! Just for my own knowledge, how did you learn / measure that?
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.
compared safe and unsafe versions with godbolt, and saw they were the same: https://godbolt.org/z/qf4cnaWax
keypair/src/lib.rs
Outdated
let keypair_bytes: [u8; ed25519_dalek::KEYPAIR_LENGTH] = keypair_slice.try_into().unwrap(); | ||
let secret: ed25519_dalek::SecretKey = keypair_bytes[..ed25519_dalek::SECRET_KEY_LENGTH] | ||
.try_into() | ||
.unwrap(); | ||
let signing_key = ed25519_dalek::SigningKey::from_bytes(&secret); | ||
let public = ed25519_dalek::VerifyingKey::try_from( | ||
&keypair_bytes[ed25519_dalek::SECRET_KEY_LENGTH..], | ||
) | ||
.map_err(SignatureError::from_source)?; | ||
let expected_public = signing_key.verifying_key(); | ||
(public == expected_public) | ||
.then_some(Self(ed25519_dalek::Keypair { secret, public })) | ||
.then_some(Self(signing_key)) | ||
.ok_or(SignatureError::from_source(String::from( | ||
"keypair bytes do not specify same pubkey as derived from their secret key", | ||
))) |
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 looks like it's doing pretty much the same exact thing as from_keypair_bytes
How about just calling that instead?
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 to me!
@@ -78,19 +75,19 @@ impl Keypair { | |||
/// Returns this `Keypair` as a base58-encoded string | |||
pub fn to_base58_string(&self) -> String { | |||
let mut out = [0u8; five8::BASE58_ENCODED_64_MAX_LEN]; | |||
let len = five8::encode_64(&self.0.to_bytes(), &mut out); | |||
let len = five8::encode_64(&self.to_bytes(), &mut out); |
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.
Ah you're right, sorry, I was looking at methods on SigningKey
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.
Some minor comments below, but looks good to me!
))) | ||
}; | ||
// compiler elides the second len check so try_into().unwrap() is as fast as unsafe code | ||
let keypair_bytes: &[u8; ed25519_dalek::KEYPAIR_LENGTH] = keypair_slice.try_into().unwrap(); |
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 do you think about merging the length check with this line? It seems like the code will be slightly more concise and we can remove the unwrap as well.
let keypair_bytes: &[u8; ed25519_dalek::KEYPAIR_LENGTH] = bytes
.try_into()
.map_err(|_| SignatureError::from_source(String::from(
"candidate keypair byte array is the wrong length",
)))?;
Ok(Keypair(dalek_keypair)) | ||
// this won't fail as we've already checked the length | ||
let secret_key = | ||
ed25519_dalek::SecretKey::try_from(&seed[..ed25519_dalek::SECRET_KEY_LENGTH]).unwrap(); |
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: an unwrap
should be safe here, but why not just use ?
?
ed25519_dalek::SecretKey::try_from(&seed[..ed25519_dalek::SECRET_KEY_LENGTH]).unwrap(); | |
ed25519_dalek::SecretKey::try_from(&seed[..ed25519_dalek::SECRET_KEY_LENGTH])?; |
I can't imagine this changing, but this can future-proof any api changes that introduce a new way of erroring.
Ported from anza-xyz/agave#3088
Summary of Changes
Keypair::generate
now relies on traits from a newer version of the rand crate - it no longer works with rand 0.7.