Taproot support
Introduction
Taproot scripts (P2TR) are a new SegWit version 1 output type that is more efficient in terms of verification computational requirements, it is in many cases cheaper in terms of fees, uses schnorr signatures (which allows us to do some extra magic easierly) and solves few problems that allows for example participate in coinjoins with hardware wallets, among other many goodnesses.
Goal
To support pay-to-taproot in a fullt-transparent way so users can take advantage of the benefits without paying virtually any cost. This is becase supporting pay-to-taproot scripts would allow us to have creaper coinjoins, what is in general a good things; coinjoin with hardware wallets and implement solutions that involve DH key sharing (like SNICKER just to mention one random example)
Scope
End-to-end support needs changes in the compact filters, KeyManager class (KeyChain class and DestinationProvider class), TransactionProcessor class, Hardware wallet integration, CoinjoinClient class, AmountDecomposer class and PayJoinClient class.
Also, it will require tiny changes in WasabiJsonRpcServer class, HdPubKey class, TransactionFactory class, AliceClient class, ArenaClient class.
Finally, quite a lot of things should be removed from the GUI because they are wrong, unconvenient or simply make no sense. However, in some cases we would want to use also some extra information to improve the quality of what we providing.
Receving taproot transactions
It is necessary to be able to generate taproot
scripts, ideally for both internal and external usage, what
requires changes in the KeyManager
. The new script
generated must be recognized in the incoming transactions, what requires
Compact Filters
to include this new script types and in the
TransactionProcessor
to recognize the received transaction
could be relevant. Once these three things are in place the wallet’s
balance can be calculated taking into account transactions comming
in/going out the wallet.
Auto-upgraded wallets
Current wallet .json files will be upgraded automatically to support
taproot by generating m/86h
keys by adding new fields
TaprootExtPubKey
and TaprootAccountKeyPath
. In
the case of the TaprootExtPubKey
field it needs to be
generated from the master extended private key which is
in protected with a password (at least in many cases) so, it is only
possible to do after a correct login because at that moment we know the
password to decrypt the key.
Read-Only wallets
Read-only wallets don’t have secret material and for that reason it is impossible to derive the new extended public key. In case of RO wallets generated by importing HWs then it is possible to implement a mechanism for upgrading by querying the device for the taproot extpubkey while in case of simply RO wallets created manually the process of upgrading have to be done manually too.
Sending taproot transactions
The wallet should be able to send transactions containing the new type of script, this means that the fee calculation needs to have the script type into account (the taproot inputs size and the taproot output size) and be able to sign the transaction which hash includes data from spending transaction outputs (such as amounts).
Also, most of the times a transaction uses a change output that could need to consider the script type too. Other algorithms invoved in sending needs to take the script type (or the size/fee) in order to select the combination of coins (manual coinjoin selection should display the script type because it is important in that context)
Coinjoining with taproot
Given a coinjoin is a kind of self-spending transaction, it requires the same changes that we saw above. However there are addictional considerations to take into account regarding to anonscore calculation and input selection involving different script types, as well as cost function.
GUI
The GUI currently display nonsenses like max gap
for
internal external (segwit) keys and that should be removed. The same
happends with output descriptors
which should be moved to
rpc because it is somehow an advance-user-only feature, at leat for
now.
In Wallet Info we are displaying segwit derivation path and extpubkey. We should display the same for taproot scripts.
During recovery process the GUI allows the user to specify a custom derivation path for segwit keys (crazy) and we should remove it. Things like the alert notification after the minimum gap limit is overreached, that was never ported from ww1 and remains an incompleted feature, has to be removed.
The coin selection page/coins viewer would need to display the script type.
Hardware wallets
Currently Wasabi, when imporing wallets from HW only uses the segwit derivation path but that can be improved to cover taproot too. In fact, in the context of future usage of wabisabi by Trezor HW it is important that Wasabi can at least display the same segwit and taproot keys/balance.
Something similar happens with ColdCard wallet because that wallet generates an skeleton Wasabi wallet .json file containing only the segwit path but they could also include the extended key path taproot.
Backward compatibility
By it nature this is not backward compatible in the sense that one you received a taproot payment you cannot downgrade tour wallet without creating confusion on the user. The issues were explained here: https://github.com/zkSNACKs/WalletWasabi/pull/8994#issuecomment-1227348740
Development
The amount of work required to cover all the details is too big to implement in only one Big Bang Pull request so, the idea is to split the development in tree stages:
Supporting taproot internally
To Send, receive and coinjoin with taproot scripts in a fully transparent way comes first. The goal is to have the plumbing working well and no more than that. No changes in UI, no address hardest questions nor small details, only implement what must be implemented.
Coinjoin startegies
Update AmountDecomposer
to understand script types and
do the same for the coin selection algorithm for coinjoins. Review
automatic coin selection for spending (BnB too). Make sure payjoin
payments can support taproot (or prevent using taproot). Review Hardware
wallet importing code to create the new keymanager fields too.
Update GUI
This consists mostly in removing useless things but also in displaying new info (or move that info somewhere else when it is too messy).
Questions
- Give minimum denomination outputs are more expensive to spend if they are taproot. Should we do something about it?
- Do we want to randomize change output types?