diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index e2ee14b0..e0566623 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -1776,11 +1776,11 @@ func (s *Switch) AddLink(link ChannelLink) error { chanID := link.ChanID() - // If a link already exists, then remove the prior one so we can - // replace it with this fresh instance. + // First, ensure that this link is not already active in the switch. _, err := s.getLink(chanID) if err == nil { - s.removeLink(chanID) + return fmt.Errorf("unable to add ChannelLink(%v), already "+ + "active", chanID) } // Get and attach the mailbox for this link, which buffers packets in diff --git a/htlcswitch/switch_test.go b/htlcswitch/switch_test.go index 904113e4..5b37c448 100644 --- a/htlcswitch/switch_test.go +++ b/htlcswitch/switch_test.go @@ -25,6 +25,65 @@ func genPreimage() ([32]byte, error) { return preimage, nil } +// TestSwitchAddDuplicateLink tests that the switch will reject duplicate links +// for both pending and live links. It also tests that we can successfully +// add a link after having removed it. +func TestSwitchAddDuplicateLink(t *testing.T) { + t.Parallel() + + alicePeer, err := newMockServer(t, "alice", nil) + if err != nil { + t.Fatalf("unable to create alice server: %v", err) + } + + s, err := initSwitchWithDB(nil) + if err != nil { + t.Fatalf("unable to init switch: %v", err) + } + if err := s.Start(); err != nil { + t.Fatalf("unable to start switch: %v", err) + } + defer s.Stop() + + chanID1, _, aliceChanID, _ := genIDs() + + pendingChanID := lnwire.ShortChannelID{} + + aliceChannelLink := newMockChannelLink( + s, chanID1, pendingChanID, alicePeer, false, + ) + if err := s.AddLink(aliceChannelLink); err != nil { + t.Fatalf("unable to add alice link: %v", err) + } + + // Alice should have a pending link, adding again should fail. + if err := s.AddLink(aliceChannelLink); err == nil { + t.Fatalf("adding duplicate link should have failed") + } + + // Update the short chan id of the channel, so that the link goes live. + aliceChannelLink.setLiveShortChanID(aliceChanID) + err = s.UpdateShortChanID(chanID1) + if err != nil { + t.Fatalf("unable to update alice short_chan_id: %v", err) + } + + // Alice should have a live link, adding again should fail. + if err := s.AddLink(aliceChannelLink); err == nil { + t.Fatalf("adding duplicate link should have failed") + } + + // Remove the live link to ensure the indexes are cleared. + if err := s.RemoveLink(chanID1); err != nil { + t.Fatalf("unable to remove alice link: %v", err) + } + + // Alice has no links, adding should succeed. + if err := s.AddLink(aliceChannelLink); err != nil { + t.Fatalf("unable to add alice link: %v", err) + } +} + // TestSwitchSendPending checks the inability of htlc switch to forward adds // over pending links, and the UpdateShortChanID makes a pending link live. func TestSwitchSendPending(t *testing.T) { diff --git a/peer.go b/peer.go index a9911dda..6d1a7c3e 100644 --- a/peer.go +++ b/peer.go @@ -1526,8 +1526,8 @@ out: ) if err != nil { peerLog.Errorf("can't register new channel "+ - "link(%v) with NodeKey(%x): %v", chanPoint, - p.PubKey(), err) + "link(%v) with NodeKey(%x)", chanPoint, + p.PubKey()) } close(newChanReq.done)