This content originally appeared on DEV Community and was authored by μ΄κ΄νΈ(Gwanho LEE)
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.
This content originally appeared on DEV Community and was authored by μ΄κ΄νΈ(Gwanho LEE)