Solving Transaction Malleability

Todays newsletter continues chapter 3 from Bitcoin: A Work in Progress.

This week I was a guest at the Bitcoin.Review podcast episode 20!

Solving Transaction Malleability

As we explained last week, it’s easy to see how much of an issue malleability was.

A transaction consists of all the transaction data and the signature. It’s identified by the transaction ID, which, before SegWit, was the hash of those two things. For example, the 10 BTC transaction from Satoshi to Hal Finney is f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.

However, because the signature can be tweaked, the hash (transaction ID) can also be tweaked, and you end up with basically the same transaction but with a different transaction ID. That’s the problem that needed to be solved: somehow either making sure the signature can’t be modified, or that such a modification won’t change the transaction hash. The first approach appears to be very difficult if not impossible, (see BIP 62 so SegWit involves the second approach.

The solution was to append the signature to the end of a transaction. This new transaction part isn’t included when calculating the identifier hash. It’s also not given to old nodes. As far as old nodes are concerned, the signature is empty and anyone can spend the transaction. To be more precise: The scriptSig is empty, where before it would’ve put a public key and signature on the stack. In turn, the scriptPubKey is a 0 followed by a public key hash. To old nodes, this combination results in a non-zero item on the stack, i.e. True, which is a valid spend. On the other hand, SegWit-enabled nodes will interpret the scriptPubKey as a SegWit v0 program and use the new witness field when evaluating. See BIP 141. Because the new signature part isn’t included in the transaction hash, its identifier doesn’t change when the signature changes. Both new nodes, which have the signature, and old nodes which don’t, can calculate the transaction ID and it’s identical for both.

In short, SegWit solved the transaction malleability issue, where transaction IDs could be altered without invalidating the transactions themselves. In turn, solving the transaction malleability issue enabled second-layer protocols like the Lightning network.