Skip to content

Commit 328a711

Browse files
committed
contractcourt: enhance chainAction type
We distinguish between dangling and dust htlcs. This does not change any logic but only introduces new types to later act on them differently when we begin to fail dust htlcs earlier in a later commit.
1 parent 8890f83 commit 328a711

File tree

1 file changed

+67
-16
lines changed

1 file changed

+67
-16
lines changed

contractcourt/channel_arbitrator.go

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,19 +1256,28 @@ func (c *ChannelArbitrator) stateStep(
12561256
return StateError, closeTx, err
12571257
}
12581258

1259-
// If we can fail an HTLC immediately (an outgoing HTLC
1260-
// with no contract and it was not canceled before),
1261-
// then we'll assemble an HTLC fail packet to send.
1259+
// We can fail the upstream HTLC for an outgoing
1260+
// dangling and dust HTLC because we can be sure they
1261+
// will not be resolved onchain.
12621262
getIdx := func(htlc channeldb.HTLC) uint64 {
12631263
return htlc.HtlcIndex
12641264
}
12651265
remoteDangling := fn.NewSet(fn.Map(
1266-
getIdx, htlcActions[HtlcFailNowAction],
1266+
getIdx, htlcActions[HtlcFailDanglingAction],
12671267
)...)
12681268
err := c.abandonForwards(remoteDangling)
12691269
if err != nil {
12701270
return StateError, closeTx, err
12711271
}
1272+
1273+
dustHTLCs := fn.NewSet(fn.Map(
1274+
getIdx, htlcActions[HtlcFailDustAction],
1275+
)...)
1276+
1277+
err = c.abandonForwards(dustHTLCs)
1278+
if err != nil {
1279+
return StateError, closeTx, err
1280+
}
12721281
}
12731282

12741283
// Now that we know we'll need to act, we'll process all the
@@ -1716,10 +1725,11 @@ const (
17161725
// before its timeout period.
17171726
HtlcClaimAction = 2
17181727

1719-
// HtlcFailNowAction indicates that we should fail an outgoing HTLC
1720-
// immediately by cancelling it backwards as it has no corresponding
1721-
// output in our commitment transaction.
1722-
HtlcFailNowAction = 3
1728+
// HtlcFailDustAction indicates that we should fail the upstream HTLC
1729+
// for an outgoing dust HTLC immediately (even before the commitment
1730+
// transaction is confirmed) because it has no output on the commitment
1731+
// transaction. This also includes remote pending outgoing dust HTLCs.
1732+
HtlcFailDustAction = 3
17231733

17241734
// HtlcOutgoingWatchAction indicates that we can't yet timeout this
17251735
// HTLC, but we had to go to chain on order to resolve an existing
@@ -1738,6 +1748,13 @@ const (
17381748
// HtlcIncomingDustFinalAction indicates that we should mark an incoming
17391749
// dust htlc as final because it can't be claimed on-chain.
17401750
HtlcIncomingDustFinalAction = 6
1751+
1752+
// HtlcFailDanglingAction indicates that we should fail the upstream
1753+
// HTLC for an outgoing HTLC immediately after the commitment
1754+
// transaction has confirmed because it has no corresponding output on
1755+
// the commitment transaction. This category does NOT include any dust
1756+
// HTLCs which are mapped in the "HtlcFailDustAction" category.
1757+
HtlcFailDanglingAction = 7
17411758
)
17421759

17431760
// String returns a human readable string describing a chain action.
@@ -1752,8 +1769,8 @@ func (c ChainAction) String() string {
17521769
case HtlcClaimAction:
17531770
return "HtlcClaimAction"
17541771

1755-
case HtlcFailNowAction:
1756-
return "HtlcFailNowAction"
1772+
case HtlcFailDustAction:
1773+
return "HtlcFailDustAction"
17571774

17581775
case HtlcOutgoingWatchAction:
17591776
return "HtlcOutgoingWatchAction"
@@ -1764,6 +1781,9 @@ func (c ChainAction) String() string {
17641781
case HtlcIncomingDustFinalAction:
17651782
return "HtlcIncomingDustFinalAction"
17661783

1784+
case HtlcFailDanglingAction:
1785+
return "HtlcFailDanglingAction"
1786+
17671787
default:
17681788
return "<unknown action>"
17691789
}
@@ -1944,8 +1964,8 @@ func (c *ChannelArbitrator) checkCommitChainActions(height uint32,
19441964
"failing dust htlc=%x", c.cfg.ChanPoint,
19451965
htlc.RHash[:])
19461966

1947-
actionMap[HtlcFailNowAction] = append(
1948-
actionMap[HtlcFailNowAction], htlc,
1967+
actionMap[HtlcFailDustAction] = append(
1968+
actionMap[HtlcFailDustAction], htlc,
19491969
)
19501970

19511971
// If we don't need to immediately act on this HTLC, then we'll
@@ -2138,12 +2158,30 @@ func (c *ChannelArbitrator) checkRemoteDanglingActions(
21382158
continue
21392159
}
21402160

2161+
// Dust htlcs can be canceled back even before the commitment
2162+
// transaction confirms. Dust htlcs are not enforceable onchain.
2163+
// If another version of the commit tx would confirm we either
2164+
// gain or lose those dust amounts but there is no other way
2165+
// than cancelling the incoming back because we will never learn
2166+
// the preimage.
2167+
if htlc.OutputIndex < 0 {
2168+
log.Infof("ChannelArbitrator(%v): fail dangling dust "+
2169+
"htlc=%x from local/remote commitments diff",
2170+
c.cfg.ChanPoint, htlc.RHash[:])
2171+
2172+
actionMap[HtlcFailDustAction] = append(
2173+
actionMap[HtlcFailDustAction], htlc,
2174+
)
2175+
2176+
continue
2177+
}
2178+
21412179
log.Infof("ChannelArbitrator(%v): fail dangling htlc=%x from "+
21422180
"local/remote commitments diff",
21432181
c.cfg.ChanPoint, htlc.RHash[:])
21442182

2145-
actionMap[HtlcFailNowAction] = append(
2146-
actionMap[HtlcFailNowAction], htlc,
2183+
actionMap[HtlcFailDanglingAction] = append(
2184+
actionMap[HtlcFailDanglingAction], htlc,
21472185
)
21482186
}
21492187

@@ -2232,8 +2270,21 @@ func (c *ChannelArbitrator) checkRemoteDiffActions(
22322270
continue
22332271
}
22342272

2235-
actionMap[HtlcFailNowAction] = append(
2236-
actionMap[HtlcFailNowAction], htlc,
2273+
// Dust HTLCs on the remote commitment can be failed back.
2274+
if htlc.OutputIndex < 0 {
2275+
log.Infof("ChannelArbitrator(%v): fail dangling dust "+
2276+
"htlc=%x from remote commitments diff",
2277+
c.cfg.ChanPoint, htlc.RHash[:])
2278+
2279+
actionMap[HtlcFailDustAction] = append(
2280+
actionMap[HtlcFailDustAction], htlc,
2281+
)
2282+
2283+
continue
2284+
}
2285+
2286+
actionMap[HtlcFailDanglingAction] = append(
2287+
actionMap[HtlcFailDanglingAction], htlc,
22372288
)
22382289

22392290
log.Infof("ChannelArbitrator(%v): fail dangling htlc=%x from "+

0 commit comments

Comments
 (0)