Skip to content

Commit d1f04df

Browse files
committed
misc(p2p/peerTracker): extend conditions for peers handling
1 parent 0c5d8c2 commit d1f04df

File tree

10 files changed

+205
-217
lines changed

10 files changed

+205
-217
lines changed

go.mod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,24 @@ require (
2424
github.com/benbjohnson/clock v1.3.5 // indirect
2525
github.com/beorn7/perks v1.0.1 // indirect
2626
github.com/cespare/xxhash/v2 v2.2.0 // indirect
27+
github.com/containerd/cgroups v1.1.0 // indirect
28+
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
2729
github.com/davecgh/go-spew v1.1.1 // indirect
2830
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
2931
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
32+
github.com/docker/go-units v0.5.0 // indirect
33+
github.com/elastic/gosigar v0.14.2 // indirect
3034
github.com/flynn/noise v1.0.0 // indirect
3135
github.com/francoispqt/gojay v1.2.13 // indirect
3236
github.com/go-logr/logr v1.4.1 // indirect
3337
github.com/go-logr/stdr v1.2.2 // indirect
3438
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
39+
github.com/godbus/dbus/v5 v5.1.0 // indirect
3540
github.com/golang/protobuf v1.5.3 // indirect
3641
github.com/google/gopacket v1.1.19 // indirect
3742
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
3843
github.com/google/uuid v1.5.0 // indirect
44+
github.com/gorilla/websocket v1.5.0 // indirect
3945
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
4046
github.com/huin/goupnp v1.3.0 // indirect
4147
github.com/ipfs/go-cid v0.4.1 // indirect
@@ -73,6 +79,9 @@ require (
7379
github.com/multiformats/go-multistream v0.5.0 // indirect
7480
github.com/multiformats/go-varint v0.0.7 // indirect
7581
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
82+
github.com/opencontainers/runtime-spec v1.1.0 // indirect
83+
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
84+
github.com/pkg/errors v0.9.1 // indirect
7685
github.com/pmezard/go-difflib v1.0.0 // indirect
7786
github.com/prometheus/client_golang v1.14.0 // indirect
7887
github.com/prometheus/client_model v0.4.0 // indirect
@@ -82,7 +91,10 @@ require (
8291
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
8392
github.com/quic-go/quic-go v0.39.4 // indirect
8493
github.com/quic-go/webtransport-go v0.6.0 // indirect
94+
github.com/raulk/go-watchdog v1.3.0 // indirect
8595
github.com/spaolacci/murmur3 v1.1.0 // indirect
96+
go.uber.org/dig v1.17.1 // indirect
97+
go.uber.org/fx v1.20.1 // indirect
8698
go.uber.org/mock v0.3.0 // indirect
8799
go.uber.org/multierr v1.11.0 // indirect
88100
go.uber.org/zap v1.26.0 // indirect

go.sum

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,17 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE
120120
github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
121121
github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
122122
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
123+
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
123124
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
124125
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
125126
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
126127
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
127128
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
128-
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI=
129129
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
130130
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
131131
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
132132
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
133+
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
133134
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
134135
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
135136
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -152,6 +153,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
152153
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
153154
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
154155
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
156+
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
155157
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
156158
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
157159
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
@@ -698,6 +700,7 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
698700
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
699701
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
700702
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
703+
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
701704
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
702705
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
703706
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -779,6 +782,7 @@ github.com/quic-go/webtransport-go v0.6.0/go.mod h1:9KjU4AEBqEQidGHNDkZrb8CAa1ab
779782
github.com/raulk/clock v1.1.0/go.mod h1:3MpVxdZ/ODBQDxbN+kzshf5OSZwPjtMDx6BBXBmOeY0=
780783
github.com/raulk/go-watchdog v1.2.0/go.mod h1:lzSbAl5sh4rtI8tYHU01BWIDzgzqaQLj6RcA1i4mlqI=
781784
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
785+
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
782786
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
783787
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
784788
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -896,8 +900,11 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
896900
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
897901
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
898902
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
903+
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
899904
go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc=
905+
go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
900906
go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk=
907+
go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg=
901908
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
902909
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
903910
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=

p2p/exchange.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ func NewExchange[H header.Header[H]](
8080
}
8181
}
8282

83+
id := protocolID(params.networkID)
8384
ex := &Exchange[H]{
8485
host: host,
85-
protocolID: protocolID(params.networkID),
86-
peerTracker: newPeerTracker(host, gater, params.pidstore, metrics),
86+
protocolID: id,
87+
peerTracker: newPeerTracker(host, gater, params.networkID, params.pidstore, metrics),
8788
Params: params,
8889
metrics: metrics,
8990
}
@@ -98,7 +99,6 @@ func (ex *Exchange[H]) Start(ctx context.Context) error {
9899
ex.ctx, ex.cancel = context.WithCancel(context.Background())
99100
log.Infow("client: starting client", "protocol ID", ex.protocolID)
100101

101-
go ex.peerTracker.gc()
102102
go ex.peerTracker.track()
103103

104104
// bootstrap the peerTracker with trusted peers as well as previously seen
@@ -172,7 +172,7 @@ func (ex *Exchange[H]) Head(ctx context.Context, opts ...header.HeadOption[H]) (
172172
trace.WithAttributes(attribute.String("peerID", from.String())),
173173
)
174174
defer newSpan.End()
175-
175+
176176
headers, err := ex.request(reqCtx, from, headerReq)
177177
if err != nil {
178178
newSpan.SetStatus(codes.Error, err.Error())

p2p/exchange_test.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import (
88

99
"github.com/ipfs/go-datastore"
1010
"github.com/ipfs/go-datastore/sync"
11+
"github.com/libp2p/go-libp2p"
1112
libhost "github.com/libp2p/go-libp2p/core/host"
1213
"github.com/libp2p/go-libp2p/core/network"
1314
"github.com/libp2p/go-libp2p/core/peer"
1415
"github.com/libp2p/go-libp2p/core/peerstore"
1516
blankhost "github.com/libp2p/go-libp2p/p2p/host/blank"
1617
"github.com/libp2p/go-libp2p/p2p/net/conngater"
18+
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
1719
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
1820
swarm "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
1921
"github.com/stretchr/testify/assert"
@@ -242,7 +244,7 @@ func TestExchange_RequestFullRangeHeaders(t *testing.T) {
242244
require.NoError(t, err)
243245
servers[index].Start(context.Background()) //nolint:errcheck
244246
exchange.peerTracker.peerLk.Lock()
245-
exchange.peerTracker.trackedPeers[hosts[index].ID()] = &peerStat{peerID: hosts[index].ID()}
247+
exchange.peerTracker.trackedPeers[hosts[index].ID()] = struct{}{}
246248
exchange.peerTracker.peerLk.Unlock()
247249
}
248250

@@ -262,30 +264,38 @@ func TestExchange_RequestFullRangeHeaders(t *testing.T) {
262264
// TestExchange_RequestHeadersFromAnotherPeer tests that the Exchange instance will request range
263265
// from another peer with lower score after receiving header.ErrNotFound
264266
func TestExchange_RequestHeadersFromAnotherPeer(t *testing.T) {
265-
hosts := createMocknet(t, 3)
267+
hosts := quicHosts(t, 3)
268+
266269
// create client + server(it does not have needed headers)
267270
exchg, store := createP2PExAndServer(t, hosts[0], hosts[1])
271+
272+
serverSideStore := headertest.NewStore[*headertest.DummyHeader](t, headertest.NewTestSuite(t), 10)
273+
tmServerSideStore := &timedOutStore{timeout: time.Millisecond * 200, Store: *serverSideStore}
274+
275+
hosts[0].ConnManager().TagPeer(hosts[1].ID(), string(protocolID(networkID)), 100)
276+
hosts[0].ConnManager().TagPeer(hosts[2].ID(), string(protocolID(networkID)), 90)
277+
268278
// create one more server(with more headers in the store)
269279
serverSideEx, err := NewExchangeServer[*headertest.DummyHeader](
270-
hosts[2], headertest.NewStore[*headertest.DummyHeader](t, headertest.NewTestSuite(t), 10),
280+
hosts[2], tmServerSideStore,
271281
WithNetworkID[ServerParameters](networkID),
272282
)
273283
require.NoError(t, err)
274284
require.NoError(t, serverSideEx.Start(context.Background()))
275285
t.Cleanup(func() {
276286
serverSideEx.Stop(context.Background()) //nolint:errcheck
277287
})
288+
278289
exchg.peerTracker.peerLk.Lock()
279-
exchg.peerTracker.trackedPeers[hosts[2].ID()] = &peerStat{peerID: hosts[2].ID(), peerScore: 20}
290+
exchg.peerTracker.trackedPeers[hosts[2].ID()] = struct{}{}
280291
exchg.peerTracker.peerLk.Unlock()
281-
282292
h, err := store.GetByHeight(context.Background(), 5)
283293
require.NoError(t, err)
284294

285295
_, err = exchg.GetRangeByHeight(context.Background(), h, 8)
286296
require.NoError(t, err)
287297
// ensure that peerScore for the second peer is changed
288-
newPeerScore := exchg.peerTracker.trackedPeers[hosts[2].ID()].score()
298+
newPeerScore := score(t, exchg.peerTracker.host, hosts[2].ID())
289299
require.NotEqual(t, 20, newPeerScore)
290300
}
291301

@@ -464,7 +474,9 @@ func TestExchange_HandleHeaderWithDifferentChainID(t *testing.T) {
464474
func TestExchange_RequestHeadersFromAnotherPeerWhenTimeout(t *testing.T) {
465475
// create blankhost because mocknet does not support deadlines
466476
swarm0 := swarm.GenSwarm(t)
467-
host0 := blankhost.NewBlankHost(swarm0)
477+
mngr, err := connmgr.NewConnManager(0, 50)
478+
require.NoError(t, err)
479+
host0 := blankhost.NewBlankHost(swarm0, blankhost.WithConnectionManager(mngr))
468480
swarm1 := swarm.GenSwarm(t)
469481
host1 := blankhost.NewBlankHost(swarm1)
470482
swarm2 := swarm.GenSwarm(t)
@@ -495,24 +507,25 @@ func TestExchange_RequestHeadersFromAnotherPeerWhenTimeout(t *testing.T) {
495507
t.Cleanup(func() {
496508
serverSideEx.Stop(context.Background()) //nolint:errcheck
497509
})
498-
prevScore := exchg.peerTracker.trackedPeers[host1.ID()].score()
510+
prevScore := score(t, exchg.host, host1.ID())
499511
exchg.peerTracker.peerLk.Lock()
500-
exchg.peerTracker.trackedPeers[host2.ID()] = &peerStat{peerID: host2.ID(), peerScore: 200}
512+
host0.ConnManager().TagPeer(host2.ID(), string(protocolID(networkID)), 100)
513+
exchg.peerTracker.trackedPeers[host2.ID()] = struct{}{}
501514
exchg.peerTracker.peerLk.Unlock()
502515

503516
gen, err := store.GetByHeight(context.Background(), 1)
504517
require.NoError(t, err)
505518

506519
_, err = exchg.GetRangeByHeight(context.Background(), gen, 3)
507520
require.NoError(t, err)
508-
newPeerScore := exchg.peerTracker.trackedPeers[host1.ID()].score()
521+
newPeerScore := score(t, exchg.host, host1.ID())
509522
assert.NotEqual(t, newPeerScore, prevScore)
510523
}
511524

512525
// TestExchange_RequestPartialRange enusres in case of receiving a partial response
513526
// from server, Exchange will re-request remaining headers from another peer
514527
func TestExchange_RequestPartialRange(t *testing.T) {
515-
hosts := createMocknet(t, 3)
528+
hosts := quicHosts(t, 3)
516529
exchg, store := createP2PExAndServer(t, hosts[0], hosts[1])
517530

518531
// create one more server(with more headers in the store)
@@ -523,13 +536,14 @@ func TestExchange_RequestPartialRange(t *testing.T) {
523536
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
524537
t.Cleanup(cancel)
525538

539+
hosts[0].ConnManager().TagPeer(hosts[1].ID(), string(protocolID(networkID)), 100)
540+
526541
require.NoError(t, err)
527542
require.NoError(t, serverSideEx.Start(ctx))
528543
exchg.peerTracker.peerLk.Lock()
529-
prevScoreBefore1 := exchg.peerTracker.trackedPeers[hosts[1].ID()].peerScore
530-
prevScoreBefore2 := 50
531-
// reducing peerScore of the second server, so our exchange will request host[1] first.
532-
exchg.peerTracker.trackedPeers[hosts[2].ID()] = &peerStat{peerID: hosts[2].ID(), peerScore: 50}
544+
prevScoreBefore1 := score(t, exchg.host, hosts[1].ID())
545+
prevScoreBefore2 := score(t, exchg.host, hosts[2].ID())
546+
exchg.peerTracker.trackedPeers[hosts[2].ID()] = struct{}{}
533547
exchg.peerTracker.peerLk.Unlock()
534548

535549
gen, err := store.GetByHeight(context.Background(), 1)
@@ -540,8 +554,8 @@ func TestExchange_RequestPartialRange(t *testing.T) {
540554
require.NoError(t, err)
541555

542556
exchg.peerTracker.peerLk.Lock()
543-
prevScoreAfter1 := exchg.peerTracker.trackedPeers[hosts[1].ID()].peerScore
544-
prevScoreAfter2 := exchg.peerTracker.trackedPeers[hosts[2].ID()].peerScore
557+
prevScoreAfter1 := score(t, exchg.host, hosts[1].ID())
558+
prevScoreAfter2 := score(t, exchg.host, hosts[2].ID())
545559
exchg.peerTracker.peerLk.Unlock()
546560

547561
assert.NotEqual(t, prevScoreBefore1, prevScoreAfter1)
@@ -561,7 +575,6 @@ func createP2PExAndServer(
561575
host, tpeer libhost.Host,
562576
) (*Exchange[*headertest.DummyHeader], *headertest.Store[*headertest.DummyHeader]) {
563577
store := headertest.NewStore[*headertest.DummyHeader](t, headertest.NewTestSuite(t), 5)
564-
565578
serverSideEx, err := NewExchangeServer[*headertest.DummyHeader](tpeer, store,
566579
WithNetworkID[ServerParameters](networkID),
567580
)
@@ -582,7 +595,7 @@ func createP2PExAndServer(
582595
time.Sleep(time.Millisecond * 100) // give peerTracker time to add a trusted peer
583596

584597
ex.peerTracker.peerLk.Lock()
585-
ex.peerTracker.trackedPeers[tpeer.ID()] = &peerStat{peerID: tpeer.ID(), peerScore: 100.0}
598+
ex.peerTracker.trackedPeers[tpeer.ID()] = struct{}{}
586599
ex.peerTracker.peerLk.Unlock()
587600

588601
t.Cleanup(func() {
@@ -595,12 +608,15 @@ func createP2PExAndServer(
595608

596609
func quicHosts(t *testing.T, n int) []libhost.Host {
597610
hosts := make([]libhost.Host, n)
611+
var err error
598612
for i := range hosts {
599-
swrm := swarm.GenSwarm(t, swarm.OptDisableTCP)
600-
hosts[i] = blankhost.NewBlankHost(swrm)
613+
require.NoError(t, err)
614+
hosts[i], err = libp2p.New()
601615
for _, host := range hosts[:i] {
602616
hosts[i].Peerstore().AddAddrs(host.ID(), host.Network().ListenAddresses(), peerstore.PermanentAddrTTL)
603617
host.Peerstore().AddAddrs(hosts[i].ID(), hosts[i].Network().ListenAddresses(), peerstore.PermanentAddrTTL)
618+
err = hosts[i].Connect(context.Background(), peer.AddrInfo{ID: host.ID(), Addrs: host.Addrs()})
619+
require.NoError(t, err)
604620
}
605621
}
606622

@@ -647,3 +663,15 @@ func (t *timedOutStore) Head(context.Context, ...header.HeadOption[*headertest.D
647663
time.Sleep(t.timeout)
648664
return nil, header.ErrNoHead
649665
}
666+
667+
func (t *timedOutStore) GetRange(ctx context.Context, from, to uint64) ([]*headertest.DummyHeader, error) {
668+
time.Sleep(t.timeout)
669+
return t.Store.GetRange(ctx, from, to)
670+
}
671+
672+
func score(t *testing.T, h libhost.Host, id peer.ID) int {
673+
t.Helper()
674+
tags := h.ConnManager().GetTagInfo(id)
675+
tag, _ := tags.Tags[string(protocolID(networkID))]
676+
return tag
677+
}

p2p/peer_stats.go

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ type peerStat struct {
1414
sync.RWMutex
1515
peerID peer.ID
1616
// score is the average speed per single request
17-
peerScore float32
18-
// pruneDeadline specifies when disconnected peer will be removed if
19-
// it does not return online.
20-
pruneDeadline time.Time
17+
peerScore int
2118
}
2219

2320
// updateStats recalculates peer.score by averaging the last score
@@ -26,33 +23,28 @@ type peerStat struct {
2623
// by dividing the amount by time, so the result score will represent how many bytes
2724
// were retrieved in 1 millisecond. This value will then be averaged relative to the
2825
// previous peerScore.
29-
func (p *peerStat) updateStats(amount uint64, duration time.Duration) {
30-
p.Lock()
31-
defer p.Unlock()
26+
func (p *peerStat) updateStats(amount uint64, duration time.Duration) int {
27+
if amount == 0 && duration == 0 {
28+
// decrease peerScore by 20% of the peer that failed the request by any reason.
29+
// NOTE: peerScore will not be decreased if the score is less than 100.
30+
p.peerScore -= p.peerScore / 100 * 20
31+
return p.peerScore
32+
}
33+
3234
averageSpeed := float32(amount)
3335
if duration != 0 {
3436
averageSpeed /= float32(duration.Milliseconds())
3537
}
3638
if p.peerScore == 0.0 {
37-
p.peerScore = averageSpeed
38-
return
39+
p.peerScore = int(averageSpeed * 100)
40+
return p.peerScore
3941
}
40-
p.peerScore = (p.peerScore + averageSpeed) / 2
41-
}
42-
43-
// decreaseScore decreases peerScore by 20% of the peer that failed the request by any reason.
44-
// NOTE: decreasing peerScore in one session will not affect its position in queue in another
45-
// session(as we can have multiple sessions running concurrently).
46-
// TODO(vgonkivs): to figure out the better scoring increments/decrements
47-
func (p *peerStat) decreaseScore() {
48-
p.Lock()
49-
defer p.Unlock()
50-
51-
p.peerScore -= p.peerScore / 100 * 20
42+
p.peerScore = (p.peerScore + int(averageSpeed*100)) / 2
43+
return p.peerScore
5244
}
5345

5446
// score reads a peer's latest score from the queue
55-
func (p *peerStat) score() float32 {
47+
func (p *peerStat) score() int {
5648
p.RLock()
5749
defer p.RUnlock()
5850
return p.peerScore
@@ -123,10 +115,6 @@ func newPeerQueue(ctx context.Context, stats []*peerStat) *peerQueue {
123115
// in case if there are no peer available in current session, it blocks until
124116
// the peer will be pushed in.
125117
func (p *peerQueue) waitPop(ctx context.Context) *peerStat {
126-
// TODO(vgonkivs): implement fallback solution for cases when peer queue is empty.
127-
// As we discussed with @Wondertan there could be 2 possible solutions:
128-
// * use libp2p.Discovery to find new peers outside peerTracker to request headers;
129-
// * implement IWANT/IHAVE messaging system and start requesting ranges from the Peerstore;
130118
select {
131119
case <-ctx.Done():
132120
return &peerStat{}

0 commit comments

Comments
 (0)