The Taproot Tweak

Until now we went from a tweaked key that looks like

Q=P+t×G=P+hash(Pdata)×GQ = P + t \times G = P + \text{hash}(P \, || \, \text{data}) \times G

into

Q=P+taggedhash(P)×GQ = P + \text{taggedhash}(P) \times G

And from the Tagged Hashes lesson we know that

tagged_hash(tagName,P)=sha256(sha256(tagName)sha256(tagName)P)\text{tagged\_hash}(\text{tagName}, P) = \text{sha256}(\text{sha256}(\text{tagName}) \, || \, \text{sha256}(\text{tagName}) \, || \, P)

We need now the tag we use for the tweak.

The tag we use for the tweak is "TapTweak".

So our tweak becomes:

t=tagged_hash("TapTweak",P)t = \text{tagged\_hash}(\text{"TapTweak"}, P)

Why a tagged hash again?

Remember the reason we use a tagged hash: it lets us hash the same data in different contexts and get different results. Here we hash PP with the tag "TapTweak". If we hashed the same PP with another tag like "TapTweak2", we would get a completely different result.

So we end up with the final tweaked key QQ:

Q=P+sha256(sha256("TapTweak")sha256("TapTweak")P)×GQ = P + \text{sha256}(\text{sha256}(\text{"TapTweak"}) \, || \, \text{sha256}(\text{"TapTweak"}) \, || \, P) \times G

Code

Let's do an exercise. We take an internal public key PP and compute the tweaked key QQ.

Steps:

  • generate a private key xx and its public key P=x×GP = x \times G
  • calculate the tweak t=tagged_hash("TapTweak",P)t = \text{tagged\_hash}(\text{"TapTweak"}, P)
  • compute Q=P+t×GQ = P + t \times G
  • assert Q==(x+t)×GQ == (x + t) \times G
Click to reveal next hint (0/2)
  • tagged_hash needs bytes. Hash P's x-coordinate: P[0].to_bytes(32, 'big'). (This is the x-only form from the X-only Public Keys lesson.)
  • Turn the digest into a scalar mod n, then Q = add(P, mul(t)).

Solution code

You may have noticed the hint: we hashed only PP's x-coordinate, 32 bytes. That is not an accident. It is the x-only form we covered in X-only Public Keys.

Suggest Edits