Secure Commitment
Let's examine the cause of our insecure commitment first.
We have:
The root cause is that nothing ties to .
Alice can pick any contract she wants, and then compute a that makes it fit the same .
Let's fix that.
The fix
One small change: put inside the hash.
t = hash(P || contract)Q = P + t·GNow let's take the same scenario, where Alice wants to swap the contract.
She needs a new key and a new tweak:
For her forgery to work she needs the same , so she needs:
She knows , , and the fake contract'. The only thing missing is . So let's solve for it:
Look at the last line.
appears on both sides of the equation.
To compute she first needs . But is a hash of . So she needs before she can get .
Alice can't pick and solve for .
Her only other option is to guess: try random values until one happens to work. That means breaking the hash function.
The commitment is now binding.
This is what taproot really does
This is exactly the shape taproot uses. The real tweak is
t = tagged_hash("TapTweak", P || merkle_root)
