Designing for taproot

Carrots

UPDATE: Taproot offers space savings and potential transaction fees savings, however it’s complicated and requires nuance to be accurate. There were several things I didn’t understand properly when I wrote this for the first time. Thanks to Murch for pointing this out for me and helping me understand this better. I’ve left the old stuff in-tact but crossed out, and marked the revisions throughout. If there are any other inaccuracies, the failing is mine.

The BitDevs LA meetup group recently threw their own conference! PlebFi LA, a “potluck” version of Jeremy Rubin‘s PlebFi, was a 2-day event focused entirely on taproot. I had the honor of speaking there and acting as one of the hackathon judges. The following is a recap of what I spoke about there.

Special thanks to Christoph Ono for the Bitcoin UI Kit used to make the UI flows in this post!

Who this is for

This is written with two types of folks in mind:

  • Designers who want to understand what value taproot can bring the user
  • Developers who are working on rolling out taproot support in bitcoin wallets and other services.

Why taproot matters

Taproot might be exciting stuff to talk about if you’re a bitcoin developer. However, it’s good to sometimes set aside Schnorr signatures and MAST and consider what value taproot can give to the user.

Why Taproot Matters

Quick disclaimer: I’m a front-end guy and not a protocol developer. If anything in this post doesn’t seem technically accurate to you, feel free to DM me on Twitter and we’ll get it sorted out.

Lower transaction fees

Schnorr signatures means a smaller witness size. Smaller witness means smaller transaction size. Smaller transaction size requires less in fees.

To see a quick visual of what I mean, click on the following randomly selected transactions, click the “details” button, and then compare the “witness” fields:

Crossed out screenshots from Mempool.space
You should see something like this when comparing the above transactions on mempool.space

Optimize Transactions and Fees

Taproot offers potential transaction size savings. It’s not accurate to just say “taproot will always result in smaller transactions”. It depends on the situation. If you’re interested in these subtleties, keep reading; otherwise, skip to “Better Privacy”.

Receiving to P2TR

If I am owed bitcoin, then I might be incentivized to receive bitcoin to a P2TR address. It will actually be more expensive in terms of weight for the sender to create this transaction output, but when I go to spend this P2TR output in the future, it will be cheaper for me in terms of weight.

In other words:

P2TR outputs are more expensive for the sender to create than P2WPKH outputs, but P2TR outputs are cheaper for the recipient to spend.

Multi-sig optimizations

When it comes to multi-sig, P2TR outputs have smaller weight than prior output types.

This creates transaction size savings for multi-sig and would make P2TR outputs preferable over P2WSH outputs, but requires a little more work on protocols like MuSig2 and FROST.

While this does not directly result in transaction size reduction for single-sig, it could help to reduce transaction size overall, which helps us fit more transactions into a block. Fees, of course, will depend on how many transactions are being submitted into the mempool. There’s no way to say for 100% certain that this results in fee reductions, but the ability to fit more transactions into a block could help reduce the pressure to pay higher fees.

Better privacy

Currently, it’s relatively easy to tell when an address is multi-sig (or “threshold-signature” as we’re now saying). If an address begins with “3”, you know it’s P2SH (Pay-to-script-hash). This doesn’t mean it’s definitely multi-sig, but it’s very likely since that’s a common use-case for P2SH. However, regardless if an address begins with 3 or bc1q, once an output from that address is spent, you can definitely tell it’s multi-sig from the witness script, like this one here.

Ignore the above crossed-out text — some of the claims are incorrect based on this data.

Once a UTXO is spent on-chain, it’s easy to tell that it’s multi-sig by looking at the witness script, like this one here.

Furthermore, when people craft unique spending conditions for their transaction outputs, all of these spending conditions will be revealed once that output is spent.

Taproot fixes this. Using taproot, it will be possible to create multi-sig outputs that look the same as single-sig outputs once spent. One day, it may be possible to make lightning channel closes indistinguishable from ordinary single-sig transactions. In the case of complex spending conditions, it will be possible to spend an output while only revealing the condition you are satisfying to spend it.

UPDATE: It’s important to note that merely using P2TR outputs shouldn’t be viewed as some kind of one-step solution for privacy. While it will eventually be possible for single-sig and multi-sig UTXOs to look indistinguishable, this doesn’t prevent basic traceability of transactions on the blockchain. Taproot is an improvement, but shouldn’t be seen as a replacement for things like CoinJoins, using lightning, and more experimental ideas like CoinSwaps and FediMint.

More powerful scripting

