Menu
BOLT-bolt-03 Final

BOLT-03: Bitcoin Transactions

Lightning transaction format specification. Funding transactions, commitment transactions, and HTLC outputs.

Type Basis of Lightning Technology
Number bolt-03
Status Final
Authors Lightning Network Developers
Original https://github.com/lightning/bolts/blob/master/03-bitcoin-transaction-and-script-formats.md
Requires

BOLT-03: Bitcoin Transaction Formats

BOLT-03 specifies the exact Bitcoin transaction formats used in Lightning channels. This includes funding transactions, commitment transactions, and HTLC output scripts.

Specification Summary

AspectValue
StatusFinal
LayerBitcoin
PurposeTransaction formats
DependenciesBOLT-02

Transaction Types

TransactionPurposeWhen Created
FundingCreates channelChannel open
CommitmentCurrent stateEach update
HTLC-SuccessClaim HTLCPreimage reveal
HTLC-TimeoutRefund HTLCAfter timeout
ClosingCooperative closeMutual agreement

Funding Transaction

Creates the channel by locking funds in a 2-of-2 multisig.

Output Script

OP_2 <pubkey1> <pubkey2> OP_2 OP_CHECKMULTISIG

Where pubkey1 < pubkey2 (lexicographically sorted).

P2WSH Address

def funding_script(pubkey1: bytes, pubkey2: bytes) -> bytes:
    """Generate funding output script."""
    keys = sorted([pubkey1, pubkey2])
    return bytes([
        0x52,  # OP_2
        0x21, *keys[0],  # 33-byte pubkey
        0x21, *keys[1],  # 33-byte pubkey
        0x52,  # OP_2
        0xae   # OP_CHECKMULTISIG
    ])

def funding_address(script: bytes) -> str:
    """Generate P2WSH address from script."""
    script_hash = sha256(script)
    return bech32_encode("bc", 0, script_hash)

Commitment Transaction

Represents current channel state. Each party holds their own asymmetric version.

Structure

Input:
  - Funding transaction output

Outputs (example):
  - to_local: Delayed output to holder
  - to_remote: Immediate output to peer
  - HTLCs: Offered and received HTLCs
  - Anchors: Fee bumping outputs (if enabled)

to_local Output

Holder’s funds with revocation and CSV delay:

OP_IF
    <revocationpubkey>
OP_ELSE
    <to_self_delay>
    OP_CHECKSEQUENCEVERIFY
    OP_DROP
    <local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG

Spending paths:

  1. Revocation: Peer can claim if revoked state broadcast
  2. Local: Holder can claim after CSV delay

to_remote Output

Peer’s funds, immediately spendable:

# With static_remotekey feature
<remotepubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY

# Or simple P2WPKH
<remotepubkey>

Anchor Outputs

Small outputs for CPFP fee bumping:

<local_funding_pubkey> OP_CHECKSIG
OP_IFDUP
OP_NOTIF
    16 OP_CHECKSEQUENCEVERIFY
OP_ENDIF

Value: 330 satoshis each (anchor dust limit).

HTLC Outputs

Offered HTLC (Outgoing)

You’re offering payment, peer can claim with preimage:

# To remote node with preimage:
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
    OP_CHECKSIG
OP_ELSE
    <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
    OP_IF
        # Payment preimage provided
        OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
        2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
    OP_ELSE
        # Timeout path
        OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
        OP_CHECKSIG
    OP_ENDIF
OP_ENDIF

Received HTLC (Incoming)

You’re receiving payment, can claim with preimage:

# Similar structure but inverted roles
OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
    OP_CHECKSIG
OP_ELSE
    <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
    OP_NOTIF
        # Timeout path for remote
        OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
    OP_ELSE
        # Payment path with preimage
        OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
        2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
    OP_ENDIF
    <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_ENDIF

HTLC-Success Transaction

Claims received HTLC with preimage:

Version: 2
Inputs:
  - HTLC output from commitment
  - Witness: 0 <remotehtlcsig> <localhtlcsig> <payment_preimage>

Outputs:
  - to_local script (with CSV delay)

Locktime: 0

HTLC-Timeout Transaction

Reclaims offered HTLC after timeout:

Version: 2
Inputs:
  - HTLC output from commitment
  - Witness: 0 <remotehtlcsig> <localhtlcsig> <>

Outputs:
  - to_local script (with CSV delay)

Locktime: cltv_expiry

Key Derivation

Per-Commitment Keys

Each commitment uses unique derived keys:

def derive_pubkey(base_point: bytes, per_commitment_point: bytes) -> bytes:
    """Derive pubkey for this commitment."""
    tweak = sha256(per_commitment_point + base_point)
    return point_add(base_point, G * tweak)

def derive_revocation_key(
    revocation_basepoint: bytes,
    per_commitment_point: bytes
) -> bytes:
    """Derive revocation key."""
    # Complex derivation for security
    pass

Basepoints

Each party provides in open_channel/accept_channel:

  • funding_pubkey: For funding output
  • revocation_basepoint: Derive revocation keys
  • payment_basepoint: to_remote outputs
  • delayed_payment_basepoint: to_local outputs
  • htlc_basepoint: HTLC outputs

Fee Calculation

Weight Estimation

ComponentWeight
Base commitment724
Per-HTLC (no anchors)172
Per-HTLC (with anchors)172
Anchor output330
def commitment_weight(num_htlcs: int, has_anchors: bool) -> int:
    base = 724
    htlc_weight = 172 * num_htlcs
    anchor_weight = 660 if has_anchors else 0
    return base + htlc_weight + anchor_weight

def calculate_fee(weight: int, feerate_per_kw: int) -> int:
    """Calculate fee in satoshis."""
    return (weight * feerate_per_kw + 999) // 1000

Dust Limits

Outputs below dust limit are omitted:

DUST_LIMIT_P2WPKH = 294
DUST_LIMIT_P2WSH = 330

def is_dust(value: int, output_type: str) -> bool:
    if output_type == "p2wpkh":
        return value < DUST_LIMIT_P2WPKH
    return value < DUST_LIMIT_P2WSH

Closing Transaction

Cooperative close with negotiated fee:

Input:
  - Funding output

Outputs:
  - to_local_scriptpubkey (immediate)
  - to_remote_scriptpubkey (immediate)

No timelocks, immediately spendable by both parties.

  • BOLT-02 - Channel protocol using these transactions
  • BOLT-05 - On-chain transaction handling

Machine-Readable Summary

{
  "bolt": "03",
  "title": "Bitcoin Transaction Formats",
  "status": "final",
  "transaction_types": [
    "funding",
    "commitment",
    "htlc_success",
    "htlc_timeout",
    "closing"
  ],
  "key_concepts": [
    "2-of-2-multisig",
    "csv-delays",
    "revocation",
    "htlc-scripts"
  ]
}