diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index f2ab707c0..1429b139e 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -51,13 +51,17 @@ func newMockServer(t *testing.T, name string) *mockServer { copy(id[:], h[:]) return &mockServer{ - t: t, - id: id, - name: name, - messages: make(chan lnwire.Message, 3000), - quit: make(chan bool), - registry: newMockRegistry(), - htlcSwitch: New(Config{}), + t: t, + id: id, + name: name, + messages: make(chan lnwire.Message, 3000), + quit: make(chan bool), + registry: newMockRegistry(), + htlcSwitch: New(Config{ + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + return nil + }, + }), recordFuncs: make([]func(lnwire.Message), 0), } } diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index ffbdaf464..dacf73539 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -88,6 +88,10 @@ type Config struct { // or forced unilateral closure of the channel initiated by a local // subsystem. LocalChannelClose func(pubKey []byte, request *ChanClose) + + // UpdateTopology sends the onion error failure topology update to router + // subsystem. + UpdateTopology func(msg *lnwire.ChannelUpdate) error } // Switch is the central messaging bus for all incoming/outgoing HTLCs. @@ -313,6 +317,31 @@ func (s *Switch) handleLocalDispatch(payment *pendingPayment, packet *htlcPacket err) log.Error(userErr) } else { + // Process payment failure by updating the lightning network + // topology by using router subsystem handler. + var update *lnwire.ChannelUpdate + + switch failure := failure.(type) { + case *lnwire.FailTemporaryChannelFailure: + update = failure.Update + case *lnwire.FailAmountBelowMinimum: + update = &failure.Update + case *lnwire.FailFeeInsufficient: + update = &failure.Update + case *lnwire.FailIncorrectCltvExpiry: + update = &failure.Update + case *lnwire.FailExpiryTooSoon: + update = &failure.Update + case *lnwire.FailChannelDisabled: + update = &failure.Update + } + + if update != nil { + log.Info("Received payment failure(%v), applying lightning "+ + "network topology update", failure.Code()) + s.cfg.UpdateTopology(update) + } + userErr = errors.New(failure.Code()) } diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index cbcf1351a..2279d8baa 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -40,7 +40,11 @@ func TestSwitchForward(t *testing.T) { aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer) - s := New(Config{}) + s := New(Config{ + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + return nil + }, + }) s.Start() if err := s.AddLink(aliceChannelLink); err != nil { t.Fatalf("unable to add alice link: %v", err) @@ -118,7 +122,11 @@ func TestSwitchCancel(t *testing.T) { aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer) - s := New(Config{}) + s := New(Config{ + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + return nil + }, + }) s.Start() if err := s.AddLink(aliceChannelLink); err != nil { t.Fatalf("unable to add alice link: %v", err) @@ -194,7 +202,11 @@ func TestSwitchAddSamePayment(t *testing.T) { aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer) - s := New(Config{}) + s := New(Config{ + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + return nil + }, + }) s.Start() if err := s.AddLink(aliceChannelLink); err != nil { t.Fatalf("unable to add alice link: %v", err) @@ -290,7 +302,11 @@ func TestSwitchSendPayment(t *testing.T) { alicePeer := newMockServer(t, "alice") aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer) - s := New(Config{}) + s := New(Config{ + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + return nil + }, + }) s.Start() if err := s.AddLink(aliceChannelLink); err != nil { t.Fatalf("unable to add link: %v", err) diff --git a/server.go b/server.go index 81b5fa496..e8ab4ac82 100644 --- a/server.go +++ b/server.go @@ -176,6 +176,10 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, peer.localCloseChanReqs <- request }, + UpdateTopology: func(msg *lnwire.ChannelUpdate) error { + s.discoverSrv.ProcessRemoteAnnouncement(msg, nil) + return nil + }, }) // If external IP addresses have been specified, add those to the list