cnct: always create incoming contest resolver

One of the first things the incoming contest resolver does is checking
if the preimage is available and if it is, convert itself into a success
resolver.

This behaviour makes it unnecessary to already determine earlier in the
process whether an incoming contest or a success resolver is needed.

By having all incoming htlcs go through the incoming contest resolver,
the number of execution paths is reduced and it becomes easier to
ascertain that the implemented logic is correct.

The only functional change in this commit is that a forwarded htlc for
which is the preimage is known, is no longer settled when the htlc is
already expired. Previously a success resolver would be instantiated
directly, skipping the expiry height check.

This created a risk that the success resolver would never finish,
because an expired htlc could already have been swept by the remote
party and there is no detection of this remote spend in the success
resolver currently.

With the new change, the general direction that an expired htlc
shouldn't be settled and instead given up on is implemented more
consistently.

This commit prepares for fixing edges cases related to hodl
invoice on-chain resolution.
This commit is contained in:
Joost Jager 2019-04-15 14:20:25 +02:00
parent 863bf2f91b
commit 6886a0117f
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
2 changed files with 5 additions and 18 deletions

View File

@ -1214,26 +1214,10 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
// either learn of it eventually from the outgoing HTLC, or the sender
// will timeout the HTLC.
for _, htlc := range c.activeHTLCs.incomingHTLCs {
// If we have the pre-image, then we should go on-chain to
// redeem the HTLC immediately.
if _, ok := c.cfg.PreimageDB.LookupPreimage(htlc.RHash); ok {
log.Tracef("ChannelArbitrator(%v): preimage for "+
"htlc=%x is known!", c.cfg.ChanPoint,
htlc.RHash[:])
actionMap[HtlcClaimAction] = append(
actionMap[HtlcClaimAction], htlc,
)
continue
}
log.Tracef("ChannelArbitrator(%v): watching chain to decide "+
"action for incoming htlc=%x", c.cfg.ChanPoint,
htlc.RHash[:])
// Otherwise, we don't yet have the pre-image, but should watch
// on-chain to see if either: the remote party times out the
// HTLC, or we learn of the pre-image.
actionMap[HtlcIncomingWatchAction] = append(
actionMap[HtlcIncomingWatchAction], htlc,
)

View File

@ -57,8 +57,11 @@ func (h *htlcIncomingContestResolver) Resolve() (ContractResolver, error) {
return nil, err
}
// If we're past the point of expiry of the HTLC, then at this point
// the sender can sweep it, so we'll end our lifetime.
// If we're past the point of expiry of the HTLC, then at this point the
// sender can sweep it, so we'll end our lifetime. Here we deliberately
// forego the chance that the sender doesn't sweep and we already have
// or will learn the preimage. Otherwise the resolver could potentially
// stay active indefinitely and the channel will never close properly.
if uint32(currentHeight) >= h.htlcExpiry {
// TODO(roasbeef): should also somehow check if outgoing is
// resolved or not