-
Notifications
You must be signed in to change notification settings - Fork 100
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
bitcoin: add support for tr() wallet policies/descriptors #1231
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
e1ebd6a
to
e481155
Compare
86d08c5
to
f2dcb4e
Compare
9e5112c
to
e3b8167
Compare
Pushed another commit to implement detection of provably unspendable Taproot internal keys, see commit msg and comments for more infos. |
a4fca57
to
474de0d
Compare
4997ec4
to
3ef2408
Compare
Rebased |
3ef2408
to
06bf7a5
Compare
Beerosagos
approved these changes
Sep 24, 2024
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.
utACK with a few comments
a9bb383
to
11bb9a0
Compare
Support for Taproot wallet policies: `tr(INTERNALKEY,{TREE})` where `TREE=SCRIPT` or `TREE={TREE,TREE}`. SCRIPT can be an arbitrary miniscript like we already suppot in `wsh(<miniscript>)` policies, with slight adaptations for the tr() context. References: - https://github.com/bitcoin/bips/blob/master/bip-0388.mediawiki - https://github.com/bitcoin/bitcoin/blob/efbf4e71ce8e3cd49ccdfb5e55e14fa4b338453c/doc/descriptors.md `tr(@0/**)` is equivalent to BIP-86 that we already support as a SimpleType (single signature). The Taproot output key (which is in the Taproot address) is `internalkey + tweak` where tweak is either a standard tweak if no tree is present, or the merkle root hash of the tree. A tr() UTXO can be spent by signing with the private key of the output key (i.e. the tweaked private key of the internal key), called a key path spend, or by providing and satisfying a script that is a leaf of the tree, called a script path spend. When spending using the the output key, it is the same as BIP-86 and the BIP341 sighash computation is the same. When spending using a leaf script, the sighash algo is extended - see the changes to bip341.rs and the documentation that is referenced there. We change keystore_secp256k1_schnorr_bip86_sign to keystore_secp256k1_schnorr_sign, taking the tweak as an argument instead, which we feed from signtx.rs depending on whether we are spending BIP-86, a policy with/without a tree. This commit adds significant binary bloat (~47kB), in large part because rust-miniscript uses generics, so Miniscript<Tr> duplicates a lot of the code of Miniscript<Wsh>, even though it is nearly identical. This can be solved over time in rust-miniscript to reduce the binary size cost of this feature. With these commits since the previous release, we also reduced space by more than this feature pulls in: daa745f debb871 2fa257c 61a82ff ``` 749548 build/bin/firmware.bin (based on this commit) 753272 firmware.v9.19.0.bin ```
In Taproot policies, it is a common pattern to use an unspendable internal public key if one only wants to use script path spends, e.g. tr(UNSPENDABLE,{...}) https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs decribes that one could use the NUMS point for that: > One example of such a point is H = lift_x(0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0) which is constructed by taking the hash of the standard uncompressed encoding of the secp256k1 base point G as X coordinate. Wallet policy keys however must be xpubs, and also it is not desirable to use the NUMS point, as described in https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304: > 1. unspendable keys should be indistinguishable from a random key for an external observer; > 2. in a descriptor with the range operator (like the wallet policies > compatible with most known wallet account formats), each > change/address_index combination must generate a different unspendable > pubkey, and they should not be relatable to each other (in order to > avoid fingerprinting); The proposal in https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304/21 to use an xpub with the NUMS public key and a chain_code derived as the hash from the xpubs in the descriptor was adopted by Liana wallet. This commit implements this. Note that even though this proposal it not a standard yet, it is still provably unspendable, so we can display this info to the user. A future standard to achieve the same can be included later.
11bb9a0
to
aa9b932
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
See commit msg.
This can also be tested using
then in in this branch of bitbox-api-rs: BitBoxSwiss/bitbox-api-rs#80: