Skip to content

Commit 440ff5c

Browse files
authored
fix: exclude bootnode from protocol requests (#4909)
1 parent 23445a1 commit 440ff5c

File tree

5 files changed

+84
-11
lines changed

5 files changed

+84
-11
lines changed

pkg/storer/internal/reserve/reserve_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,9 @@ func TestEvictSOC(t *testing.T) {
648648
if err != nil {
649649
t.Fatal(err)
650650
}
651-
checkChunk(t, ts, chunks[9], false) // chunk should still persist, eg refCnt > 0
651+
if has, _ := ts.ChunkStore().Has(context.Background(), chunks[0].Address()); !has {
652+
t.Fatal("same address chunk should still persist, eg refCnt > 0")
653+
}
652654

653655
evicted, err := r.EvictBatchBin(context.Background(), batch.ID, 10, swarm.MaxBins)
654656
if err != nil {

pkg/topology/kademlia/internal/metrics/metrics.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ const (
3333
// operation whose execution modifies a specific metrics.
3434
type RecordOp func(*Counters)
3535

36+
// Bootnode will mark the peer metric as bootnode based on the bool arg.
37+
func IsBootnode(b bool) RecordOp {
38+
return func(cs *Counters) {
39+
cs.Lock()
40+
defer cs.Unlock()
41+
cs.isBootnode = b
42+
}
43+
}
44+
3645
// PeerLogIn will first update the current last seen to the give time t and as
3746
// the second it'll set the direction of the session connection to the given
3847
// value. The force flag will force the peer re-login if he's already logged in.
@@ -155,6 +164,7 @@ type Counters struct {
155164
// Bookkeeping.
156165
isLoggedIn bool
157166
peerAddress swarm.Address
167+
isBootnode bool
158168

159169
// Counters.
160170
lastSeenTimestamp int64
@@ -308,6 +318,13 @@ func (c *Collector) IsUnreachable(addr swarm.Address) bool {
308318
// ExcludeOp is a function type used to filter peers on certain fields.
309319
type ExcludeOp func(*Counters) bool
310320

321+
// IsBootnode is used to filter bootnode peers.
322+
func Bootnode() ExcludeOp {
323+
return func(cs *Counters) bool {
324+
return cs.isBootnode
325+
}
326+
}
327+
311328
// Reachable is used to filter reachable or unreachable peers based on r.
312329
func Reachability(filterReachable bool) ExcludeOp {
313330
return func(cs *Counters) bool {

pkg/topology/kademlia/internal/metrics/metrics_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,39 @@ func TestPeerMetricsCollector(t *testing.T) {
193193
t.Fatalf("unexpected snapshot difference:\n%s", diff)
194194
}
195195
}
196+
197+
func TestExclude(t *testing.T) {
198+
t.Parallel()
199+
200+
db, err := shed.NewDB("", nil)
201+
if err != nil {
202+
t.Fatal(err)
203+
}
204+
testutil.CleanupCloser(t, db)
205+
206+
mc, err := metrics.NewCollector(db)
207+
if err != nil {
208+
t.Fatal(err)
209+
}
210+
211+
var addr = swarm.RandAddress(t)
212+
213+
// record unhealthy, unreachable, bootnode
214+
mc.Record(addr, metrics.PeerHealth(false), metrics.IsBootnode(true), metrics.PeerReachability(p2p.ReachabilityStatusPrivate))
215+
216+
if have, want := mc.Exclude(addr), false; have != want {
217+
t.Fatal("should not exclude any")
218+
}
219+
220+
if have, want := mc.Exclude(addr, metrics.Bootnode()), true; have != want {
221+
t.Fatal("should exclude bootnodes")
222+
}
223+
224+
if have, want := mc.Exclude(addr, metrics.Reachability(false)), true; have != want {
225+
t.Fatal("should exclude unreachble")
226+
}
227+
228+
if have, want := mc.Exclude(addr, metrics.Health(false)), true; have != want {
229+
t.Fatal("should exclude unhealthy")
230+
}
231+
}

pkg/topology/kademlia/kademlia.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ func (k *Kad) connectBootNodes(ctx context.Context) {
843843
}
844844

845845
k.metrics.TotalOutboundConnections.Inc()
846-
k.collector.Record(bzzAddress.Overlay, im.PeerLogIn(time.Now(), im.PeerConnectionDirectionOutbound))
846+
k.collector.Record(bzzAddress.Overlay, im.PeerLogIn(time.Now(), im.PeerConnectionDirectionOutbound), im.IsBootnode(true))
847847
loggerV1.Debug("connected to bootnode", "bootnode_address", addr)
848848
connected++
849849

@@ -1061,8 +1061,7 @@ outer:
10611061
addrs = append(addrs, connectedPeer)
10621062

10631063
if !fullnode {
1064-
// we continue here so we dont gossip
1065-
// about lightnodes to others.
1064+
// dont gossip about lightnodes to others.
10661065
continue
10671066
}
10681067
// if kademlia is closing, dont enqueue anymore broadcast requests
@@ -1314,9 +1313,9 @@ func (k *Kad) ClosestPeer(addr swarm.Address, includeSelf bool, filter topology.
13141313

13151314
// EachConnectedPeer implements topology.PeerIterator interface.
13161315
func (k *Kad) EachConnectedPeer(f topology.EachPeerFunc, filter topology.Select) error {
1317-
filters := excludeOps(filter)
1316+
filters := excludeFromIterator(filter)
13181317
return k.connectedPeers.EachBin(func(addr swarm.Address, po uint8) (bool, bool, error) {
1319-
if len(filters) > 0 && k.opt.ExcludeFunc(filters...)(addr) {
1318+
if k.opt.ExcludeFunc(filters...)(addr) {
13201319
return false, false, nil
13211320
}
13221321
return f(addr, po)
@@ -1325,9 +1324,9 @@ func (k *Kad) EachConnectedPeer(f topology.EachPeerFunc, filter topology.Select)
13251324

13261325
// EachConnectedPeerRev implements topology.PeerIterator interface.
13271326
func (k *Kad) EachConnectedPeerRev(f topology.EachPeerFunc, filter topology.Select) error {
1328-
filters := excludeOps(filter)
1327+
filters := excludeFromIterator(filter)
13291328
return k.connectedPeers.EachBinRev(func(addr swarm.Address, po uint8) (bool, bool, error) {
1330-
if len(filters) > 0 && k.opt.ExcludeFunc(filters...)(addr) {
1329+
if k.opt.ExcludeFunc(filters...)(addr) {
13311330
return false, false, nil
13321331
}
13331332
return f(addr, po)
@@ -1391,9 +1390,11 @@ func (k *Kad) SubscribeTopologyChange() (c <-chan struct{}, unsubscribe func())
13911390
return channel, unsubscribe
13921391
}
13931392

1394-
func excludeOps(filter topology.Select) []im.ExcludeOp {
1393+
func excludeFromIterator(filter topology.Select) []im.ExcludeOp {
13951394

1396-
ops := make([]im.ExcludeOp, 0, 2)
1395+
ops := make([]im.ExcludeOp, 0, 3)
1396+
1397+
ops = append(ops, im.Bootnode())
13971398

13981399
if filter.Reachable {
13991400
ops = append(ops, im.Reachability(false))

pkg/topology/kademlia/kademlia_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1200,13 +1200,17 @@ func TestStart(t *testing.T) {
12001200
t.Parallel()
12011201

12021202
var bootnodes []ma.Multiaddr
1203+
var bootnodesOverlays []swarm.Address
12031204
for i := 0; i < 10; i++ {
1204-
multiaddr, err := ma.NewMultiaddr(underlayBase + swarm.RandAddress(t).String())
1205+
overlay := swarm.RandAddress(t)
1206+
1207+
multiaddr, err := ma.NewMultiaddr(underlayBase + overlay.String())
12051208
if err != nil {
12061209
t.Fatal(err)
12071210
}
12081211

12091212
bootnodes = append(bootnodes, multiaddr)
1213+
bootnodesOverlays = append(bootnodesOverlays, overlay)
12101214
}
12111215

12121216
t.Run("non-empty addressbook", func(t *testing.T) {
@@ -1253,6 +1257,19 @@ func TestStart(t *testing.T) {
12531257

12541258
waitCounter(t, &conns, 3)
12551259
waitCounter(t, &failedConns, 0)
1260+
1261+
err := kad.EachConnectedPeer(func(addr swarm.Address, bin uint8) (stop bool, jumpToNext bool, err error) {
1262+
for _, b := range bootnodesOverlays {
1263+
if b.Equal(addr) {
1264+
return false, false, errors.New("did not expect bootnode address from the iterator")
1265+
}
1266+
}
1267+
return false, false, nil
1268+
1269+
}, topology.Select{})
1270+
if err != nil {
1271+
t.Fatal(err)
1272+
}
12561273
})
12571274
}
12581275

0 commit comments

Comments
 (0)