TeachMeBitcoin

Two-party CoinJoin with SIGHASH_SINGLE:

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

13. SIGHASH_SINGLE — Signing One Output

Overview

SIGHASH_SINGLE (value 0x03) commits to all inputs but only to the one output whose index matches the current input's index. It allows other outputs to be freely added without invalidating the signature.

Commits to:
✓ All inputs (their outpoints)
✓ The output at the same index as the signed input
✓ Current input's sequence

Does NOT commit to:
✗ Outputs at other indices
✗ Other inputs' sequences

The Correspondence Rule

With SIGHASH_SINGLE, input N is bound to output N:

Input 0 (SIGHASH_SINGLE) ─────────── binds to ──→ Output 0
Input 1 (SIGHASH_ALL)    ─────────── binds to ──→ Outputs 0, 1, 2... (all)
Input 2 (SIGHASH_SINGLE) ─────────── binds to ──→ Output 2

Outputs 1, 3, 4... are "open" and can be added by anyone

Serialization Logic

def apply_sighash_single(tx_copy, input_index):
    if input_index >= len(tx_copy.outputs):
        # The famous SIGHASH_SINGLE bug:
        # No corresponding output exists; the protocol returns hash of 1
        return None  # signals the 0x01 hash quirk

    # Truncate outputs to just index + 1
    tx_copy.outputs = tx_copy.outputs[:input_index + 1]

    # Null out all outputs before input_index
    for i in range(input_index):
        tx_copy.outputs[i].value = 0xFFFFFFFFFFFFFFFF  # -1 as uint64
        tx_copy.outputs[i].script = b''

    # Set other inputs' sequences to 0
    for i, inp in enumerate(tx_copy.inputs):
        if i != input_index:
            inp.sequence = 0

    return tx_copy

Use in Fee Bumping and CoinJoin

SIGHASH_SINGLE is useful when multiple parties are assembling a transaction and each wants to control their own output:

# Two-party CoinJoin with SIGHASH_SINGLE:
Transaction:
  Input 0 (Alice, 1.0 BTC, SIGHASH_SINGLE) → Output 0 (Alice, 0.9 BTC, her change)
  Input 1 (Bob, 1.0 BTC, SIGHASH_SINGLE)   → Output 1 (Bob, 0.9 BTC, his change)

Alice signs: commits to [Input 0, Input 1 outpoints] + [Output 0]
Bob signs:   commits to [Input 0, Input 1 outpoints] + [Output 1]

Neither Alice nor Bob needs to know the other's output script to sign.

Lightning Network Payment Channels

SIGHASH_SINGLE combined with SIGHASH_ANYONECANPAY is used in some Lightning channel constructions to allow fee bumping through transaction splicing:

# Initial commitment transaction uses SIGHASH_SINGLE|ANYONECANPAY
# so external inputs/outputs can be added to pay fees without
# invalidating the channel partners' signatures
☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!