-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Add OutputType::BECH32M and related wallet support for fetching bech32m addresses #22154
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
Conversation
4549a29 to
3f68bb5
Compare
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
3f68bb5 to
73ddcb8
Compare
fjahr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks close, only some style nits and open questions/suggestions.
src/wallet/scriptpubkeyman.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could use constexpr I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried that but it doesn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't constexpr things that need allocation. You could use an array instead of an unordered_set, and use std::find to look up (which will likely be faster too, due to the tiny size), but it really doesn't matter here.
02657d1 to
05ff76c
Compare
|
utACK 05ff76c3aad6905d984ba1764c8045ca530fbf8f |
Sjors
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK 05ff76c
I made a followup PR that makes the defaults a bit more friendly, and adds GUI support: #22260
src/wallet/scriptpubkeyman.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a1373469af96bf77bad65415c4b456f182dbc3fe : is this just belt and suspenders? When I do getnewaddress Test bech32m on legacy wallet for this commit, it's caught earlier and returns No bech32m addresses available. That's because CWallet::GetNewDestination tries GetScriptPubKeyMan first for the requested type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, just belt and suspenders.
src/wallet/wallet.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an extra safety measure, maybe double-check that Taproot is active like in #22156
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is generic for future segwit versions, I'm not sure doing that makes sense. For taproot specifically, there won't be a bech32m ScriptPubKeyMan until taproot activates anyways.
05ff76c to
f70d55c
Compare
|
re-utACK f70d55c136d9fc0bc986cc86e619570e0417d188 |
maflcko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left two comments.
src/wallet/wallet.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how difficult it would be to fix, but the general idea for translations is to pass up the bilingual string and let the caller pick the right version. Otherwise the RPC responses (and debug log) might be partially translated. Functional test might fail when run with the gui.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that will be a bit invasive since several of the functions involved use std::string error rather than bilingual_str. Perhaps for a followup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if you're going to translate anything, it's better to use bilingual_str. I would prefer to do this right in the first go, instead of having another follow-up commit to prevent RPC messages from being translated.
Alternatively just leave this untranslated for now. This is marked for 22.0 and we've passed the translation string freeze.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the strings I added, I was just following the pattern already in use in these functions. For this change in particular, it was to make the style unified. Unless this is considered a blocker, I'm going to leave it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok…
cae6672 to
f33361c
Compare
|
Concept ACK |
|
re-utACK f33361c17f3937ee8819fcea76548e19f6ac6558 |
|
re-ACK f33361c The only changes since my last review was a reorganization of the code changes in |
|
Code review ACK f33361c17f3937ee8819fcea76548e19f6ac6558 I think the potential RPC error message translation issue mentioned in #22154 (comment) needs to be addressed at some point, but also think it's not a blocker for 22.0. |
|
I get an error in wallet_taproot.py: Remaining jobs: [wallet_taproot.py]
1/1 - wallet_taproot.py failed, Duration: 1 s
stdout:
2021-06-23T01:47:26.095000Z TestFramework (INFO): Initializing test directory /tmp/test_runner_₿_🏃_20210623_134725/wallet_taproot_0
2021-06-23T01:47:26.359000Z TestFramework (INFO): Creating wallets...
2021-06-23T01:47:26.605000Z TestFramework (INFO): Mining blocks...
2021-06-23T01:47:26.694000Z TestFramework (INFO): Testing tr(XPRV) address derivation
2021-06-23T01:47:26.745000Z TestFramework (INFO): Testing tr(XPRV) through sendtoaddress
2021-06-23T01:47:26.770000Z TestFramework (ERROR): JSONRPC error
Traceback (most recent call last):
File "/home/meshcollider/bitcoin/test/functional/test_framework/test_framework.py", line 128, in main
self.run_test()
File "/home/meshcollider/bitcoin/test/functional/wallet_taproot.py", line 347, in run_test
1
File "/home/meshcollider/bitcoin/test/functional/wallet_taproot.py", line 314, in do_test
self.do_test_sendtoaddress(comment, pattern, privmap, treefn, keys[0:nkeys], keys[nkeys:2*nkeys])
File "/home/meshcollider/bitcoin/test/functional/wallet_taproot.py", line 262, in do_test_sendtoaddress
addr_g = self.rpc_online.getnewaddress(address_type='bech32')
File "/home/meshcollider/bitcoin/test/functional/test_framework/coverage.py", line 47, in __call__
return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
File "/home/meshcollider/bitcoin/test/functional/test_framework/authproxy.py", line 146, in __call__
raise JSONRPCException(response['error'], status)
test_framework.authproxy.JSONRPCException: Error: No bech32 addresses available. (-12)
2021-06-23T01:47:26.821000Z TestFramework (INFO): Stopping nodes
2021-06-23T01:47:27.028000Z TestFramework (WARNING): Not cleaning up dir /tmp/test_runner_₿_🏃_20210623_134725/wallet_taproot_0
2021-06-23T01:47:27.028000Z TestFramework (ERROR): Test failed. Test logging available at /tmp/test_runner_₿_🏃_20210623_134725/wallet_taproot_0/test_framework.log |
Make sure that LegacyScriptPubKeyMan can only be used for legacy, p2sh-segwit, and bech32 address types.
Bech32m addresses need their own OutputType We are not ready to create DescriptorScriptPubKeyMans which produce bech32m addresses. So don't allow generating them.
If a transaction as a segwit output, use a bech32m change address if they are available. If not, fallback to bech32. If bech32 change addresses are unavailable, fallback to the default address type.
f33361c to
fbf142e
Compare
The tr() descriptor, WitnessV1Taproot CTxDestination, and WitnessUnknown CTxDestination are OutputType::BECH32M so they should report as such.
We don't want the legacy wallet to ever have bech32m addresses so don't allow importing them. This includes addmultisigaddress as that is a legacy wallet only RPC Additionally, bech32m multisigs are not available yet, so disallow them in createmultisig.
Adds an error output parameter to all GetReservedDestination functions so that callers can get the actual reason that a change address could not be fetched. This more closely matches GetNewDestination. This allows for more granular error messages, such as one that indicates that bech32m addresses cannot be generated yet.
|
Silent merge conflict, rebased and fixed. |
fbf142e to
754f134
Compare
|
re-utACK 754f134: only change is switching to |
jonatack
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 754f134
When should bech32m be added to the -addresstype and -changetype wallet config option helps?
| std::optional<OutputType> GetOutputType() const override { return std::nullopt; } | ||
| }; | ||
|
|
||
| static std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In commit 87a0e7a, src/script/descriptor.cpp should include outputtype.h where OutputTypeFromDestination() is moved.
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -5,6 +5,7 @@
#include <script/descriptor.h>
#include <key_io.h>
+#include <outputtype.h>
#include <pubkey.h>
#include <script/script.h>
#include <script/standard.h>| self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32') | ||
|
|
||
| if self.options.descriptors: | ||
| self.log.info("Descriptor wallets do not have bech32m addresses by default yet") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/addreses/addresses/ should be fixed one commit earlier in 87a0e7a
When we make bech32m descriptors by default. |
|
re-ACK 754f134 Confirmed only changes were rebasing and fixing |
|
I rebased my followup in #22260 (which probably works best if you don't set |
Currently bech32m addresses are classfied as bech32. Because bech32m is incompatible with bech32, we need to define a new
OutputTypefor it so that it can be handled correctly. This PR addsOutputType::BECH32M, updates all of the relevantOutputTypeclassifications, and handle requests for bech32m addresses. There is now abech32maddress type string that can be used.tr()descriptors now report their output type asOutputType::BECH32M.WtinessV1TaprootandWitnessUnknownare also classified asOutputType::BECH32M.importaddressandimportmulti), will not be created when getting all destinations for a pubkey, and will not be added withaddmultisigaddress. Additional protections have been added toLegacyScriptPubKeyManto disallow attempting to retrieve bech32m addresses.createmultisigwill also disallow the bech32m address type.DescriptorScriptPubKeyMancannot and will not create atr()descriptor. Protections have been added to make sure this cannot occur.bech32mwhen there is a segwit v1+ output script and the wallet has a bech32mScriptPubKeyMan, falling back to bech32 if one is not available.