-
Notifications
You must be signed in to change notification settings - Fork 220
[PoC] Wallet policies (and miniscript support) #647
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
base: master
Are you sure you want to change the base?
Conversation
Hi Salvatore, I successfully used this PR with simples scripts from Liana, but getting some issue with some more complex one: $ python3 -m hwi --debug --device-type ledger registerpolicy --policy "wsh(or_i(and_v(v:thresh(1,pkh(@0/<8;9>/*),a:pkh(@1/<4;5>/*),a:pkh(@2/<4;5>/*)),older(65535)),or_i(and_v(v:thresh(2,pkh(@0/<6;7>/*),a:pkh(@1/<2;3>*)),older(15001)),or_i(and_v(v:thresh(2,pkh(@0/<4;5>/*),a:pkh(@2/<2;3>/*)),older(15000)),or_d(multi(2,@0/**,@3/**),and_v(v:thresh(3,pkh(@1/**),a:pkh(@2/**),a:pkh(@0/<2;3>/*)),older(1)))))))#lnc99art" --name "Liana" --keys "[\"[9978d14e/84h/0h/0h]zpub6s7PH15YtcVFyEPJjjdNhEjA4n1D77DUhZyU4JZMXsWQ4C8kssYGDrne6jcDTXHRXajxFNTTiCbqpVtqZAhfV37Zm6wcDj4reSujMH3AFgC\",\"[0063c8e2/84h/0h/0h]zpub6rj3eaikqs5UF3gDggHC8inmnYcEFCfSNB3Sja3NkC4bNDURbmGequcC8uPa9GMbcUs7WSBbernhxHgoctjNvmveT5vYQGHQSvSA12g1UwW\",\"[945d917c/84h/0h/0h]zpub6rWPeMxpZS9xpwBadedssZ71UzeutatXnegqqrWkrrSim4BiFrcUdTPtLxtPGpUtBzbiM1ZPaXXVcrhb9Su1ettffQ6B1y5JHcyd4P516rm\",\"[8a491f24/84h/0h/0h]zpub6qaBba3PS8R8k61SueSazVotxKP7iwQ3Gp3c42DTSaWKP5qt6fcSqRjGxw7hRHLP7XaFiEQXDHcKHoZ9rurD9n1SkPFSoYsfP2H7Ch9vbmQ\"]" (keys have been generated for this example) output:
note: i firstly fail to register this policy from Liana before trying with this PR |
@pythcoiner: most likely the reason is that |
i just checked the original keys that throw the errow were |
Fixing those, I was able to register the policy on local tests on NanoS+, so I think it should also work with |
1 + 2 solved my issue, thanks @bigspider! |
@bigspider Unfortunately I found this PR too late. Looks like it's exactly what we need for our project. Apart from the obvious (testing and review), how can we help to move this forward? Would you be willing to rebase so we can test on top of latest master? |
FYI all signing devices supporting miniscript are supported by async-hwi, it should be possible to bind to other languages (or at list to call the cli) |
@guggero Unfortunately, with the little interest over this PR, it has not been feasible to move past the PoC stage when it was proposed. Perhaps now that wallet policies have a BIP number and at least two or more other vendors implemented them, there might be more interest - but at this time, async-hwi is probably the most mature solution. Besides, I can see numerous advantages of a compiled solution (for which it should be feasible to add bindings to pretty much all common languages), over a python implementation. Should there be interest in reviving the work from this PR, perhaps a way to reduce the impact on the public interface would be to encode the BIP-388 policy information inside the PSBT (so the signing API stays |
Thank you both for your responses. Sounds like
That's something I was wondering about as well. Seems like using miniscript descriptors as policies is the agreed path forward, at least for several of the hardware wallet manufacturers. I agree that the BIP might be quite a bit of work. Especially to make sure there isn't a bunch of duplicate information in the PSBT, since some of the information (e.g. xpubs, derivation paths) might already be present in other fields. |
Can you split out a separate PR that just adds miniscript support? See #782. Although I like wallet policies, it would also require changes in Bitcoin Core, so it's a bigger lift. |
Unfortunately I will not be able to work on this at least for the next month or so. Happy to leave it to someone else who might want to take it. Note that adding 'just miniscript support' is quite a bit harder than the native wallet-policy-aware API, as the structure of the descriptor template and keys information must be deduced from the descriptor and the PSBT, which will require some pattern matching. A subset of it could take inspiration from the example code from BIP-388, but that doesn't include the key informations, whose decoding is necessarily based on the info in the PSBT (similarly to what HWI already does for multisig). |
I'm guessing async-hwi converts descriptors to policy and passes that to the device? |
It appears to be here, but this assumes knowledge of the descriptor. When signing transactions, HWI's sign_tx just gets the PSBT. It should in theory be possible to reconstruct it from the scripts, but that's the hard part, and I'm not sure it's worth it: all software wallets trying to sign the transaction already know the descriptor/wallet policy, so they could just pass it along. |
Hello,
this in an exploratory PR as a proof of concept of how wallet policies could look like in HWI.
Wallet policies were presented to the bitcoin-dev mailing list back in May.
A BIP proposal is in preparation here.
The goals of this PR are to:
Wallet policies are designed to be vendor-agnostic.
In fact, they are ready for miniscript wallets, and they might in my opinion be a convenient, opinionated way of adding miniscript support to HWI.
They are implemented in the Ledger bitcoin app since version 2.1.0, which uses them to support miniscript (on segwit only, at this time).
Implementation details
Not production-ready!
In this PR, I attempted to add wallet policies as a first-class object, while not breaking compatibility with existing code.
The three commit add:
HardwareWalletClient
:can_register_wallet_policies
,register_wallet_policy
,display_wallet_policy_address
,sign_tx_with_wallet_policy
.displayaddress
andsigntx
; addedregisterpolicy
.ledger.py
.For subclasses not implementing wallet policies, a compatibility layer guarantees that if the policy falls back into the supported cases (single-signature, or standard multisignature), calls to functions using wallet policies are automatically converted to the corresponding single-sig or multi-sig function to show addresses or sign transactions.
With this approach, software wallets adopting wallet policies, therefore, could use them directly without using any other
HardwareWalletClient
function without wallet policies.Demo
In the following, I'd like to walk you through an end-to-end demo of wallet policies that can be tested from this PR's branch using the Ledger bitcoin testnet app version 2.1.0 in the speculos emulator; the app will be released in production within a few weeks.
In all the examples with multiple keys, internal keys are the ones with fingerprint
f5acc2fd
, which is the fingerprint for the default seed used by the speculos emulator.The command should be run from the root folder of the HWI repository, or after installing the module from this PR (e.g. with
pip install .
).Screenshots are based on the UX for a Ledger NanoS+ device.
Single-signature
In this example, we use a wallet policy for a standard BIP-86 taproot address. Ledger devices require no registration for standard single-signature policies, so this can be used directly.
Device screen:
Output:
Multisignature
Register policy
Device screen:

Output:
Display address
Device screen:

Output:
Sign a psbt with policy
It is relevant to point out that when using wallet policies, it makes sense to use a more specific action rather than "sign a transaction": in fact, the wallet policy specifies exactly what kind of scripts/inputs should be signed, and similarly, what outputs can match a change address.
This allows hardware wallets to correctly identify internal inputs and outputs.
The necessary information about what exact wallet policy should be used for signing is in fact typically available to the software wallet.
Therefore, the action is "sign a transaction with a certain wallet policy".
Device screen:

Output:
Miniscript
Miniscript policy: a 3-of-3 that becomes a 2-of-3 after 90 days:
thresh(3,pk(key_1),pk(key_2),pk(key_3),older(12960))
.Register policy
Device screen:

Output:
Display address
Device screen:

Output:
Sign a psbt with the policy
Device screen:

Output:
Conclusions
I hope this is interesting and I look forward to hearing your comments about whether (and how) wallet policies could be added to hwi.