Skip to content

Re-write crate level API#128

Merged
apoelstra merged 1 commit intorust-bitcoin:masterfrom
tcharding:09-01-api
Sep 29, 2023
Merged

Re-write crate level API#128
apoelstra merged 1 commit intorust-bitcoin:masterfrom
tcharding:09-01-api

Conversation

@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding commented Sep 4, 2023

Now includes updates to fuzzing and is on top of #130 (bug fix).

Now we have all the new primitives pieces in place we can re-write the public API to take advantage of them - WIN!

Close: #126

@tcharding
Copy link
Copy Markdown
Member Author

tcharding commented Sep 4, 2023

This PR more or less follows the proposal in #126 but I'm not auto-closing it because it does not include the suggested checksum example.

If you want to define your own checksum you should use the Checksum trait. We should provide an example, maybe of the BIP-93 checksum.

FTR, I did not work off of the proposal except for the docs stuff, I just hacked up what I thought was a useful API (on the plane). I rekon this needs a bit of thought to see if we like it or not? Once we are more-or-less happy with the API I'll go over the docs again and add examples etc. as needed.

Note the segwit API and main API are not exactly uniform because I managed to get on the plane with a three month old git index so did not have the segwit module to look at. I've left it as I wrote it because I would like input from reviewers please as to what is best instead of me just picking the one I think is best.

@tcharding tcharding force-pushed the 09-01-api branch 2 times, most recently from 92f020a to c5bcd1e Compare September 4, 2023 15:37
@tcharding
Copy link
Copy Markdown
Member Author

The commented out example function is code for some module level docs examples.

@tcharding tcharding force-pushed the 09-01-api branch 4 times, most recently from b6c4fda to d2623ec Compare September 11, 2023 15:03
@tcharding
Copy link
Copy Markdown
Member Author

tcharding commented Sep 11, 2023

This might need splitting up into separate PRs now because I've made some changes to the HRP constants to make them more readable.

I've audited the two top level APIs (lib.rs and segwit.rs) and I'm happy they are uniform. Open to naming improvements still of course.

I've improved docs and examples.

Note please the new crate::hrp module that is soley to improve import ergonomics because I noticed we use hrp::BC any time we use the segwit API but one used to have to reach into primitives to get it.

Now includes Codex32 checksum.

I changed the embedded tests so that one uses bech32 and one uses bech32m

@tcharding tcharding force-pushed the 09-01-api branch 3 times, most recently from c036c7f to d45d759 Compare September 11, 2023 16:42
@tcharding
Copy link
Copy Markdown
Member Author

Ok, if CI goes green this is ready for review please @apoelstra, I edited the "what I did" post above, so in case you read a stale version please not this now adds Codex32. If you are more-or-less happy with the current state I can spilt the PR up. I'll ping you @clarkmoody when we are at a "final" re-viewable state so you don't have to follow along if you don't want to.

@tcharding
Copy link
Copy Markdown
Member Author

tcharding commented Sep 11, 2023

FYI to check the embedded tests locally one must pin with cargo update -p proc-macro2 --precise 1.0.60.

I updated to latest nightly while debugging the cargo check command, you might need to do that also.

@tcharding
Copy link
Copy Markdown
Member Author

In case its useful to you @clarkmoody I'm building the docs locally to review them using

RUSTDOCFLAGS="--cfg docsrs" cargo +nightly rustdoc --all-features -- -D rustdoc::broken-intra-doc-links

let hrp = Hrp::parse("bech32").unwrap();

bech32::encode_to_fmt_anycase(&mut encoded, hrp, &base32, Variant::Bech32).unwrap().unwrap();
bech32::encode_to_fmt::<Bech32, ArrayString<30>>(&mut encoded, hrp, &data)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In 4da0a7b:

Could use <Bech32, _> rather than repeating ArrayString<30>.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done, thanks.

/// The codex32 checksum algorithm, defined in [BIP-93].
/// [BIP-350]: <https://github.com/bitcoin/bips/blob/master/bip-0093.mediawiki>
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Codex32 {}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In 4da0a7b:

This can live in a doccomment or something but we probably shouldn't export it from this library.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

@apoelstra
Copy link
Copy Markdown
Member

