accessman: skip restriction for existing peers

When a peer already has a connection with us, there's no need to check
for available slots as we will either close the old conn or refuse the
new conn.
This commit is contained in:
yyforyongyu
2025-05-31 03:22:09 +08:00
committed by Olaoluwa Osuntokun
parent 5dfc5f4b42
commit b527f19de7
2 changed files with 192 additions and 24 deletions

View File

@@ -1,6 +1,7 @@
package lnd
import (
"context"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
@@ -250,9 +251,8 @@ func TestAssignPeerPerms(t *testing.T) {
expectedErr: ErrGossiperBan,
},
// peer6 has no channel with us, and we expect it to have a
// restricted status. We also expect the error
// `ErrNoMoreRestrictedAccessSlots` to be returned given
// we only allow 1 restricted peer in this test.
// restricted status. Since this peer is seen, we don't expect
// the error `ErrNoMoreRestrictedAccessSlots` to be returned.
{
name: "peer with no channels and restricted",
peerPub: genPeerPub(),
@@ -264,7 +264,7 @@ func TestAssignPeerPerms(t *testing.T) {
numRestricted: 1,
expectedStatus: peerStatusRestricted,
expectedErr: ErrNoMoreRestrictedAccessSlots,
expectedErr: nil,
},
}
@@ -394,3 +394,135 @@ func TestAssignPeerPermsBypassRestriction(t *testing.T) {
})
}
}
// TestAssignPeerPermsBypassExisting asserts that when the peer is a
// pre-existing peer, it won't be restricted.
func TestAssignPeerPermsBypassExisting(t *testing.T) {
t.Parallel()
// genPeerPub is a helper closure that generates a random public key.
genPeerPub := func() *btcec.PublicKey {
peerPriv, err := btcec.NewPrivateKey()
require.NoError(t, err)
return peerPriv.PubKey()
}
// peer1 exists in `peerCounts` map.
peer1 := genPeerPub()
peer1Str := string(peer1.SerializeCompressed())
// peer2 exists in `peerScores` map.
peer2 := genPeerPub()
peer2Str := string(peer2.SerializeCompressed())
// peer3 is a new peer.
peer3 := genPeerPub()
// Create params to init the accessman.
initPerms := func() (map[string]channeldb.ChanCount, error) {
return map[string]channeldb.ChanCount{
peer1Str: {},
}, nil
}
disconnect := func(*btcec.PublicKey) (bool, error) {
return false, nil
}
cfg := &accessManConfig{
initAccessPerms: initPerms,
shouldDisconnect: disconnect,
maxRestrictedSlots: 0,
}
a, err := newAccessMan(cfg)
require.NoError(t, err)
// Add peer2 to the `peerScores`.
a.peerScores[peer2Str] = peerSlotStatus{
state: peerStatusTemporary,
}
// Assigning to peer1 should not return an error.
status, err := a.assignPeerPerms(peer1)
require.NoError(t, err)
require.Equal(t, peerStatusRestricted, status)
// Assigning to peer2 should not return an error.
status, err = a.assignPeerPerms(peer2)
require.NoError(t, err)
require.Equal(t, peerStatusTemporary, status)
// Assigning to peer3 should return an error.
status, err = a.assignPeerPerms(peer3)
require.ErrorIs(t, err, ErrNoMoreRestrictedAccessSlots)
require.Equal(t, peerStatusRestricted, status)
}
// TestHasPeer asserts `hasPeer` returns the correct results.
func TestHasPeer(t *testing.T) {
t.Parallel()
ctx := context.Background()
// Create a testing accessMan.
a := &accessMan{
peerCounts: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// peer1 exists with an open channel.
peer1 := "peer1"
a.peerCounts[peer1] = channeldb.ChanCount{
HasOpenOrClosedChan: true,
}
peer1Access := peerStatusProtected
// peer2 exists with a pending channel.
peer2 := "peer2"
a.peerCounts[peer2] = channeldb.ChanCount{
PendingOpenCount: 1,
}
peer2Access := peerStatusTemporary
// peer3 exists without any channels.
peer3 := "peer3"
a.peerCounts[peer3] = channeldb.ChanCount{}
peer3Access := peerStatusRestricted
// peer4 exists with a score.
peer4 := "peer4"
peer4Access := peerStatusTemporary
a.peerScores[peer4] = peerSlotStatus{state: peer4Access}
// peer5 doesn't exist.
peer5 := "peer5"
// We now assert `hasPeer` returns the correct results.
//
// peer1 should be found with peerStatusProtected.
access, found := a.hasPeer(ctx, peer1)
require.True(t, found)
require.Equal(t, peer1Access, access)
// peer2 should be found with peerStatusTemporary.
access, found = a.hasPeer(ctx, peer2)
require.True(t, found)
require.Equal(t, peer2Access, access)
// peer3 should be found with peerStatusRestricted.
access, found = a.hasPeer(ctx, peer3)
require.True(t, found)
require.Equal(t, peer3Access, access)
// peer4 should be found with peerStatusTemporary.
access, found = a.hasPeer(ctx, peer4)
require.True(t, found)
require.Equal(t, peer4Access, access)
// peer5 should NOT be found.
access, found = a.hasPeer(ctx, peer5)
require.False(t, found)
require.Equal(t, peerStatusRestricted, access)
}