Introduction
If you’re building Bitcoin or Lightning applications in Rust, understanding the difference between legacy transactions and SegWit is crucial.
In this post, I’ll walk you through:
- How UTXOs and scripts work
- The problems with legacy transactions
- How SegWit solved these problems
- Why this matters for the Lightning Network
1. Legacy Transactions (P2PKH)
In Bitcoin’s original system, when Alice wants to send BTC to Bob, she must:
- Sign the transaction with her private key
- Provide her public key
- Specify Bob’s public key hash as the output
Legacy Transaction Structure
Input (scriptSig = Unlocking script):
<signature> <publicKey>
Output (locking script):
OP_DUP OP_HASH160 <Bob’s publicKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Diagram – Legacy Transaction
[ Input ] -------------------------> [ Output ]
scriptSig: locking script:
<AliceSig> <AlicePubKey> OP_DUP OP_HASH160 <BobPKH> OP_EQUALVERIFY OP_CHECKSIG
Here:
- Alice proves ownership with her signature + public key.
- Miners hash Alice’s public key, compare it to the UTXO’s public key hash, and check the signature.
2. Problems With Legacy Transactions
Malleability:
Transaction IDs included the signature. If anyone slightly modified the signature, the txid changed. This caused big problems for advanced protocols like Lightning.High Fees:
Signatures and public keys are large. Bigger transactions → higher fees.
3. Enter SegWit (P2WPKH)
SegWit (Segregated Witness) moved the unlocking data (signature + public key) out of the scriptSig
into a new structure called the witness.
-
scriptSig
is now empty (or minimal). - Witness data is not included in the transaction ID calculation.
SegWit Transaction Structure
Input (scriptSig):
(empty or minimal)
Witness:
<signature> <publicKey>
Output (locking script – unchanged):
OP_DUP OP_HASH160 <Bob’s publicKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Diagram – SegWit Transaction
[ Input ] -----> [ Output ] + [ Witness ]
scriptSig: locking script: witness data:
(empty) OP_DUP OP_HASH160 <AliceSig> <AlicePubKey>
<BobPKH>
OP_EQUALVERIFY
OP_CHECKSIG
4. Why This Matters
SegWit fixed two key issues:
- No more malleability: Txids are stable because signatures aren’t included in the hash.
- Lower fees: Witness data is discounted, making transactions smaller and cheaper.
5. Impact on Lightning Network
SegWit wasn’t just a cleanup. It enabled:
- Lightning Network: Needs stable txids to work.
- Scalability: More transactions fit into each block.
- Future upgrades: Like Taproot, which builds on SegWit.
6. Rust Code Example
Here’s a simplified Rust example showing how legacy and SegWit signatures differ when building transactions.
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::consensus::encode::serialize;
use bitcoin::util::sighash::SighashCache;
use bitcoin::{Amount, EcdsaSighashType};
// Legacy P2PKH signing
fn sign_legacy(tx: &Transaction, input_index: usize, script_pubkey: &bitcoin::Script, value: u64, privkey: &secp256k1::SecretKey) {
let secp = secp256k1::Secp256k1::new();
let mut cache = SighashCache::new(tx);
let sighash = cache.legacy_signature_hash(input_index, script_pubkey, value, EcdsaSighashType::All).unwrap();
let msg = secp256k1::Message::from_slice(&sighash).unwrap();
let sig = secp.sign_ecdsa(&msg, privkey);
println!("Legacy signature: {:?}", sig);
}
// SegWit P2WPKH signing
fn sign_segwit(tx: &Transaction, input_index: usize, script_code: &bitcoin::Script, value: u64, privkey: &secp256k1::SecretKey) {
let secp = secp256k1::Secp256k1::new();
let mut cache = SighashCache::new(tx);
let sighash = cache.p2wpkh_signature_hash(input_index, script_code, Amount::from_sat(value), EcdsaSighashType::All).unwrap();
let msg = secp256k1::Message::from_slice(&sighash[..]).unwrap();
let sig = secp.sign_ecdsa(&msg, privkey);
println!("SegWit signature: {:?}", sig);
}
Conclusion
By moving signatures into the witness field, Bitcoin became cheaper, safer, and faster.
As developers, understanding this transition is essential — not just for implementing wallets but also for building scalable Layer 2 solutions like Lightning.
Top comments (0)