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

Deprecate from_slice methods in favor of arrays #737

Merged
merged 2 commits into from
Sep 12, 2024

Conversation

jamillambert
Copy link
Contributor

As brought up in issue rust-bitcoin/rust-bitcoin#3102 support for Rust arrays is now much better so slice-accepting methods that require a fixed length can be replaced with a method that accepts an array.

from_slice() methods have been deprecated and calls to it from within the crate have been changed to use the equivalent array method.

Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

Only did shallow review, but everything apart from try_from thing looks good to me, my reviews don't carry much weight in this repo though.

src/key.rs Outdated Show resolved Hide resolved
@tcharding
Copy link
Member

tcharding commented Sep 10, 2024

There are currently not formatting issues on master so there should be no need for a separate formatting patch in this PR bro.

@jamillambert
Copy link
Contributor Author

Third patch removed and incorporated in first two

Copy link
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Hard no deprecating PublicKey::from_slice (but only that one). Other suggestions are not that critical but I'd obviously prefer to fix them.

src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
src/key.rs Outdated Show resolved Hide resolved
@jamillambert
Copy link
Contributor Author

Removed deprecation of PublicKey::from_slice and addressed other suggestions. Thanks.

@apoelstra
Copy link
Member

code review ack 46e06da except that the expect message is still wrong. Honestly I think you should just unwrap here. It is very obvious that let x: [u8; N] = slice[..N].try_into() will succeed and why.

Functions have been added to PrivateKey, PublicKey and XOnlyPublicKey to
allow the creation of a key directly from a byte array.
The PrivateKey and XOnlyPublicKey from_slice functions have been
deprecated and calls to them from within the crate have been changed to
use the equivalent array function.
@jamillambert
Copy link
Contributor Author

Thanks for the review. I have replaced expect with unwrap.

Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 537b85b successfully ran local tests

Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

ACK 537b85b

My suggestions are just because we all enjoy coding round here and it amused me to find a way to re-write your changes using combinators.

Comment on lines 1212 to +1217
pub fn from_slice(data: &[u8]) -> Result<XOnlyPublicKey, Error> {
if data.is_empty() || data.len() != constants::SCHNORR_PUBLIC_KEY_SIZE {
return Err(Error::InvalidPublicKey);
match <[u8; constants::SCHNORR_PUBLIC_KEY_SIZE]>::try_from(data) {
Ok(data) => Self::from_byte_array(&data),
Err(_) => Err(InvalidPublicKey),
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This function could be written with combinators like this:

    pub fn from_slice(data: &[u8]) -> Result<XOnlyPublicKey, Error> {
        <[u8; constants::SCHNORR_PUBLIC_KEY_SIZE]>::try_from(data)
            .map_err(|_| InvalidPublicKey)
            .and_then(|data| Self::from_byte_array(&data))
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does look quite neat with a combinator

@@ -64,6 +64,7 @@ impl SharedSecret {
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret { SharedSecret(bytes) }

/// Creates a shared secret from `bytes` slice.
#[deprecated(since = "TBD", note = "Use `from_bytes` instead.")]
Copy link
Member

Choose a reason for hiding this comment

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

I would have expected with this addition to see a change to call from_bytes. If you like the combinator style you could use

    pub fn from_slice(bytes: &[u8]) -> Result<SharedSecret, Error> {
        <[u8; SHARED_SECRET_SIZE]>::try_from(bytes)
            .map_err(|_| Error::InvalidSharedSecret)
            .and_then(|a| Ok(Self::from_bytes(a)))
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I need to change anything again I'll add this too, thanks

@apoelstra
Copy link
Member

I also prefer the combinator version, though of course I won't hold up the PR over it.

But @Kixunil we need you to take a look at this one again since your status is "change requested".

@Kixunil
Copy link
Collaborator

Kixunil commented Sep 12, 2024

I find match cleaner in cases like this where we're transforming stuff in both branches but if we want combinators then I'd use ? instead of and_then.

Copy link
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

ACK 537b85b

Ok(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) => PublicKey::from_slice(&res),
Ok(constants::PUBLIC_KEY_SIZE) => {
let bytes: [u8; constants::PUBLIC_KEY_SIZE] =
res[0..constants::PUBLIC_KEY_SIZE].try_into().unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Strictly speaking, it'd be better to create a reference here (simply annotating the type with & should work because the conversion is defined) to avoid useless copying but there's a good chance compiler will optimize it out anyway.

Copy link
Member

Choose a reason for hiding this comment

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

Are you saying you can convert a &[u8] to a &[u8; N] via try_into and the compiler will just cast the pointers rather than copying?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Exactly.

Copy link
Member

Choose a reason for hiding this comment

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

Wow, that's a huge win and I feel like a clippy lint should exist for it. (Though it'd be a bit tough in general to tell when the array is only used by reference.)

@@ -1156,8 +1161,7 @@ impl str::FromStr for XOnlyPublicKey {
fn from_str(s: &str) -> Result<XOnlyPublicKey, Error> {
let mut res = [0u8; constants::SCHNORR_PUBLIC_KEY_SIZE];
match from_hex(s, &mut res) {
Ok(constants::SCHNORR_PUBLIC_KEY_SIZE) =>
XOnlyPublicKey::from_slice(&res[0..constants::SCHNORR_PUBLIC_KEY_SIZE]),
Copy link
Collaborator

Choose a reason for hiding this comment

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

LOL, the previous code...

@apoelstra apoelstra merged commit 3453adb into rust-bitcoin:master Sep 12, 2024
30 checks passed
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.

4 participants