Transaction Creation
Creating Bitcoin transactions programmatically involves selecting inputs, creating outputs, calculating fees, signing, and broadcasting. This guide covers the complete process.
Transaction Structure
Basic Components
Transaction:
Version: 4 bytes
Input Count: VarInt
Inputs: Array of inputs
Output Count: VarInt
Outputs: Array of outputs
Locktime: 4 bytes
Witness: (if SegWit)
Input Structure
Input:
Previous TXID: 32 bytes
Previous Output Index: 4 bytes
Script Length: VarInt
Script: Variable
Sequence: 4 bytes
Output Structure
Output:
Value: 8 bytes (satoshis)
Script Length: VarInt
Script: Variable (typically 22-34 bytes)
Serializing a Transaction Output
Step-by-Step Process
Step 1: Select UTXOs
Choose which UTXOs to spend:
# List available UTXOs
bitcoin-cli listunspent
# Select UTXOs (coin selection algorithm)
# Total value >= payment + fee
Step 2: Create Raw Transaction
# Create transaction
bitcoin-cli createrawtransaction \
'[{"txid":"abc123...", "vout":0}]' \
'{"<destination_address>": 0.001}'
Parameters:
- Inputs: Array of UTXOs to spend
- Outputs: Destination address and amount
Step 3: Sign Transaction
# Sign transaction
bitcoin-cli signrawtransactionwithwallet <hex>
For Multisig:
# Sign with specific key
bitcoin-cli signrawtransactionwithkey <hex> \
'["<private_key>"]' \
'[{"txid":"...", "vout":0, "scriptPubKey":"...", "redeemScript":"..."}]'
Step 4: Broadcast Transaction
# Broadcast to network
bitcoin-cli sendrawtransaction <signed_hex>
Fee Calculation
Estimating Transaction Size
Base Transaction:
- Version: 4 bytes
- Input count: 1-9 bytes
- Output count: 1-9 bytes
- Locktime: 4 bytes
Per Input:
- Previous output: 36 bytes
- Script length: 1-9 bytes
- Script: Variable (depends on script type)
- Sequence: 4 bytes
Per Output:
- Value: 8 bytes
- Script length: 1-9 bytes
- Script: Variable (typically 22-34 bytes)
Virtual Size (SegWit)
Weight = (Base Size × 3) + Total Size
Virtual Size = Weight / 4
Fee Calculation
Fee = Transaction Size (vBytes) × Fee Rate (sat/vB)
Example:
Transaction Size: 250 vBytes
Fee Rate: 10 sat/vB
Fee: 2,500 sats
Change Outputs
When to Create Change
Create change output if:
- Input value > Payment + Fee + Dust Threshold
- Change amount > Dust threshold (546 sats)
Change Output Creation
# Include change output
bitcoin-cli createrawtransaction \
'[{"txid":"...", "vout":0}]' \
'{"<destination>": 0.001, "<change_address>": 0.0005}'
Signing Process
Single Signature
P2PKH:
Script: <signature> <public_key>
P2WPKH:
Witness: <signature> <public_key>
Multisig Signing
Process:
- Create transaction
- Sign with first key
- Sign with second key (using partially signed tx)
- Continue until M signatures collected
- Broadcast fully signed transaction
Transaction Validation
Before Broadcasting
- Check Inputs: Verify UTXOs are still unspent
- Verify Balance: Ensure sufficient funds
- Validate Fee: Check fee meets minimum
- Check Size: Ensure transaction is valid size
- Verify Signatures: All signatures valid
Common Validation Errors
- Insufficient funds: Not enough input value
- Invalid signature: Signature doesn't match
- Double spend: UTXO already spent
- Dust output: Output below dust threshold
- Fee too low: Fee below minimum
Best Practices
For Developers
- Fee Estimation: Accurate fee estimation is critical
- UTXO Management: Efficient coin selection
- Error Handling: Handle all error cases
- Validation: Validate before broadcasting
- Testing: Test on testnet first
For Users
- Verify Address: Double-check destination address
- Check Fee: Ensure reasonable fee
- Wait for Confirmation: Don't assume immediate confirmation
- Backup: Backup transaction if needed
- Monitor: Track transaction status
Common Issues
Transaction Stuck
Problem: Transaction not confirming
Solutions:
- Wait for confirmation
- Use Replace-by-Fee (RBF) if enabled
- Increase fee (if possible)
- Wait for mempool to clear
Insufficient Fee
Problem: Fee too low, transaction rejected
Solutions:
- Increase fee rate
- Use higher priority
- Wait for lower network activity
Invalid Transaction
Problem: Transaction rejected by network
Causes:
- Invalid signature
- Double spend
- Dust output
- Invalid script
Solution: Fix issue and recreate transaction
Advanced Topics
Replace-by-Fee (RBF)
Enable RBF:
# Set sequence to enable RBF
# Sequence < 0xFFFFFFFF - 1
Replace Transaction:
# Create replacement with higher fee
bitcoin-cli createrawtransaction ... --replaceable
Partially Signed Bitcoin Transactions (PSBT)
Create PSBT:
bitcoin-cli walletcreatefundedpsbt \
'[]' \
'[{"<address>": <amount>}]'
Sign PSBT:
bitcoin-cli walletprocesspsbt <psbt>
Finalize PSBT:
bitcoin-cli finalizepsbt <psbt>
Summary
Transaction creation involves:
- UTXO Selection: Choose inputs to spend
- Output Creation: Create payment and change outputs
- Fee Calculation: Calculate appropriate fees
- Signing: Sign with private keys
- Broadcasting: Send to network
- Validation: Verify transaction is valid
Understanding transaction creation is essential for building Bitcoin wallets and applications.
Related Topics
- Bitcoin Wallets - Introduction to Bitcoin wallets
- Coin Selection - How wallets choose UTXOs to spend
- Multisig - Multi-signature transaction signing
- PSBT - Partially Signed Bitcoin Transactions standard
- Mempool - Where unconfirmed transactions wait
