Pay to Taproot

So far we've seen many types of scriptPubKey in the previous modules: P2PKH, P2WPKH, P2SH, P2WSH.

Reminder of the previous scripts

P2PKHOP_DUP OP_HASH160 <20B pubkey hash> OP_EQUALVERIFY OP_CHECKSIGP2WPKHOP_0 <20B pubkey hash>P2SHOP_HASH160 <20B script hash> OP_EQUALP2WSHOP_0 <32B script hash>

Today we will learn about a new type of scriptPubKey called P2TR.

P2TR has the following format:

OP_1 <32B tweaked key>
  • OP_1 means segwit version 1
  • <32B tweaked key> is what we are going to spend the next chapters explaining

Segwit v0 vs v1

Segwit v0 is used in P2WPKH and P2WSH:

P2WPKHOP_0 <20B pubkey hash>P2WSHOP_0 <32B script hash>

So far this looks like a simple script, and it can be spent with the private key corresponding to the tweaked key.

But the tweaked key is built in a way that makes it interesting. Let's see how.

Tweaking a public key

The term "tweak" means we start from an original public key and we make a change to it, to get a tweaked public key.

And that's exactly what we are going to do here.

Let's say we have an original public key PP. Tweaking it means we alter it with a value (we call it the tweak tt), so that we get a new tweaked public key we call QQ.

Q=P+tGQ = P + t \cdot G

There's a lot going on here, so let's break this equation into two parts: PP the original public key, and tGt \cdot G.

Part 1: PP

PP is our original public key. Let's call dd its private key.

P=dGP = d \cdot G

That's just scalar multiplication, the operation that turns a private key dd into a public key PP. We do this by adding the generator point GG to itself dd times.

PP is also a point on the secp256k1 curve.

We know from the previous lessons that if we have funds locked to a public key PP, we can use the private key dd to sign and spend from it.

Part 2: tGt \cdot G

Now notice the second part of the equation, tGt \cdot G.

Doesn't this also look like a normal point on the secp256k1 curve, with tt acting as its private key?

That's exactly what it is. tGt \cdot G is a point, made by adding GG to itself tt times.

We are going to call this point TT, so it's easier to reference.

  • TT is the tweak point
  • tt is the tweak value

T=tGT = t \cdot G

Putting it back together

So QQ, the tweaked public key, is just the addition of two points: PP the original public key, and TT the tweak point.

Q=P+TQ = P + T

Q=dG+tG=(d+t)GQ = d \cdot G + t \cdot G = (d + t) \cdot G

Adding the two public keys dGd \cdot G and tGt \cdot G gives us the point whose private key is the sum d+td + t.

That means if we have funds locked to the tweaked public key QQ, we can spend them with the tweaked private key d+td + t.

This works because QQ is just another point on the curve, made by an addition.

The P2TR output

Remember the scriptPubKey we saw at the beginning:

OP_1 <32B tweaked key>

That <32B tweaked key> is the QQ we just computed.

OP_1 <Q> = OP_1 <P + T> = OP_1 <d·G + t·G>

A tweaked key looks like any other key

Someone looking at this script cannot tell a tweaked public key from an untweaked one. They both look the same, 32 bytes, just like any other public key. This is one of the properties of taproot: privacy.

Right now the tweak tt is just some value. In the next lessons we will see what happens when we make tt commit to something. That is where taproot gets interesting.

Signing with a tweaked keypair

We said that funds locked in QQ can be spent with the tweaked private key x+tx + t. Let's prove it in code.

Fill in the two tweaked values, then press Run.

Click to reveal next hint (0/2)
  • T is already t*G. Add two points with add(P, T).
  • The tweaked private key is the sum of the scalars, reduced mod n: (x + t) % n.

Solution code

The verifier only ever sees QQ. It has no idea the key was built by adding a tweak. In the next lessons we make that tweak carry data, which is where taproot gets powerful.

Suggest Edits