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

Add support for prefixes to the FromHex trait #58

Closed
wants to merge 3 commits into from

Conversation

tcharding
Copy link
Member

@tcharding tcharding commented Jan 8, 2024

Draft because error handling of FromHex needs attention and also I can't work out how to print backwards in hashes anymore.

Add support for parsing prefixed strings as well as requiring the presence or absence of the prefix.

This code was copied from rust-bitcoin. The error type was re-named.

@apoelstra
Copy link
Member

concept ACK. I'd drop the bolding from "not" in "not recommended for user input".

@tcharding tcharding force-pushed the 01-08-improve-traits branch from dc955db to 4668969 Compare January 9, 2024 03:54
@tcharding
Copy link
Member Author

Added a solution to the inner String error, WIP for feedback, probably falls in @Kixunil's wheelhouse.

@tcharding tcharding force-pushed the 01-08-improve-traits branch 2 times, most recently from da62234 to e44ed4f Compare January 9, 2024 04:00
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.

I was just writing an objection but I've just realized the from_hex method was wrong from the beginning of this crate. It changed the semantics of to allow 0x which previously wasn't allowed causing everyone who used it to accidentally implement the broken "robustness" principle. While we've strictly issued breaking versions it's still subtle and people probably thought it's the same method.

Thankfully it didn't affect most of the hashes because of reversed handling. But it does affect FromStr for Midstate.

And since the robustness principle is broken, I would prefer changing the semantics of from_hex to what it originally was and use from_maybe_prefixed_hex for the current one.

Definitely concept ACK doing something about this.

@Kixunil
Copy link
Collaborator

Kixunil commented Jan 15, 2024

Regarding InputString, it was never intended to appear in stable public API and pulling in bitcoin_internals sucks for the same reason this crate is not called bitcoin_hex. So I suggest just creating #[non_exhaustive] pub struct MissingPrefixError(#[cfg(feature = "alloc")] String); and using that one in the variant.

@tcharding
Copy link
Member Author

The main difference being that hex-encoded bytes never start with 0x prefix so trying to write that code would be silly/buggy.

Quote for #2323

I had definitely forgotten this, this is a simple discreet problem that we can fix. Leave it with me.

As suggested by clippy remove the needless borrow.
@tcharding tcharding force-pushed the 01-08-improve-traits branch from e44ed4f to 2b1359f Compare February 12, 2024 03:12
@tcharding tcharding marked this pull request as ready for review February 12, 2024 03:12
Hex strings may or may not include a prefix. We want to default to
explicitly disallowing a prefix in `FromHex` because that is the
behaviour we expect in `rust-bitcoin`.

Add functions to the `FromHex` trait for various prefix states.
@tcharding tcharding force-pushed the 01-08-improve-traits branch from 2b1359f to c5a4cdf Compare February 12, 2024 03:43
#[cfg(not(feature = "alloc"))] S: AsRef<str>,
>(s: S) -> Result<Self, Self::Error> {
if s.as_ref().starts_with("0x") {
Self::from_no_prefix_hex(s.as_ref().trim_start_matches("0x"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

trim_start_matches removes repeated matches so it allows 0x0x0x0x42, which is wrong. Also the whole code seems to be needlessly complicated. You should only need this:

Self::from_no_prefix_hex(s.strip_prefix("0x").unwrap_or(s))

#[rustfmt::skip]
fn from_hex<
#[cfg(feature = "alloc")] S: AsRef<str> + Into<String>,
#[cfg(not(feature = "alloc"))] S: AsRef<str>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is broken because people can call the method for non-alloc and then alloc would silently add the bound.

/// Parses provided string as hex explicitly requiring there to not be a `0x` prefix.
///
/// This is not recommended for user-supplied inputs because of possible confusion with decimals.
/// It should be only used for existing protocols which always encode values as hex without 0x prefix.
Copy link
Collaborator

Choose a reason for hiding this comment

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

There should be a note that this is equivalent to from_hex But maybe let's not duplicate the method?

#[cfg(not(feature = "alloc"))]
return Err(MissingPrefix(MissingPrefixError()));
} else {
Ok(Self::from_no_prefix_hex(s.as_ref().trim_start_matches("0x"))?)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same problem as above, you can use s.as_ref().strip_prefix("0x").ok_or_else(|| MissingPrefixError(s.into()).into())

@tcharding
Copy link
Member Author

This PR is tied up with the FromHex error stuff.

@tcharding tcharding marked this pull request as draft February 12, 2024 23:18
@tcharding
Copy link
Member Author

Consumed by #67

@tcharding tcharding closed this Feb 13, 2024
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.

3 participants