In 4da0a7b:

  • I'm a bit confused why decode and decode_bech32m/decode_bech32.
  • Could you add an analogous encode_to_write / decode_to_read pair to encode_to_fmt? Then no-alloc users could encode the string either to an io::Write or fmt::Write. (Annoyingly this will require a std gate, but that's ok, it would still be useful I think.)

Otherwise this looks great!

Copy link
Copy Markdown
Member

@clarkmoody clarkmoody left a comment

Choose a reason for hiding this comment

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

Nice top-level examples in the doc code!

Comment on lines +127 to +157
/// Re-exports the hrp types from [`primitives::hrp`] to make importing ergonomic for the top level APIs.
pub mod hrp;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Love the re-exports to the top-level hrp module.

Do the doc comments need to point out that these are re-exports?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a stupid compiler warning now if re-exports don't have doccomments. Since they appear in the docs under Re-exports with a link to their definition, this isn't really sensible, so we've been putting "placeholder comments" like this in rust-bitcoin.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Commented on this below.

pub enum Bech32m {}

/// The codex32 checksum algorithm, defined in [BIP-93].
/// [BIP-350]: <https://github.com/bitcoin/bips/blob/master/bip-0093.mediawiki>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be [BIP-93] here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks, odd that -D rustdoc::broken-intra-doc-links didn't catch that. I've moved the codex32 stuff to a rustdoc comment and remove the link altogether.

pub mod hrp;
/// All the primitive types and functionality used in encoding and decoding.
pub mod primitives;
/// API for encoding and decoding segwit addresses.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In the docs, this comment collides with the existing module-level docs in segwit.rs, giving us:

API for encoding and decoding segwit addresses. Segregated Witness API - enables typical usage for encoding and decoding segwit addresses.

We should remove one of the comments to avoid the redundant sentence.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ha, I saw this once and didn't fix it. Thanks for taking the time to build the docs and check them!

I've removed the docs from rust-bech32/src/hrp.rs and clippy seems to be ok with it, although I'm unsure why. Like @apoelstra said above we saw a new lint trigger for this situation in rust-bitcoin, will see how it goes in CI.

@tcharding
Copy link
Copy Markdown
Member Author

In 4da0a7b:

  • I'm a bit confused why decode and decode_bech32m/decode_bech32.

Ok, I removed them and added more docs about decoding with the checksum algorithm to the decode docs.

  • Could you add an analogous encode_to_write / decode_to_read pair to encode_to_fmt? Then no-alloc users could encode the string either to an io::Write or fmt::Write. (Annoyingly this will require a std gate, but that's ok, it would still be useful I think.)

Done!

Otherwise this looks great!

Thanks man, this force push was the result of a pretty wild session, you can wait to review until I've had a chance to re-look at it with fresh eyes to catch my own mistakes if you like.

@tcharding tcharding force-pushed the 09-01-api branch 3 times, most recently from ecf941f to 68c4dfd Compare September 18, 2023 23:58
src/segwit.rs Outdated
) -> Result<(Hrp, Fe32, Vec<u8>), DecodeFromReaderError> {
let mut s = String::new();
r.read_to_string(&mut s)?;
Ok(decode(&s)?)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In 68c4dfd:

I'll go ahead and ACK this since it's not API-visible, but the string allocation (and UTF-8 checks and everything that comes with it) are all unnecessary here. You should be able to just use the bytes() iterator on the Read, adapt it wiht char::from to get characters, then use the iterator API.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I like it! I'll have go.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I had a bit of a play with this, unless I'm missing something:

  • The iterator API (you mean iter.rs, right?) is for encoding not decoding
  • The API in decode.rs could be changed to enable decoding from a reader but its non-trivial because all the decoding types (eg, UncheckedHrpstring) have lifetimes that expect a string somewhere to reference.

We could read into a buffer because a bech32 string is max 90 chars, then parse it out however we like.

Or am I totally missing something?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No, you may be correct. Several iterations ago I had an idea for decoding through the iterator API and I guess that got dropped.

I think it's fine to just drop this function then. I don't have a clear usecase for it and it doesn't even work with nostd.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed, both in lib.rs and segwit.rs

Copy link
Copy Markdown
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 68c4dfd

apoelstra added a commit that referenced this pull request Sep 19, 2023
ea644f0 decode: Add unit test for parsing segwit address (Tobin C. Harding)
5d6e5c3 decode: Add empty data check (Tobin C. Harding)

Pull request description:

  Noob bug here, I accessed an array without first checking that it was non-empty :(

  Adds unit test as a separate patch, re-arrange to verify the bug.

  Discovered while fuzzing #128.

ACKs for top commit:
  apoelstra:
    ACK ea644f0

Tree-SHA512: dda0b91f8e2f94ba47b0d6f386e1edc17938bf4c71851ec387f922389ba384693655ed863e98bb95f60970bbf36844cc6c58b654c666b6ab1116cd6dea970ba2
Copy link
Copy Markdown
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 9a90d64

Now we have all the new `primitives` pieces in place we can re-write the
public API to take advantage of them - WIN!
@tcharding
Copy link
Copy Markdown
Member Author

Rebaes only, no other changes.

Copy link
Copy Markdown
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 79918f6

Copy link
Copy Markdown
Member

@clarkmoody clarkmoody left a comment

Choose a reason for hiding this comment

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

ACK 79918f6

@apoelstra apoelstra merged commit f982bb9 into rust-bitcoin:master Sep 29, 2023
@apoelstra apoelstra deleted the 09-01-api branch September 29, 2023 17:17
apoelstra added a commit to apoelstra/rust-bech32 that referenced this pull request Mar 29, 2024
In rust-bitcoin#128 we dropped the benchmarks. They can be restore with only minor
tweaks, so do so.
apoelstra added a commit to apoelstra/rust-bech32 that referenced this pull request Jul 6, 2024
In rust-bitcoin#128 we dropped the benchmarks. They can be restore with only minor
tweaks, so do so.
apoelstra added a commit that referenced this pull request Jul 6, 2024
e0b95f1 benchmarks: add benchmarks for checksum param generation (Andrew Poelstra)
cce8a7a benchmarks: restore benchmarks (Andrew Poelstra)
72421dc clippy: remove a couple redundant test imports (Andrew Poelstra)

Pull request description:

  In #128 we dropped the benchmarks. They can be restored with only minor tweaks, so do so.

ACKs for top commit:
  clarkmoody:
    ACK e0b95f1

Tree-SHA512: 6a23ba658ac8536ef6feb9400feddfbc4a561ff5ef1e10eb90bab6cf637c631f73901e7d8a738f8bad3389340fb532d74fe6129e2eb3d115ad01436c2ee298e5
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.

0.10-alpha API changes

3 participants