Skip to content

Commit 250a61a

Browse files
committed
lnd: remove peer from peerChanInfo when necessary
We now remove the peer from `peerChanInfo` if this peer doesn't have channels with us. Also patched a unit test for `removePeerAccess`.
1 parent 32d8e21 commit 250a61a

File tree

3 files changed

+140
-11
lines changed

3 files changed

+140
-11
lines changed

accessman.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -611,18 +611,14 @@ func (a *accessMan) addPeerAccess(remotePub *btcec.PublicKey,
611611

612612
// removePeerAccess removes the peer's access from the maps. This should be
613613
// called when the peer has been disconnected.
614-
func (a *accessMan) removePeerAccess(remotePub *btcec.PublicKey) {
615-
ctx := btclog.WithCtx(
616-
context.TODO(), lnutils.LogPubKey("peer", remotePub),
617-
)
618-
acsmLog.DebugS(ctx, "Removing peer access")
614+
func (a *accessMan) removePeerAccess(peerPubKey string) {
615+
ctx := btclog.WithCtx(context.TODO(), "peer", peerPubKey)
616+
acsmLog.DebugS(ctx, "Removing access:")
619617

620618
a.banScoreMtx.Lock()
621619
defer a.banScoreMtx.Unlock()
622620

623-
peerMapKey := string(remotePub.SerializeCompressed())
624-
625-
status, found := a.peerScores[peerMapKey]
621+
status, found := a.peerScores[peerPubKey]
626622
if !found {
627623
acsmLog.InfoS(ctx, "Peer score not found during removal")
628624
return
@@ -639,7 +635,31 @@ func (a *accessMan) removePeerAccess(remotePub *btcec.PublicKey) {
639635
"new_restricted", a.numRestricted)
640636
}
641637

642-
acsmLog.TraceS(ctx, "Deleting peer from peerScores")
638+
acsmLog.TraceS(ctx, "Deleting from peerScores:")
639+
640+
delete(a.peerScores, peerPubKey)
641+
642+
// We now check whether this peer has channels with us or not.
643+
info, found := a.peerChanInfo[peerPubKey]
644+
if !found {
645+
acsmLog.DebugS(ctx, "Chan info not found during removal:")
646+
return
647+
}
648+
649+
// Exit early if the peer has channel(s) with us.
650+
if info.HasOpenOrClosedChan {
651+
acsmLog.DebugS(ctx, "Skipped removing peer with channels:")
652+
return
653+
}
654+
655+
// Skip removing the peer if it has pending open/close with us.
656+
if info.PendingOpenCount != 0 {
657+
acsmLog.DebugS(ctx, "Skipped removing peer with pending "+
658+
"channels:")
659+
return
660+
}
643661

644-
delete(a.peerScores, peerMapKey)
662+
// Given this peer has no channels with us, we can now remove it.
663+
delete(a.peerChanInfo, peerPubKey)
664+
acsmLog.TraceS(ctx, "Removed peer from peerChanInfo:")
645665
}

accessman_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,111 @@ func TestAddPeerAccessOutbound(t *testing.T) {
703703
expecedScore = peerSlotStatus{state: peerStatusTemporary}
704704
require.Equal(t, expecedScore, score)
705705
}
706+
707+
// TestRemovePeerAccess asserts `removePeerAccess` correctly update the
708+
// accessman's internal state based on the peer's status.
709+
func TestRemovePeerAccess(t *testing.T) {
710+
t.Parallel()
711+
712+
// Create a testing accessMan.
713+
a := &accessMan{
714+
peerChanInfo: make(map[string]channeldb.ChanCount),
715+
peerScores: make(map[string]peerSlotStatus),
716+
}
717+
718+
// numRestrictedExpected specifies the final value to expect once the
719+
// test finishes.
720+
var numRestrictedExpected int
721+
722+
// peer1 exists with an open channel, which should not be removed. Since
723+
// it has protected status, the numRestricted should stay unchanged.
724+
peer1 := "peer1"
725+
a.peerChanInfo[peer1] = channeldb.ChanCount{
726+
HasOpenOrClosedChan: true,
727+
}
728+
peer1Access := peerStatusProtected
729+
a.peerScores[peer1] = peerSlotStatus{state: peer1Access}
730+
731+
// peer2 exists with a pending channel, which should not be removed.
732+
// Since it has temporary status, the numRestricted should stay
733+
// unchanged.
734+
peer2 := "peer2"
735+
a.peerChanInfo[peer2] = channeldb.ChanCount{
736+
PendingOpenCount: 1,
737+
}
738+
peer2Access := peerStatusTemporary
739+
a.peerScores[peer2] = peerSlotStatus{state: peer2Access}
740+
741+
// peer3 exists without any channels, which will be removed. Since it
742+
// has restricted status, the numRestricted should be decremented.
743+
peer3 := "peer3"
744+
a.peerChanInfo[peer3] = channeldb.ChanCount{}
745+
peer3Access := peerStatusRestricted
746+
a.peerScores[peer3] = peerSlotStatus{state: peer3Access}
747+
numRestrictedExpected--
748+
749+
// peer4 exists with a score and a temporary status, which will be
750+
// removed.
751+
peer4 := "peer4"
752+
peer4Access := peerStatusTemporary
753+
a.peerScores[peer4] = peerSlotStatus{state: peer4Access}
754+
755+
// peer5 doesn't exist, removing it will be a NOOP.
756+
peer5 := "peer5"
757+
758+
// We now assert `removePeerAccess` behaves as expected.
759+
//
760+
// Remove peer1 should change nothing.
761+
a.removePeerAccess(peer1)
762+
763+
// peer1 should be removed from peerScores but not peerChanInfo.
764+
_, found := a.peerScores[peer1]
765+
require.False(t, found)
766+
_, found = a.peerChanInfo[peer1]
767+
require.True(t, found)
768+
769+
// Remove peer2 should change nothing.
770+
a.removePeerAccess(peer2)
771+
772+
// peer2 should be removed from peerScores but not peerChanInfo.
773+
_, found = a.peerScores[peer2]
774+
require.False(t, found)
775+
_, found = a.peerChanInfo[peer2]
776+
require.True(t, found)
777+
778+
// Remove peer3 should remove it from the maps.
779+
a.removePeerAccess(peer3)
780+
781+
// peer3 should be removed from peerScores and peerChanInfo.
782+
_, found = a.peerScores[peer3]
783+
require.False(t, found)
784+
_, found = a.peerChanInfo[peer3]
785+
require.False(t, found)
786+
787+
// Remove peer4 should remove it from the maps.
788+
a.removePeerAccess(peer4)
789+
790+
// peer4 should be removed from peerScores and NOT be found in
791+
// peerChanInfo.
792+
_, found = a.peerScores[peer4]
793+
require.False(t, found)
794+
_, found = a.peerChanInfo[peer4]
795+
require.False(t, found)
796+
797+
// Remove peer5 should be NOOP.
798+
a.removePeerAccess(peer5)
799+
800+
// peer5 should NOT be found.
801+
_, found = a.peerScores[peer5]
802+
require.False(t, found)
803+
_, found = a.peerChanInfo[peer5]
804+
require.False(t, found)
805+
806+
// Finally, assert the numRestricted is decremented as expected. Given
807+
// we only have peer3 which has restricted access, it should decrement
808+
// once.
809+
//
810+
// NOTE: The value is actually negative here, which is allowed in
811+
// accessman.
812+
require.EqualValues(t, numRestrictedExpected, a.numRestricted)
813+
}

server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4964,7 +4964,8 @@ func (s *server) removePeer(p *peer.Brontide) {
49644964
}
49654965

49664966
// Remove the peer's access permission from the access manager.
4967-
s.peerAccessMan.removePeerAccess(p.IdentityKey())
4967+
peerPubStr := string(p.IdentityKey().SerializeCompressed())
4968+
s.peerAccessMan.removePeerAccess(peerPubStr)
49684969

49694970
// Copy the peer's error buffer across to the server if it has any items
49704971
// in it so that we can restore peer errors across connections.

0 commit comments

Comments
 (0)