witness_beacon: do not look up invoice preimages

This commit isolates preimages of forwarded htlcs from invoice
preimages. The reason to do this is to prevent the incoming contest
resolver from settling exit hop htlcs for which the invoice isn't marked
as settled.
This commit is contained in:
Joost Jager 2019-04-16 12:32:51 +02:00
parent 99e42ddde6
commit 1a80a1e540
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
3 changed files with 48 additions and 28 deletions

@ -620,7 +620,10 @@ func (c *ChannelArbitrator) stateStep(triggerHeight uint32,
// chain, we'll check to see if we need to make any on-chain
// claims on behalf of the channel contract that we're
// arbitrating for.
chainActions := c.checkChainActions(triggerHeight, trigger)
chainActions, err := c.checkChainActions(triggerHeight, trigger)
if err != nil {
return StateError, closeTx, err
}
// If there are no actions to be made, then we'll remain in the
// default state. If this isn't a self initiated event (we're
@ -1082,7 +1085,7 @@ func (c *ChannelArbitrator) shouldGoOnChain(htlcExpiry, broadcastDelta,
// been sufficiently confirmed, the HTLC's should be canceled backwards. For
// redeemed HTLC's, we should send the pre-image back to the incoming link.
func (c *ChannelArbitrator) checkChainActions(height uint32,
trigger transitionTrigger) ChainActionMap {
trigger transitionTrigger) (ChainActionMap, error) {
// TODO(roasbeef): would need to lock channel? channel totem?
// * race condition if adding and we broadcast, etc
@ -1122,7 +1125,12 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
// know the pre-image and it's close to timing out. We need to
// ensure that we claim the funds that our rightfully ours
// on-chain.
if _, ok := c.cfg.PreimageDB.LookupPreimage(htlc.RHash); !ok {
preimageAvailable, err := c.isPreimageAvailable(htlc.RHash)
if err != nil {
return nil, err
}
if !preimageAvailable {
continue
}
@ -1151,7 +1159,7 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
if !haveChainActions && trigger == chainTrigger {
log.Tracef("ChannelArbitrator(%v): no actions to take at "+
"height=%v", c.cfg.ChanPoint, height)
return actionMap
return actionMap, nil
}
// Now that we know we'll need to go on-chain, we'll examine all of our
@ -1223,7 +1231,42 @@ func (c *ChannelArbitrator) checkChainActions(height uint32,
)
}
return actionMap
return actionMap, nil
}
// isPreimageAvailable returns whether the hash preimage is available in either
// the preimage cache or the invoice database.
func (c *ChannelArbitrator) isPreimageAvailable(hash lntypes.Hash) (bool,
error) {
// Start by checking the preimage cache for preimages of
// forwarded HTLCs.
_, preimageAvailable := c.cfg.PreimageDB.LookupPreimage(
hash,
)
if preimageAvailable {
return true, nil
}
// Then check if we have an invoice that can be settled by this HTLC.
//
// TODO(joostjager): Check that there are still more blocks remaining
// than the invoice cltv delta. We don't want to go to chain only to
// have the incoming contest resolver decide that we don't want to
// settle this invoice.
invoice, _, err := c.cfg.Registry.LookupInvoice(hash)
switch err {
case nil:
case channeldb.ErrInvoiceNotFound, channeldb.ErrNoInvoicesCreated:
return false, nil
default:
return false, err
}
preimageAvailable = invoice.Terms.PaymentPreimage !=
channeldb.UnknownPreimage
return preimageAvailable, nil
}
// prepContractResolutions is called either int he case that we decide we need

@ -374,7 +374,6 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
}
s.witnessBeacon = &preimageBeacon{
invoices: s.invoices,
wCache: chanDB.NewWitnessCache(),
subscribers: make(map[uint64]*preimageSubscriber),
}

@ -5,7 +5,6 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/contractcourt"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lntypes"
)
@ -23,8 +22,6 @@ type preimageSubscriber struct {
type preimageBeacon struct {
sync.RWMutex
invoices *invoices.InvoiceRegistry
wCache *channeldb.WitnessCache
clientCounter uint64
@ -71,25 +68,6 @@ func (p *preimageBeacon) LookupPreimage(
p.RLock()
defer p.RUnlock()
// First, we'll check the invoice registry to see if we already know of
// the preimage as it's on that we created ourselves.
invoice, _, err := p.invoices.LookupInvoice(payHash)
switch {
case err == channeldb.ErrInvoiceNotFound:
// If we get this error, then it simply means that this invoice
// wasn't found, so we don't treat it as a critical error.
case err != nil:
return lntypes.Preimage{}, false
}
// If we've found the invoice, then we can return the preimage
// directly.
if err != channeldb.ErrInvoiceNotFound &&
invoice.Terms.PaymentPreimage != channeldb.UnknownPreimage {
return invoice.Terms.PaymentPreimage, true
}
// Otherwise, we'll perform a final check using the witness cache.
preimage, err := p.wCache.LookupSha256Witness(payHash)
if err != nil {