Taproot will allow for creating more feature-rich smart contracts on top of bitcoin. We have to use our imagination here, because nobody is creating full-on products like this yet. For an early example, see TARO.

The user doesn’t care

We have to keep in mind that the word “taproot” is going to refer to a type of vegetable or alternative metal band from the early 2000s for most folks. Most users are not going to understand or care much about the underlying technology.

However, things like lower transaction fees, better privacy, and new useful features improve their experience — and we can build all those things with taproot. Avoid talking much about taproot to the user, and instead focus more on what value they are being given.

Adding taproot support to an existing wallet

So, now that we’ve covered the basics of why taproot matters and what value it can bring to the user, let’s talk about what it might look like to add taproot support to an existing wallet.

Send support

Currently, many wallets and services have rolled out support for sending to taproot addresses (referred to as P2TR or bech32m). But there are several that have not. You can keep track of this here on the Bitcoin Wiki.

If you haven’t added support for P2TR to your wallet or service, hopefully you have a decent error state like this one. If you not, you can find examples of this kind of thing in the Bitcoin Design Guide and Bitcoin UI Kit.

Adding in the actual P2TR send support should be a matter of adding in proper address validation. This is likely low-hanging fruit. In my opinion, this is something to add quietly.

❌ This message makes a big deal out of something that may not have a lot of value to the user.

The above UI screen makes a big deal out of taproot sends. Ultimately, sending to taproot is probably too much detail for the average user. It doesn’t benefit them directly, it just makes them more interoperable with other wallets (which should really be the expected norm anyways). I think it’s best to launch taproot sends quietly and avoid talking about them.

✅ Instead, perhaps it’s enough just to let the user know that their software has been updated.

If you must bring mention of taproot sends in your app, perhaps consider adding it to a “change log” notification. Nothing wrong with providing the information for users who are curious and like to dig deeper, but it doesn’t need to be front-and-center. In the above example, there is a notification every time the app updates. Most users will probably just choose “got this”, but some may decide to dig deeper and read the change log.

Receive support

Adding receive support is where things start to get really interesting. This involves upgrading your wallet so that it can generate P2TR addresses.

Taproot addresses: default?

One decision to make is whether or not taproot addresses should be the default for your wallet.

In my opinion: they should be. As outline above, taproot will give clear benefits to the user like improved privacy and lower transaction fees. Take the cognitive burden off of the user and make the best decision for them.

UPDATE: it’s also important to note that if a product improperly implements support for bech32m, then funds could accidentally be burned. We started a conversation about this over in the Bitcoin Design slack to talk about testing wallets and services for proper bech32m support.

However, the user may still find themselves transacting with someone who can not send to P2TR addresses. It’s good to leave in the option generate native segwit addresses for compatibility.

Even if a wallet does not default to P2TR, it can still help the user take advantage of taproot with change addresses. Basically, when the user performs a transaction, a change output is created. Wallets could default change outputs to P2TR addresses, so overtime, more of the user’s funds are stored in taproot addresses. Thanks to Steve Myers for sharing this concept with me.

Diagram showing a transaction where the user's change ouput is a P2TR output
A previous version of this image had the non-taproot outputs labeled simply as “segwit”.
As Murch pointed out to me, technically, they’re all different variations of segwit outputs.

Rolling out the update

Unlike adding send support, adding receive support has some implications for the user and it may be good to notify them of the changes, particularly if this is a wallet that was generated prior to your rolling out taproot support.

That’s because there is the issue of backups. It’s a good idea for the user to have a taproot descriptor backed up so they can properly restore their wallet. This is less important if they are restoring using the same software in which the wallet was created, but great to have for interoperability.

Explain the benefits before you inconvenience the user by having them perform another backup

If your wallet app uses an automatic cloud backup scheme, this step may not be necessary, as you can just have your app automatically add the necessary descriptors to the user’s cloud storage.

However, if your app relies on a manual backup scheme (or offers one in addition to the cloud backup), then you could make this process easier by allowing the user to download a document with less sensitive info like derivation paths and descriptors pre-populated. The user can fill it in with their seed phrase manually.

Muun is already using a user flow similar to this. Users with existing wallets during the taproot activation in November 2021 saw something like this:

Where is taproot going?

Taproot opens the door for a lot of innovation on bitcoin. One area I am watching is FROST and MuSig2, because I am curious if these new multi-key protocols will fit in with our existing multi-sig design patterns.

Beyond that, I think we’ll see people building very interesting things with taproot. TARO is one such idea, but I imagine we’ll see lots of other interesting ideas.

Designers: watch this space for opportunities to help with the UX of these new possibilities. 🎨