Copies of all published parts of our weekly series on preparing for taproot activation at block 709,632.

  1. Bech32m sending support
  2. Is taproot even worth it for single-sig?
  3. Taproot descriptors
  4. From P2WPKH to single-sig P2TR
  5. Why are we waiting?
  6. Learn taproot by using it
  7. Multisignature overview
    1. Using multisignatures
    2. Threshold signing
  8. Multisignature nonces
  9. Signature adaptors
    1. Adaptor magic
    2. Multisignature adaptors
  10. PTLCs
    1. Privacy problems with HTLCs
    2. The PTLC solution
  11. LN with taproot
    1. PTLCs Over LN
    2. P2TR Channels
    3. Time Frames
  12. Vaults with taproot
  13. Backup and security schemes
  14. Testing on signet
  15. Signmessage protocol still needed
  16. Output linking
  17. Is cooperation always an option?
  18. Trivia
  19. Future consensus changes
  20. What happens at activation?
  21. Thank you!

Bech32m sending support

Originally published in Newsletter #154

Starting at block 709,632, expected in November, Bitcoin users will be able to safely receive payments to taproot addresses. Given the user enthusiasm for taproot and the five months that wallet developers have to implement support for it, Optech expects there to be several popular wallets that will allow their users to generate taproot addresses at the earliest possible moment.

That means any other wallet or service that sends bitcoins to user-provided addresses needs to be able to send to taproot addresses by block 709,632 or risk confusing and disappointing its users. Pay to TapRoot (P2TR) addresses use bech32m as specified in BIP350, which is slightly different than BIP173’s bech32 algorithm used for segwit v0 P2WPKH and P2WSH addresses. Bech32m uses the constant 0x2bc830a3 instead of bech32’s 0x01 in the checksum function.

Changing that single constant provides the ability to verify bech32m checksums, but the code still needs to use the original constant for existing P2WPKH and P2WSH addresses. The code needs to decode the address without verifying the checksum, determine whether it uses v0 segwit (bech32) or v1+ segwit (bech32m), and then validate the checksum with the appropriate constant. For examples, see the PR that updated the bech32 reference implementations for C, C++, JS, and Python. If the code already uses the reference libraries, they can be updated to the latest code from that repository, although note that some of the APIs have slight changes. BIP350 and the reference implementations provide test vectors that all bech32m implementations should use.

Although receiving payments to taproot addresses won’t be safe until block 709,632, sending payments should not cause any problems for the sender. Bitcoin Core has supported relaying and mining transactions with taproot-paying outputs since version 0.19 (released November 2019). Optech encourages developers of wallets and services to implement support for paying bech32m taproot addresses now rather than waiting until after taproot activates.

Is taproot even worth it for single-sig?

Originally published in Newsletter #155

Using Optech’s transaction size calculator, we can compare the sizes of different types of single-sig transactions. As expected, transactions using P2WPKH inputs and outputs are much smaller than those using P2PKH inputs and outputs—but, perhaps surprisingly, P2TR transactions are slightly larger than equivalent P2WPKH transactions.

  P2PKH (legacy) P2WPKH (segwit v0) P2TR (taproot/segwit v1)
Output 34 31 43
Input 148 68 57.5
2-in, 2-out tx 374 208.5 211.5

