Skip to content

Commit ba6cbfa

Browse files
committed
[drop me] fuzz: add force-close corpus and notes
1 parent 94c4875 commit ba6cbfa

368 files changed

Lines changed: 763 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fc-crashes.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Force-close fuzzer LDK crashes
2+
3+
Minimized crash sequences found by the chanmon_consistency fuzzer with
4+
force-close support. All crashes are `debug_assert` or `panic!` inside
5+
LDK, not in the fuzzer harness. Byte 0 encodes monitor styles (bits
6+
0-2) and channel type (bits 3-4: 0=Legacy, 1=KeyedAnchors).
7+
8+
## 1. channelmonitor.rs:2727 - HTLC input not found in transaction
9+
10+
```
11+
debug_assert!(htlc_input_idx_opt.is_some());
12+
```
13+
14+
When resolving an HTLC spend, the monitor searches for the HTLC
15+
outpoint in the spending transaction's inputs but doesn't find it.
16+
Falls back to index 0 in release mode, which would produce incorrect
17+
tracking.
18+
19+
Minimized (17 bytes):
20+
```
21+
0x40 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xdc 0xde 0xff
22+
```
23+
24+
Byte 0 = 0x40: Legacy channels, no async monitors. The sequence is
25+
mostly 0xff (settlement) repeated, with height advances (0xdc, 0xde)
26+
near the end. This suggests the crash happens during settlement when
27+
processing on-chain HTLC spends after repeated settlement attempts.
28+
29+
## 2. onchaintx.rs:913 - Duplicate claim ID in pending requests
30+
31+
```
32+
debug_assert!(self.pending_claim_requests.get(&claim_id).is_none());
33+
```
34+
35+
The OnchainTxHandler registers a claim event with a claim_id that
36+
already exists in the pending_claim_requests map.
37+
38+
Minimized (10 bytes):
39+
```
40+
0x08 0xd2 0x70 0x70 0x71 0x70 0x10 0x19 0xde 0xff
41+
```
42+
43+
Byte 0 = 0x08: KeyedAnchors channels, no async monitors.
44+
- 0xd2: B force-closes the A-B channel
45+
- 0x70/0x71: disconnect/reconnect peers
46+
- 0x10, 0x19: process messages on nodes A and B
47+
- 0xde: advance chain 200 blocks
48+
- 0xff: settle
49+
50+
B force-closes, peers disconnect and reconnect, messages are exchanged,
51+
then height advances and settlement triggers the duplicate claim.
52+
53+
## 3. onchaintx.rs:1025 - Inconsistent internal maps
54+
55+
```
56+
panic!("Inconsistencies between pending_claim_requests map and claimable_outpoints map");
57+
```
58+
59+
The OnchainTxHandler detects that its `pending_claim_requests` and
60+
`claimable_outpoints` maps are out of sync.
61+
62+
Minimized (14 bytes):
63+
```
64+
0x00 0x3c 0x11 0x19 0xd0 0xde 0xff 0xff 0x19 0x21 0x19 0xde 0x26 0xff
65+
```
66+
67+
Byte 0 = 0x00: Legacy channels, all monitors completed.
68+
- 0x3c: send hop payment A->B->C (1M msat)
69+
- 0x11, 0x19: process messages to commit HTLC on A-B
70+
- 0xd0: A force-closes A-B
71+
- 0xde: advance 200 blocks
72+
- 0xff: settle (first round)
73+
- 0xff: settle again (second round, processes more messages)
74+
- 0x19, 0x21, 0x19: continue processing B and C messages
75+
- 0xde: advance 200 more blocks
76+
- 0x26: process events on node C
77+
- 0xff: settle (third round)
78+
79+
A hop payment partially committed, then A force-closes. Multiple
80+
settlement rounds with continued message processing in between triggers
81+
the internal map inconsistency.
82+
83+
## 4. test_channel_signer.rs:395 - Signing revoked commitment
84+
85+
```
86+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={}")
87+
```
88+
89+
The test channel signer is asked to sign an HTLC transaction for a
90+
commitment number that has already been revoked.
91+
92+
Minimized (18 bytes):
93+
```
94+
0x22 0x71 0x71 0x71 0x71 0x71 0x71 0x71 0xff 0xff 0xff 0xff 0xff 0xff 0xde 0xde 0xb5 0xff
95+
```
96+
97+
Byte 0 = 0x22: Legacy channels, async monitors on node B.
98+
- 0x71: disconnect B-C peers (repeated, only first effective)
99+
- 0xff: settle (repeated 6 times)
100+
- 0xde 0xde: advance 400 blocks
101+
- 0xb5: restart node B with alternate monitor state
102+
- 0xff: settle
103+
104+
Async monitors on B with peer disconnection, repeated settlements,
105+
height advances, and a node restart with a different monitor state.
106+
The stale monitor combined with the restart puts B's signer in a state
107+
where it's asked to sign for an already-revoked commitment.
108+
109+
## 5. channelmanager.rs:9836 - Payment blocker not found
110+
111+
```
112+
debug_assert!(found_blocker);
113+
```
114+
115+
During payment processing, the ChannelManager expects to find a
116+
specific blocker entry for an in-flight payment but it's missing.
117+
118+
Minimized (13 bytes):
119+
```
120+
0x00 0x3c 0x11 0x19 0x11 0x1f 0x19 0x21 0x19 0x27 0x27 0xde 0xff
121+
```
122+
123+
Byte 0 = 0x00: Legacy channels, all monitors completed.
124+
- 0x3c: send hop A->B->C (1M msat)
125+
- 0x11, 0x19, 0x11: commit HTLC on A-B
126+
- 0x1f: B processes events (forwards HTLC to C)
127+
- 0x19, 0x21, 0x19: commit HTLC on B-C
128+
- 0x27, 0x27: C processes events (claims payment)
129+
- 0xde: advance 200 blocks
130+
- 0xff: settle
131+
132+
A straightforward A->B->C hop payment that completes normally (C
133+
claims), followed by a height advance and settlement. No force-close
134+
in this sequence, so the height advance before settlement may cause
135+
HTLC timeout processing that conflicts with the claim path.
136+
137+
## 6. channelmanager.rs:19484 - Monitor update ID ordering violation
138+
139+
```
140+
debug_assert!(update.update_id >= pending_update.update_id);
141+
```
142+
143+
A ChannelMonitorUpdate has an update_id that is less than a pending
144+
update's id, violating the expected monotonic ordering.
145+
146+
Minimized (10 bytes):
147+
```
148+
0x84 0x70 0x11 0x19 0x11 0x1f 0xd0 0x11 0x1f 0xba
149+
```
150+
151+
Byte 0 = 0x84: Legacy channels, no async monitors, high bits set
152+
(bits 3-4 = 0, bits 7 and 2 set).
153+
- 0x70: disconnect A-B peers
154+
- 0x11, 0x19, 0x11: process messages (likely reestablish after setup)
155+
- 0x1f: process B events
156+
- 0xd0: A force-closes A-B channel
157+
- 0x11: process A messages
158+
- 0x1f: process B events
159+
- 0xba: restart node B with alternate monitor state
160+
161+
A force-close followed by continued message/event processing and a
162+
node B restart triggers a monitor update with an out-of-order ID.

0 commit comments

Comments
 (0)