Skip to content

Full BIP173 (Bech32) support#11167

Merged
laanwj merged 9 commits intobitcoin:masterfrom
sipa:201708_bech32
Sep 29, 2017
Merged

Full BIP173 (Bech32) support#11167
laanwj merged 9 commits intobitcoin:masterfrom
sipa:201708_bech32

Conversation

@sipa
Copy link
Member

@sipa sipa commented Aug 26, 2017

Builds on top of #11117.

This adds support for:

  • Creating BIP173 addresses for testing (through addwitnessaddress, though by default it still produces P2SH versions)
  • Sending to BIP173 addresses (including non-v0 ones)
  • Analysing BIP173 addresses (through validateaddress)

It includes a reformatted version of the C++ Bech32 reference code and an independent implementation of the address encoding/decoding logic (integrated with CTxDestination). All BIP173 test vectors are included.

Not included (and intended for other PRs):

  • Full wallet support for SegWit (which would include automatically adding witness scripts to the wallet during automatic keypool topup, SegWit change outputs, ...) [see SegWit wallet support #11403]
  • Splitting base58.cpp and tests/base58_tests.cpp up into base58-specific code, and "address encoding"-code [see Address encoding cleanup #11372]
  • Error locating in UI for BIP173 addresses.

@luke-jr
Copy link
Member

luke-jr commented Aug 26, 2017

Would prefer to have simply sending-to (maybe validating/analyzing too?) as a separate PR, before wallet upgrades.

I'm not sure when it would make sense to convert between P2SH and BIP173...

@sipa
Copy link
Member Author

sipa commented Aug 26, 2017

@luke-jr I agree, but I consider addwitnessaddress an RPC to aid with testing, not full support.

I'm not sure when it would make sense to convert between P2SH and BIP173...

I think you're right. I'll remove that.

@gmaxwell
Copy link
Contributor

addwitnessaddress is very much not actual support, it's a test shim.

@luke-jr
Copy link
Member

luke-jr commented Aug 26, 2017

But it modifies the wallet, no? Seems useful to review independently from the rest. Especially since it has the additional considerations of what happens if you try to use it and then downgrade to an older version...

@sipa
Copy link
Member Author

sipa commented Aug 26, 2017

@luke-jr Consider that we've since 0.13.1 had support for receiving and spending native witness outputs in the wallet (without that, testing the consensus logic for it would have been much harder), just no way to encode such outputs as strings. So I think the encoding is somewhat orthogonal.

It does modify the wallet, but I'm not sure it's worth trying to separate the logic. We only have one data type (CTxDestination) to encode things we can receive on or send to. Having the ability to send to something but not being able to encode it ourselves would require separating the two, and I expect would be more work then just implementing it all.

Wallet backward compatibility is only affected when you use an import or addwitnessaddress with p2sh=false (the default is `true).

@sipa
Copy link
Member Author

sipa commented Aug 27, 2017

Added support in Python framework, and some integrated some functional tests into the segwit.py test.

FelixWeis referenced this pull request in richardkiss/pycoin Aug 27, 2017
Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

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

Fast code review. Move 4bc71a6 to #11117??

src/bech32.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO bool Decode(const std::string& str, const std::string& hrp, data& d) feels better, and this way below it can early return.

Copy link
Member Author

@sipa sipa Aug 27, 2017

Choose a reason for hiding this comment

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

It's not often used in the Bitcoin Core codebase, but using pairs for multiple returned values is very typical in C++ (see the return type of std::map::insert for example). In C++03 it was a bit verbose to use, but with C++11's auto types and std::tie for assigning to multiple variables, it's pretty convenient. I'd rather stick with the current approach.

src/base58.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Return in new line?

Copy link
Member Author

Choose a reason for hiding this comment

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

done

src/base58.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Sort.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

src/bech32.h Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Sort.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

src/base58.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Must come first? If not which is the cheapest?

Copy link
Member Author

Choose a reason for hiding this comment

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

bech32 is far cheaper (no basis conversion, no SHA256).

src/base58.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Must come first? If not which is the cheapest?

Copy link
Member Author

@sipa sipa Aug 27, 2017

Choose a reason for hiding this comment

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

I haven't benchmarked, but Bech32 should be far cheaper (no SHA256, no basis conversion). There should never be overlap between the addresses, so the order shouldn't matter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, in terms of functionality the order doesn't matter. But at the moment most addresses (don't know numbers) are base58 so for now move bech32::Decode() after DecodeBase58Check()?

It would be cool to move this out of base58.cpp, follow up maybe?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, in terms of functionality the order doesn't matter. But at the moment most addresses (don't know numbers) are base58 so for now move bech32::Decode() after DecodeBase58Check()?

I was using a fail-fast approach, making the thing that most quickly fails first. You're right that as long as there are hardly any bech32 addresses, putting Base58 would be overall faster. But none of this is performance critical anyway...

Copy link
Member Author

Choose a reason for hiding this comment

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

I arbitrarily chose a bech32 prefix for regtest. Feel free to bikeshed (it doesn't even need to be just 2 characters).

src/bech32.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Early return?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

src/bech32.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Early return?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

src/bech32.cpp Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Early return?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

src/bech32.h Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you leave a comment referring the reader to more complete documentation on bech32 (either the BIP or reference repo)? Also would be nice to document somewhere in the codebase what hrp stands for.

I'm thinking something as simple as: "Bech32 is a data encoding used for some newer address formats. Output consists of a human-readable part (HRP) followed by a separator, then the data itself with a checksum. For more details, see documentation of BIP 173."

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done again - I somehow lost this change.

Copy link
Member

Choose a reason for hiding this comment

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

I don't see the comment... I think you lost it again.

Copy link
Member Author

@sipa sipa Sep 15, 2017

Choose a reason for hiding this comment

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

It's there, just a bit higher up in the file.

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Maybe use toupper here to be more descriptive and succinct.

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately, toupper is locale-dependent, so it can't be used for consistent behaviour.

Copy link
Contributor

@jimpo jimpo Sep 3, 2017

Choose a reason for hiding this comment

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

std::toupper(c, std::locale::classic())?

Copy link
Member Author

Choose a reason for hiding this comment

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

Seems overkill.

@sipa sipa force-pushed the 201708_bech32 branch 3 times, most recently from d7dd8a5 to f77636b Compare September 3, 2017 20:14
@sipa sipa added this to the 0.15.1 milestone Sep 5, 2017
@instagibbs
Copy link
Member

Include a test with v1+ address?

laanwj added a commit that referenced this pull request Mar 6, 2018
92f1f8b Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f8 Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)

Pull request description:

  This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.

  This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.

Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
zkbot added a commit to zcash/zcash that referenced this pull request Apr 23, 2018
Bech32 encoding support and t-addr encoding refactor

Cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#7922
- bitcoin/bitcoin#7825
- bitcoin/bitcoin#8317
- bitcoin/bitcoin#9804
  - Only the commit that changed `base58.cpp`
- bitcoin/bitcoin#11117
- bitcoin/bitcoin#11259
- bitcoin/bitcoin#11167
  - Only the first three commits (the fourth commit depends on #2390, later ones are SegWit-specific).

Part of #3058.
zkbot added a commit to zcash/zcash that referenced this pull request May 4, 2018
Refactor t-address encoding

Includes code cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#11117
- bitcoin/bitcoin#11259
  - Only the second commit (first is for QT code)
- bitcoin/bitcoin#11167
  - Only the first commit (the rest are not part of the t-address encoding refactor).

Part of #3058. Precursor to #3202.
mkjekk added a commit to mkjekk/zcash that referenced this pull request May 4, 2018
zkbot added a commit to zcash/zcash that referenced this pull request May 7, 2018
Bech32 encoding support

Cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#8578
- bitcoin/bitcoin#11167
  - Only the second and third commits (first is in #3228, fourth depends on #2390, later ones are SegWit-specific).
- bitcoin/bitcoin#12757
  - Only the change to `src/bech32.h`

Part of #3058.
zkbot added a commit to zcash/zcash that referenced this pull request May 8, 2018
Bech32 encoding support

Cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#8578
- bitcoin/bitcoin#11167
  - Only the second and third commits (first is in #3228, fourth depends on #2390, later ones are SegWit-specific).
- bitcoin/bitcoin#12757
  - Only the change to `src/bech32.h`

Part of #3058.
str4d added a commit to str4d/zcash that referenced this pull request Jun 7, 2018
zkbot added a commit to zcash/zcash that referenced this pull request Jun 11, 2018
Sapling address encodings

This PR enables Sapling keys and addresses to be passed in anywhere Sprout keys
and addresses are used. Doing so will cause crashes until those places are updated
with Sapling support.

Includes code cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#11167
- bitcoin/bitcoin#11630

Closes #3058.
zkbot added a commit to zcash/zcash that referenced this pull request Jun 19, 2018
Sapling address encodings

This PR enables Sapling keys and addresses to be passed in anywhere Sprout keys
and addresses are used. Doing so will cause crashes until those places are updated
with Sapling support.

Includes code cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#11167
  - Only the `ConvertBits()` function.
- bitcoin/bitcoin#11630

Closes #3058.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.