That may make it seem counterproductive for single-sig wallets to implement taproot spending in preparation for block 709,632, but a closer look reveals that there are a number of advantages to using P2TR for single-sigs, both for wallet users and for the network as a whole.

  • Cheaper to spend: it costs about 15% less at the input level to spend a single-sig P2TR UTXO than it does to spend a P2WPKH UTXO. An overly simple analysis like the table above hides the detail that the spender can’t choose which addresses they’re asked to pay, so if you stay on P2WPKH and everyone else upgrades to P2TR, the actual typical size of your 2-in-2-out transactions will be 232.5 vbytes—while all-P2TR transactions will still only be 211.5 vbytes.

  • Privacy: although some privacy is lost when early adopters change to a new script format, users switching to taproot also immediately receive a privacy boost. Your transactions will be able to look indistinguishable from people working on new LN channels, more efficient DLCs, secure multisignatures, various clever wallet backup recovery schemes, or a hundred other pioneering developments.

    Using P2TR for single-sig now also allows your wallet to upgrade to multisignatures, tapscripts, LN support, or other features later on without affecting the privacy of your existing users. It won’t matter whether a UTXO was received to an old version or a new version of your software—both UTXOs will look the same onchain.

  • More convenient for hardware signing devices: since the rediscovery of the fee overpayment attack, several hardware signing devices have refused to sign a transaction unless each UTXO spent in that transaction is accompanied by metadata containing a copy of significant parts of the entire transaction which created that UTXO. This greatly increases the worst-case processing that hardware signers need to perform and is especially problematic for hardware signers using limited-size QR codes as their primary communication medium. Taproot eliminates the vulnerability underlying the fee overpayment attack and so can significantly improve the performance of hardware signers.

  • More predictable feerates: ECDSA signatures for P2PKH and P2WPKH UTXOs can vary in size (see Newsletter #3). Since wallets need to choose a transaction’s feerate before creating the signature, most wallets just assume the worst case signature size and accept that they’ll slightly overpay the feerate when a smaller signature is generated. For P2TR, the exact size of the signature is known in advance, allowing the wallet to reliably choose a precise feerate.

  • Help full nodes: the overall security of the Bitcoin system depends on a significant percentage of Bitcoin users verifying every confirmed transaction with their own nodes. That includes verifying the transactions your wallet creates. Taproot’s schnorr signatures can be efficiently batch verified, reducing by about 1/2 the number of CPU cycles nodes need to expend when verifying signatures during the process of catching up on previous blocks. Even if you rejected every other point on this list, consider preparing to use taproot for the benefit of people running full nodes.

Taproot descriptors

Originally published in Newsletter #156

Output script descriptors provide a generic way for wallets to store the information needed to create addresses, efficiently scan for outputs paying those addresses, and later spend from those addresses. In addition, descriptors are reasonably compact and contain a basic checksum, making them convenient for backing up address information, copying it between different wallets, or sharing it between wallets that are cooperating to provide multiple signatures.

Although descriptors are currently only used by a few projects, they and the related miniscript project have the potential to significantly improve interoperability between different wallets and tools. This will become increasingly important as more users take advantage of the benefits of taproot to improve their security through multisignatures and their resiliency through backup spending conditions.

Before that can happen, descriptors need to be updated to work with taproot. That was the subject of the recently merged Bitcoin Core #22051 pull request. The syntax has been designed to allow a single descriptor template to provide all the information necessary to use both P2TR keypath spends and script path spends. For simple single-sig, the following descriptor is sufficient:

tr(<key>)

The same syntax may also be used for multisignatures and threshold signatures. For example, Alice, Bob, and Carol aggregate their keys using MuSig and then pay to tr(<combined_key>).

Unintuitively, the key specified by tr(<key>) won’t be the key encoded in the address. The tr() descriptor follows a safety recommendation from BIP341 to use an internal key that commits to an unspendable script tree. This eliminates an attack against users of naive key aggregation schemes (more advanced schemes such as MuSig and MuSig2 are not affected).

For scriptpath spending, a new syntax is added that allows specifying the contents of a binary tree. For example, { {B,C} , {D,E} } specifies the following tree:

Internal key
    / \
   /   \
  / \ / \
  B C D E

A tree can be specified as an optional second parameter to the descriptor template we used before. For example if Alice wants to be able to spend via keypath, but she also wants to allow Bob, Carol, Dan, and Edmond spend via a scriptpath that generates an audit trail for her (but not for third-party chain surveillance), Alice can use the following descriptor:

tr( <a_key> , { {pk(<b_key>),pk(<c_key>)} , {pk(<d_key>),pk(<e_key>)} )

The above features are all that’s required to use descriptors for taproot, but PR #22051 notes that there are still some things missing that could be added to make descriptors better at completely describing expected policies:

  • Voided keypaths: some users may want to prevent usage of keypath spending in order to force scriptpath spending. That can be done now by using an unspendable key as the first parameter to tr(), but it’d be nice to allow wallets to store this preference in the descriptor itself and have it compute a privacy-preserving unspendable keypath.

  • Tapscript multisig: for legacy and v0 segwit, the multi() and sortedmulti() descriptors support the OP_CHECKMULTISIG opcode. To allow batch verification in taproot, script-based multisig is handled a bit differently in tapscript, so tr() descriptors currently need to specify any necessary multisig opcodes via a raw() script. Updated versions of multi() and sortedmulti() for tapscripts would be nice to have.

  • MuSig-based multisignatures: earlier in this article, we described Alice, Bob, and Carol manually aggregating their keys in order to use a tr() descriptor. Ideally, there would be a function that allows them to specify something like tr(musig(<a_key>, <b_key>, <c_key>)) so that they could retain all the original key information and use it to populate fields in the PSBTs they use to coordinate signing.

  • Timelocks, hashlocks, and pointlocks: these powerful constructions used in LN, DLCs, coinswaps, and many other protocols can currently only be described via the raw() function. Adding support for them directly to descriptors is possible, but it may be the case that support will be added instead through descriptor’s sibling project, miniscript. Integration of miniscript into Bitcoin Core is still an ongoing project, but we expect its innovations to spread to other wallets in the same way that tools like PSBTs and descriptors already have.

Wallets don’t need to implement descriptors in order to start using taproot, but those that do will give themselves a better foundation for using more advanced taproot features later.

From P2WPKH to single-sig P2TR

Originally published in Newsletter #157

For wallets that already support receiving and spending v0 segwit P2WPKH outputs, upgrading to v1 segwit P2TR for single-sig should be easy. Here are the main steps:

  • Use a new BIP32 key derivation path: you don’t need to change your BIP32 Hierarchical Deterministic (HD) code and your users don’t need to change their seeds.1 However, you are strongly encouraged to use a new derivation path for your P2TR public keys (such as defined by BIP86); if you don’t do this, there’s a possible attack that can occur if you use the same keys with both ECDSA and schnorr signatures.

  • Tweak your public key by its hash: although technically not required for single-sig, especially when all your keys are derived from a randomly-chosen BIP32 seed, BIP341 recommends having your key commit to an unspendable scripthash tree. This is as simple as using an Elliptic Curve addition operation that sums your public key with the curve point of that key’s hash. Advantages of complying with this recommendation are that you’ll be able to use the same code if you later add scriptless multisignature support or if you add support for tr() descriptors.

  • Create your addresses and monitor for them: use bech32m to create your addresses. Payments will be sent to the scriptPubKey OP_1 <tweaked_pubkey>. You can scan for transactions paying the script using whatever method you use to scan for v0 segwit addresses like P2WPKH.

  • Creating a spending transaction: all the non-witness fields for taproot are the same as for P2WPKH, so you don’t need to worry about changes to the transaction serialization.

  • Create a signature message: this is a commitment to the data from the spending transaction. Most of the data is the same as what you sign for a P2WPKH transaction, but the order of the fields is changed and a few extra things are signed. Implementing this is just a matter of serializing and hashing various data, so writing the code should be easy.

  • Sign a hash of the signature message: there are different ways to create schnorr signatures. The best is not to “roll your own crypto” but instead to use the function from a well-reviewed library you trust. But if you can’t do that for some reason, BIP340 provides an algorithm that should be straightforward to implement if you already have available the primitives for making ECDSA signatures. When you have your signature, put it in the witness data for your input and send your spending transaction.

Even before taproot activates at block 709,632, you can test your code using testnet, the public default signet, or Bitcoin Core’s private regtest mode. If you add taproot support to your open source wallet, we encourage you to add a link to the PR(s) implementing it on the taproot uses and bech32m adoption pages of the Bitcoin Wiki so other developers can learn from your code.

Why are we waiting?

Originally published in Newsletter #158

Earlier entries in this series saw us encouraging developers working on wallets and services to begin implementing taproot upgrades now so that they’re ready when taproot activates. But we’ve also warned against generating any addresses for P2TR before block 709,632 as this could cause your service or your users to lose money.

The reason not to generate addresses in advance is that any payment to a P2TR-style output can be spent by anyone prior to block 709,632. The money would be completely unsecured. But starting with that block, thousands of full nodes will begin enforcing the rules of BIP341 and BIP342 (and, by association, BIP340).

If it was guaranteed that there wouldn’t be a reorganization of the block chain, it would be safe to start generating addresses for P2TR as soon as the final pre-taproot block was seen (block 709,631). But there’s reason to be concerned about block chain reorgs—not just accidental reorgs but also those deliberately created to take money from early P2TR payments.

Imagine a large number of people all wanting to be one of the first to receive a P2TR payment. They naively send themselves some money as soon as they see block 709,631.2 Those payments will be secure in block 709,632, but they can be stolen by any miner who creates an alternative to block 709,631. If the value of the money sent to P2TR outputs is large enough, it could easily become more profitable to attempt to mine two blocks instead of just one (see our fee sniping topic for more details).

For this reason, we don’t recommend your software or service generate addresses for P2TR until you think the reorg risk has been effectively eliminated. We think waiting 144 blocks (approximately one day) after activation is a reasonably conservative margin that minimizes risk without significantly delaying you or your users from taking advantage of the benefits of taproot.

In short:

  • 709,631: last block where anyone can spend money sent to a P2TR-style output
  • 709,632: first block where P2TR outputs can only be spent if they satisfy the BIP341 and BIP342 rules.
  • 709,776: a reasonable block at which wallets can start giving their users bech32m receiving addresses for P2TR outputs

None of the above changes the advice given in the first part of this series to enable paying to bech32m addresses as soon as possible. If someone requests payment to an address for P2TR before you think it’s safe, that’s their risk to take.

Learn taproot by using it

Originally published in Newsletter #159

Almost two years ago, James Chiang and Elichai Turkel produced an open source repository of Jupyter notebooks for a series of Optech workshops to train developers on taproot technology. Workshops held in San Francisco, New York City, and London received positive reviews, but travel restrictions prevented subsequent in-person workshops.

Since the publication of the Jupyter notebooks, taproot underwent several changes. However, taproot support was also merged into Bitcoin Core, allowing the notebooks to drop their dependency on a custom branch of Bitcoin Core. Developer Elle Mouton has kindly updated the notebooks for all those changes, making them again a great way to quickly build hands-on experience working with taproot’s algorithms and data types.

The notebooks are divided into four sections:

  • Section 0 contains a notebook that helps you set up your environment, covers the basics of elliptic curve cryptography, and teaches you about the tagged hashes used throughout BIPs 340, 341, and 342.

  • Section 1 walks you through creating schnorr signatures. Once you’ve mastered them, you learn how to create multisignatures with the MuSig protocol.

  • Section 2 gives you experience with every aspect of taproot. It starts with a review of the principles of segwit v0 transactions and then helps you create and send segwit v1 (taproot) transactions. Applying the knowledge from section 1, you then create and spend a taproot output using MuSig. The concept of key tweaking is introduced and you learn how taproot allows you to use its public key to commit to data. Now that you can create commitments, you learn about tapscripts—how they differ from legacy and segwit v0 script, and how to commit to a tree of tapscripts. Finally, a short notebook introduces huffman encoding for creating optimal script trees.

  • Section 3 provides an optional exercise in creating a taproot output that changes which signatures are required the longer the output goes unspent—allowing the output to be efficiently spent under normal circumstances but also providing for a robust backup in case of problems.

The notebooks include numerous programming exercises that are relatively easy but which will ensure that you actually learned the material presented. The author of this column, who is no great coder, was able to complete the notebooks in six hours and only regretted that he had not taken the time to learn from them earlier.

Multisignature overview

Originally published in Newsletter #160

In the 1,000 blocks received prior to this writing, 11% of all transaction inputs contained a multisig opcode. Two of the largest and most immediate benefits of taproot will manifest if many of the users and services creating those transactions switch from multisig opcodes to scriptless multisignatures.

The first major benefit will be a reduction in transaction size. Script-based multisigs increase in size as more keys and signatures are required, but multisignatures are a constant small size. The smallest effective multisig policy (1-of-2) requires more space than a multisignature policy that can involve thousands of signers. The decrease in size leads to direct reduction in fees for the multisignature users and an indirect reduction in fees for all users as the same amount of demand for confirmed transactions can be fulfilled using a smaller amount of block space.

Plot showing the savings for multisignatures compared to multisig

The second major benefit is improved privacy. Each use of multisigs is distinctively recorded to the block chain where surveillants can use them to make informed guesses about the wallet history and current balance of individual users. For example, looking at block 692,039, we can distinguish not just the multisig spends from the single-sig spends but also distinguish between different set sizes and thresholds for the multisigs.

Illustration of the lack of witness fungibility in current blocks

By comparison, a third party looking only at block chain data can’t tell that a spender used a multisignature. When a multisignature is used for a keypath spend, it is indistinguishable from single-sig spends. If all single-sig and multisigs in the block above were switched to P2TR keypath spends, only a few exotic spends would be distinguishable by their scripts (and even those could use keypath spends in the best case).

Illustration of how fungibile witnesses could be ideally

Using multisignatures

We’re aware of three schnorr-based multisignature schemes designed specifically for Bitcoin, all members of the MuSig family:

  • MuSig (also called MuSig1), which should be simple to implement but which requires three rounds of communication during the signing process.

  • MuSig2, also simple to implement. It eliminates one round of communication and allows another round to be combined with key exchange. That can allow using a somewhat similar signing process to what we use today with script-based multisig. This does require storing extra data and being very careful about ensuring your signing software or hardware can’t be tricked into unknowingly repeating part of the signing session. We’ll examine the tradeoffs in more detail in next week’s preparing for taproot column.

  • MuSig-DN (Deterministic Nonce), significantly more complex to implement. Its communication between participants can’t be combined with key exchange, but it has the advantage that it’s not vulnerable to the repeated session attack.

All signers have to agree on the protocol to use, so there may be a network effect where many implementations choose to use the same protocol. The authors of the MuSig proposals suggest that will be MuSig2 due to its relative simplicity and high utility.

There’s an open and actively-developed PR to the libsecp256k1-zkp project to add MuSig2 support. We expect the basic multisignature workflow for most software will look something like the following:

  1. The wallet for each participant generates a BIP32 xpub that is shared with all the other participants through an output script descriptor or another method (the same as is commonly done now for multisigs).

  2. Any of the wallets can then generate an aggregated public key by combining its pubkey at a certain BIP32 depth with pubkeys at the same depth from all other wallets in the multisignature association. The aggregated public key can be used to receive P2TR payments.

  3. When one of the wallets wants to spend the funds, it uses a PSBT-based workflow similar to what it would use with script-based multisig, but now two rounds of communication between signers are required. In the first round, the proposer creates the unsigned transaction and includes a pair of randomly-generated nonces. It’s absolutely essential that the nonces not be derived in an entirely deterministic way that could lead to the same nonce being used again for a different signature. The proposer sends the PSBT with the nonces to the other wallets.

  4. The other wallets receive the PSBT and send a further updated PSBT with their own pair of random nonces to the other wallets, or to a coordinator who works trustlessly on behalf of the wallets.

  5. When all the wallets have all the nonce pairs, they combine them into a single nonce. The coordinator may also do this for them. The wallets then all update their versions of the PSBT with their partial signatures, sending the PSBTs to the other wallets or the coordinator. The partial signatures are then combined to create the final signature and the transaction is broadcast.

Threshold signing

By themselves, the MuSig family of multisignature schemes only give you n-of-n signing—every party who contributes a key towards the aggregated public key must also contribute a partial signature to the final signature. That works perfectly well as a direct replacement for some uses of script-based multisig today, such as spending 2-of-2 LN funding outputs, but it’s a departure from other popular policies such as the 2-of-3 multisig script used by many exchanges.

Several developers are working on threshold signature schemes that will bring the same efficiency and privacy benefits of multisignatures to k-of-n scenarios, but there’s a simple trick that can be used until those schemes are available.

In many threshold cases, it’s known in advance which participants are most likely to sign. For example, in a 2-of-3 situation, it might be known that normally Alice and Bob will co-sign, while Carol only signs if one of the others is unavailable. For this set of circumstances, the primary keys can use a multisignature for the taproot keypath spend (e.g. between Alice and Bob) and the additional outcomes (Alice and Carol, or Bob and Carol) can use multisignatures with the OP_CHECKSIG opcode in separate branches in a tree of tapscripts.

In the normal case, the above has exactly as much efficiency and privacy as a single-sig or multisignature transaction. In the abnormal case, spending still works as expected and remains more efficient and private than publishing your multisig parameters onchain.

Although users wanting minimal fees and maximal privacy may eventually switch to pure threshold signature schemes, the above scheme may also continue to remain in use because it provides onchain proof to an auditor (if they know all of the participants’ public keys) about which corresponding private keys were used to sign.

Edit: some of the text above about MuSig2 was updated to clarify that extra care is required when pre-sharing nonces, so most normal wallets using MuSig2 are expected to generate new random nonces at the moment they’re needed. We thank members of the #secp256k1 IRC room for sharing their concerns.

Multisignature nonces

Originally published in Newsletter #161

In last week’s column, we wrote about multisignatures and gave an example using MuSig2. Our description appears to have been technically correct, but several cryptographers who contributed to MuSig2 worried that the way we suggested using it was dangerous. We updated our description to address their immediate concerns and then began researching the issue more thoroughly. In this post, we’ll look at what we learned may be the greatest challenge for safely implementing multisignatures: avoiding nonce reuse.

To validate a signature in Bitcoin, you fill out a publicly known equation with the signature, the message that was signed (e.g. a transaction), your public key, and a public nonce. It’s only possible for you to balance that equation if you know your private key and the private form of the nonce. Thus anyone seeing such a balanced equation considers the signature for that message and public key to be valid.

The motivation for including the signature and the message in the equation is obvious. The public key is a stand-in for your private key. What’s the public nonce for? If it wasn’t there, every other value in the equation except for your private key would be known, meaning we could use basic algebra to solve for that single unknown value. But algebra can’t solve for two unknown values, so the private form of the nonce serves to keep your private key secret. And, just as your public key is a stand-in for your private key in the signature equation, the public form of the nonce stands in for its private form.

Nonces in this context are not only numbers used once but numbers that must only ever be used once. If you reuse the same nonce with two different signatures, the two signature equations can be combined, the nonce can be canceled out, and someone can again solve for the only remaining unknown value—your private key. If you use BIP32 standard derivation (non-hardened derivation), which likely nearly all multisignature wallets will do, then the revelation of one private key means the reveal of every other private key in the same BIP32 path (and possibly in other paths as well). That means a multisignature wallet which has received bitcoins to a hundred different addresses will have every one of those addresses compromised for the signer who reuses even a single nonce.

Single-sig wallets, or those using script-based multisig, can use a simple trick to avoid reusing nonces: they make their nonce dependent on the message they’re signing. If there’s any change to the message, the nonce changes, and so they never reuse a nonce.

Multisignatures can’t use this trick. They require each cosigner contribute not just a partial signature but also a partial public nonce. The partial public nonces are combined together to produce an aggregated public nonce which is included with the message to sign.

That means it’s not safe to use the same partial nonce more than once even if the transaction stays the same. If, the second time you sign, one of your cosigners changed their partial nonce (changing the aggregated nonce), your second partial signature will effectively be for a different message. That reveals your private key. Since it’s impossibly circular for every party to make their private nonce dependent on all the other party’s partial public nonces, there’s no simple trick to avoid nonce reuse in multisignatures.

At first glance, this doesn’t seem like a big problem. Just have signers generate a new random nonce each time they need to sign something. This is harder to get right than it sounds—since at least 2012, people have been finding bitcoin-losing bugs in wallets that depended on generating random nonces.

But even if a wallet does generate high-quality random nonces, it has to ensure each nonce is only used a maximum of a single time. That can be a real challenge. In the original version of our column last week, we described a MuSig2-compatible cold wallet or hardware signing device that would create a large number of nonces on its first run. The wallet or device would then need to ensure each of those nonces was never used with more than one partial signature. Although that sounds simple—just increment a counter each time a nonce is used—it can be a real challenge when dealing with all the ways software and hardware can fail by accident, not to mention how they can be affected by external and possibly malicious intervention.

Perhaps the easiest way for a wallet to reduce its risk of nonce reuse is to store nonces for as short a time as possible. Our example from last week suggested storing nonces for months or years, which not only creates a lot of opportunity for something to go wrong but also requires recording nonces to a persistent storage medium which may be backed up and restored or otherwise put into an unexpected state. An alternative way to use MuSig2 would be to only create nonces on demand, such as when a PSBT is received. The nonces could be kept in volatile memory for the short time they were needed and so be automatically destroyed (made unreusable) in several cases of the unexpected happening, such as a software crash or a loss of power.

Still, the cryptographers working on this problem seem very concerned about the lack of foolproof way to prevent nonce reuse in the original MuSig protocol (MuSig1) and MuSig2. MuSig-DN (deterministic nonce) does offer a solution, but it’s complex and slow (an alpha implementation takes almost a second to create a nonce proof on a 2.9 GHz Intel i7; it’s unknown to us how long that might take on a 16 MHz hardware signing device with a much less sophisticated processor).

Our advice to anyone implementing multisignature signing is to consider stopping by the #secp256k1 IRC room or another place where Bitcoin cryptographers congregate and describe your plans before you make any major investments of time or resources.

Signature adaptors

Originally published in Newsletter #162

Imagine someone offers to donate 1,000 BTC to a particular charity if anyone can guess that person’s favorite very large number. An easy way for the donor to do this is to create an unsigned transaction paying the 1,000 BTC and then publish an encrypted copy of their signature for the transaction, with the favorite number being the decryption key.

In theory, anyone who guesses the number can decrypt the signature and then broadcast the transaction, paying the charity. But if the donor uses a standard encryption scheme like AES, there’s no easy way for third parties to know before decryption that the signature is actually valid for that transaction. Anyone who wants to put effort into number guessing has to trust that the donor is sincere and not a troll.

Let’s extend this problem a bit further. Third parties Alice and Bob want to bet on whether or not the signature is revealed. They could perhaps ask the signer for the hash of the signature and use that as the hash in an HTLC function, but that again requires trusting the donor to act honestly. Even if the signature was eventually revealed, the donor could sabotage Alice and Bob’s contract by giving them an incorrect hash.

Adaptor magic

Signature adaptors, also commonly called adaptor signatures and one-time verifiably encrypted signatures, are a solution to these problems—and to many other problems actually faced today in production systems built on Bitcoin. Although usable with Bitcoin’s existing ECDSA signature scheme, it’s much easier to use adaptors privately and costlessly in combination with the BIP340 implementation of schnorr signatures for taproot. Let’s see how our example above changes if we use adaptors.

As before, the donor prepares a 1,000 BTC transaction. They sign in almost the normal way, with the one difference being that they essentially generate their nonce in two parts: a true random nonce that they will forever keep secret, and their favorite number—which they’ll initially keep secret but which is safe for other people to discover. The donor generates a fully valid signature using both of these values, adding them together as if they were a single nonce.

BIP340 signature commitments use the nonce in two forms: a numeric representation (called a scalar), which normally only the signer knows, and as a point on the Elliptic Curve (EC), which is published to enable verification.

The donor takes the commitment part of their valid signature and subtracts out the hidden scalar. This makes the signature incomplete (and thus invalid) but allows the donor to share the (invalid) signature commitment, the (valid) point for the complete nonce, and the (valid) point for the hidden number. Together these three pieces of information are a signature adaptor.

Using a slight variant on the BIP340 signature verification algorithm, anyone can verify that the signature adaptor would provide a valid signature if the hidden scalar was simply added back in to the (currently invalid) signature commitment. This is possible to verify even without knowing what that hidden number is. In short, it is now possible for users to trustlessly begin making guesses about the value of hidden scalar, secure in the knowledge that a correct guess will allow them to get the signature and send the transaction.

Like everyone else who received the donor’s signature adaptor, Alice and Bob now have a copy of the EC point for the hidden number. Also like everyone else, they don’t know the actual scalar. But, if you recall, all the donor did to turn their valid signature into an invalid signature is subtract out the hidden number from their signature commitment while continuing to have the signature commit to the point of the hidden number. Alice can just as easily create an invalid signature by not committing to the scalar she doesn’t know but still committing to the EC point she does know. She does this by creating her own nonce pair, using the private form when creating her (invalid) signature but commiting to the aggregation of the public form of her nonce and the EC point from the donor’s signature adaptor. This produces a signature adaptor for a transaction that pays Bob. If Bob learns the scalar, he can convert that adaptor into a valid signature and send the transaction, winning the bet.

But how does Bob learn the winning number? Does he have to wait for someone else who guesses it to publish a press release? Nope. Recall one more time that the signature adaptor the donor published was their actual signature minus the scalar. When the hidden number is discovered and somebody sends the 1,000 BTC transaction, they must publish the original (valid) signature commitment. Bob can take that (valid) signature commitment and subtract from it the (invalid) signature commitment in the original signature adaptor to get the scalar. He then uses that scalar to convert Alice’s adaptor into a valid signature.

Multisignature adaptors

The previous section shows individual users modifying how they create their signatures to produce signature adaptors. It’s also possible for the parties to a multisignature to use the same trick. That’s extraordinarily useful, as many cases where signature adaptors will be used require the cooperation of two users.

For example, when Alice and Bob make the bet above, they might start by depositing funds into a script only spendable by a multisignature between them. Then Alice can produce her partial signature in the form of a signature adaptor; if Bob learns the hidden number, he can transform Alice’s adaptor into her valid partial signature and then provide his partial signature to produce a full signature spending the money.

This gives signature adaptors all the same advantages of multisignatures in general: they look like and use the same amount of space as a single signature, minimizing fees and maximizing privacy and fungibility.

In next week’s preparing for taproot column, we’ll explore one of the main ways we expect to see signature adaptors used: Point Time Locked Contracts (PTLCs), an upgrade for the venerable Hash Time Lock Contracts (HTLCs) used extensively in LN, coinswaps, and a number of other protocols.

PTLCs

Originally published in Newsletter #163

In last week’s column, we looked at signature adaptors and how the activation of taproot with schnorr signatures will make it easier to use adaptors privately and efficiently. There are several ways signature adaptors can be used on Bitcoin but one of the most immediately beneficial will be Point Time Locked Contracts (PTLCs), which can replace the venerable Hash Time Locked Contracts (HTLCs) used for years. This will bring several advantages, but it also comes with some challenges. To understand both, we first start with a simplified example of HTLCs in use; the example below could be offchain LN payments, onchain coinswaps, or a hybrid onchain/offchain system like Lightning Loop—it’s this flexibility that makes HTLCs so widely used.

Alice wants to pay Carol by routing a payment through Bob, who neither Alice nor Carol wants to trust. Carol creates a random preimage and hashes it with the SHA256 algorithm. Carol gives the hash to Alice and keeps the preimage secret. Alice initiates a payment to Bob which he can claim with a signature for his public key plus the preimage; alternatively, Alice can receive a refund after 10 blocks by spending the transaction back to herself with a signature for her public key. Here’s that policy described in the Minsc language:

(pk($bob) && sha256($preimage)) || (pk($alice) && older(10))

Bob can now initiate a payment for the same amount (perhaps minus fees) to Carol with basically the same script, only with the parties updated and a lower refund time out.

(pk($carol) && sha256($preimage)) || (pk($bob) && older(5))

Now Carol can claim her payment from Bob within five blocks by using the preimage, which reveals the preimage to Bob and allows him to claim the payment from Alice, also within five blocks.

Privacy problems with HTLCs

If the scripts above are published onchain, the reuse of the same hash and preimage makes it immediately clear that A paid C via B. This can be a significant problem for same-chain and cross-chain coinswaps. Less obviously, this is also a problem for offchain routing protocols like LN. If we imagine a longer routing path where one person controls multiple hops along the path, they can see the reuse of the same hash and preimage to determine that some nodes are routing nodes, increasing the probability that the remaining nodes are either the spender or the receiver. This is one part of the linkability problem that may be LN’s greatest current privacy weakness.

Illustration of HTLC linkability problem

Although multipath payments partially mitigate other aspects of LN’s linkability problem, e.g. payment amount linkability, it may make worse the hash linkability problem by giving surveillance routing nodes more opportunity to correlate hashes.

An additional problem with HTLCs today is that any scripts which need to go onchain are obviously distinct from normal spender scripts. This makes it easier for surveillants to identify usage patterns and, perhaps, make effective guesses about information specific to individual users.

The PTLC solution

In the previous Minsc-style scripts, we had a function that would only return true if it was passed a particular value chosen in advance (the preimage). A signature adaptor is similar in that it can only be transformed into a valid signature if a function is passed a revealed value (the scalar). If we ignore multisignatures for the moment, this allows us to transform the HTLC scripts from earlier into the following PTLCs:

(pk($bob) && pk($alice_adaptor)) || (pk($alice) && older(10))
(pk($carol) && pk($bob_adaptor)) || (pk($bob) && older(5))

In short, Carol gives Alice the EC point for her hidden scalar, Alice uses that with a public key she chooses and creates a signature adaptor that she gives to Bob; Bob can use the same point with a public key he chooses and creates an adaptor he gives to Carol. Carol reveals the scalar by transforming Bob’s adaptor into a valid signature, claiming Bob’s coins. Bob recovers the scalar from the valid signature, allowing him to transform Alice’s adaptor into its own valid signature, claiming her coins.

This solves the linkability problem against onchain surveillance because all that anyone sees when they look at the block chain are a bunch of valid signatures for distinct public keys. Third parties can’t know that adaptors were used, much less what scalar those adaptors were based upon.

However, the procedure above doesn’t prevent surveillance nodes who participate in the routing from linking together the payments. If all the payments are based on the same scalar, then all the payments are just as linked as if they used a hashlock and preimage. This can be fixed by each routing node choosing their own scalar and then removing its corresponding point as the payment passes through its node. Let’s revise our example:

As before, Carol gives Alice the point for her scalar, but this time Alice also requests a point from Bob. Alice constructs the adaptor she gives Bob using the aggregation of both Carol’s point and Bob’s point. Bob knows his point, so he’s able to subtract that out from the adaptor he receives from Alice. Using the resultant point (which Bob doesn’t know is now just the point Alice originally received from Carol), Bob constructs the adaptor he gives to Carol. Carol knows the scalar for that final point and so converts Bob’s adaptor into a valid signature. As before, Bob recovers Carol’s scalar from her signature and uses it and his own scalar to convert Alice’s adaptor into a valid signature.

In the two hops in this path, Alice→Bob and Bob→Carol, two different EC points and scalars were used, eliminating linkability. We can extend this to the longer path we examined when considering HTLCs and see how this improves privacy:

Illustration of PTLC lack of linkability problem

As mentioned last week, schnorr signatures make it easy to compose adaptor signatures with multisignatures. For the case of generic PTLCs, this allows us to reduce our onchain scripts to:

pk($bob_with_alice_adaptor) || (pk($alice) && older(10))
pk($carol_with_bob_adaptor) || (pk($bob)   && older(5) )

With taproot, the left branch can become a keypath and the right branch can become a tapleaf. If the payment routes successfully, Bob and Carol can settle their parts onchain without further cooperation from their counterparties, making this routed payment indistinguishable from single-sig payments, normal multisignature payments, and cooperatively resolved contracts. It also minimizes the use of block space. If one of the refund conditions needs to be executed, that’s still fairly efficient and fairly private—pk(x) && older(n) is indistinguishable from degrading multisig, enforced hodling, and a variety of other possible scripts.

In next week’s column, a guest post from one of our favorite LN developers will discuss some of the changes necessary for LN to adopt keypath spends, multisignatures, PTLCs, and other features enabled by taproot.

LN with taproot

Originally published in Newsletter #164

By ZmnSCPxj, LN protocol developer

In this post, we’ll look at two privacy features that taproot enables for LN:

  • PTLCs over LN.
  • P2TR Channels.

PTLCs Over LN

PTLCs enable many features, with a major feature for LN being payment decorrelation without any need to randomize routes.3 Every node along a single-path or multipath route can be given a scalar that is used to tweak each forwarded PTLC, enabling payment decorrelation where individual forwards no longer leak the unique identifier for each LN payment.

PTLCs are not a privacy panacea. If a surveillant node sees a forward with a particular timelock and value, and a second surveillant node shortly after sees a forward with a lower timelock and slightly lower value, then very likely those forwards belong to the same payment path, even if the surveillant nodes can no longer correlate them via a unique identifying hash. However, we do get:

  • Increased uncertainty in the analysis. The probabilities a surveillant can work with are now lower and thus their information is that much less valuable.
  • A lot more decorrelation in multipath payments. Separate paths will not have strong timelock and value correlation with each other, and if LN succeeds, there should be enough payments that timing correlation is not reliable either.
  • No increase in cost compared to an HTLC (and possibly even a slight cost reduction due to multisignature efficiency).

In principle, a pre-taproot channel can be upgraded to support PTLCs without closing and reopening the channel. Existing channels can host PTLCs by creating an offchain transaction that spends the existing non-taproot funding output to a taproot output containing a PTLC. That means adding support for PTLCs over LN does not require any cost to users beyond each node and its channel peers upgrading their software.

However, to actually use PTLCs, every forwarding node from the spender to the receiver must support PTLCs. This means PTLC support may remain largely unused until a sufficient number of nodes have upgraded. They don’t all necessary need to use the same protocol (there could be multiple PTLC protocols), but they all must support some PTLC protocol. Having to support multiple PTLC protocols would be an added maintenance burden and I hope we do not have too many such protocols (ideally just one).

P2TR Channels

One solution for improving the decorrelation between the base layer and the LN layer has been unpublished channels—channels whose existence isn’t gossiped on LN.

Unfortunately, every LN channel requires cooperation between two signers, and in the current pre-taproot Bitcoin, every 2-of-2 script is openly coded. LN is the most popular user of 2-of-2 multisignature, so any block chain explorer can show that this is a LN channel being closed. The funds can then be traced from there, and if they go to another P2WSH output, then that is likely to be another unpublished channel. Thus, even unpublished channels are identifiable onchain once they are closed, with some level of false positives.

Taproot, by using schnorr signatures, allows for n-of-n to look exactly the same as 1-of-1. With some work, even k-of-n will also look the same as 1-of-1 (and n-of-n). We can then propose a feature where an LN channel is backed by a P2TR UTXO, i.e. a P2TR channel, which increases the onchain privacy of unpublished channels.4

This (rather small) privacy boost also helps published channels as well. Published channels are only gossiped for as long as they are open, so somebody trying to look for published channels will not be able to learn about historical channels. If a surveillant wants to see every published channel, it has to store all that data itself and cannot rely on any kind of “archival” node.

In addition, taproot keypath spends are 38.5 vbytes (40%) smaller than LN’s existing P2WSH spends. Unfortunately, you cannot upgrade an existing pre-taproot channel to a P2TR channel. The existing channel uses the existing P2WSH 2-of-2 scheme and has to be closed in order to switch to a P2TR channel.

In theory, the actual funding transaction outpoint is only a concern of the two nodes that use the channel. Other nodes on the network will not care about what secures the channel between any two nodes. However, published channels are shared over the LN gossip network. When a node receives a gossiped published channel, it consults its own trusted Bitcoin full node, checking if the funding outpoint exists, and more importantly has the correct address. Checking the address helps ensure that it is difficult to spam the channel gossip mechanism; you need actual funds on the blockchain in order to send channel gossip. Thus, in practice, even P2TR channels require some amount of remote compatibility; otherwise, senders will ignore these channels for routing, as they cannot validate that those channels exist.

Time Frames

I think the best way to create time frames for features on a distributed FOSS project is to look at previous features and how long they took, and use those as the basis for how long features will take to actually deploy.5

The most recent new major feature that I believe is similar in scope to PTLCs over LN is dual-funding. Lisa Neigut created an initial proposal for a dual-funding protocol in BOLTs #524, with the first dual-funded channel on mainnet being opened almost 2 years and 6 months later. Dual-funding only requires compatibility with your direct peers. PTLCs over LN require compatibilty with all routing nodes on your selected paths, including the receiver, so I feel justified in giving this feature a +50% time modifier due to the added complication, for an estimate of 3 years and 9 months starting from when a specific PTLC protocol is proposed.

For P2TR channels, we should note that while this is “only” between two direct peers, it also has lower benefits. Thus, I expect it will be lower priority. Assuming most developers prioritize PTLC-over-LN, then I expect P2TR channels will start getting worked on by the time the underlying SIGHASH_ANYPREVOUT or other ways to implement Decker-Russell-Osuntokun (“Eltoo”) are available.

Vaults with taproot

Originally published in Newsletter #165

By Antoine Poinsot, Revault developer

Bitcoin vaults are a type of contract that require two sequential transactions for a user to spend money from their wallet. Numerous such protocols have been proposed (single or multi-party, with or without covenants) so we’ll focus on what they have in common.

Contrary to batched payments that execute multiple payments with a single onchain transaction, vaults use multiple transactions to execute a single payment. The first transaction, the unvault, pays to either:

  1. a set of pubkeys after a relative timelock, or
  2. a single pubkey without any timelocks.

The first spending path is the mainline case, expected to be used with “hotter” key(s). The second spending path allows for a cancel transaction (sometimes called the clawback, recovery or re-vaulting transaction).

As such, Bitcoin vaults are contrary to the insight of taproot that most contracts have a happy path where all participants collaborate with a signature (and the dispute path usually contains timelocks). Rather the opposite. The spend transaction must use the taproot script sending path, since it is encumbered by the relative timelock6 while the cancel transaction could in theory use the key spending path.

Since multi-party vaults already require a lot of interactivity in practice, they could theoretically benefit from interactive multisignature and threshold signature schemes made possible by BIP340, such as Musig2. However, these schemes come with new safety challenges. Since vault protocols are intended to be used for cold storage, the design choices are more conservative and vaults would probably be the last to use these new technologies.

By switching to taproot, vaults would also benefit from a slight privacy and efficiency improvement due to the use of merkle branches and shorter BIP340 signatures (especially for multi-party ones). For instance, the unvault output script in a multi-party setup with 6 “cold” keys and 3 “active” keys (with a threshold of 2) could be represented as a Taproot of depth 2 with leaves:

  • <X> CSV DROP <active key 1> CHECKSIG <active key 2> CHECKSIGADD 2 EQUAL
  • <X> CSV DROP <active key 2> CHECKSIG <active key 3> CHECKSIGADD 2 EQUAL
  • <X> CSV DROP <active key 3> CHECKSIG <active key 1> CHECKSIGADD 2 EQUAL
  • <cold key 1> CHECKSIG <cold key 2> CHECKSIGADD <cold key 3> CHECKSIGADD <cold key 4> CHECKSIGADD <cold key 5> CHECKSIGADD <cold key 6> CHECKSIGADD 6 EQUAL

In taproot, only the leaf being used to spend the output needs to be revealed, so the transaction weight is considerably smaller than for the equivalent P2WSH script:

IF
  6 <cold key 1> <cold key 2> <cold key 3> <cold key 4> <cold key 5> <cold key 6> 6 CHECKMULTISIG
ELSE
  <X> CSV DROP
  2 <active key 1> <active key 2> <active key 3> 3 CHECKMULTISIG
ENDIF

Although the revocation branch can be hidden in case of a successful spending (and if using a multisig threshold, its existence and the number of participants obfuscated), the privacy gains are minimal as the vault usage pattern would be trivially identifiable onchain.

Finally, vault protocols, like most pre-signed transactions protocols, would largely benefit from further proposed Bitcoin upgrades based on taproot such as BIP118’s SIGHASH_ANYPREVOUT. Although requiring further caution and protocol tweaks, ANYPREVOUT and ANYPREVOUTANYSCRIPT would enable rebindable cancel signatures, which could largely reduce interactivity and allow 0(1) signature storage. This is particularly interesting for the emergency signature in the Revault protocol, as it would largely reduce the DoS attack surface. By having an ANYPREVOUTANYSCRIPT signature in an output, you are effectively creating a covenant by restricting how the transaction spending this coin can create its outputs. Even more customizable future signature hashes would permit more flexible restrictions.

Backup and security schemes

Originally published in Newsletter #166

In last week’s column, Antoine Poinsot described how taproot can make vault-style coin backup and security schemes more private and fee efficient. In this week’s column, we’ll look at several other backup and security schemes that are improved by converting to taproot.

  • Simple 2-of-3: as mentioned in a previous week, it’s easy to use a combination of multisignatures and scriptpath spends to create a 2-of-3 spending policy that’s normally just as efficient onchain as a single-sig spend and which is much more private than current P2SH and P2WSH multisigs. It’s still fairly efficient and private in the abnormal cases as well. This makes taproot great for upgrading your security from a single-signer wallet to a multi-signer policy.

    We expect future techniques for threshold signatures to further improve 2-of-3 and other k-of-n cases.

  • Degrading multisignatures: one of the exercises in the Optech Taproot Workshop allows you to experiment with creating a taproot script that can be spent at any time by three keys, or after three days with two of the original keys, or after ten days with only one of the original keys. (That exercise also uses backup keys, but we’ll cover that separately in the next point.) Tweaking the time parameters and the key settings provides you with a flexible and powerful backup construct.

    For example, imagine you can normally spend using a combination of your laptop, mobile phone, and a hardware signing device. If one of those becomes unavailable, you can wait a month to be able to spend with the remaining two devices. If two devices become unavailable, you can spend using just one after six months.

    In the normal case of using all three devices, your onchain script is maximally efficient and private. In the other cases, it’s a bit less efficient but may still be reasonably private (your script and its tree depth will look similar to the scripts and depths used in many other contracts).

  • Social recovery for backups and security: the example above is great at protecting you if one of your devices gets stolen by an attacker, but what happens if two of your devices are stolen? Also, if you frequently use your wallet, do you really want to wait even a month before you can start spending again after losing a device?

    Taproot makes it easy, cheap, and private to add a social element to your backups. In addition to the scripts in the previous example, you can also allow immediate spending of your bitcoins with two of your devices plus signatures from two of your friends or family members. Or immediate spending with only a single one of your keys plus signatures from five people you trust. (A similar non-social version of this would simply be using extra devices or seed phrases you have stored in secure locations.)

  • Combining time and social thresholds for inheritance: combining the techniques above, you can allow someone or a group of people to recover your funds in case you suddenly die or become incapacitated. For example, if you haven’t moved your bitcoins for six months, you can allow your lawyer and any three of your five most trusted relatives to spend your coins. If you normally move your bitcoins every six months anyway, this inheritance preparation has no added onchain cost for as long as you live and is completely private from outside observers. You can even keep the transactions you make private from your lawyer and family as long as you have a reliable way for them to learn your wallet’s extended public key (xpub) after your death.

    Please note that making it possible for your heirs’ to spend your bitcoins doesn’t mean that they’ll be able to spend those coins legally. We recommend that anyone planning to pass on Bitcoins read Cryptoasset Inheritance Planning by Pamela Morgan (physical book and DRM’d ebook or DRM-free ebook) and use its information to discuss details with a local expert in estate planning.

  • Compromise detection: an idea proposed prior to the invention of taproot is to put a key controlling some amount of bitcoin on all of the devices you care about as a way of detecting when the device has been compromised. If the amount of bitcoin is large enough, the attacker will probably spend it to themselves for the immediate gain rather than wait to use their illicit access in a long-term attack that might cause you more overall harm.

    A problem with this approach is that you want to make the amount of bitcoin offered large enough to entice the attacker but you don’t want to put large amounts of bitcoin on every one of your devices—you’d prefer to offer only one large bounty. However, if you were to put the same key on every device, the attacker transaction spending the bitcoin wouldn’t reveal which device was compromised. Taproot makes it easy to put a different key with a different scriptpath on every device. Any one of those keys will be able to spend all the funds controlled by that address, but it can also uniquely identify to you which device was compromised.

Testing on signet

Originally published in Newsletter #167

Although you can’t safely use taproot before block 709,632 on mainnet, you can use taproot today with either testnet or signet. Compared to creating a local test network with Bitcoin Core’s regtest mode, as done in the Optech taproot workbooks, using testnet or signet makes it easier to test how your wallet interacts with other people’s wallets.

In this post, we’ll receive and spend a taproot transaction using Bitcoin Core’s built-in wallet on signet. You should be able to adapt these instructions for testing receives and spends between your own wallet and Bitcoin Core.

Although it’s technically possible to receive and spend taproot transactions using the built-in wallet in Bitcoin Core 22.0, we recommend that you instead build Bitcoin Core pull request #22364, which makes taproot the default for descriptor wallets. Once built, start signet:

$ bitcoind -signet -daemon

If this is your first time using signet, you’ll need to sync its block chain. That currently includes less than 200 MB of data and can finish syncing in as little as a minute. You can monitor sync progress using the getblockchaininfo RPC. After syncing, create a descriptor wallet:

$ bitcoin-cli -signet -named createwallet wallet_name=p4tr descriptors=true load_on_startup=true
{
  "name": "p4tr",
  "warning": "Wallet is an experimental descriptor wallet"
}

Now you can create a bech32m address:

$ bitcoin-cli -named -signet getnewaddress address_type=bech32m
tb1p6h5fuzmnvpdthf5shf0qqjzwy7wsqc5rhmgq2ks9xrak4ry6mtrscsqvzp

With this address, you can request funds from the signet faucet. You’ll then need to wait for a confirmation, which will take the same variable amount of time you’d expect on mainnet (typically up to 30 minutes, but sometimes longer). If you look at the transaction, you’ll notice the P2TR script you created.

$ bitcoin-cli -signet getrawtransaction 688f8c792a7b3d9cb46b95bfa5b10fe458617b758fe4100c5a1b9536bedae4cd true | jq .vout[0]
{
  "value": 0.001,
  "n": 0,
  "scriptPubKey": {
    "asm": "1 d5e89e0b73605abba690ba5e00484e279d006283bed0055a0530fb6a8c9adac7",
    "hex": "5120d5e89e0b73605abba690ba5e00484e279d006283bed0055a0530fb6a8c9adac7",
    "address": "tb1p6h5fuzmnvpdthf5shf0qqjzwy7wsqc5rhmgq2ks9xrak4ry6mtrscsqvzp",
    "type": "witness_v1_taproot"
  }
}

You can then create a second bech32m address and send the funds there to test spending.

$ bitcoin-cli -named -signet getnewaddress address_type=bech32m
tb1p53qvqxja52ge4a7dlcng6qsqggdd85fydxs4f5s3s4ndd2yrn6ns0r6uhx
$ bitcoin-cli -named -signet sendtoaddress address=tb1p53qvqxja52ge4a7dlcng6qsqggdd85fydxs4f5s3s4ndd2yrn6ns0r6uhx amount=0.00099
24083fdac05edc9dbe0bb836272601c8893e705a2b046f97193550a30d880a0c

For this spend, we can look at one of the inputs and see that its witness contains nothing but a single 64-byte signature. That’s smaller in vbytes than the witness which would’ve been required if this was a P2WPKH spend or any other type of older Bitcoin spend.

$ bitcoin-cli -signet getrawtransaction 24083fdac05edc9dbe0bb836272601c8893e705a2b046f97193550a30d880a0c true | jq .vin[0]
{
  "txid": "bd6dbd2271a95bce8a806288a751a33fc4cf2c336e52a5b98a5ded432229b6f8",
  "vout": 0,
  "scriptSig": {
    "asm": "",
    "hex": ""
  },
  "txinwitness": [
    "2a926abbc29fba46e0ba9bca45e1e747486dec748df1e07ee8d887e2532eb48e0b0bff511005eeccfe770c0c1bf880d0d06cb42861212832c5f01f7e6c40c3ce"
  ],
  "sequence": 4294967294
}

By playing around with the above commands, you should find it easy to receive and spend money using taproot with any wallet that supports signet.

Signmessage protocol still needed

Originally published in Newsletter #168

Since the activation of segwit over four years ago, there’s been no widely accepted way to create signed text messages for bech32 or bech32m addresses. Arguably, that means we can now assume that widespread message signing support must not be very important to users or developers, otherwise more work would’ve been dedicated to it. But it still feels like Bitcoin wallet software has regressed since the days when everyone used legacy addresses and could easily trade signed messages.

The generic signmessage solution we wrote about two years ago in our bech32 spending support series has floundered, not even being adopted by Bitcoin Core despite occasional updates of its protocol documentation, BIP322 (see Newsletters #118 and #130). Despite that, we’re unaware of any better alternative, and so BIP322 should still be the preferred choice of any developer who wants to add signmessage support to their P2TR wallet.

If implemented, generic signmessage will allow signing messages for P2TR outputs that are truly single-sig, which use multisignatures, or which use any tapscript. It will also provide backwards compatibility with all legacy and bech32 addresses as well as forward compatibility with the types of changes currently envisioned for the near future (some of which we’ll preview in a future preparing for taproot column). Applications with access to the full UTXO set (e.g. via a full node) can also use BIP322 to generate and validate reserve proofs, providing evidence that the signer controlled a certain amount of bitcoin at a certain time.

It should be very easy to implement support for creating generic signed messages. BIP322 uses a technique called virtual transactions. A first virtual transaction is created to be deliberately invalid by attempting to spend from a non-existent previous transaction (one whose txid is all zeroes). This first transaction pays the address (script) the user wants to sign for and contains a hash commitment to the desired message. A second transaction spends the output of the first transaction—if the signatures and other data for that spend could be a valid transaction, then the message is considered signed (although the second virtual transaction still can’t be included onchain because it spends from an invalid previous transaction).

Verifying generic signed messages is harder for many wallets. To be able to fully verify any BIP322 message requires implementing essentially all of Bitcoin’s consensus rules. Most wallets don’t do that, so BIP322 allows them to return an “inconclusive” state when they can’t fully verify a script. In practice, and especially with taproot’s encouragement of keypath spends, that may be rare. Any wallet that implements just a few of the most popular script types will be able to verify signed messages for over 99% of all UTXOs.

Generic signmessage support would be a useful addition to Bitcoin. Although we can’t ignore the lack of attention paid to it in the past several years, we do encourage wallet developers reading this to consider adding experimental support for it to your programs. It’s an easy way to give users back a feature they’ve been missing for several years now. If you are either a developer working on BIP322 or related reserve proof implementation or a service provider that would find such features useful, feel free to reach out to info@bitcoinops.org to coordinate efforts.

Output linking

Originally published in Newsletter #169

After taproot activates, users will begin receiving payments to P2TR outputs. Later, they’ll spend those outputs. In some cases, they’ll make payments to non-P2TR outputs but will still return their change to themselves using a P2TR change output.

Example transaction P2TR -> {P2WPKH, P2TR}

It’s easy for an expert or an algorithm observing such a transaction to reasonably infer that the P2TR output is the user’s own change output, making the other output the payment output. This isn’t guaranteed to be true, but it is the most likely explanation.

Some have argued that the many privacy benefits of taproot should be ignored because of this possible temporary decrease in privacy during the transition of wallets to P2TR. Many experts have called that an unwarranted overreaction. We agree and can also offer a few additional counterpoints to consider:

  • Other metadata: transactions may contain other metadata that reveals which outputs are change and which are payments. One of the most concerning is the large percentage of outputs that currently reuse addresses, significantly reducing privacy for both the spenders and receivers involved in those transactions. For as long as those problems persist, it seems foolish not to proceed with significant privacy upgrades for users of wallets and services that implement best practices.

  • Output script matching: Bitcoin Core’s built in wallet defaults to using a segwit change output if any of the payment output types are also segwit. Otherwise, it uses the default change address type. For example, when paying a P2PKH output, a P2PKH change output might be used; for a P2WPKH output, P2WPKH change is used. As described in Newsletter #155, after taproot activation Bitcoin Core will begin to opportunistically use P2TR change outputs when any other output in the same transaction is P2TR. This can minimize any increase in change identifiability during the transitional period.

  • Request upgrades: with P2TR, we have an opportunity for the first time in Bitcoin’s history to get everyone using the same type of output script no matter their security requirements, and also to frequently use indistinguishable inputs, which significantly improves privacy. If you want to see a meaningful increase in Bitcoin privacy, you can ask the users and services you pay to provide taproot support (and also to stop reusing addresses, if applicable). If both you and they upgrade, then change outputs become harder to identify and we also get all of taproot’s other amazing privacy benefits.

Is cooperation always an option?

Originally published in Newsletter #170

The original taproot proposal by Gregory Maxwell suggested an interesting principle for contract design:

“It is almost always the case that interesting scripts have a logical top level branch which allows satisfaction of the contract with nothing other than a signature by all parties. Other branches would only be used where some participant is failing to cooperate. More strongly stated, I believe that any contract with a fixed finite participant set upfront can be, and should be, represented as an OR between an N-of-N and whatever more complex contract you might want to represent.” (emphasis in original)

Since then, experts have debated the universality of this principle, with two possible exceptions we’re aware of being focused on timelocks:

  • Consensus augmented self-control: some people have used timelocks to prevent themselves from spending their own bitcoins for a period of time. The timelock requirement seems to suggest that more than a signature is required, but a few criticisms have been raised:

    • Someone truly desperate to spend their timelocked bitcoins can take out a loan, perhaps secured by some other asset. This undermines the utility of this self contract.

    • In addition to the consensus-enforced scriptpath timelock, the user can allow keypath spending between their key and the key of a third party who only signs when the timelock has expired. This is not only more efficient, but it also allows implementing a more flexible spending policy such as providing the user the ability to sell any forkcoins they receive or to work with a third party who will allow them to spend early in case of major life changes or price appreciations.

  • Vaults: as mentioned in Antoine Poinsot’s column here a few weeks ago, vaults also use timelocks extensively to help protect funds, which seems “contrary to the insight of taproot that most contracts have a happy path where all participants collaborate with a signature.” Others have argued that there’s no case where the vault user wouldn’t want an option to escape the vault’s conditions through a keypath spend, and that because it costs nothing to add a keypath option to a contract created for scriptpaths, it would be strictly superior to enable a keypath.

The argument against always providing a keypath option seems to be that there are cases even when all the signers acting together don’t trust themselves. They instead trust other people—the operators of economic full nodes who enforce Bitcoin’s consensus rules—to enforce restrictions on the signers spending ability which the signers are unwilling to enforce themselves.

The counterpoint is that, at least purely in theory, you can create a keypath spend between the regular signers and all those economic full node operators to obtain the same security. More practically, there’s probably some subset or alternative set of those node operators who can be added to your keypath multisig set who will enforce the policy you want, if they’re available (and, if they aren’t, you’ve lost nothing since you can still use the scriptpath spend).

Theory aside, we recommend taking some extra time to consider whether there’s an opportunity to use a keypath spend in a taproot-based contract even when it doesn’t seem like an option.

Trivia

Originally published in Newsletter #171

  • What is a taproot? Wikipedia says, “A taproot is a large, central, and dominant root from which other roots sprout laterally. Typically a taproot is somewhat straight and very thick, is tapering in shape, and grows directly downward. In some plants, such as the carrot, the taproot is a storage organ so well developed that it has been cultivated as a vegetable.”

    How does this apply to Bitcoin?

    • “I always assumed the origin of the name was ‘taps into the Merkle root’, but I don’t actually know what Gregory Maxwell’s thinking was.” —Pieter Wuille (source)

    • “I originally had to look the word up; but I took it as the key path being the ‘taproot’ because that’s the tasty one that you make carrot soup out of, and the merklized scripts would be the other lesser roots that you hope to ignore.” —Anthony Towns (source)

    • “The name originated in a visualization of a tree with a thick central truck like a dandelion taproot—the technique is mostly useful because of the assumption that there is one high probability path and the rest is fuzzy stragglers, and I thought it was a good one because of the punny fact that it verifies script-path spends by tapping into the hidden commitment in the root.

      […] Alas, calling the hash tree with the sorted interior nodes a ‘myrtle tree’ didn’t catch on. (Myrtle tree because the set of policies with an equal hash root are ones whos ordering differs by a permutation which can be defined by a t-function, and Myrtle is the family which includes melaleuca, the tea-tree, and it sounds like ‘merkle’. :p )” —Gregory Maxwell (source)

  • Schnorr signatures predate ECDSA: we talk about schnorr signatures as an upgrade on Bitcoin’s original ECDSA signatures because they make it easier to implement various cryptographic tricks, but the schnorr signature algorithm predates the DSA algorithm that ECDSA is based upon. Indeed, DSA was created in part to circumvent Claus Peter Schnorr’s patent on schnorr signatures but Schnorr still claimed “[my] patents apply to various implementations of discrete log signatures of that sorts and hence covers the use of Nyberg-Rueppel and DSA signatures in these instances.” No court is known to have supported Schnorr’s claim and his patent expired by 2011.

  • Unsure what name to use: although it didn’t work out, there was a suggestion early in the development of adapting schnorr signatures for Bitcoin that Claus Peter Schnorr’s name shouldn’t be used in association with them because his patent on them prevented the widespread use of a valuable cryptographic technique for over 20 years. Pieter Wuille writes, “we did consider calling BIP340 ‘DLS’ for ‘Discrete Logarithm Signatures’, but I think we eventually didn’t go through with that because the name Schnorr was already so much talked about.”

  • Schnorr signatures for twisted Edwards curves: an application of schnorr signatures using elliptic curves was published in 2011. The scheme, EdDSA, is now the basis of several standards. Although not used in Bitcoin consensus, references to it in the context of other systems can be found in many of the Bitcoin repositories tracked by Optech.

  • Pay to contract: Ilja Gerhardt and Timo Hanke created a protocol, presented by Hanke at the 2013 San Jose Bitcoin conference, for allowing a payment to commit to the hash of its contract. Anyone with a copy of the contract, and the nonce used to avoid certain attacks, can verify the commitment—but to anyone else the payment looks like any other Bitcoin payment.

    A slight improvement to this pay-to-contract (P2C) protocol was included in the 2014 paper about sidechains, where the commitment also includes the original public key to pay. Taproot uses this same construction but, instead of committing to the terms of an offchain contract, the output creator commits to consensus-enforced terms chosen by the receiver for how they can spend the received bitcoins onchain.

  • A Good Morning: the idea to use P2C so that payments to scripts can look identical onchain to paying public keys was invented in Los Altos, California, at the diner “A Good Morning” on 22 January 2018. Pieter Wuille writes that the idea was developed by Andrew Poelstra and Gregory Maxwell “while I briefly left the table… !$%@” [sic].

  • 2.5 years in 1.5 days: choosing the optimal constant for bech32m required about 2.5 years of CPU time, which was performed in just 1.5 days mostly using a CPU cluster belonging to Gregory Maxwell.

We thank Anthony Towns, Gregory Maxwell, Jonas Nick, Pieter Wuille, and Tim Ruffing for enjoyable conversations related to this column. Any errors are the author’s.

Future consensus changes

Originally published in Newsletter #172

As taproot nears activation at block 709,632, we can start to look forward to some of the consensus changes that developers have previously expressed the desire to build on top of taproot.

  • Cross-input signature aggregation: schnorr signatures make it easy for owners of several distinct public and private key pairs to create a single signature that proves all of the key owners cooperated in creating the signature. With a future consensus change, this may allow a transaction to contain a single signature which proves the owners of all the UTXOs being spent in that transaction authorized the spend. This will save about 16 vbytes per keypath spend after the first input, providing significant savings for consolidation and coinjoins. It could even make coinjoin-based spending cheaper than spending by yourself, providing a mild incentive to use more private spending.

  • SIGHASH_ANYPREVOUT: every normal Bitcoin transaction includes one or more inputs, and each of those inputs references the output of a previous transaction, using its txid. That reference tells full verification nodes like Bitcoin Core how much money the transaction can spend and what conditions need to be fulfilled to prove the spend was authorized. All ways of generating signatures for Bitcoin transactions, both with and without taproot, either commit to the txids in the prevouts or don’t commit to the prevouts at all.

    That’s a problem for multiuser protocols that don’t want to use a precise pre-arranged series of transactions. If any user can skip a particular transaction, or change any detail of any transaction besides its witness data, that will change any later transaction’s txid. Changing the txid invalidates any signatures previously created for later transactions. This forces offchain protocols to implement mechanisms (such as LN-penalty) that penalize any user who submits an older transaction.

    SIGHASH_ANYPREVOUT can eliminate this problem by allowing a signature to skip committing to the prevout txid. Depending on other flags used, it will still commit to other details about the prevout and the transaction (such as amount and script), but it will no longer matter what txid is used for the previous transaction. This will make it possible to implement both the eltoo layer for LN and improvements in vaults and other contract protocols.

  • Delegation and generalization: after you create a script (taproot or otherwise), there’s almost no way for you to delegate to additional people the ability to spend from that script short of giving them your private key (which can be extremely dangerous when using BIP32 wallets). Additionally, taproot could be made more affordable for users who want to use a keypath spend plus just a small number of script-based conditions. Several methods for enhancing taproot by generalizing it and providing signer delegation have been proposed:

    • Graftroot: proposed shortly after the introduction of the idea for taproot, graftroot would give an extra feature to anyone capable of making a taproot keypath spend. Instead of directly spending their funds, the keypath signers could instead sign a script that described new conditions under which the funds could be spent, delegating spending authority to anyone capable of satisfying the script. The signature, the script, and whatever data was needed to satisfy the script would be provided in the spending transaction. The keypath signers could delegate to an unlimited number of scripts in this way without creating any onchain data until an actual spend occurred.

    • Generalized taproot (g’root): a few months later, Anthony Towns suggested a way to use public key points to commit to multiple different spending conditions without necessarily using a MAST-like construction. This generalized taproot (g’root) construction is “potentially more efficient for cases where the taproot assumption doesn’t hold”. It also “offers an easy way to construct a softfork-safe cross-input aggregation system”.

    • Entroot: a more recent synthesis of graftroot and g’root that simplifies many cases and makes them more bandwidth efficient. It can support signer delegation from anyone able to satisfy any of the entroot branches, not just those able to create a top-level keypath spend.

  • New and old opcodes: the taproot soft fork includes support for tapscript which provides an improved way to add new opcodes to Bitcoin, OP_SUCCESSx opcodes. Similar to the OP_NOPx (no operation) opcodes added early in Bitcoin’s history, the OP_SUCCESSx opcodes are designed to be replaced with opcodes that don’t always return success. Some proposed new opcodes include:

    • Restore old opcodes: a number of opcodes for math and string operations were disabled in 2010 due to concerns about security vulnerabilities. Many developers would like to see these opcodes re-enabled after a security review, and (in some cases) perhaps extended to handle larger numbers.

    • OP_CAT: one of the previously-disabled opcodes that deserves special mention is OP_CAT, which researchers have since discovered can enable all sorts of interesting behavior on Bitcoin by itself, or which can be combined with other new opcodes in interesting ways.

    • OP_TAPLEAF_UPDATE_VERIFY: as described in Newsletter #166, an OP_TLUV opcode can enable covenants in a way that’s particularly efficient and powerful when used with taproot’s keypath and scriptpath capabilities. This can be used to implement joinpools, vaults, and other security and privacy improvements. It may also combine well with OP_CHECKTEMPLATEVERIFY.

All of the ideas above are still only proposals. None is guaranteed to be successful. It’ll be up to researchers and developers to bring each proposal to maturity and then for users to decide whether adding each feature to Bitcoin is worth the effort of changing Bitcoin’s consensus rules.

What happens at activation?

Originally published in Newsletter #173

Less than two weeks after the publication of this post, taproot is expected to activate at block 709,632. We know what we expect to happen, and we also know about a few possible failure modes.

The best and most likely outcome is that everything goes fine. Nothing that happens should be visible to normal users. Only those carefully monitoring their nodes or trying to create taproot transactions should notice anything. At block 709,631 nearly all full nodes we’re aware of will be enforcing the same consensus rules. One block later, nodes running Bitcoin Core 0.21.1, 22.0, or related releases will be enforcing the additional taproot rules not enforced by earlier software releases.

This carries a risk that earlier and later versions of node software will accept different blocks. This happened during the activation of the BIP66 soft fork in 2015, resulting in a six-block chain split and several shorter chain splits. Significant engineering effort has been invested in preventing a repeat of that problem. A similar problem should only happen with taproot if a miner either deliberately mines a taproot-invalid block or has disabled safety measures hardcoded into Bitcoin Core and related node software.

Specifically, to create a chain split, a miner would need to create or accept a transaction that spends from a taproot output (segwit v1 output) without following taproot’s rules. If a miner did that, they would lose at least 6.25 BTC (about $400,000 USD at the time of writing) if the economic consensus of Bitcoin node operators rejects the taproot-invalid blocks.

We can’t know for sure without creating an invalid block what those node operators will do—nodes can be run entirely privately—but proxy measures indicate that perhaps more than 50% of node operators are running taproot-enforcing versions of Bitcoin Core. That’s probably more than sufficient to ensure any miner who creates a taproot-invalid block will see it rejected by the network.

Although very unlikely, a temporary chain split is theoretically possible. It should be possible to monitor for it using services such as ForkMonitor.info or using the getchaintips RPC in Bitcoin Core. If it does happen, lightweight clients may receive false confirmations. Although it is theoretically possible to get 6 confirmations, like in the 2015 chain split, that would imply miners had lost almost $2.5 million in value (compared to losses of about $50,000 in 2015). We can hope with values that large at stake, miners will actually enforce the taproot rules they signaled preparedness for six months ago.

In almost any failure circumstance we can imagine, a simple but effective temporary response is to raise your confirmation limit. If you normally wait for 6 confirmations before accepting a payment, you can quickly raise that 30 confirmations for a few hours until the problem has been resolved or it becomes clear that an even higher confirmation limit is required.

For users and services that are convinced the economic consensus of full node operators will enforce taproot’s rules, an even simpler solution is to only get information about which transactions are confirmed from Bitcoin Core 0.21.1 or later (or a compatible alternative node implementation).

Optech expects taproot activation to proceed smoothly, but we do encourage exchanges and anyone accepting large values around block 709,632 to either upgrade their node or be prepared to temporarily raise their confirmation limit if there are any indications of problems.

Thank you!

Originally published in Newsletter #174

Taproot will activate at block 709,632, which is anticipated a few days after the publication of this column. As the final entry in this series, we would like to thank some of the many people who helped develop and activate taproot—and who will soon begin enforcing it. Many others not mentioned below are also deserving of thanks—we apologize for all such omissions.

Bitcoin-dev mailing list discussions

The key idea behind taproot originated on the morning of 22 January 2019 at a meeting between several cryptographers. It was posted to the Bitcoin-Dev mailing list later the same day. Each of the people named below contributed to a thread with “taproot” in its name.

Adam Back, Andrea Barontini, Andreas Schildbach, Andrew Chow, Andrew Poelstra, Anthony Towns, Antoine Riard, Ariel Lorenzo-Luaces, Aymeric Vitte, Ben Carman, Ben Woosley, Billy Tetrud, BitcoinMechanic, Bryan Bishop, Carlo Spiller, Chris Belcher, Christopher Allen, Clark Moody, Claus Ehrenberg, Craig Raw, Damian Mee, Daniel Edgecumbe, David A. Harding, DA Williamson, Elichai Turkel, Emil Pfeffer, Eoin McQuinn, Eric Voskuil, Erik Aronesty, Felipe Micaroni Lalli, Giacomo Caironi, Gregory Maxwell, Greg Sanders, Jay Berg, Jeremy Rubin, John Newbery, Johnson Lau, Jonas Nick, Karl-Johan Alm, Keagan McClelland, Lloyd Fournier, Luke Dashjr, Luke Kenneth Casson Leighton, Mark Friedenbach, Martin Schwarz, Matt Corallo, Matt Hill, Michael Folkson, Natanael, Oleg Andreev, Pavol Rusnak, Pieter Wuille, Prayank, R E Broadley, Riccardo Casatta, Robert Spigler, Ruben Somsen, Russell O’Connor, Rusty Russell, Ryan Grant, Salvatore Ingala, Samson Mow, Sjors Provoost, Steve Lee, Tamas Blummer, Thomas Hartman, Tim Ruffing, Vincent Truong, vjudeu, yancy, yanmaani—, and ZmnSCPxj.

However, many of the ideas included in taproot, such as schnorr signatures and MAST, predate taproot by years or even decades. It’s beyond our capacity to list the many contributors to those ideas, but we owe them our thanks nonetheless.

Taproot BIP review

Starting in November 2019, a large number of users and developers participated in an organized review of taproot and related developments.

achow101, afk11, aj, alec, amiti, _andrewtoth, andytoshi, ariard, arik, b10c, belcher, bjarnem, BlueMatt, bsm1175321, cdecker, chm-diederichs, Chris_Stewart_5, cle1408, CubicEarth, Day, ddustin, devrandom, digi_james, dr-orlovsky, dustinwinski, elichai2, evoskuil, fanquake, felixweis, fjahr, ghost43, ghosthell, gmaxwell, harding, hebasto, instagibbs, jeremyrubin, jnewbery, jonatack, justinmoon, kabaum, kanzure, luke-jr, maaku, mattleon, michaelfolkson, midnight, mol, Moller40, moneyball, murch, nickler, nothingmuch, orfeas, pinheadmz, pizzafrank13, potatoe_face, pyskell, pyskl, queip, r251d, raj_149, real_or_random, robert_spigler, roconnor, sanket1729, schmidty, sipa, soju, sosthene, stortz, taky, t-bast, theStack, Tibo, waxwing, xoyi-, and ZmnSCPxj.

GitHub pull requests

The main implementation of taproot in Bitcoin Core was submitted for review starting in January 2020 in two pull requests. The following people left a GitHub review on those PRs.

Andrew Chow (achow101), Anthony Towns (ajtowns), Antoine Riard (ariard), Ben Carman (benthecarman), Ben Woosley (Empact), Bram (brmdbr), Cory Fields (theuni), Dmitry Petukhov (dgpv), Elichai Turkel (elichai), Fabian Jahr (fjahr), Andreas Flack (flack), Gregory Maxwell (gmaxwell), Gregory Sanders (instagibbs), James O’Beirne (jamesob), Janus Troelsen (ysangkok), Jeremy Rubin (JeremyRubin), João Barbosa (promag), John Newbery (jnewbery), Jon Atack (jonatack), Jonathan Underwood (junderw), Kalle Alm (kallewoof), Kanon (decryp2kanon), kiminuo, Luke Dashjr (luke-jr), Marco Falke (MarcoFalke), Martin Habovštiak (Kixunil), Matthew Zipkin (pinheadmz), Max Hillebrand (MaxHillebrand), Michael Folkson (michaelfolkson), Michael Ford (fanquake), Adam Ficsor (nopara73), Pieter Wuille (sipa) Sjors Provoost (Sjors), Steve Huguenin-Elie (StEvUgnIn), Tim Ruffing (real-or-random), and Yan Pritzker (skwp).

This doesn’t count several other related PRs to Bitcoin Core as well as the work of implementing taproot in other software, including schnorr support in libsecp256k1 (used by Bitcoin Core) or alternative node software.

Taproot activation discussion

As the taproot implementation was merged into Bitcoin Core, it fell on the community to decide how it would be activated. This led to several months of discussion, with the most active conversations on the taproot activation IRC channel between the following users, developers, and miners:

6102bitcoin, AaronvanW, achow101, aj, alec, Alexandre_Chery, Alistair_Mann, amiti, andrewtoth, andytoshi, AnthonyRonning, ariel25, arturogoosnargh, AsILayHodling, averagepleb, bcman, belcher, benthecarman, Billy, bitcoinaire, bitentrepreneur, bitsharp, bjarnem, blk014, BlueMatt, bobazY, brg444, btcactivator, btcbb, cato, catwith1hat, cguida, CodeShark__, conman, copumpkin, Crash78, criley, CriptoLuis, CubicEarth, darbsllim, darosior, Day, DeanGuss, DeanWeen, debit, Decentralizedb, devrandom, DigDug, dome, dr_orlovsky, duringo, dustinwinski, eeb77f71f26eee, eidnrf, elector, elichai2, Emcy, emzy, entropy5000, eoin, epson121, erijon, eris, evankaloudis, faketoshi, fanquake, fedorafan, felixweis, fiach_dubh, fjahr, friendly_arthrop, GeraldineG, gevs, gg34, ghost43, ghosthell, giaki3003, gloved, gmaxwell, graeme1, GreenmanPGI, gr-g, GVac, gwillen, gwj, gz12, gz77, h4shcash, harding, hebasto, hiro8, Hotmetal, hsjoberg, huesal, instagibbs, Ironhelix, IT4Crypto, ja, jaenu, JanB, jeremyrubin, jimmy53, jnewbery, jonatack, jonny100051, jtimon, kallewoof, kanon, kanzure, Kappa, keblek, ksedgwic, landeau, lucasmoten, luke-jr, maaku, Majes, maybehuman, mblackmblack, mcm-mike, Memesan, michaelfolkson, midnight, MikeMarzig, mips, mol, molz, moneyball, mrb07r0, MrHodl, murch, naribia, newNickName, nickler, nikitis, NoDeal, norisgOG, nothingmuch, occupier, OP_NOP, OtahMachi, p0x, pinheadmz, PinkElephant, pox, prayank, prepaid, proofofkeags, provoostenator, prusnak, qubenix, queip, r251d, rabidus, Raincloud, raj, RamiDz94, real_or_random, rgrant, riclas, roasbeef, robert_spigler, rocket_fuel, roconnor, rovdi, rubikputer, RusAlex, rusty, sanket1729, satosaurian, schmidty, sdaftuar, setpill, shesek, shinobiusmonk, snash779, solairis, somethinsomethin, stortz, sturles, sugarpuff, taPrOOteD, TechMiX, TheDiktator, thomasb06, tiagocs, tomados, tonysanak, TristanLamonica, UltrA1, V1Technology, vanity, viaj3ro, Victorsueca, virtu, walletscrutiny, wangchun, warren, waxwing, Whatisthis, whuha, willcl_ark, WilliamSantiago, windsok, wumpus, xxxxbtcking, yanmaani, yevaud, ygrtiugf, Yoghurt11411, zmnscpxj, and zndtoshi.

Miner signaling

We also thank all of the miners since block 681,408 that have signaled their readiness to enforce taproot’s rules.

Side projects

Activation of taproot is only the start. It will now be up to developers and users to begin using the new features made available. Some have been preparing for this for years, working on projects such as MuSig and others. There’s no convenient way to get a list of such developers, but we thank all of them any way.

Node operators

Most importantly, we all owe thanks to the thousands of operators of Bitcoin full verification nodes that have upgraded to Bitcoin Core 0.21.1 or later (or compatible software) and who use their nodes for receiving payments, ensuring that they will only accept transactions in blocks that obey taproot’s rules starting with block 709,632. This provides an economic incentive for every other Bitcoin user to also only accept taproot-compliant blocks, making it safe for everyone to use taproot’s features.

Footnotes

  1. When Electrum upgraded to segwit v0, it required anyone who wanted to receive to bech32 addresses generate new seeds. This was not technically required but it allowed the authors of Electrum to introduce some new features into their custom seed derivation method. One of those features was ability for a seed version number to specify which scripts a seed is meant to be used with. This allows safe deprecation of old scripts (e.g., a future a version of Electrum may be released that no longer supports receiving to legacy P2PKH addresses).

    Around the same time the Electrum developers were deploying their versioned seeds, Bitcoin Core developers began using output script descriptors to solve the same problem of allowing script deprecation (in addition to solving other problems). The following table compares Electrum’s versioned seeds and Bitcoin Core’s descriptors to the implicit scripts method previously used by both wallets and still in common use among most other wallets.

    Script management Initial backup Introducing new scripts Scanning (bandwidth/CPU cost) Deprecating scripts
    Implicit scripts (e.g. BIP44) Seed words Automatic (no user action required) Must scan for all supported scripts, O(n) No way to warn users that they're using unsupported scripts
    Explicit scripts (versioned seeds) Seed words (includes version bits) User must backup new seed; funds are either partitioned into two separate wallets or user must send funds from the old wallet to the new Only scans for a single script template, O(1) Users warned about unsupported scripts
    Explicit scripts (descriptors) Seed words and descriptor User must back up the new descriptor Only scans for the script templates that were actually used, O(n); n=1 for a new wallet Users warned about unsupported scripts

  2. Users who want to receive a P2TR payment in the first taproot block should generate an address they don’t share with anyone and then create a transaction to that address with nLockTime set to 709,631. That transaction can be broadcast at as soon as block 709,631 has been received. The nLockTime will ensure the transaction can’t be included into any block before 709,632, where taproot rules are enforced. Messing about with new script types and custom locktimes can be dangerous if you don’t know what you’re doing, so please take care. 

  3. A payer can choose a very twisty path (i.e. route randomization) to make HTLC correlation analysis wrong, but that has its own drawbacks:

    • Twisty paths are costlier and less reliable (more nodes have to be paid, and more nodes need to successfully forward in order for the payment to reach the destination).
    • Twisty paths are longer, meaning the payer is telling more nodes about the payment, making it more likely they will hit some surveillant node. Thus, twisty paths are not necessarily a perfect improvement in privacy.

  4. When considering unpublished channels, remember that it takes two to tango, and if an unpublished channel is closed, then one participant (say, an LN service provider) uses the remaining funds for a published channel, a blockchain explorer can guess that the source of the funds has some probability of having been an unpublished channel that was closed. 

  5. Yes, details matter, but they also do not: from a high enough vantage point, the unexpected hardships of some aspect of development and the unexpected non-hardships of other aspects of development cancel out, and we are left with every major feature being roughly around some average time frame. If we want to make accurate estimates as opposed to feel-good estimates, we should use methods that avoid the planning fallacy. Thus, we should just look for a similar previous completed feature, and deliberately ignore its details, only looking at how long the feature took to implement. 

  6. If known in advance you could pre-sign the spend transaction with a specific nSequence, but then you don’t need an alternative spending path with “active” keys at all. Also, you don’t usually know how you are going to spend your coins at the time you receive them.