From 79b8d26b1ac285547cf840a5a9c0c6baeae1c69b Mon Sep 17 00:00:00 2001 From: Andrey Samokhvalov Date: Thu, 29 Jun 2017 17:03:42 +0300 Subject: [PATCH] htlcswitch+router+server: handle payment error topology updates In previous commits we have intoduced the onion errors. Some of this errors include lnwire.ChannelUpdate message. In order to change topology accordingly to the received error, from nodes where failure have occured, we have to propogate the update to the router subsystem. --- htlcswitch/mock.go | 18 +++++++++++------- htlcswitch/switch.go | 29 +++++++++++++++++++++++++++++ htlcswitch/switch_test.go | 24 ++++++++++++++++++++---- server.go | 4 ++++ 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index f2ab707c..1429b139 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 ffbdaf46..dacf7353 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 cbcf1351..2279d8ba 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 81b5fa49..e8ab4ac8 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