funding+htlcswitch: dynamically update short chan id of existing link

In this commit, we fix an existing bug that would result in some
payments getting “stuck”. This would happen if one side restarted
before the channel was fully locked in. In this case, since upon
re-connection, the link will get added to the switch with a *short
channel ID of zero*. If A then tries to make a multi-hop payment
through B, B will fail to forward the payment, as it’ll mistakenly
think that the payment originated from a local-subsystem as the channel
ID is zero. A short channel ID of zero is used to map local payments
back to their caller.

With fix this by allowing the funding manager to dynamically update the
short channel ID of a link after it discovers the short channel ID.

In this commit, we fix a second instance of reported “stuck” payments
by users.
This commit is contained in:
Olaoluwa Osuntokun committed 2018-02-03 18:14:15 -08:00
1 parent 71a837630a
commit 30dbbd69a0
7 files changed
+145 -14

No files matched your search

+64 -1
View File
@@ -941,6 +941,10 @@ func (s *Switch) htlcForwarder() {
links, err := s.getLinks(cmd.peer)
cmd.done <- links
cmd.err <- err
case *updateForwardingIndexCmd:
cmd.err <- s.updateShortChanID(
cmd.chanID, cmd.shortChanID,
)
}
case <-s.quit:
@@ -1006,6 +1010,8 @@ func (s *Switch) AddLink(link ChannelLink) error {
// addLink is used to add the newly created channel link and start use it to
// handle the channel updates.
func (s *Switch) addLink(link ChannelLink) error {
// TODO(roasbeef): reject if link already tehre?
// First we'll add the link to the linkIndex which lets us quickly look
// up a channel when we need to close or register it, and the
// forwarding index which'll be used when forwarding HTLC's in the
@@ -1097,7 +1103,8 @@ func (s *Switch) RemoveLink(chanID lnwire.ChannelID) error {
case s.linkControl <- command:
return <-command.err
case <-s.quit:
return errors.New("unable to remove link htlc switch was stopped")
return errors.New("unable to remove link htlc switch was " +
"stopped")
}
}
@@ -1123,6 +1130,62 @@ func (s *Switch) removeLink(chanID lnwire.ChannelID) error {
return nil
}
// updateForwardingIndexCmd is a command sent by outside sub-systems to update
// the forwarding index of the switch in the event that the short channel ID of
// a particular link changes.
type updateForwardingIndexCmd struct {
chanID lnwire.ChannelID
shortChanID lnwire.ShortChannelID
err chan error
}
// UpdateShortChanID updates the short chan ID for an existing channel. This is
// required in the case of a re-org and re-confirmation or a channel, or in the
// case that a link was added to the switch before its short chan ID was known.
func (s *Switch) UpdateShortChanID(chanID lnwire.ChannelID,
shortChanID lnwire.ShortChannelID) error {
command := &updateForwardingIndexCmd{
chanID: chanID,
shortChanID: shortChanID,
err: make(chan error, 1),
}
select {
case s.linkControl <- command:
return <-command.err
case <-s.quit:
return errors.New("unable to remove link htlc switch was " +
"stopped")
}
}
// updateShortChanID updates the short chan ID of an existing link.
func (s *Switch) updateShortChanID(chanID lnwire.ChannelID,
shortChanID lnwire.ShortChannelID) error {
// First, we'll extract the current link as is from the link link
// index. If the link isn't even in the index, then we'll return an
// error.
link, ok := s.linkIndex[chanID]
if !ok {
return fmt.Errorf("link %v not found", chanID)
}
log.Infof("Updating short_chan_id for ChannelLink(%v): old=%v, new=%v",
chanID, link.ShortChanID(), shortChanID)
// At this point the link is actually active, so we'll update the
// forwarding index with the next short channel ID.
s.forwardingIndex[shortChanID] = link
// Finally, we'll notify the link of its new short channel ID.
link.UpdateShortChanID(shortChanID)
return nil
}
// getLinksCmd is a get links command wrapper, it is used to propagate handler
// parameters and return handler error.
type getLinksCmd struct {