Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
6450bcc4
Unverified
Commit
6450bcc4
authored
Mar 22, 2023
by
mergify[bot]
Committed by
GitHub
Mar 22, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5204 from ethereum-optimism/refcell/fix/pscores
fix(op-node): Peer Scoring Metrics
parents
8dd0248b
787db60c
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
277 additions
and
65 deletions
+277
-65
p2p_flags.go
op-node/flags/p2p_flags.go
+13
-0
metrics.go
op-node/metrics/metrics.go
+23
-17
band_scorer_test.go
op-node/p2p/band_scorer_test.go
+83
-0
load_config.go
op-node/p2p/cli/load_config.go
+15
-0
config.go
op-node/p2p/config.go
+7
-0
gossip.go
op-node/p2p/gossip.go
+3
-1
ConnectionGater.go
op-node/p2p/mocks/ConnectionGater.go
+5
-2
GossipMetricer.go
op-node/p2p/mocks/GossipMetricer.go
+5
-9
PeerGater.go
op-node/p2p/mocks/PeerGater.go
+1
-1
Peerstore.go
op-node/p2p/mocks/Peerstore.go
+1
-1
peer_scorer.go
op-node/p2p/peer_scorer.go
+81
-13
peer_scorer_test.go
op-node/p2p/peer_scorer_test.go
+26
-17
peer_scores.go
op-node/p2p/peer_scores.go
+1
-1
peer_scores_test.go
op-node/p2p/peer_scores_test.go
+7
-3
prepared.go
op-node/p2p/prepared.go
+4
-0
docker-compose.yml
ops-bedrock/docker-compose.yml
+2
-0
No files found.
op-node/flags/p2p_flags.go
View file @
6450bcc4
...
...
@@ -34,6 +34,15 @@ var (
Value
:
"none"
,
EnvVar
:
p2pEnv
(
"PEER_SCORING"
),
}
PeerScoreBands
=
cli
.
StringFlag
{
Name
:
"p2p.score.bands"
,
Usage
:
"Sets the peer score bands used primarily for peer score metrics. "
+
"Should be provided in following format: <threshold>:<label>;<threshold>:<label>;..."
+
"For example: -40:graylist;-20:restricted;0:nopx;20:friend;"
,
Required
:
false
,
Value
:
"-40:graylist;-20:restricted;0:nopx;20:friend;"
,
EnvVar
:
p2pEnv
(
"SCORE_BANDS"
),
}
// Banning Flag - whether or not we want to act on the scoring
Banning
=
cli
.
BoolFlag
{
...
...
@@ -276,6 +285,10 @@ var p2pFlags = []cli.Flag{
NoDiscovery
,
P2PPrivPath
,
P2PPrivRaw
,
PeerScoring
,
PeerScoreBands
,
Banning
,
TopicScoring
,
ListenIP
,
ListenTCPPort
,
ListenUDPPort
,
...
...
op-node/metrics/metrics.go
View file @
6450bcc4
...
...
@@ -15,7 +15,6 @@ import (
pb
"github.com/libp2p/go-libp2p-pubsub/pb"
libp2pmetrics
"github.com/libp2p/go-libp2p/core/metrics"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
...
...
@@ -66,7 +65,7 @@ type Metricer interface {
RecordSequencerSealingTime
(
duration
time
.
Duration
)
Document
()
[]
metrics
.
DocumentedMetric
// P2P Metrics
RecordPeerScoring
(
peerID
peer
.
ID
,
score
float64
)
SetPeerScores
(
scores
map
[
string
]
float64
)
}
// Metrics tracks all the metrics for the op-node.
...
...
@@ -287,21 +286,24 @@ func NewMetrics(procName string) *Metrics {
Name
:
"peer_count"
,
Help
:
"Count of currently connected p2p peers"
,
}),
StreamCount
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
ns
,
Subsystem
:
"p2p"
,
Name
:
"stream_count"
,
Help
:
"Count of currently connected p2p streams"
,
}),
// Notice: We cannot use peer ids as [Labels] in the GaugeVec
// since peer ids would open a service attack vector.
// Each peer id would be a separate metric, flooding prometheus.
//
// [Labels]: https://prometheus.io/docs/practices/naming/#labels
PeerScores
:
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
ns
,
Subsystem
:
"p2p"
,
Name
:
"peer_scores"
,
Help
:
"
Peer scoring
"
,
Help
:
"
Count of peer scores grouped by score
"
,
},
[]
string
{
// No label names here since peer ids would open a service attack vector.
// Each peer id would be a separate metric, flooding prometheus.
// See: https://prometheus.io/docs/practices/naming/#labels
"band"
,
}),
StreamCount
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
ns
,
Subsystem
:
"p2p"
,
Name
:
"stream_count"
,
Help
:
"Count of currently connected p2p streams"
,
}),
GossipEventsTotal
:
factory
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
ns
,
...
...
@@ -350,6 +352,14 @@ func NewMetrics(procName string) *Metrics {
}
}
// SetPeerScores updates the peer score [prometheus.GaugeVec].
// This takes a map of labels to scores.
func
(
m
*
Metrics
)
SetPeerScores
(
scores
map
[
string
]
float64
)
{
for
label
,
score
:=
range
scores
{
m
.
PeerScores
.
WithLabelValues
(
label
)
.
Set
(
score
)
}
}
// RecordInfo sets a pseudo-metric that contains versioning and
// config info for the opnode.
func
(
m
*
Metrics
)
RecordInfo
(
version
string
)
{
...
...
@@ -491,10 +501,6 @@ func (m *Metrics) RecordGossipEvent(evType int32) {
m
.
GossipEventsTotal
.
WithLabelValues
(
pb
.
TraceEvent_Type_name
[
evType
])
.
Inc
()
}
func
(
m
*
Metrics
)
RecordPeerScoring
(
peerID
peer
.
ID
,
score
float64
)
{
m
.
PeerScores
.
WithLabelValues
(
peerID
.
String
())
.
Set
(
score
)
}
func
(
m
*
Metrics
)
IncPeerCount
()
{
m
.
PeerCount
.
Inc
()
}
...
...
@@ -627,7 +633,7 @@ func (n *noopMetricer) RecordSequencerReset() {
func
(
n
*
noopMetricer
)
RecordGossipEvent
(
evType
int32
)
{
}
func
(
n
*
noopMetricer
)
RecordPeerScoring
(
peerID
peer
.
ID
,
score
float64
)
{
func
(
n
*
noopMetricer
)
SetPeerScores
(
scores
map
[
string
]
float64
)
{
}
func
(
n
*
noopMetricer
)
IncPeerCount
()
{
...
...
op-node/p2p/band_scorer_test.go
0 → 100644
View file @
6450bcc4
package
p2p
import
(
"testing"
"github.com/stretchr/testify/require"
)
// TestBandScorer_ParseDefault tests the [BandScorer.Parse] function
// on the default band scores cli flag value.
func
TestBandScorer_ParseDefault
(
t
*
testing
.
T
)
{
// Create a new band scorer.
bandScorer
,
err
:=
NewBandScorer
(
"-40:graylist;-20:restricted;0:nopx;20:friend;"
)
require
.
NoError
(
t
,
err
)
// Validate the [BandScorer] internals.
require
.
ElementsMatch
(
t
,
bandScorer
.
bands
,
[]
scorePair
{
{
band
:
"graylist"
,
threshold
:
-
40
},
{
band
:
"restricted"
,
threshold
:
-
20
},
{
band
:
"nopx"
,
threshold
:
0
},
{
band
:
"friend"
,
threshold
:
20
},
})
}
// TestBandScorer_BucketCorrectly tests the [BandScorer.Bucket] function
// on a variety of scores.
func
TestBandScorer_BucketCorrectly
(
t
*
testing
.
T
)
{
// Create a new band scorer.
bandScorer
,
err
:=
NewBandScorer
(
"-40:graylist;-20:restricted;0:nopx;20:friend;"
)
require
.
NoError
(
t
,
err
)
// Validate the [BandScorer] internals.
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
100
),
"graylist"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
40
),
"graylist"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
39
),
"restricted"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
20
),
"restricted"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
19
),
"nopx"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
0
),
"nopx"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
1
),
"friend"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
20
),
"friend"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
21
),
"friend"
)
}
// TestBandScorer_BucketInverted tests the [BandScorer.Bucket] function
// on a variety of scores, in descending order.
func
TestBandScorer_BucketInverted
(
t
*
testing
.
T
)
{
// Create a new band scorer.
bandScorer
,
err
:=
NewBandScorer
(
"20:friend;0:nopx;-20:restricted;-40:graylist;"
)
require
.
NoError
(
t
,
err
)
// Validate the [BandScorer] internals.
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
100
),
"graylist"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
40
),
"graylist"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
39
),
"restricted"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
20
),
"restricted"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
-
19
),
"nopx"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
0
),
"nopx"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
1
),
"friend"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
20
),
"friend"
)
require
.
Equal
(
t
,
bandScorer
.
Bucket
(
21
),
"friend"
)
}
// TestBandScorer_ParseEmpty tests the [BandScorer.Parse] function
// on an empty string.
func
TestBandScorer_ParseEmpty
(
t
*
testing
.
T
)
{
// Create a band scorer on an empty string.
bandScorer
,
err
:=
NewBandScorer
(
""
)
require
.
NoError
(
t
,
err
)
// Validate the [BandScorer] internals.
require
.
Len
(
t
,
bandScorer
.
bands
,
0
)
}
// TestBandScorer_ParseWhitespace tests the [BandScorer.Parse] function
// on a variety of whitespaced strings.
func
TestBandScorer_ParseWhitespace
(
t
*
testing
.
T
)
{
// Create a band scorer on an empty string.
bandScorer
,
err
:=
NewBandScorer
(
" ; ; ; "
)
require
.
NoError
(
t
,
err
)
// Validate the [BandScorer] internals.
require
.
Len
(
t
,
bandScorer
.
bands
,
0
)
}
op-node/p2p/cli/load_config.go
View file @
6450bcc4
...
...
@@ -58,6 +58,10 @@ func NewConfig(ctx *cli.Context, blockTime uint64) (*p2p.Config, error) {
return
nil
,
fmt
.
Errorf
(
"failed to load p2p peer scoring options: %w"
,
err
)
}
if
err
:=
loadPeerScoreBands
(
conf
,
ctx
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load p2p peer score bands: %w"
,
err
)
}
if
err
:=
loadBanningOption
(
conf
,
ctx
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load banning option: %w"
,
err
)
}
...
...
@@ -121,6 +125,17 @@ func loadPeerScoringParams(conf *p2p.Config, ctx *cli.Context, blockTime uint64)
return
nil
}
// loadPeerScoreBands loads [p2p.BandScorer] from the CLI context.
func
loadPeerScoreBands
(
conf
*
p2p
.
Config
,
ctx
*
cli
.
Context
)
error
{
scoreBands
:=
ctx
.
GlobalString
(
flags
.
PeerScoreBands
.
Name
)
bandScorer
,
err
:=
p2p
.
NewBandScorer
(
scoreBands
)
if
err
!=
nil
{
return
err
}
conf
.
BandScoreThresholds
=
*
bandScorer
return
nil
}
// loadBanningOption loads whether or not to ban peers from the CLI context.
func
loadBanningOption
(
conf
*
p2p
.
Config
,
ctx
*
cli
.
Context
)
error
{
ban
:=
ctx
.
GlobalBool
(
flags
.
Banning
.
Name
)
...
...
op-node/p2p/config.go
View file @
6450bcc4
...
...
@@ -54,6 +54,9 @@ type Config struct {
PeerScoring
pubsub
.
PeerScoreParams
TopicScoring
pubsub
.
TopicScoreParams
// Peer Score Band Thresholds
BandScoreThresholds
BandScoreThresholds
// Whether to ban peers based on their [PeerScoring] score.
BanningEnabled
bool
...
...
@@ -151,6 +154,10 @@ func (conf *Config) PeerScoringParams() *pubsub.PeerScoreParams {
return
&
conf
.
PeerScoring
}
func
(
conf
*
Config
)
PeerBandScorer
()
*
BandScoreThresholds
{
return
&
conf
.
BandScoreThresholds
}
func
(
conf
*
Config
)
BanPeers
()
bool
{
return
conf
.
BanningEnabled
}
...
...
op-node/p2p/gossip.go
View file @
6450bcc4
...
...
@@ -55,6 +55,7 @@ type GossipSetupConfigurables interface {
TopicScoringParams
()
*
pubsub
.
TopicScoreParams
BanPeers
()
bool
ConfigureGossip
(
params
*
pubsub
.
GossipSubParams
)
[]
pubsub
.
Option
PeerBandScorer
()
*
BandScoreThresholds
}
type
GossipRuntimeConfig
interface
{
...
...
@@ -64,7 +65,8 @@ type GossipRuntimeConfig interface {
//go:generate mockery --name GossipMetricer
type
GossipMetricer
interface
{
RecordGossipEvent
(
evType
int32
)
RecordPeerScoring
(
peerID
peer
.
ID
,
score
float64
)
// Peer Scoring Metric Funcs
SetPeerScores
(
map
[
string
]
float64
)
}
func
blocksTopicV1
(
cfg
*
rollup
.
Config
)
string
{
...
...
op-node/p2p/mocks/ConnectionGater.go
View file @
6450bcc4
// Code generated by mockery v2.
14.0
. DO NOT EDIT.
// Code generated by mockery v2.
22.1
. DO NOT EDIT.
package
mocks
...
...
@@ -123,13 +123,16 @@ func (_m *ConnectionGater) InterceptUpgraded(_a0 network.Conn) (bool, control.Di
ret
:=
_m
.
Called
(
_a0
)
var
r0
bool
var
r1
control
.
DisconnectReason
if
rf
,
ok
:=
ret
.
Get
(
0
)
.
(
func
(
network
.
Conn
)
(
bool
,
control
.
DisconnectReason
));
ok
{
return
rf
(
_a0
)
}
if
rf
,
ok
:=
ret
.
Get
(
0
)
.
(
func
(
network
.
Conn
)
bool
);
ok
{
r0
=
rf
(
_a0
)
}
else
{
r0
=
ret
.
Get
(
0
)
.
(
bool
)
}
var
r1
control
.
DisconnectReason
if
rf
,
ok
:=
ret
.
Get
(
1
)
.
(
func
(
network
.
Conn
)
control
.
DisconnectReason
);
ok
{
r1
=
rf
(
_a0
)
}
else
{
...
...
op-node/p2p/mocks/GossipMetricer.go
View file @
6450bcc4
// Code generated by mockery v2.
14.0
. DO NOT EDIT.
// Code generated by mockery v2.
22.1
. DO NOT EDIT.
package
mocks
import
(
mock
"github.com/stretchr/testify/mock"
peer
"github.com/libp2p/go-libp2p/core/peer"
)
import
mock
"github.com/stretchr/testify/mock"
// GossipMetricer is an autogenerated mock type for the GossipMetricer type
type
GossipMetricer
struct
{
...
...
@@ -18,9 +14,9 @@ func (_m *GossipMetricer) RecordGossipEvent(evType int32) {
_m
.
Called
(
evType
)
}
//
RecordPeerScoring provides a mock function with given fields: peerID, score
func
(
_m
*
GossipMetricer
)
RecordPeerScoring
(
peerID
peer
.
ID
,
score
float64
)
{
_m
.
Called
(
peerID
,
score
)
//
SetPeerScores provides a mock function with given fields: _a0
func
(
_m
*
GossipMetricer
)
SetPeerScores
(
_a0
map
[
string
]
float64
)
{
_m
.
Called
(
_a0
)
}
type
mockConstructorTestingTNewGossipMetricer
interface
{
...
...
op-node/p2p/mocks/PeerGater.go
View file @
6450bcc4
// Code generated by mockery v2.
14.0
. DO NOT EDIT.
// Code generated by mockery v2.
22.1
. DO NOT EDIT.
package
mocks
...
...
op-node/p2p/mocks/Peerstore.go
View file @
6450bcc4
// Code generated by mockery v2.
14.0
. DO NOT EDIT.
// Code generated by mockery v2.
22.1
. DO NOT EDIT.
package
mocks
...
...
op-node/p2p/peer_scorer.go
View file @
6450bcc4
package
p2p
import
(
"fmt"
"sort"
"strconv"
"strings"
log
"github.com/ethereum/go-ethereum/log"
pubsub
"github.com/libp2p/go-libp2p-pubsub"
peer
"github.com/libp2p/go-libp2p/core/peer"
...
...
@@ -11,6 +16,68 @@ type scorer struct {
metricer
GossipMetricer
log
log
.
Logger
gater
PeerGater
bandScoreThresholds
*
BandScoreThresholds
}
// scorePair holds a band and its corresponding threshold.
type
scorePair
struct
{
band
string
threshold
float64
}
// BandScoreThresholds holds the thresholds for classifying peers
// into different score bands.
type
BandScoreThresholds
struct
{
bands
[]
scorePair
}
// NewBandScorer constructs a new [BandScoreThresholds] instance.
func
NewBandScorer
(
str
string
)
(
*
BandScoreThresholds
,
error
)
{
s
:=
&
BandScoreThresholds
{
bands
:
make
([]
scorePair
,
0
),
}
for
_
,
band
:=
range
strings
.
Split
(
str
,
";"
)
{
// Skip empty band strings.
band
:=
strings
.
TrimSpace
(
band
)
if
band
==
""
{
continue
}
split
:=
strings
.
Split
(
band
,
":"
)
if
len
(
split
)
!=
2
{
return
nil
,
fmt
.
Errorf
(
"invalid score band: %s"
,
band
)
}
threshold
,
err
:=
strconv
.
ParseFloat
(
split
[
0
],
64
)
if
err
!=
nil
{
return
nil
,
err
}
s
.
bands
=
append
(
s
.
bands
,
scorePair
{
band
:
split
[
1
],
threshold
:
threshold
,
})
}
// Order the bands by threshold in ascending order.
sort
.
Slice
(
s
.
bands
,
func
(
i
,
j
int
)
bool
{
return
s
.
bands
[
i
]
.
threshold
<
s
.
bands
[
j
]
.
threshold
})
return
s
,
nil
}
// Bucket returns the appropriate band for a given score.
func
(
s
*
BandScoreThresholds
)
Bucket
(
score
float64
)
string
{
for
_
,
pair
:=
range
s
.
bands
{
if
score
<=
pair
.
threshold
{
return
pair
.
band
}
}
// If there is no band threshold higher than the score,
// the peer must be placed in the highest bucket.
if
len
(
s
.
bands
)
>
0
{
return
s
.
bands
[
len
(
s
.
bands
)
-
1
]
.
band
}
return
""
}
// Peerstore is a subset of the libp2p peerstore.Peerstore interface.
...
...
@@ -34,12 +101,13 @@ type Scorer interface {
}
// NewScorer returns a new peer scorer.
func
NewScorer
(
peerGater
PeerGater
,
peerStore
Peerstore
,
metricer
GossipMetricer
,
log
log
.
Logger
)
Scorer
{
func
NewScorer
(
peerGater
PeerGater
,
peerStore
Peerstore
,
metricer
GossipMetricer
,
bandScoreThresholds
*
BandScoreThresholds
,
log
log
.
Logger
)
Scorer
{
return
&
scorer
{
peerStore
:
peerStore
,
metricer
:
metricer
,
log
:
log
,
gater
:
peerGater
,
bandScoreThresholds
:
bandScoreThresholds
,
}
}
...
...
@@ -48,13 +116,13 @@ func NewScorer(peerGater PeerGater, peerStore Peerstore, metricer GossipMetricer
// The returned [pubsub.ExtendedPeerScoreInspectFn] is called with a mapping of peer IDs to peer score snapshots.
func
(
s
*
scorer
)
SnapshotHook
()
pubsub
.
ExtendedPeerScoreInspectFn
{
return
func
(
m
map
[
peer
.
ID
]
*
pubsub
.
PeerScoreSnapshot
)
{
scoreMap
:=
make
(
map
[
string
]
float64
)
for
id
,
snap
:=
range
m
{
// Record peer score in the metricer
s
.
metricer
.
RecordPeerScoring
(
id
,
snap
.
Score
)
// Update with the peer gater
band
:=
s
.
bandScoreThresholds
.
Bucket
(
snap
.
Score
)
scoreMap
[
band
]
+=
1
s
.
gater
.
Update
(
id
,
snap
.
Score
)
}
s
.
metricer
.
SetPeerScores
(
scoreMap
)
}
}
...
...
op-node/p2p/peer_scorer_test.go
View file @
6450bcc4
...
...
@@ -20,15 +20,18 @@ type PeerScorerTestSuite struct {
mockGater
*
p2pMocks
.
PeerGater
mockStore
*
p2pMocks
.
Peerstore
mockMetricer
*
p2pMocks
.
GossipMetricer
bandScorer
*
p2p
.
BandScoreThresholds
logger
log
.
Logger
}
// SetupTest sets up the test suite.
func
(
testSuite
*
PeerScorerTestSuite
)
SetupTest
()
{
testSuite
.
mockGater
=
&
p2pMocks
.
PeerGater
{}
// testSuite.mockConnGater = &p2pMocks.ConnectionGater{}
testSuite
.
mockStore
=
&
p2pMocks
.
Peerstore
{}
testSuite
.
mockMetricer
=
&
p2pMocks
.
GossipMetricer
{}
bandScorer
,
err
:=
p2p
.
NewBandScorer
(
"0:graylist;"
)
testSuite
.
NoError
(
err
)
testSuite
.
bandScorer
=
bandScorer
testSuite
.
logger
=
testlog
.
Logger
(
testSuite
.
T
(),
log
.
LvlError
)
}
...
...
@@ -37,45 +40,49 @@ func TestPeerScorer(t *testing.T) {
suite
.
Run
(
t
,
new
(
PeerScorerTestSuite
))
}
// Test
PeerScorer
OnConnect ensures we can call the OnConnect method on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
Test
PeerScorer
OnConnect
()
{
// Test
Scorer_
OnConnect ensures we can call the OnConnect method on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
Test
Scorer_
OnConnect
()
{
scorer
:=
p2p
.
NewScorer
(
testSuite
.
mockGater
,
testSuite
.
mockStore
,
testSuite
.
mockMetricer
,
testSuite
.
bandScorer
,
testSuite
.
logger
,
)
scorer
.
OnConnect
()
}
// Test
PeerScorer
OnDisconnect ensures we can call the OnDisconnect method on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
Test
PeerScorer
OnDisconnect
()
{
// Test
Scorer_
OnDisconnect ensures we can call the OnDisconnect method on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
Test
Scorer_
OnDisconnect
()
{
scorer
:=
p2p
.
NewScorer
(
testSuite
.
mockGater
,
testSuite
.
mockStore
,
testSuite
.
mockMetricer
,
testSuite
.
bandScorer
,
testSuite
.
logger
,
)
scorer
.
OnDisconnect
()
}
// TestSnapshotHook tests running the snapshot hook on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
TestSnapshotHook
()
{
// TestS
corer_S
napshotHook tests running the snapshot hook on the peer scorer.
func
(
testSuite
*
PeerScorerTestSuite
)
TestS
corer_S
napshotHook
()
{
scorer
:=
p2p
.
NewScorer
(
testSuite
.
mockGater
,
testSuite
.
mockStore
,
testSuite
.
mockMetricer
,
testSuite
.
bandScorer
,
testSuite
.
logger
,
)
inspectFn
:=
scorer
.
SnapshotHook
()
// Mock the snapshot updates
// This doesn't return anything
testSuite
.
mockMetricer
.
On
(
"RecordPeerScoring"
,
peer
.
ID
(
"peer1"
),
float64
(
-
100
))
.
Return
(
nil
)
// Mock the peer gater call
testSuite
.
mockGater
.
On
(
"Update"
,
peer
.
ID
(
"peer1"
),
float64
(
-
100
))
.
Return
(
nil
)
// The metricer should then be called with the peer score band map
testSuite
.
mockMetricer
.
On
(
"SetPeerScores"
,
map
[
string
]
float64
{
"graylist"
:
1
,
})
.
Return
(
nil
)
// Apply the snapshot
snapshotMap
:=
map
[
peer
.
ID
]
*
pubsub
.
PeerScoreSnapshot
{
peer
.
ID
(
"peer1"
)
:
{
...
...
@@ -85,24 +92,26 @@ func (testSuite *PeerScorerTestSuite) TestSnapshotHook() {
inspectFn
(
snapshotMap
)
}
// TestS
napshotHookBlock
Peer tests running the snapshot hook on the peer scorer with a peer score below the threshold.
// TestS
corer_SnapshotHookBlocks
Peer tests running the snapshot hook on the peer scorer with a peer score below the threshold.
// This implies that the peer should be blocked.
func
(
testSuite
*
PeerScorerTestSuite
)
TestS
napshotHookBlock
Peer
()
{
func
(
testSuite
*
PeerScorerTestSuite
)
TestS
corer_SnapshotHookBlocks
Peer
()
{
scorer
:=
p2p
.
NewScorer
(
testSuite
.
mockGater
,
testSuite
.
mockStore
,
testSuite
.
mockMetricer
,
testSuite
.
bandScorer
,
testSuite
.
logger
,
)
inspectFn
:=
scorer
.
SnapshotHook
()
// Mock the snapshot updates
// This doesn't return anything
testSuite
.
mockMetricer
.
On
(
"RecordPeerScoring"
,
peer
.
ID
(
"peer1"
),
float64
(
-
101
))
.
Return
(
nil
)
// Mock the peer gater call
testSuite
.
mockGater
.
On
(
"Update"
,
peer
.
ID
(
"peer1"
),
float64
(
-
101
))
.
Return
(
nil
)
// The metricer should then be called with the peer score band map
testSuite
.
mockMetricer
.
On
(
"SetPeerScores"
,
map
[
string
]
float64
{
"graylist"
:
1
,
})
.
Return
(
nil
)
// Apply the snapshot
snapshotMap
:=
map
[
peer
.
ID
]
*
pubsub
.
PeerScoreSnapshot
{
peer
.
ID
(
"peer1"
)
:
{
...
...
op-node/p2p/peer_scores.go
View file @
6450bcc4
...
...
@@ -14,7 +14,7 @@ func ConfigurePeerScoring(h host.Host, g ConnectionGater, gossipConf GossipSetup
peerScoreThresholds
:=
NewPeerScoreThresholds
()
banEnabled
:=
gossipConf
.
BanPeers
()
peerGater
:=
NewPeerGater
(
g
,
log
,
banEnabled
)
scorer
:=
NewScorer
(
peerGater
,
h
.
Peerstore
(),
m
,
log
)
scorer
:=
NewScorer
(
peerGater
,
h
.
Peerstore
(),
m
,
gossipConf
.
PeerBandScorer
(),
log
)
opts
:=
[]
pubsub
.
Option
{}
// Check the app specific score since libp2p doesn't export it's [validate] function :/
if
peerScoreParams
!=
nil
&&
peerScoreParams
.
AppSpecificScore
!=
nil
{
...
...
op-node/p2p/peer_scores_test.go
View file @
6450bcc4
...
...
@@ -11,7 +11,7 @@ import (
p2pMocks
"github.com/ethereum-optimism/optimism/op-node/p2p/mocks"
testlog
"github.com/ethereum-optimism/optimism/op-node/testlog"
mock
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/mock"
suite
"github.com/stretchr/testify/suite"
log
"github.com/ethereum/go-ethereum/log"
...
...
@@ -30,6 +30,7 @@ type PeerScoresTestSuite struct {
mockGater
*
p2pMocks
.
ConnectionGater
mockStore
*
p2pMocks
.
Peerstore
mockMetricer
*
p2pMocks
.
GossipMetricer
bandScorer
p2p
.
BandScoreThresholds
logger
log
.
Logger
}
...
...
@@ -38,6 +39,9 @@ func (testSuite *PeerScoresTestSuite) SetupTest() {
testSuite
.
mockGater
=
&
p2pMocks
.
ConnectionGater
{}
testSuite
.
mockStore
=
&
p2pMocks
.
Peerstore
{}
testSuite
.
mockMetricer
=
&
p2pMocks
.
GossipMetricer
{}
bandScorer
,
err
:=
p2p
.
NewBandScorer
(
"0:graylist;"
)
testSuite
.
NoError
(
err
)
testSuite
.
bandScorer
=
*
bandScorer
testSuite
.
logger
=
testlog
.
Logger
(
testSuite
.
T
(),
log
.
LvlError
)
}
...
...
@@ -68,6 +72,7 @@ func newGossipSubs(testSuite *PeerScoresTestSuite, ctx context.Context, hosts []
rt
:=
pubsub
.
DefaultGossipSubRouter
(
h
)
opts
:=
[]
pubsub
.
Option
{}
opts
=
append
(
opts
,
p2p
.
ConfigurePeerScoring
(
h
,
testSuite
.
mockGater
,
&
p2p
.
Config
{
BandScoreThresholds
:
testSuite
.
bandScorer
,
PeerScoring
:
pubsub
.
PeerScoreParams
{
AppSpecificScore
:
func
(
p
peer
.
ID
)
float64
{
if
p
==
hosts
[
0
]
.
ID
()
{
...
...
@@ -118,8 +123,7 @@ func (testSuite *PeerScoresTestSuite) TestNegativeScores() {
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
defer
cancel
()
testSuite
.
mockMetricer
.
On
(
"RecordPeerScoring"
,
mock
.
Anything
,
float64
(
0
))
.
Return
(
nil
)
testSuite
.
mockMetricer
.
On
(
"RecordPeerScoring"
,
mock
.
Anything
,
float64
(
-
1000
))
.
Return
(
nil
)
testSuite
.
mockMetricer
.
On
(
"SetPeerScores"
,
mock
.
Anything
)
.
Return
(
nil
)
testSuite
.
mockGater
.
On
(
"ListBlockedPeers"
)
.
Return
([]
peer
.
ID
{})
...
...
op-node/p2p/prepared.go
View file @
6450bcc4
...
...
@@ -68,6 +68,10 @@ func (p *Prepared) PeerScoringParams() *pubsub.PeerScoreParams {
return
nil
}
func
(
p
*
Prepared
)
PeerBandScorer
()
*
BandScoreThresholds
{
return
nil
}
func
(
p
*
Prepared
)
BanPeers
()
bool
{
return
false
}
...
...
ops-bedrock/docker-compose.yml
View file @
6450bcc4
...
...
@@ -61,6 +61,8 @@ services:
--p2p.listen.ip=0.0.0.0
--p2p.listen.tcp=9003
--p2p.listen.udp=9003
--p2p.scoring.peers=light
--p2p.ban.peers=true
--snapshotlog.file=/op_log/snapshot.log
--p2p.priv.path=/config/p2p-node-key.txt
--metrics.enabled
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment