We’ll also look at how Bitcoin Improvement Protocols (or BIPs) are activated to implement upgrades into Bitcoin.

Tapscript (BIP 342)

The third part of the proposal, BIP 342, describes an upgrade that complements both Schnorr and Taproot, known as Tapscript. As explained in our first part on Schnorr/Taproot/Tapscript, Bitcoin Script is used to define the spending policies of coins.

BIP 342 improves signature hashing so we can validate taproot scripts, introduces flexibility to add new opcodes to enhance Bitcoin’s smart contract capability, and also changes some limits for resource requirements.

What is an Opcode?

Opcodes, short for operation codes, are basically script words or commands. These commands can return either “TRUE” or “FALSE”, and are used to send/receive transactions successfully.

For example, the instructions specify the number of signatures required to unlock the script. They also indicate the amount of bitcoin that is sent, along with the recipient’s address.

Opcodes can be used to remove items and perform calculations, where the result is added back onto the stack. Remember, as a stack-based programming language, Script commands are executed sequentially, starting from the top of the stack and finishing at the bottom.

What is Tapscript?

As an upgraded version of Bitcoin’s programming language (Script), Tapscript enables easier addition of new features and builds on the batch verifiability of Schnorr signatures.

What is batch verification? Find out in our first part on Schnorr/Taproot/Tapscript here.

Tapscript also complements the improvements to Bitcoin’s script structure proposed in BIP 341 (Taproot) — which requires certain opcodes to change, and BIP 342 concerns itself with the changes that need to happen.

Another way of understanding Tapscript is by considering the Merkle tree of Taproot, where every leaf is a script that is combined with what is called a leaf version — similar to script versioning with SegWit.

But the difference is that the scripts aren’t revealed at payment time, only at spending time. Different leaves can have different versions, where only the one that is actually used is revealed. Tapscript is the proposed version 0 of the leaf version under Taproot.

Tapscript shares most operations with legacy and SegWit Bitcoin Script, but there are a few differences:

The signature opcode verifies Schnorr signatures (instead of ECDSA signatures).

Multi-signature opcodes OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY are replaced by a OP_CHECKSIGADD opcode — which allows for signature batch verification with Schnorr.

Since the verification of signatures is the most CPU intensive operation in Bitcoin Script, these opcodes are essential in realising the efficiency gains associated with Schnorr-based multi-signature schemes.

Currently, the script for a 2-of-3 multi-signature transaction looks like:

2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG

With Taproot/Tapscript, the same multi-signature policy can be created in a batch verifiable way, where the script is:

<A pubkey> OP_CHECKSIG <B pubkey> OP_CSADD <C pubkey> OP_CHECKSIGADD OP_2 OP_EQUAL

Many opcodes are redefined to be OP_SUCCESS opcodes that unconditionally render the entire script valid to simplify soft fork upgrades.

The introduction of new opcodes is made easier with OP_SUCCESS as compared to the existing mechanism with OP_NOP .

Tapscript turns previously unusable opcodes that would normally return “FALSE” to return “TRUE” instead. Any time these opcodes exist inside the script, you can spend it unconditionally, where practical advantage is that opcodes can be redefined to be anything and need not be backward compatible.

This new mechanism that extends scripts with new opcodes is far simpler to coordinate and use than the existing witness versioning. The result is that it hopefully clears the way for adding more useful opcodes to Bitcoin’s Script in the future.

The existing NOP opcodes were probably added specifically with the intent of having an upgrade mechanism so that we can easily add new opcodes to the Bitcoin Script language.

But so far they have only been used for CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY . To be soft-fork compatible, these NOPs are only capable of doing one of two things: 1) abort or 2) not do anything at all.

Because of their redefinition of a NOP, CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY opcodes today cannot modify the stack in any way. As a result, they don’t pop their argument from the stack and you always need an OP_DROP after that.

As a solution to having an opcode that doesn’t do anything, i.e., a NOP, Tapscript introduces OP_SUCCESS as a new opcode that just “returns TRUE”. These opcodes are not utilised until there is a use for them, and will not be used until they have defined locked-in semantics on the network.

The result is that disabled and never-defined opcode numbers are turned into “return TRUE”. Later, these opcodes can be redefined to be anything, because everything is soft-fork compatible with “return TRUE”.

Signature hashes ( SIGHASH ) are calculated differently than in legacy script or BIP143 v0 segwit.

What is a signature hash? In short, signature hashes are a flag to Bitcoin signatures that indicates what parts of the transaction the signature signs.

With scriptsigs, a signature proves that you have authorization to spend a coin. These signatures are constructed in a certain way and there is a single byte appended to a signature that specifies in what way the transaction was signed. So there are a few SIGHASH flags that are implemented and have been deployed already.

The most commonly used is SIGHASH_ALL , where everything is signed except for the scriptsigs. Others like SIGHASH_ANYONECANPAY are used when only the current input is signed and everything else in the transaction is not considered part of the signature, it is not covered under the commitment.

There have been many proposed improvements for these SIGHASH types where you only want to sign certain aspects of the transaction, and you could specify under what conditions you’re interested in (and not interested in) when spending coins. Numerous SIGHASH flags have been proposed for how to do this, including SIGHASH_NOINPUT .

The way it works is by masking out different parts of the transaction. The idea with SIGHASH_NOINPUT is that you don’t care what specific input is being provided, you don’t care what the transaction ID is that provides the input into the transaction, however you do care about the amount. This was proposed in 2015 as a malleability fix before SegWit — which itself is a malleability fix. The concerns and risk around SIGHASH_NOINPUT meant that the community did not incorporate it (but the introduction of SegWit re-opens the door to this upgrade).

The main benefit of SIGHASH_NOINPUT is that it greatly siplifies how payment channels, such as in the Lightning Network, are enforced. A proposal to change the way Lightning works, eltoo, which simplifies the use of channels by making it unneccessary to have penalty closures in the case by trying to cheat by transmitting a prior state which has been invalidated.

This requires a change in Bitcoin Script. In particular, the change involves the way signatures are applied to transactions (i.e., the sighash system) which allows users to rebalance to a different input.

Although some existing sighash types are tweaked a bit, the Schnorr/Taproot/Tapscript proposal offers nothing similar to BIP 118, i.e., SIGHASH_NOINPUT (the reason being that there is already a lot of discussion about various ways of doing it and making it safe).

Instead of including SIGHASH_NOINPUT , Tapscript comes with several flexibility mechanisms (i.e., tagged public keys) that would allow open up this capability in the future with no additional cost. This mechanism will make it easy for future soft forks to extend the signature-checking opcodes with new sighash types or other changes.

With Tapscript, public keys that start with a byte you don’t know are automatically valid. Consequently, new types of signature schemes and new sighash schemes can be introduced without the need to add new checksig opcodes for each. Things like SIGHASH_NOINPUT can be included with no additional cost as a new public key version.

Tapscript also changes resource limitations.

For example, Bitcoin script today has a 10,000 byte script size limit which will be dropped. It also removes the limit on the number of opcodes.

Since there is no scriptCode directly included in the signature hash (only indirectly through a pre-computable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed.

In Tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction cumbersome because it is an additional constraint — along with weight. Instead, the number of Tapscript signature opcodes is limited by witness weight.

Tapscript, along with BIPs 340/341, expands the number of interesting applications possible with Bitcoin, an example being expressive Taproot contracts. Expressive Taproot contracts permit more complicated multi-party contracts and opens up the possibility of Decentralised Autonomous Organisations (DAOs) based on Bitcoin.

Activating BIPs 340–342 on Bitcoin

How do upgrades get added to the Bitcoin protocol?

After the submission of a BIP, code is written to match the specification, which is then submitted as a pull request. After this stage, users and developers vote on the pull request. Even if it gets merged, users place their real vote by running the new code (or not, and sticking with the old).

The Schnorr/Taproot/Tapscript upgrade is currently at the ecosystem feedback stage (shown in the diagram below). The next steps are to work on the code, getting pull requests up for Bitcoin and having a test net ready.

Although the diagram suggests that progress occurs linearly, there may be some feedback loops between the ecosystem feedback and protocol implementation stages (e.g., the proposal may go through further changes as the specification is translated into working code).

An overview of how BIPs are included into the Bitcoin protocol

As seen with the SegWit upgrade in 2017, the use of BIP 9 — which requires 95% of miners to signal their readiness for activation — can lead to a tug of war between different players in the ecosystem, between developers/users and miners.

Some argue that Bitcoin miners may use the BIP 9 as a power play and mould the protocol to their benefit. For example, SegWit failed to activate with BIP 9 and instead turned to a variation created by shaolinfry, known as a User Activated Soft Fork or BIP 148.

To activate BIPs 340–342, Bitcoin developer Matt Carallo proposed the ‘Great Consensus Clean Up’ as a possible method, drawing on the lessons from the SegWit upgrade. This proposal combines the desirable properties of BIP 8 and BIP 9 and would look something like this:

The activation method would initially be like a standard BIP 9 deployment (with the usual 95% miner readiness required over a one-year time horizon), If activation fails along this avenue, a six-month period allows the community to discuss the reasons that the upgrade was not activated, Users could opt into a BIP 8 deployment with a two-year time horizon for activation.

This activation method attempts to balances following the will of the community but also making the activation period long enough to ensure that the changes to the Bitcoin protocol do not set a negative precedent.

Timings are uncertain, as it is not known whether unexpected hiccups may occur when translating these proposals into working code. We could see the activation of BIPs 340–342 by late 2020, perhaps much later.

Schnorr/Taproot/Tapscript is arguably the most significant change to Bitcoin yet and improves scaling, spending policy privacy and smart contract functionality. While it many take — at least — another two years or more to see wide adoption (using SegWit adoption as a gauge), the benefits for Bitcoin will be far reaching.

If you have any questions about Tapscript (BIP 342), please leave them in the comments below.