TYPE 0x0702 · COMPOUND FAMILY
HTLC
Hash Time Locked Contract — hash preimage verification, relative timelock, and signature check combined in a single block. Collapses a hash + CSV + SIG three-block pattern, saving 16 bytes on wire.
Compound Non-InvertibleLadder Diagram
Fields
| Field | Data Type | Size | Side | Description |
|---|---|---|---|---|
| hash | HASH256 | 32 B | Conditions | SHA-256 hash that the receiver-path preimage must match. F24: the descriptor surface accepts either form — htlc(@r, @s, <preimage_hex>, csv) auto-SHA256s the input, while htlc(@r, @s, h:<HASH256_hex>, csv) stores the supplied 32-byte hash verbatim. Both produce identical conditions; the h: form is what formatladder emits so that parse → format → parse round-trips at the conditions-root level. |
| csv | NUMERIC | 1-4 B | Conditions | Relative timelock in blocks (BIP-68 sequence value) for the refund path. |
| scheme | SCHEME | 1 B | Conditions | Signature scheme byte routed into VerifySigWithScheme on either path. |
| receiver_pubkey | PUBKEY | 32-33 B | Witness | Receiver pubkey (witness PUBKEY index 0). Used by the receiver/early path. |
| sender_pubkey | PUBKEY | 32-33 B | Witness | Sender pubkey (witness PUBKEY index 1). Used by the sender/refund path. Both keys are revealed even if only one is consumed by the sig — the rung leaf reconstruction at MLSC-proof level needs both. |
| signature | SIGNATURE | var | Witness | Single signature; verified against receiver_pubkey on path 0 or sender_pubkey on path 1. |
| preimage | PREIMAGE | var | Witness | On path 0 (receiver): non-empty preimage whose SHA-256 must equal hash. On path 1 (refund): must be empty — closes the embedding channel. |
| path | NUMERIC | 1 B | Witness | Path indicator: 0 = receiver (hashlock claim, no CSV), 1 = sender (CSV refund, no preimage). Any other value → ERROR. |
PubkeyCountForBlock = 2; both pubkeys revealed in the witness for leaf reconstruction (closes audit finding E-002 by ensuring both keys are consumed across the two paths). The implicit witness layout has a strict 5-field shape; the evaluator rejects anything that does not match exactly.
Wire Format Breakdown
Conditions side (committed in the rung leaf):
0x0702
0
3
HASH256 · 32B
NUMERIC · 3B
SCHEME · 1B
≈ 40 bytes
Witness side:
0x0702
0
5
PUBKEY · 35B (rcv)
PUBKEY · 35B (snd)
SIGNATURE · 66B
PREIMAGE · var
NUMERIC · 1B (path)
≈ 175 + len bytes
Total (conditions + witness)
≈ 215 + len bytes
Compared to separate hash + CSV + SIG blocks: 233 bytes → 217 bytes (saves 16B / 6.9%)
Compared to equivalent Tapscript (2-leaf P2TR, claim path): 265 bytes → 217 bytes (saves 48B / 18.1%)
Evaluation Logic
1.
Strict shape check: the merged conditions+witness block must have exactly
3 + 5 = 8 fields with the exact type sequence HASH256, NUMERIC, SCHEME, PUBKEY, PUBKEY, SIGNATURE, PREIMAGE, NUMERIC. Anything else → ERROR
2.
Verify the conditions HASH256 is exactly 32 B. ReadNumeric the path indicator (witness NUMERIC); undecodable → ERROR
3.
path == 0 (receiver/early): PREIMAGE must be non-empty (else UNSATISFIED). Compute
SHA256(PREIMAGE); mismatch with conditions HASH256 → UNSATISFIED. Then dispatch VerifySigWithScheme(receiver_pubkey, sig, scheme, ...); the sig result is the block result. CSV is not enforced on this path.
4.
path == 1 (sender/refund): PREIMAGE must be empty (anti-data-embedding); else → ERROR. ReadNumeric the conditions CSV; undecodable → ERROR. SEQUENCE_LOCKTIME_DISABLE_FLAG set → ERROR (defeats the refund timer). Range guard: out of uint32 → UNSATISFIED. CheckSequence(uint32_t(csv)) fails → UNSATISFIED. Then dispatch VerifySigWithScheme(sender_pubkey, sig, scheme, ...); the sig result is the block result.
5.
Any other path value → ERROR. On UNSATISFIED,
ctx.error_message_out (if non-null) is populated with the specific check that fired ("HTLC: path=0 preimage hash mismatch", etc.) so mempool reject reasons carry the diagnostic.
Return Values
| Condition | Result |
|---|---|
| Field count or type sequence does not match the strict 8-field shape | ERROR |
| HASH256 not exactly 32 B; or path NUMERIC undecodable; or path not in {0,1} | ERROR |
| path == 0 (receiver): PREIMAGE empty | UNSATISFIED |
path == 0: SHA256(preimage) ≠ hash | UNSATISFIED |
| path == 1 (refund): PREIMAGE non-empty (anti-embedding) | ERROR |
| path == 1: SEQUENCE_LOCKTIME_DISABLE_FLAG set, or CSV undecodable | ERROR |
path == 1: CSV out of uint32 range, or CheckSequence fails | UNSATISFIED |
| SIG verification fails on the selected pubkey | UNSATISFIED |
| Selected path's checks all pass | SATISFIED |
JSON Wire Format
Conditions (committed in the rung leaf)
{
"type": "HTLC",
"inverted": false,
"fields": [
{ "type": "HASH256", "hex": "e3b0c44298fc1c... preimage hash 32 bytes" },
{ "type": "NUMERIC", "value": 144 },
{ "type": "SCHEME", "hex": "01" }
]
}Witness — receiver path (path = 0, hashlock claim)
{
"type": "HTLC",
"fields": [
{ "type": "PUBKEY", "hex": "02aabb... receiver pubkey" },
{ "type": "PUBKEY", "hex": "02ccdd... sender pubkey (still revealed)" },
{ "type": "SIGNATURE", "hex": "... receiver Schnorr sig ..." },
{ "type": "PREIMAGE", "hex": "deadbeef... preimage hashing to the conditions HASH256" },
{ "type": "NUMERIC", "value": 0 }
]
}Witness — refund path (path = 1, CSV must be elapsed)
{
"type": "HTLC",
"fields": [
{ "type": "PUBKEY", "hex": "02aabb... receiver pubkey (still revealed)" },
{ "type": "PUBKEY", "hex": "02ccdd... sender pubkey" },
{ "type": "SIGNATURE", "hex": "... sender Schnorr sig ..." },
{ "type": "PREIMAGE", "hex": "" },
{ "type": "NUMERIC", "value": 1 }
]
}Use Cases
Lightning Network Payment Channels
HTLCs are the core payment routing primitive. Each pending payment in a channel commitment has a claim path (preimage + sig) and timeout path (CSV + sig). The compound HTLC block handles the claim path in a single evaluation dispatch, reducing per-HTLC overhead.
Cross-Chain Atomic Swaps
Alice locks BTC with an HTLC where Bob can claim with a preimage. Bob locks altcoin with the same hash. Alice claims the altcoin (revealing preimage), Bob uses the revealed preimage to claim BTC.
Conditional Escrow
Payment released when a secret is revealed (preimage), but only within a time window. After the CSV delay, the sender can reclaim funds via a separate timeout rung.