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 encoding/decoding bech32 addresses using iterators #117

Merged
merged 1 commit into from
Jul 31, 2023

Conversation

tcharding
Copy link
Member

@tcharding tcharding commented Jul 12, 2023

(Friendly note: clarkmoody unless you are just loving all this iterator stuff I suggest you don't bother reviewing this one (or #113) until apoelstra acks :)

This is a slightly different approach to #113. Done on top of #116, so just the last patch.

  • Conversion to/from bytes/fes by way of the extension traits as in Add iter and hrpstring #113 (still in iter.rs)
  • Checksum iter adapter as in Add iter and hrpstring #113
  • Decoding by way of three structs depending on usage.
  • Encoding by way of a new struct Encoder, uses a builder-like pattern to construct the encoder and then one can call chars() to get a character iterator or fes() to get a field-element iterator (over all the fes that go into the checksum).

This should mean:

  • Cleaner API i.e., easier to use but also easier to not use incorrectly
  • Incorrect use of iterator adaptors should now be harder

IMNSHO the bech32 spec is convoluted as f**k, hiding all the details is not totally possible but this new API attempts to make it possible to correctly use the API without having to spend two weeks reading and re-reading bips 173 and 350.

PR currently does not use the new API

For example usage see:

  • the unit tests in decode and encode
  • the module level rustdocs in encode.rs and decode.rs
  • BIP-173 and BIP-350 test vectors in tests/

@tcharding tcharding mentioned this pull request Jul 12, 2023
src/primitives/encode.rs Outdated Show resolved Hide resolved
src/primitives/iter.rs Outdated Show resolved Hide resolved
@apoelstra
Copy link
Member

Done reviewing 5c9b549. This is definitely shaping up.

@tcharding
Copy link
Member Author

Thanks for the review @apoelstra, I read your comments but didn't get to work on this today. I'm good to implement all suggestions except unsure about the thing I commented on.

@tcharding
Copy link
Member Author

I pushed up what I've done. Currently there is no invariant on the checksum being in data (decode::Hrpstring). Perhaps we should pull out a Parsed type again from decode::Hrpstring that is the pre-parsed concept we had before. I had a play but didn't get anything I really liked.

@tcharding
Copy link
Member Author

ooo, I've come up with something mad. Converting to draft while I polish it, will push shortly.

@tcharding tcharding marked this pull request as draft July 17, 2023 02:02
@tcharding
Copy link
Member Author

tcharding commented Jul 17, 2023

Hey @apoelstra check this re-write of the decode module out. I'm not happy with the three type names but I'm super happy with the abstractions - let me know what you think. (Its in a separate patch, will squash once you've had a look.)

EDIT: I originally called them Adt0, Adt1, and Adt2, while writing docs I came up with the current names.

@apoelstra
Copy link
Member

@tcharding looks great! I'm unsure whether KnownHrp is worth the reduction in flexibility, since we don't really use it for anything.

Agreed that the names are no good. I suggest

  • Parsed becomes UncheckedHrpString or maybe Unchecked
  • Base32 becomes HrpString
  • Segwit can stay as Segwit, or maybe it should be SegwitHrpString.

@tcharding
Copy link
Member Author

Used UnvalidatedHrpString instead so as not to overload "check" and SegwitHrpString, I think we should err on the side of explicitness with this module.

@tcharding
Copy link
Member Author

Removed KnownHrp and inlined the check.

@tcharding tcharding force-pushed the 07-11-bech32-segwit-iter branch 2 times, most recently from bd690b0 to d4051b4 Compare July 19, 2023 02:07
@tcharding
Copy link
Member Author

Just the padding thing left to do.

@tcharding tcharding force-pushed the 07-11-bech32-segwit-iter branch 2 times, most recently from 341ed48 to b2e335e Compare July 19, 2023 05:55
@tcharding
Copy link
Member Author

tcharding commented Jul 19, 2023

Added non-zero padding checks.

I changed two of the validate functions that convert from one type to another HrpString to SegwitHrpString to consume self, can you think of any reason why this might be too restrictive?

I found some bugs in the len methods I wrote, now fixed.

@tcharding tcharding marked this pull request as ready for review July 19, 2023 05:57
@tcharding
Copy link
Member Author

tcharding commented Jul 20, 2023

Changes in force push:

  • Added a bunch more rustdocs incl. examples
  • Removed the with_checksum function from BytesIterExt (I added it recently and it is no good, found this out while adding doc tests).

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 3ca7a19

@tcharding
Copy link
Member Author

Changes in force push (all to decode:

  • Fixed stale local variable names (after all the type naming churn)
  • Fixed an error variant (also stale)
  • Fixed incorrect docs on error types (cut'n'pasta fails)

@tcharding
Copy link
Member Author

@clarkmoody this one is ready for review if you have the cycles to spare please. Take your time.

@tcharding
Copy link
Member Author

While depending on this branch in rust-bitcoin I noticed one error variant was misnamed, renamed SegwitError -> SegwitHrpstringError

@tcharding
Copy link
Member Author

tcharding commented Jul 21, 2023

Ah sorry @clarkmoody, might want to wait some more ...

@apoelstra this HRP ("bc", "tb", "bcrt") thing is pernicious. I attempted to use this branch today in rust-bitcoin and its basically unusable because of the HRP checks, one cannot get any segwit checks done for a regtest address. Pushed a quick Friday afternoon fix to get the discussion started.

See rust-bitcoin/rust-bitcoin#1951 for usage of this branch, oh and BTW its pretty nice ;)

@apoelstra
Copy link
Member

Lol that Bitcoin Core doesn't even respect the "rule" that the HRP has to be bc or tb. It's a stupid rule and ACK dropping it.

@apoelstra
Copy link
Member

apoelstra commented Jul 21, 2023

ACK e3d62d4 except that the last commit should be cleaned up (at least, fix the CI error and remove 'WIP' from the commit message).

@tcharding
Copy link
Member Author

Cleaned up and squashed! Note also the additional functions on Hrp commented on above.

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 de7da50

@tcharding
Copy link
Member Author

Ok @clarkmoody, now its ready for you please if you have time.

@tcharding
Copy link
Member Author

If/when this merges should we consider releasing a new version at this stage? The benefit is that the primitives module is in place so if we release we can use it in rust-bitcoin and the play around with it and improve it as needed. Also I do not think that we can get much more done in time for the next release of rust-bitcoin and it would be super nice to be using this stuff already so we can start work on other address improvements in rust-bitcoin. Is there any downsides of doing so that I'm overlooking?

@apoelstra
Copy link
Member

@tcharding we should look at the diff and see how many APIs we've deleted already, and consider trying to make best-effort replacements of those as a stop-gap.

@apoelstra
Copy link
Member

Actually, I think we should release this with a -alpha0 suffix or something rather than trying to emulate the old API. Then people can use it but nobody will feel forced into it.

@tcharding
Copy link
Member Author

I think we should release this with a -alpha0 suffix

Good idea.

Add support for:

- Converting bytes to field elements using two extension traits (and
iterator apaptors).
- Checksumming an stream of field elements.
- Decoding bech32 hrpstrings (as well as segwit addresses).
- Encoding hrpstrings by way of an `Encoder` and a bunch of iterator
  adaptors.
@tcharding
Copy link
Member Author

Pushed code comment change to bip-173 test to mirror the bip-350 one.

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 5478e2b

This was referenced Jul 26, 2023
@tcharding
Copy link
Member Author

If you are interested @clarkmoody there is a PR in rust-bitcoin showcasing usage of this branch.

rust-bitcoin/rust-bitcoin#1951

Copy link
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.

Massive changes! Thanks for the hard work. Agreed with the comment in rust-bitcoin about a shortcut method to collapse that large iterator chain.

@tcharding
Copy link
Member Author

Thanks man, we worked hard on this one.

@apoelstra apoelstra merged commit d998236 into rust-bitcoin:master Jul 31, 2023
12 checks passed
@tcharding tcharding deleted the 07-11-bech32-segwit-iter branch August 1, 2023 23:55
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

3 participants