From 01d21df6a541962fd95ffb131ae9783e38c5aeed Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 8 Jun 2023 21:54:24 +0300 Subject: [PATCH 01/74] Fixed isse with rest metrics reports each request path as unique collection. --- engine/access/rest/middleware/metrics.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/engine/access/rest/middleware/metrics.go b/engine/access/rest/middleware/metrics.go index 54dd5dd2c6a..4148e8ab18d 100644 --- a/engine/access/rest/middleware/metrics.go +++ b/engine/access/rest/middleware/metrics.go @@ -12,11 +12,13 @@ import ( ) func MetricsMiddleware(restCollector module.RestMetrics) mux.MiddlewareFunc { - metricsMiddleware := middleware.New(middleware.Config{Recorder: restCollector}) + cfg := middleware.Config{Recorder: restCollector} + serviceID := cfg.Service + metricsMiddleware := middleware.New(cfg) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { // This is a custom metric being called on every http request - restCollector.AddTotalRequests(req.Context(), req.Method, req.URL.Path) + restCollector.AddTotalRequests(req.Context(), serviceID, req.Method) // Modify the writer respWriter := &responseWriter{w, http.StatusOK} From fd160d4837ffd84435f879afd093da81f2a1e2f7 Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 8 Jun 2023 23:14:48 +0300 Subject: [PATCH 02/74] Renamed arguments with proper naming. --- module/metrics.go | 2 +- module/metrics/rest_api.go | 6 +++--- module/mock/access_metrics.go | 6 +++--- module/mock/rest_metrics.go | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/module/metrics.go b/module/metrics.go index 55d09b5209b..c77f068d0a5 100644 --- a/module/metrics.go +++ b/module/metrics.go @@ -605,7 +605,7 @@ type RestMetrics interface { // Example recorder taken from: // https://github.com/slok/go-http-metrics/blob/master/metrics/prometheus/prometheus.go httpmetrics.Recorder - AddTotalRequests(ctx context.Context, service string, id string) + AddTotalRequests(ctx context.Context, serviceID string, method string) } type GRPCConnectionPoolMetrics interface { diff --git a/module/metrics/rest_api.go b/module/metrics/rest_api.go index efa12688a81..ab277b77694 100644 --- a/module/metrics/rest_api.go +++ b/module/metrics/rest_api.go @@ -81,7 +81,7 @@ func NewRestCollector(cfg metricsProm.Config) module.RestMetrics { Subsystem: "http", Name: "requests_total", Help: "The number of requests handled over time.", - }, []string{cfg.ServiceLabel, cfg.HandlerIDLabel}), + }, []string{cfg.ServiceLabel, cfg.MethodLabel}), } cfg.Registry.MustRegister( @@ -108,6 +108,6 @@ func (r *RestCollector) AddInflightRequests(_ context.Context, p httpmetrics.HTT } // New custom method to track all requests made for every REST API request -func (r *RestCollector) AddTotalRequests(_ context.Context, method string, id string) { - r.httpRequestsTotal.WithLabelValues(method, id).Inc() +func (r *RestCollector) AddTotalRequests(_ context.Context, serviceID string, method string) { + r.httpRequestsTotal.WithLabelValues(serviceID, method).Inc() } diff --git a/module/mock/access_metrics.go b/module/mock/access_metrics.go index 61126096787..2b686c8f7cc 100644 --- a/module/mock/access_metrics.go +++ b/module/mock/access_metrics.go @@ -23,9 +23,9 @@ func (_m *AccessMetrics) AddInflightRequests(ctx context.Context, props metrics. _m.Called(ctx, props, quantity) } -// AddTotalRequests provides a mock function with given fields: ctx, service, id -func (_m *AccessMetrics) AddTotalRequests(ctx context.Context, service string, id string) { - _m.Called(ctx, service, id) +// AddTotalRequests provides a mock function with given fields: ctx, serviceID, method +func (_m *AccessMetrics) AddTotalRequests(ctx context.Context, serviceID string, method string) { + _m.Called(ctx, serviceID, method) } // ConnectionAddedToPool provides a mock function with given fields: diff --git a/module/mock/rest_metrics.go b/module/mock/rest_metrics.go index f1544ca5823..4d9dc09eeee 100644 --- a/module/mock/rest_metrics.go +++ b/module/mock/rest_metrics.go @@ -21,9 +21,9 @@ func (_m *RestMetrics) AddInflightRequests(ctx context.Context, props metrics.HT _m.Called(ctx, props, quantity) } -// AddTotalRequests provides a mock function with given fields: ctx, service, id -func (_m *RestMetrics) AddTotalRequests(ctx context.Context, service string, id string) { - _m.Called(ctx, service, id) +// AddTotalRequests provides a mock function with given fields: ctx, serviceID, method +func (_m *RestMetrics) AddTotalRequests(ctx context.Context, serviceID string, method string) { + _m.Called(ctx, serviceID, method) } // ObserveHTTPRequestDuration provides a mock function with given fields: ctx, props, duration From 4646bcb784297df9ec006789bcda3b6ff4dbefb5 Mon Sep 17 00:00:00 2001 From: Peter Argue <89119817+peterargue@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:51:27 -0700 Subject: [PATCH 03/74] [Access] Add parsing logic for REST urls for metrics --- engine/access/rest/router.go | 59 ++++++++++ engine/access/rest/router_test.go | 185 ++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 engine/access/rest/router_test.go diff --git a/engine/access/rest/router.go b/engine/access/rest/router.go index da39912eff9..9bee63560b0 100644 --- a/engine/access/rest/router.go +++ b/engine/access/rest/router.go @@ -1,7 +1,10 @@ package rest import ( + "fmt" "net/http" + "regexp" + "strings" "github.com/gorilla/mux" "github.com/rs/zerolog" @@ -114,3 +117,59 @@ var Routes = []route{{ Name: "getNodeVersionInfo", Handler: GetNodeVersionInfo, }} + +var routeUrlMap = map[string]string{} +var routeRE = regexp.MustCompile("/v1/([\\w]+)(/([\\w]+)(/([\\w]+))?)?") + +func init() { + for _, r := range Routes { + routeUrlMap[r.Pattern] = r.Name + } +} + +func URLToRoute(url string) (string, error) { + normalized, err := normalizeURL(url) + if err != nil { + return "", err + } + + name, ok := routeUrlMap[normalized] + if !ok { + return "", fmt.Errorf("invalid url") + } + return name, nil +} + +func normalizeURL(url string) (string, error) { + matches := routeRE.FindAllStringSubmatch(url, -1) + if len(matches) != 1 || len(matches[0]) != 6 { + return "", fmt.Errorf("invalid url") + } + + // given a URL like + // /v1/blocks/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef/payload + // groups [ 1 ] [ 3 ] [ 5 ] + // normalized form like /v1/blocks/{id}/payload + + parts := []string{matches[0][1]} + + switch len(matches[0][3]) { + case 0: + // top level resource. e.g. /v1/blocks + case 64: + // id based resource. e.g. /v1/blocks/1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + parts = append(parts, "{id}") + case 16: + // address based resource. e.g. /v1/accounts/1234567890abcdef + parts = append(parts, "{address}") + default: + // named resource. e.g. /v1/network/parameters + parts = append(parts, matches[0][3]) + } + + if matches[0][5] != "" { + parts = append(parts, matches[0][5]) + } + + return "/" + strings.Join(parts, "/"), nil +} diff --git a/engine/access/rest/router_test.go b/engine/access/rest/router_test.go new file mode 100644 index 00000000000..5b6578be8a1 --- /dev/null +++ b/engine/access/rest/router_test.go @@ -0,0 +1,185 @@ +package rest + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseURL(t *testing.T) { + tests := []struct { + name string + url string + expected string + }{ + { + name: "/v1/transactions", + url: "/v1/transactions", + expected: "createTransaction", + }, + { + name: "/v1/transactions/{id}", + url: "/v1/transactions/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getTransactionByID", + }, + { + name: "/v1/transaction_results/{id}", + url: "/v1/transaction_results/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getTransactionResultByID", + }, + { + name: "/v1/blocks", + url: "/v1/blocks", + expected: "getBlocksByHeight", + }, + { + name: "/v1/blocks/{id}", + url: "/v1/blocks/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getBlocksByIDs", + }, + { + name: "/v1/blocks/{id}/payload", + url: "/v1/blocks/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76/payload", + expected: "getBlockPayloadByID", + }, + { + name: "/v1/execution_results/{id}", + url: "/v1/execution_results/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getExecutionResultByID", + }, + { + name: "/v1/execution_results", + url: "/v1/execution_results", + expected: "getExecutionResultByBlockID", + }, + { + name: "/v1/collections/{id}", + url: "/v1/collections/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getCollectionByID", + }, + { + name: "/v1/scripts", + url: "/v1/scripts", + expected: "executeScript", + }, + { + name: "/v1/accounts/{address}", + url: "/v1/accounts/6a587be304c1224c", + expected: "getAccount", + }, + { + name: "/v1/events", + url: "/v1/events", + expected: "getEvents", + }, + { + name: "/v1/network/parameters", + url: "/v1/network/parameters", + expected: "getNetworkParameters", + }, + { + name: "/v1/node_version_info", + url: "/v1/node_version_info", + expected: "getNodeVersionInfo", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := URLToRoute(tt.url) + require.NoError(t, err) + assert.Equal(t, tt.expected, got) + }) + } +} + +func TestBenchmarkParseURL(t *testing.T) { + tests := []struct { + name string + url string + expected string + }{ + { + name: "/v1/transactions", + url: "/v1/transactions", + expected: "createTransaction", + }, + { + name: "/v1/transactions/{id}", + url: "/v1/transactions/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getTransactionByID", + }, + { + name: "/v1/transaction_results/{id}", + url: "/v1/transaction_results/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getTransactionResultByID", + }, + { + name: "/v1/blocks", + url: "/v1/blocks", + expected: "getBlocksByHeight", + }, + { + name: "/v1/blocks/{id}", + url: "/v1/blocks/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getBlocksByIDs", + }, + { + name: "/v1/blocks/{id}/payload", + url: "/v1/blocks/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76/payload", + expected: "getBlockPayloadByID", + }, + { + name: "/v1/execution_results/{id}", + url: "/v1/execution_results/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getExecutionResultByID", + }, + { + name: "/v1/execution_results", + url: "/v1/execution_results", + expected: "getExecutionResultByBlockID", + }, + { + name: "/v1/collections/{id}", + url: "/v1/collections/53730d3f3d2d2f46cb910b16db817d3a62adaaa72fdb3a92ee373c37c5b55a76", + expected: "getCollectionByID", + }, + { + name: "/v1/scripts", + url: "/v1/scripts", + expected: "executeScript", + }, + { + name: "/v1/accounts/{address}", + url: "/v1/accounts/6a587be304c1224c", + expected: "getAccount", + }, + { + name: "/v1/events", + url: "/v1/events", + expected: "getEvents", + }, + { + name: "/v1/network/parameters", + url: "/v1/network/parameters", + expected: "getNetworkParameters", + }, + { + name: "/v1/node_version_info", + url: "/v1/node_version_info", + expected: "getNodeVersionInfo", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + start := time.Now() + for i := 0; i < 100_000; i++ { + _, _ = URLToRoute(tt.url) + } + t.Logf("%s: %v", tt.name, time.Since(start)/100_000) + }) + } +} From a45628eaa935f366f919d327ef3b72229ed4d88f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Tue, 20 Jun 2023 14:46:13 -0700 Subject: [PATCH 04/74] renames setter of inspector suite with the override --- cmd/access/node_builder/access_node_builder.go | 2 +- cmd/observer/node_builder/observer_builder.go | 2 +- follower/follower_builder.go | 2 +- network/internal/p2pfixtures/fixtures.go | 2 +- network/internal/testutils/testUtil.go | 2 +- network/p2p/builder.go | 7 +------ network/p2p/mock/node_builder.go | 2 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 4 ++-- 8 files changed, 9 insertions(+), 14 deletions(-) diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index c1aba0b8a81..65afd594932 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -1244,7 +1244,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite). + OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index 253c5f5e8c7..ea337600a11 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -747,7 +747,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite). + OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index ee98a2bcb3a..cf5383efa6e 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -648,7 +648,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite). + OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index c98c261c33d..2bb756a909e 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -129,7 +129,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite) + OverrideDefaultInspectorSuite(rpcInspectorSuite) for _, opt := range opts { opt(builder) diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 47533cb2677..5528de3674c 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -518,7 +518,7 @@ func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateK SetConnectionManager(connManager). SetResourceManager(NewResourceManager(t)). SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite) + OverrideDefaultInspectorSuite(rpcInspectorSuite) for _, opt := range opts { opt(builder) diff --git a/network/p2p/builder.go b/network/p2p/builder.go index a8a89367013..0dd8f3646a0 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -61,11 +61,6 @@ type GossipSubBuilder interface { // If the routing system has already been set, a fatal error is logged. SetRoutingSystem(routing.Routing) - // SetGossipSubRPCInspectorSuite sets the gossipsub rpc inspector suite of the builder. It contains the - // inspector function that is injected into the gossipsub rpc layer, as well as the notification distributors that - // are used to notify the app specific scoring mechanism of misbehaving peers. - SetGossipSubRPCInspectorSuite(GossipSubInspectorSuite) - // Build creates a new GossipSub pubsub system. // It returns the newly created GossipSub pubsub system and any errors encountered during its creation. // @@ -111,7 +106,7 @@ type NodeBuilder interface { SetRateLimiterDistributor(UnicastRateLimiterDistributor) NodeBuilder SetGossipSubTracer(PubSubTracer) NodeBuilder SetGossipSubScoreTracerInterval(time.Duration) NodeBuilder - SetGossipSubRpcInspectorSuite(GossipSubInspectorSuite) NodeBuilder + OverrideDefaultInspectorSuite(GossipSubInspectorSuite) NodeBuilder Build() (LibP2PNode, error) } diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index a14e07363ae..3e2a22976dd 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -154,7 +154,7 @@ func (_m *NodeBuilder) SetGossipSubFactory(_a0 p2p.GossipSubFactoryFunc, _a1 p2p } // SetGossipSubRpcInspectorSuite provides a mock function with given fields: _a0 -func (_m *NodeBuilder) SetGossipSubRpcInspectorSuite(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { +func (_m *NodeBuilder) OverrideDefaultInspectorSuite(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { ret := _m.Called(_a0) var r0 p2p.NodeBuilder diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 376cd71246c..4a7a75a9eb5 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -188,7 +188,7 @@ func (builder *LibP2PNodeBuilder) SetGossipSubScoreTracerInterval(interval time. return builder } -func (builder *LibP2PNodeBuilder) SetGossipSubRpcInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) p2p.NodeBuilder { +func (builder *LibP2PNodeBuilder) OverrideDefaultInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) p2p.NodeBuilder { builder.gossipSubBuilder.SetGossipSubRPCInspectorSuite(inspectorSuite) return builder } @@ -470,7 +470,7 @@ func DefaultNodeBuilder(log zerolog.Logger, SetStreamCreationRetryInterval(uniCfg.StreamRetryInterval). SetCreateNode(DefaultCreateNodeFunc). SetRateLimiterDistributor(uniCfg.RateLimiterDistributor). - SetGossipSubRpcInspectorSuite(rpcInspectorSuite) + OverrideDefaultInspectorSuite(rpcInspectorSuite) if gossipCfg.PeerScoring { // currently, we only enable peer scoring with default parameters. So, we set the score parameters to nil. From fabbc0176167f5f3ee1df29edfbb970e60b82d51 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Tue, 20 Jun 2023 14:46:53 -0700 Subject: [PATCH 05/74] wip migraties logic from inspector builder to gossipsub builder --- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 89 +++++++++++++++---- .../inspector/rpc_inspector_builder.go | 32 +------ network/p2p/test/fixtures.go | 2 +- 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index e4422c31c70..e64cd69391f 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -11,10 +11,19 @@ import ( "github.com/libp2p/go-libp2p/core/routing" "github.com/rs/zerolog" + netconf "github.com/onflow/flow-go/config/network" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" + "github.com/onflow/flow-go/module/mempool/queue" + "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/distributor" + "github.com/onflow/flow-go/network/p2p/inspector" + "github.com/onflow/flow-go/network/p2p/inspector/validation" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/network/p2p/tracer" @@ -23,8 +32,11 @@ import ( // The Builder struct is used to configure and create a new GossipSub pubsub system. type Builder struct { + networkType network.NetworkingType + sporkId flow.Identifier logger zerolog.Logger metrics module.GossipSubMetrics + heroCacheMetricsFactory metrics.HeroCacheMetricsFactory h host.Host subscriptionFilter pubsub.SubscriptionFilter gossipSubFactory p2p.GossipSubFactoryFunc @@ -139,21 +151,21 @@ func (g *Builder) SetAppSpecificScoreParams(f func(peer.ID) float64) { g.scoreOptionConfig.SetAppSpecificScoreFunction(f) } -// SetGossipSubRPCInspectorSuite sets the gossipsub rpc inspector suite of the builder. It contains the -// inspector function that is injected into the gossipsub rpc layer, as well as the notification distributors that -// are used to notify the app specific scoring mechanism of misbehaving peers.. -func (g *Builder) SetGossipSubRPCInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) { - g.rpcInspectorSuite = inspectorSuite -} - -func NewGossipSubBuilder(logger zerolog.Logger, metrics module.GossipSubMetrics) *Builder { +func NewGossipSubBuilder( + logger zerolog.Logger, + metrics module.GossipSubMetrics, + networkType network.NetworkingType, + sporkId flow.Identifier) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() return &Builder{ logger: lg, metrics: metrics, + networkType: networkType, gossipSubFactory: defaultGossipSubFactory(), gossipSubConfigFunc: defaultGossipSubAdapterConfig(), scoreOptionConfig: scoring.NewScoreOptionConfig(lg), + sporkId: sporkId, + rpcInspectorSuite: defaultInspectorSuite(), } } @@ -169,6 +181,58 @@ func defaultGossipSubAdapterConfig() p2p.GossipSubAdapterConfigFunc { } } +type RpcInspectorSuiteFactoryFunc func( + zerolog.Logger, + flow.Identifier, + *netconf.GossipSubRPCInspectorsConfig, + module.GossipSubMetrics, + metrics.HeroCacheMetricsFactory, + network.NetworkingType, + module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) + +func defaultInspectorSuite() RpcInspectorSuiteFactoryFunc { + return func( + logger zerolog.Logger, + sporkId flow.Identifier, + inspectorCfg *netconf.GossipSubRPCInspectorsConfig, + gossipSubMetrics module.GossipSubMetrics, + heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, + networkType network.NetworkingType, + idProvider module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { + metricsInspector := inspector.NewControlMsgMetricsInspector( + logger, + p2pnode.NewGossipSubControlMessageMetrics(gossipSubMetrics, logger), + inspectorCfg.GossipSubRPCMetricsInspectorConfigs.NumberOfWorkers, + []queue.HeroStoreConfigOption{ + queue.WithHeroStoreSizeLimit(inspectorCfg.GossipSubRPCMetricsInspectorConfigs.CacheSize), + queue.WithHeroStoreCollector(metrics.GossipSubRPCMetricsObserverInspectorQueueMetricFactory(heroCacheMetricsFactory, networkType)), + }...) + notificationDistributor := distributor.DefaultGossipSubInspectorNotificationDistributor( + logger, + []queue.HeroStoreConfigOption{ + queue.WithHeroStoreSizeLimit(inspectorCfg.GossipSubRPCInspectorNotificationCacheSize), + queue.WithHeroStoreCollector(metrics.RpcInspectorNotificationQueueMetricFactory(heroCacheMetricsFactory, networkType))}...) + + inspectMsgQueueCacheCollector := metrics.GossipSubRPCInspectorQueueMetricFactory(heroCacheMetricsFactory, networkType) + clusterPrefixedCacheCollector := metrics.GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(heroCacheMetricsFactory, networkType) + rpcValidationInspector, err := validation.NewControlMsgValidationInspector( + logger, + sporkId, + &inspectorCfg.GossipSubRPCValidationInspectorConfigs, + notificationDistributor, + inspectMsgQueueCacheCollector, + clusterPrefixedCacheCollector, + idProvider, + gossipSubMetrics, + ) + if err != nil { + return nil, fmt.Errorf("failed to create new control message valiadation inspector: %w", err) + } + + return suite.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, rpcValidationInspector}, notificationDistributor), nil + } +} + // Build creates a new GossipSub pubsub system. // It returns the newly created GossipSub pubsub system and any errors encountered during its creation. // Arguments: @@ -194,17 +258,12 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p gossipSubConfigs.WithSubscriptionFilter(g.subscriptionFilter) } - if g.rpcInspectorSuite != nil { - gossipSubConfigs.WithInspectorSuite(g.rpcInspectorSuite) - } + gossipSubConfigs.WithInspectorSuite(g.rpcInspectorSuite) var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer if g.gossipSubPeerScoring { - if g.rpcInspectorSuite != nil { - g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(g.rpcInspectorSuite.AddInvCtrlMsgNotifConsumer) - } - + g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(g.rpcInspectorSuite.AddInvCtrlMsgNotifConsumer) scoreOpt = scoring.NewScoreOption(g.scoreOptionConfig) gossipSubConfigs.WithScoreOption(scoreOpt) diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index 4d67dd51b9b..c7a40a136ba 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -69,41 +69,13 @@ func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.Networkin // buildGossipSubMetricsInspector builds the gossipsub rpc metrics inspector. func (b *GossipSubInspectorBuilder) buildGossipSubMetricsInspector() p2p.GossipSubRPCInspector { - gossipSubMetrics := p2pnode.NewGossipSubControlMessageMetrics(b.metricsCfg.Metrics, b.logger) - metricsInspector := inspector.NewControlMsgMetricsInspector( - b.logger, - gossipSubMetrics, - b.inspectorsConfig.GossipSubRPCMetricsInspectorConfigs.NumberOfWorkers, - []queue.HeroStoreConfigOption{ - queue.WithHeroStoreSizeLimit(b.inspectorsConfig.GossipSubRPCMetricsInspectorConfigs.CacheSize), - queue.WithHeroStoreCollector(metrics.GossipSubRPCMetricsObserverInspectorQueueMetricFactory(b.metricsCfg.HeroCacheFactory, b.networkType)), - }...) + return metricsInspector } // buildGossipSubValidationInspector builds the gossipsub rpc validation inspector. func (b *GossipSubInspectorBuilder) buildGossipSubValidationInspector() (p2p.GossipSubRPCInspector, *distributor.GossipSubInspectorNotifDistributor, error) { - notificationDistributor := distributor.DefaultGossipSubInspectorNotificationDistributor( - b.logger, - []queue.HeroStoreConfigOption{ - queue.WithHeroStoreSizeLimit(b.inspectorsConfig.GossipSubRPCInspectorNotificationCacheSize), - queue.WithHeroStoreCollector(metrics.RpcInspectorNotificationQueueMetricFactory(b.metricsCfg.HeroCacheFactory, b.networkType))}...) - inspectMsgQueueCacheCollector := metrics.GossipSubRPCInspectorQueueMetricFactory(b.metricsCfg.HeroCacheFactory, b.networkType) - clusterPrefixedCacheCollector := metrics.GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(b.metricsCfg.HeroCacheFactory, b.networkType) - rpcValidationInspector, err := validation.NewControlMsgValidationInspector( - b.logger, - b.sporkID, - &b.inspectorsConfig.GossipSubRPCValidationInspectorConfigs, - notificationDistributor, - inspectMsgQueueCacheCollector, - clusterPrefixedCacheCollector, - b.idProvider, - b.inspectorMetrics, - ) - if err != nil { - return nil, nil, fmt.Errorf("failed to create new control message valiadation inspector: %w", err) - } return rpcValidationInspector, notificationDistributor, nil } @@ -116,5 +88,5 @@ func (b *GossipSubInspectorBuilder) Build() (p2p.GossipSubInspectorSuite, error) if err != nil { return nil, err } - return suite.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, validationInspector}, notificationDistributor), nil + return , nil } diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 32ff45a2e6f..668b62f5ce9 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -117,7 +117,7 @@ func NodeFixture( SetCreateNode(p2pbuilder.DefaultCreateNodeFunc). SetStreamCreationRetryInterval(parameters.CreateStreamRetryDelay). SetResourceManager(parameters.ResourceManager). - SetGossipSubRpcInspectorSuite(parameters.GossipSubRPCInspector) + OverrideDefaultInspectorSuite(parameters.GossipSubRPCInspector) if parameters.ResourceManager != nil { builder.SetResourceManager(parameters.ResourceManager) From 16e3f82df6ba7e8495c9b3560538a4799a15bfca Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Wed, 21 Jun 2023 11:47:30 -0700 Subject: [PATCH 06/74] refactors libp2p builder and gossipsub builder accross the code --- .../node_builder/access_node_builder.go | 22 ++---- cmd/observer/node_builder/observer_builder.go | 19 ++--- cmd/scaffold.go | 22 ++---- follower/follower_builder.go | 19 +++-- insecure/corruptlibp2p/libp2p_node_factory.go | 12 +--- network/internal/p2pfixtures/fixtures.go | 16 +++-- network/internal/testutils/testUtil.go | 24 +++---- network/p2p/mock/node_builder.go | 2 +- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 70 +++++++++++-------- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 70 +++++++++++++------ network/p2p/scoring/scoring_test.go | 2 +- 11 files changed, 141 insertions(+), 137 deletions(-) diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 65afd594932..84aff969161 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -72,7 +72,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -1199,25 +1198,19 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - // setup RPC inspectors - rpcInspectorBuilder := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network) - rpcInspectorSuite, err := rpcInspectorBuilder. - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for access node: %w", err) - } - libp2pNode, err := p2pbuilder.NewNodeBuilder( builder.Logger, - networkMetrics, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: networkMetrics, + }, + network.PublicNetwork, bindAddress, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -1244,7 +1237,6 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index ea337600a11..ae50cbc938d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -710,23 +710,19 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network). - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("could not initialize gossipsub inspectors for observer node: %w", err) - } - node, err := p2pbuilder.NewNodeBuilder( builder.Logger, - builder.Metrics.Network, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: builder.Metrics.Network, + }, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -747,7 +743,6 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 40d4181e8ad..2de8d6c4da1 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -54,7 +54,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/ping" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/unicast/protocols" @@ -344,34 +343,25 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { myAddr = fnb.BaseConfig.BindAddr } - metricsCfg := &p2pconfig.MetricsConfig{ - Metrics: fnb.Metrics.Network, - HeroCacheFactory: fnb.HeroCacheMetricsFactory(), - } - - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(fnb.Logger, fnb.SporkID, &fnb.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, fnb.IdentityProvider, fnb.Metrics.Network). - SetNetworkType(network.PrivateNetwork). - SetMetrics(metricsCfg). - Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for default libp2p node: %w", err) - } - fnb.GossipSubRpcInspectorSuite = rpcInspectorSuite builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, + network.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, - metricsCfg, + &p2pconfig.MetricsConfig{ + Metrics: fnb.Metrics.Network, + HeroCacheFactory: fnb.HeroCacheMetricsFactory(), + }, fnb.Resolver, fnb.BaseConfig.NodeRole, connGaterCfg, peerManagerCfg, &fnb.FlowConfig.NetworkConfig.GossipSubConfig, - fnb.GossipSubRpcInspectorSuite, + &fnb.FlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &fnb.FlowConfig.NetworkConfig.ResourceManagerConfig, uniCfg, &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, diff --git a/follower/follower_builder.go b/follower/follower_builder.go index cf5383efa6e..a801c99d2ee 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -611,23 +611,20 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.Metrics.Network, builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network). - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for public libp2p node: %w", err) - } node, err := p2pbuilder.NewNodeBuilder( builder.Logger, - builder.Metrics.Network, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: builder.Metrics.Network, + }, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -648,7 +645,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). + OverrideDefaultRpcInspectorSuiteFactory(rpcInspectorSuite). Build() if err != nil { diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 1cc64f3a46b..8b79efeb667 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" ) // InitCorruptLibp2pNode initializes and returns a corrupt libp2p node that should only be used for BFT testing in @@ -74,17 +73,10 @@ func InitCorruptLibp2pNode( Metrics: metricsCfg, } - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(log, sporkId, &netConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, idProvider, metricsCfg). - SetNetworkType(network.PrivateNetwork). - SetMetrics(metCfg). - Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for default libp2p node: %w", err) - } - builder, err := p2pbuilder.DefaultNodeBuilder( log, address, + network.PrivateNetwork, flowKey, sporkId, idProvider, @@ -94,7 +86,7 @@ func InitCorruptLibp2pNode( connGaterCfg, peerManagerCfg, &netConfig.GossipSubConfig, - rpcInspectorSuite, + &netConfig.GossipSubRPCInspectorsConfig, &netConfig.ResourceManagerConfig, uniCfg, &netConfig.ConnectionManagerConfig, diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index 2bb756a909e..83b34e8bc6a 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,6 +26,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -34,6 +35,7 @@ import ( p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" "github.com/onflow/flow-go/network/p2p/p2pbuilder" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/unicast" @@ -97,6 +99,7 @@ func WithSubscriptionFilter(filter pubsub.SubscriptionFilter) nodeOpt { } } +// TODO: this should be replaced by node fixture: https://github.com/onflow/flow-go/blob/master/network/p2p/test/fixtures.go func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identifier, logger zerolog.Logger, nodeIds flow.IdentityList, opts ...nodeOpt) p2p.LibP2PNode { idProvider := id.NewFixedIdentityProvider(nodeIds) defaultFlowConfig, err := config.DefaultConfig() @@ -107,17 +110,19 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif idProvider, defaultFlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - met := metrics.NewNoopCollector() - rpcInspectorSuite, err := inspectorbuilder.NewGossipSubInspectorBuilder(logger, sporkID, &defaultFlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, idProvider, met).Build() - require.NoError(t, err) - builder := p2pbuilder.NewNodeBuilder( logger, - met, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), + Metrics: metrics.NewNoopCollector(), + }, + flownet.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, + idProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, + &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), @@ -129,7 +134,6 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite) for _, opt := range opts { opt(builder) diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 5528de3674c..14fe9feb175 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -42,7 +42,7 @@ import ( p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" - inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/translator" "github.com/onflow/flow-go/network/p2p/unicast" @@ -489,36 +489,36 @@ func withUnicastManagerOpts(delay time.Duration) nodeBuilderOption { } } +// TODO: this should be replaced by node fixture: https://github.com/onflow/flow-go/blob/master/network/p2p/test/fixtures.go // generateLibP2PNode generates a `LibP2PNode` on localhost using a port assigned by the OS -func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateKey, provider *UpdatableIDProvider, opts ...nodeBuilderOption) (p2p.LibP2PNode, observable.Observable) { - - noopMetrics := metrics.NewNoopCollector() +func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateKey, idProvider module.IdentityProvider, opts ...nodeBuilderOption) (p2p.LibP2PNode, observable.Observable) { defaultFlowConfig, err := config.DefaultConfig() require.NoError(t, err) // Inject some logic to be able to observe connections of this node - connManager, err := NewTagWatchingConnManager(logger, noopMetrics, &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) - require.NoError(t, err) - met := metrics.NewNoopCollector() - - rpcInspectorSuite, err := inspectorbuilder.NewGossipSubInspectorBuilder(logger, sporkID, &defaultFlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, provider, met).Build() + connManager, err := NewTagWatchingConnManager(logger, metrics.NewNoopCollector(), &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) require.NoError(t, err) builder := p2pbuilder.NewNodeBuilder( logger, - met, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), + Metrics: metrics.NewNoopCollector(), + }, + network.PrivateNetwork, unittest.DefaultAddress, key, sporkID, + idProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, + &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), }). SetConnectionManager(connManager). SetResourceManager(NewResourceManager(t)). - SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). - OverrideDefaultInspectorSuite(rpcInspectorSuite) + SetStreamCreationRetryInterval(unicast.DefaultRetryDelay) for _, opt := range opts { opt(builder) diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index 3e2a22976dd..19171dc81ba 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -154,7 +154,7 @@ func (_m *NodeBuilder) SetGossipSubFactory(_a0 p2p.GossipSubFactoryFunc, _a1 p2p } // SetGossipSubRpcInspectorSuite provides a mock function with given fields: _a0 -func (_m *NodeBuilder) OverrideDefaultInspectorSuite(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { +func (_m *NodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { ret := _m.Called(_a0) var r0 p2p.NodeBuilder diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index e64cd69391f..136c1e34eab 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -23,6 +23,7 @@ import ( "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" @@ -35,8 +36,7 @@ type Builder struct { networkType network.NetworkingType sporkId flow.Identifier logger zerolog.Logger - metrics module.GossipSubMetrics - heroCacheMetricsFactory metrics.HeroCacheMetricsFactory + metricsCfg *p2pconfig.MetricsConfig h host.Host subscriptionFilter pubsub.SubscriptionFilter gossipSubFactory p2p.GossipSubFactoryFunc @@ -45,11 +45,12 @@ type Builder struct { gossipSubScoreTracerInterval time.Duration // the interval at which the gossipsub score tracer logs the peer scores. // gossipSubTracer is a callback interface that is called by the gossipsub implementation upon // certain events. Currently, we use it to log and observe the local mesh of the node. - gossipSubTracer p2p.PubSubTracer - scoreOptionConfig *scoring.ScoreOptionConfig - idProvider module.IdentityProvider - routingSystem routing.Routing - rpcInspectorSuite p2p.GossipSubInspectorSuite + gossipSubTracer p2p.PubSubTracer + scoreOptionConfig *scoring.ScoreOptionConfig + idProvider module.IdentityProvider + routingSystem routing.Routing + rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig + rpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } var _ p2p.GossipSubBuilder = (*Builder)(nil) @@ -151,21 +152,31 @@ func (g *Builder) SetAppSpecificScoreParams(f func(peer.ID) float64) { g.scoreOptionConfig.SetAppSpecificScoreFunction(f) } +func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) { + g.logger.Warn().Msg("overriding default rpc inspector suite factory") + g.rpcInspectorSuiteFactory = factory +} + func NewGossipSubBuilder( logger zerolog.Logger, - metrics module.GossipSubMetrics, + metricsCfg *p2pconfig.MetricsConfig, networkType network.NetworkingType, - sporkId flow.Identifier) *Builder { + sporkId flow.Identifier, + idProvider module.IdentityProvider, + rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, +) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() return &Builder{ - logger: lg, - metrics: metrics, - networkType: networkType, - gossipSubFactory: defaultGossipSubFactory(), - gossipSubConfigFunc: defaultGossipSubAdapterConfig(), - scoreOptionConfig: scoring.NewScoreOptionConfig(lg), - sporkId: sporkId, - rpcInspectorSuite: defaultInspectorSuite(), + logger: lg, + metricsCfg: metricsCfg, + sporkId: sporkId, + networkType: networkType, + idProvider: idProvider, + gossipSubFactory: defaultGossipSubFactory(), + gossipSubConfigFunc: defaultGossipSubAdapterConfig(), + scoreOptionConfig: scoring.NewScoreOptionConfig(lg), + rpcInspectorConfig: rpcInspectorConfig, + rpcInspectorSuiteFactory: defaultInspectorSuite(), } } @@ -181,16 +192,7 @@ func defaultGossipSubAdapterConfig() p2p.GossipSubAdapterConfigFunc { } } -type RpcInspectorSuiteFactoryFunc func( - zerolog.Logger, - flow.Identifier, - *netconf.GossipSubRPCInspectorsConfig, - module.GossipSubMetrics, - metrics.HeroCacheMetricsFactory, - network.NetworkingType, - module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) - -func defaultInspectorSuite() RpcInspectorSuiteFactoryFunc { +func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return func( logger zerolog.Logger, sporkId flow.Identifier, @@ -258,12 +260,20 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p gossipSubConfigs.WithSubscriptionFilter(g.subscriptionFilter) } - gossipSubConfigs.WithInspectorSuite(g.rpcInspectorSuite) + inspectorSuite, err := g.rpcInspectorSuiteFactory( + g.logger, + g.sporkId, + g.rpcInspectorConfig, + g.metricsCfg.Metrics, + g.metricsCfg.HeroCacheFactory, + g.networkType, + g.idProvider) + gossipSubConfigs.WithInspectorSuite(inspectorSuite) var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer if g.gossipSubPeerScoring { - g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(g.rpcInspectorSuite.AddInvCtrlMsgNotifConsumer) + g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(inspectorSuite.AddInvCtrlMsgNotifConsumer) scoreOpt = scoring.NewScoreOption(g.scoreOptionConfig) gossipSubConfigs.WithScoreOption(scoreOpt) @@ -271,7 +281,7 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p scoreTracer = tracer.NewGossipSubScoreTracer( g.logger, g.idProvider, - g.metrics, + g.metricsCfg.Metrics, g.gossipSubScoreTracerInterval) gossipSubConfigs.WithScoreTracer(scoreTracer) } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 4a7a75a9eb5..1549efa1e29 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,6 +27,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -51,8 +52,8 @@ type GossipSubAdapterConfigFunc func(*p2p.BasePubSubAdapterConfig) p2p.PubSubAda type LibP2PNodeBuilder struct { gossipSubBuilder p2p.GossipSubBuilder - sporkID flow.Identifier - addr string + sporkId flow.Identifier + address string networkKey fcrypto.PrivateKey logger zerolog.Logger metrics module.LibP2PMetrics @@ -72,26 +73,38 @@ type LibP2PNodeBuilder struct { disallowListCacheCfg *p2p.DisallowListCacheConfig } -func NewNodeBuilder(logger zerolog.Logger, - metrics module.LibP2PMetrics, - addr string, +func NewNodeBuilder( + logger zerolog.Logger, + metricsConfig *p2pconfig.MetricsConfig, + networkingType flownet.NetworkingType, + address string, networkKey fcrypto.PrivateKey, - sporkID flow.Identifier, + sporkId flow.Identifier, + idProvider module.IdentityProvider, rCfg *netconf.ResourceManagerConfig, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, - sporkID: sporkID, - addr: addr, + sporkId: sporkId, + address: address, networkKey: networkKey, createNode: DefaultCreateNodeFunc, - metrics: metrics, + metrics: metricsConfig.Metrics, resourceManagerCfg: rCfg, - gossipSubBuilder: gossipsubbuilder.NewGossipSubBuilder(logger, metrics), disallowListCacheCfg: disallowListCacheCfg, + gossipSubBuilder: gossipsubbuilder.NewGossipSubBuilder( + logger, + metricsConfig, + networkingType, + sporkId, + idProvider, + rpcInspectorCfg), } } +var _ p2p.NodeBuilder = &LibP2PNodeBuilder{} + // SetBasicResolver sets the DNS resolver for the node. func (builder *LibP2PNodeBuilder) SetBasicResolver(br madns.BasicResolver) p2p.NodeBuilder { builder.basicResolver = br @@ -188,8 +201,8 @@ func (builder *LibP2PNodeBuilder) SetGossipSubScoreTracerInterval(interval time. return builder } -func (builder *LibP2PNodeBuilder) OverrideDefaultInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) p2p.NodeBuilder { - builder.gossipSubBuilder.SetGossipSubRPCInspectorSuite(inspectorSuite) +func (builder *LibP2PNodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) p2p.NodeBuilder { + builder.gossipSubBuilder.OverrideDefaultRpcInspectorSuiteFactory(factory) return builder } @@ -274,7 +287,7 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { opts = append(opts, libp2p.ConnectionGater(builder.connGater)) } - h, err := DefaultLibP2PHost(builder.addr, builder.networkKey, opts...) + h, err := DefaultLibP2PHost(builder.address, builder.networkKey, opts...) if err != nil { return nil, err } @@ -312,7 +325,7 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { unicastManager := unicast.NewUnicastManager(builder.logger, stream.NewLibP2PStreamFactory(h), - builder.sporkID, + builder.sporkId, builder.createStreamRetryInterval, node, builder.metrics) @@ -428,8 +441,10 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, } // DefaultNodeBuilder returns a node builder. -func DefaultNodeBuilder(log zerolog.Logger, +func DefaultNodeBuilder( + logger zerolog.Logger, address string, + networkingType flownet.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, @@ -439,13 +454,13 @@ func DefaultNodeBuilder(log zerolog.Logger, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, gossipCfg *netconf.GossipSubConfig, - rpcInspectorSuite p2p.GossipSubInspectorSuite, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, rCfg *netconf.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { - connManager, err := connection.NewConnManager(log, metricsCfg.Metrics, connMgrConfig) + connManager, err := connection.NewConnManager(logger, metricsCfg.Metrics, connMgrConfig) if err != nil { return nil, fmt.Errorf("could not create connection manager: %w", err) } @@ -454,30 +469,39 @@ func DefaultNodeBuilder(log zerolog.Logger, peerFilter := notEjectedPeerFilter(idProvider) peerFilters := []p2p.PeerFilter{peerFilter} - connGater := connection.NewConnGater(log, + connGater := connection.NewConnGater(logger, idProvider, connection.WithOnInterceptPeerDialFilters(append(peerFilters, connGaterCfg.InterceptPeerDialFilters...)), connection.WithOnInterceptSecuredFilters(append(peerFilters, connGaterCfg.InterceptSecuredFilters...))) - builder := NewNodeBuilder(log, metricsCfg.Metrics, address, flowKey, sporkId, rCfg, disallowListCacheCfg). + builder := NewNodeBuilder( + logger, + metricsCfg, + networkingType, + address, + flowKey, + sporkId, + idProvider, + rCfg, + rpcInspectorCfg, + disallowListCacheCfg). SetBasicResolver(resolver). SetConnectionManager(connManager). SetConnectionGater(connGater). SetRoutingSystem(func(ctx context.Context, host host.Host) (routing.Routing, error) { - return dht.NewDHT(ctx, host, protocols.FlowDHTProtocolID(sporkId), log, metricsCfg.Metrics, dht.AsServer()) + return dht.NewDHT(ctx, host, protocols.FlowDHTProtocolID(sporkId), logger, metricsCfg.Metrics, dht.AsServer()) }). SetPeerManagerOptions(peerManagerCfg.ConnectionPruning, peerManagerCfg.UpdateInterval). SetStreamCreationRetryInterval(uniCfg.StreamRetryInterval). SetCreateNode(DefaultCreateNodeFunc). - SetRateLimiterDistributor(uniCfg.RateLimiterDistributor). - OverrideDefaultInspectorSuite(rpcInspectorSuite) + SetRateLimiterDistributor(uniCfg.RateLimiterDistributor) if gossipCfg.PeerScoring { // currently, we only enable peer scoring with default parameters. So, we set the score parameters to nil. builder.EnableGossipSubPeerScoring(idProvider, nil) } - meshTracer := tracer.NewGossipSubMeshTracer(log, metricsCfg.Metrics, idProvider, gossipCfg.LocalMeshLogInterval) + meshTracer := tracer.NewGossipSubMeshTracer(logger, metricsCfg.Metrics, idProvider, gossipCfg.LocalMeshLogInterval) builder.SetGossipSubTracer(meshTracer) builder.SetGossipSubScoreTracerInterval(gossipCfg.ScoreTracerInterval) diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index de5baf0420a..49327085b45 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -95,7 +95,7 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { idProvider, p2ptest.WithRole(flow.RoleConsensus), p2ptest.WithPeerScoringEnabled(idProvider), - p2ptest.WithGossipSubRpcInspectorSuite(inspectorSuite1)) + p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(inspectorSuite1)) node2, id2 := p2ptest.NodeFixture( t, From f63f5cbd77d718bdc0b3bb48638bc4d33a60edb0 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Wed, 21 Jun 2023 11:47:30 -0700 Subject: [PATCH 07/74] refactors libp2p builder and gossipsub builder accross the code --- .../node_builder/access_node_builder.go | 22 +-- cmd/observer/node_builder/observer_builder.go | 19 +- cmd/scaffold.go | 22 +-- follower/follower_builder.go | 19 +- insecure/corruptlibp2p/libp2p_node_factory.go | 12 +- network/internal/p2pfixtures/fixtures.go | 16 +- network/internal/testutils/testUtil.go | 24 +-- network/p2p/builder.go | 36 +++- network/p2p/mock/node_builder.go | 2 +- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 70 ++++---- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 70 +++++--- network/p2p/scoring/scoring_test.go | 2 +- network/p2p/test/fixtures.go | 168 +++++++++++++----- 13 files changed, 296 insertions(+), 186 deletions(-) diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 65afd594932..84aff969161 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -72,7 +72,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -1199,25 +1198,19 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - // setup RPC inspectors - rpcInspectorBuilder := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network) - rpcInspectorSuite, err := rpcInspectorBuilder. - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for access node: %w", err) - } - libp2pNode, err := p2pbuilder.NewNodeBuilder( builder.Logger, - networkMetrics, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: networkMetrics, + }, + network.PublicNetwork, bindAddress, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -1244,7 +1237,6 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index ea337600a11..ae50cbc938d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -710,23 +710,19 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network). - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("could not initialize gossipsub inspectors for observer node: %w", err) - } - node, err := p2pbuilder.NewNodeBuilder( builder.Logger, - builder.Metrics.Network, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: builder.Metrics.Network, + }, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -747,7 +743,6 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). Build() if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 40d4181e8ad..2de8d6c4da1 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -54,7 +54,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/ping" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/unicast/protocols" @@ -344,34 +343,25 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { myAddr = fnb.BaseConfig.BindAddr } - metricsCfg := &p2pconfig.MetricsConfig{ - Metrics: fnb.Metrics.Network, - HeroCacheFactory: fnb.HeroCacheMetricsFactory(), - } - - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(fnb.Logger, fnb.SporkID, &fnb.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, fnb.IdentityProvider, fnb.Metrics.Network). - SetNetworkType(network.PrivateNetwork). - SetMetrics(metricsCfg). - Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for default libp2p node: %w", err) - } - fnb.GossipSubRpcInspectorSuite = rpcInspectorSuite builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, + network.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, - metricsCfg, + &p2pconfig.MetricsConfig{ + Metrics: fnb.Metrics.Network, + HeroCacheFactory: fnb.HeroCacheMetricsFactory(), + }, fnb.Resolver, fnb.BaseConfig.NodeRole, connGaterCfg, peerManagerCfg, &fnb.FlowConfig.NetworkConfig.GossipSubConfig, - fnb.GossipSubRpcInspectorSuite, + &fnb.FlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &fnb.FlowConfig.NetworkConfig.ResourceManagerConfig, uniCfg, &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, diff --git a/follower/follower_builder.go b/follower/follower_builder.go index cf5383efa6e..a801c99d2ee 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -611,23 +611,20 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.Metrics.Network, builder.IdentityProvider, builder.FlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(builder.Logger, builder.SporkID, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, builder.IdentityProvider, builder.Metrics.Network). - SetNetworkType(network.PublicNetwork). - SetMetrics(&p2pconfig.MetricsConfig{ - HeroCacheFactory: builder.HeroCacheMetricsFactory(), - Metrics: builder.Metrics.Network, - }).Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for public libp2p node: %w", err) - } node, err := p2pbuilder.NewNodeBuilder( builder.Logger, - builder.Metrics.Network, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: builder.HeroCacheMetricsFactory(), + Metrics: builder.Metrics.Network, + }, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, + builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, + &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -648,7 +645,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite). + OverrideDefaultRpcInspectorSuiteFactory(rpcInspectorSuite). Build() if err != nil { diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 1cc64f3a46b..8b79efeb667 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" ) // InitCorruptLibp2pNode initializes and returns a corrupt libp2p node that should only be used for BFT testing in @@ -74,17 +73,10 @@ func InitCorruptLibp2pNode( Metrics: metricsCfg, } - rpcInspectorSuite, err := inspector.NewGossipSubInspectorBuilder(log, sporkId, &netConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, idProvider, metricsCfg). - SetNetworkType(network.PrivateNetwork). - SetMetrics(metCfg). - Build() - if err != nil { - return nil, fmt.Errorf("failed to create gossipsub rpc inspectors for default libp2p node: %w", err) - } - builder, err := p2pbuilder.DefaultNodeBuilder( log, address, + network.PrivateNetwork, flowKey, sporkId, idProvider, @@ -94,7 +86,7 @@ func InitCorruptLibp2pNode( connGaterCfg, peerManagerCfg, &netConfig.GossipSubConfig, - rpcInspectorSuite, + &netConfig.GossipSubRPCInspectorsConfig, &netConfig.ResourceManagerConfig, uniCfg, &netConfig.ConnectionManagerConfig, diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index 2bb756a909e..83b34e8bc6a 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,6 +26,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -34,6 +35,7 @@ import ( p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" "github.com/onflow/flow-go/network/p2p/p2pbuilder" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/unicast" @@ -97,6 +99,7 @@ func WithSubscriptionFilter(filter pubsub.SubscriptionFilter) nodeOpt { } } +// TODO: this should be replaced by node fixture: https://github.com/onflow/flow-go/blob/master/network/p2p/test/fixtures.go func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identifier, logger zerolog.Logger, nodeIds flow.IdentityList, opts ...nodeOpt) p2p.LibP2PNode { idProvider := id.NewFixedIdentityProvider(nodeIds) defaultFlowConfig, err := config.DefaultConfig() @@ -107,17 +110,19 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif idProvider, defaultFlowConfig.NetworkConfig.GossipSubConfig.LocalMeshLogInterval) - met := metrics.NewNoopCollector() - rpcInspectorSuite, err := inspectorbuilder.NewGossipSubInspectorBuilder(logger, sporkID, &defaultFlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, idProvider, met).Build() - require.NoError(t, err) - builder := p2pbuilder.NewNodeBuilder( logger, - met, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), + Metrics: metrics.NewNoopCollector(), + }, + flownet.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, + idProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, + &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), @@ -129,7 +134,6 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultInspectorSuite(rpcInspectorSuite) for _, opt := range opts { opt(builder) diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 5528de3674c..14fe9feb175 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -42,7 +42,7 @@ import ( p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" - inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/translator" "github.com/onflow/flow-go/network/p2p/unicast" @@ -489,36 +489,36 @@ func withUnicastManagerOpts(delay time.Duration) nodeBuilderOption { } } +// TODO: this should be replaced by node fixture: https://github.com/onflow/flow-go/blob/master/network/p2p/test/fixtures.go // generateLibP2PNode generates a `LibP2PNode` on localhost using a port assigned by the OS -func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateKey, provider *UpdatableIDProvider, opts ...nodeBuilderOption) (p2p.LibP2PNode, observable.Observable) { - - noopMetrics := metrics.NewNoopCollector() +func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateKey, idProvider module.IdentityProvider, opts ...nodeBuilderOption) (p2p.LibP2PNode, observable.Observable) { defaultFlowConfig, err := config.DefaultConfig() require.NoError(t, err) // Inject some logic to be able to observe connections of this node - connManager, err := NewTagWatchingConnManager(logger, noopMetrics, &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) - require.NoError(t, err) - met := metrics.NewNoopCollector() - - rpcInspectorSuite, err := inspectorbuilder.NewGossipSubInspectorBuilder(logger, sporkID, &defaultFlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, provider, met).Build() + connManager, err := NewTagWatchingConnManager(logger, metrics.NewNoopCollector(), &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) require.NoError(t, err) builder := p2pbuilder.NewNodeBuilder( logger, - met, + &p2pconfig.MetricsConfig{ + HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), + Metrics: metrics.NewNoopCollector(), + }, + network.PrivateNetwork, unittest.DefaultAddress, key, sporkID, + idProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, + &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), }). SetConnectionManager(connManager). SetResourceManager(NewResourceManager(t)). - SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). - OverrideDefaultInspectorSuite(rpcInspectorSuite) + SetStreamCreationRetryInterval(unicast.DefaultRetryDelay) for _, opt := range opts { opt(builder) diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 0dd8f3646a0..c16ad9a3296 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -13,8 +13,12 @@ import ( madns "github.com/multiformats/go-multiaddr-dns" "github.com/rs/zerolog" + netconf "github.com/onflow/flow-go/config/network" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" + "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" ) @@ -61,6 +65,13 @@ type GossipSubBuilder interface { // If the routing system has already been set, a fatal error is logged. SetRoutingSystem(routing.Routing) + // OverrideDefaultRpcInspectorSuiteFactory overrides the default RPC inspector suite factory of the builder. + // A default RPC inspector suite factory is provided by the node. This function overrides the default factory. + // The purpose of override is to allow the node to provide a custom RPC inspector suite factory for sake of testing + // or experimentation. + // It is NOT recommended to override the default RPC inspector suite factory in production unless you know what you are doing. + OverrideDefaultRpcInspectorSuiteFactory(GossipSubRpcInspectorSuiteFactoryFunc) + // Build creates a new GossipSub pubsub system. // It returns the newly created GossipSub pubsub system and any errors encountered during its creation. // @@ -85,6 +96,29 @@ type PeerScoringBuilder interface { SetAppSpecificScoreParams(func(peer.ID) float64) } +// GossipSubRpcInspectorSuiteFactoryFunc is a function that creates a new RPC inspector suite. It is used to create +// RPC inspectors for the gossipsub protocol. The RPC inspectors are used to inspect and validate +// incoming RPC messages before they are processed by the gossipsub protocol. +// Args: +// - logger: logger to use +// - sporkID: spork ID of the node +// - cfg: configuration for the RPC inspectors +// - metrics: metrics to use for the RPC inspectors +// - heroCacheMetricsFactory: metrics factory for the hero cache +// - networkingType: networking type of the node, i.e., public or private +// - identityProvider: identity provider of the node +// Returns: +// - p2p.GossipSubInspectorSuite: new RPC inspector suite +// - error: error if any, any returned error is irrecoverable. +type GossipSubRpcInspectorSuiteFactoryFunc func( + zerolog.Logger, + flow.Identifier, + *netconf.GossipSubRPCInspectorsConfig, + module.GossipSubMetrics, + metrics.HeroCacheMetricsFactory, + flownet.NetworkingType, + module.IdentityProvider) (GossipSubInspectorSuite, error) + // NodeBuilder is a builder pattern for creating a libp2p Node instance. type NodeBuilder interface { SetBasicResolver(madns.BasicResolver) NodeBuilder @@ -106,7 +140,7 @@ type NodeBuilder interface { SetRateLimiterDistributor(UnicastRateLimiterDistributor) NodeBuilder SetGossipSubTracer(PubSubTracer) NodeBuilder SetGossipSubScoreTracerInterval(time.Duration) NodeBuilder - OverrideDefaultInspectorSuite(GossipSubInspectorSuite) NodeBuilder + OverrideDefaultRpcInspectorSuiteFactory(GossipSubRpcInspectorSuiteFactoryFunc) NodeBuilder Build() (LibP2PNode, error) } diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index 3e2a22976dd..19171dc81ba 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -154,7 +154,7 @@ func (_m *NodeBuilder) SetGossipSubFactory(_a0 p2p.GossipSubFactoryFunc, _a1 p2p } // SetGossipSubRpcInspectorSuite provides a mock function with given fields: _a0 -func (_m *NodeBuilder) OverrideDefaultInspectorSuite(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { +func (_m *NodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { ret := _m.Called(_a0) var r0 p2p.NodeBuilder diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index e64cd69391f..136c1e34eab 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -23,6 +23,7 @@ import ( "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" @@ -35,8 +36,7 @@ type Builder struct { networkType network.NetworkingType sporkId flow.Identifier logger zerolog.Logger - metrics module.GossipSubMetrics - heroCacheMetricsFactory metrics.HeroCacheMetricsFactory + metricsCfg *p2pconfig.MetricsConfig h host.Host subscriptionFilter pubsub.SubscriptionFilter gossipSubFactory p2p.GossipSubFactoryFunc @@ -45,11 +45,12 @@ type Builder struct { gossipSubScoreTracerInterval time.Duration // the interval at which the gossipsub score tracer logs the peer scores. // gossipSubTracer is a callback interface that is called by the gossipsub implementation upon // certain events. Currently, we use it to log and observe the local mesh of the node. - gossipSubTracer p2p.PubSubTracer - scoreOptionConfig *scoring.ScoreOptionConfig - idProvider module.IdentityProvider - routingSystem routing.Routing - rpcInspectorSuite p2p.GossipSubInspectorSuite + gossipSubTracer p2p.PubSubTracer + scoreOptionConfig *scoring.ScoreOptionConfig + idProvider module.IdentityProvider + routingSystem routing.Routing + rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig + rpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } var _ p2p.GossipSubBuilder = (*Builder)(nil) @@ -151,21 +152,31 @@ func (g *Builder) SetAppSpecificScoreParams(f func(peer.ID) float64) { g.scoreOptionConfig.SetAppSpecificScoreFunction(f) } +func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) { + g.logger.Warn().Msg("overriding default rpc inspector suite factory") + g.rpcInspectorSuiteFactory = factory +} + func NewGossipSubBuilder( logger zerolog.Logger, - metrics module.GossipSubMetrics, + metricsCfg *p2pconfig.MetricsConfig, networkType network.NetworkingType, - sporkId flow.Identifier) *Builder { + sporkId flow.Identifier, + idProvider module.IdentityProvider, + rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, +) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() return &Builder{ - logger: lg, - metrics: metrics, - networkType: networkType, - gossipSubFactory: defaultGossipSubFactory(), - gossipSubConfigFunc: defaultGossipSubAdapterConfig(), - scoreOptionConfig: scoring.NewScoreOptionConfig(lg), - sporkId: sporkId, - rpcInspectorSuite: defaultInspectorSuite(), + logger: lg, + metricsCfg: metricsCfg, + sporkId: sporkId, + networkType: networkType, + idProvider: idProvider, + gossipSubFactory: defaultGossipSubFactory(), + gossipSubConfigFunc: defaultGossipSubAdapterConfig(), + scoreOptionConfig: scoring.NewScoreOptionConfig(lg), + rpcInspectorConfig: rpcInspectorConfig, + rpcInspectorSuiteFactory: defaultInspectorSuite(), } } @@ -181,16 +192,7 @@ func defaultGossipSubAdapterConfig() p2p.GossipSubAdapterConfigFunc { } } -type RpcInspectorSuiteFactoryFunc func( - zerolog.Logger, - flow.Identifier, - *netconf.GossipSubRPCInspectorsConfig, - module.GossipSubMetrics, - metrics.HeroCacheMetricsFactory, - network.NetworkingType, - module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) - -func defaultInspectorSuite() RpcInspectorSuiteFactoryFunc { +func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return func( logger zerolog.Logger, sporkId flow.Identifier, @@ -258,12 +260,20 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p gossipSubConfigs.WithSubscriptionFilter(g.subscriptionFilter) } - gossipSubConfigs.WithInspectorSuite(g.rpcInspectorSuite) + inspectorSuite, err := g.rpcInspectorSuiteFactory( + g.logger, + g.sporkId, + g.rpcInspectorConfig, + g.metricsCfg.Metrics, + g.metricsCfg.HeroCacheFactory, + g.networkType, + g.idProvider) + gossipSubConfigs.WithInspectorSuite(inspectorSuite) var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer if g.gossipSubPeerScoring { - g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(g.rpcInspectorSuite.AddInvCtrlMsgNotifConsumer) + g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(inspectorSuite.AddInvCtrlMsgNotifConsumer) scoreOpt = scoring.NewScoreOption(g.scoreOptionConfig) gossipSubConfigs.WithScoreOption(scoreOpt) @@ -271,7 +281,7 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p scoreTracer = tracer.NewGossipSubScoreTracer( g.logger, g.idProvider, - g.metrics, + g.metricsCfg.Metrics, g.gossipSubScoreTracerInterval) gossipSubConfigs.WithScoreTracer(scoreTracer) } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 4a7a75a9eb5..1549efa1e29 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,6 +27,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -51,8 +52,8 @@ type GossipSubAdapterConfigFunc func(*p2p.BasePubSubAdapterConfig) p2p.PubSubAda type LibP2PNodeBuilder struct { gossipSubBuilder p2p.GossipSubBuilder - sporkID flow.Identifier - addr string + sporkId flow.Identifier + address string networkKey fcrypto.PrivateKey logger zerolog.Logger metrics module.LibP2PMetrics @@ -72,26 +73,38 @@ type LibP2PNodeBuilder struct { disallowListCacheCfg *p2p.DisallowListCacheConfig } -func NewNodeBuilder(logger zerolog.Logger, - metrics module.LibP2PMetrics, - addr string, +func NewNodeBuilder( + logger zerolog.Logger, + metricsConfig *p2pconfig.MetricsConfig, + networkingType flownet.NetworkingType, + address string, networkKey fcrypto.PrivateKey, - sporkID flow.Identifier, + sporkId flow.Identifier, + idProvider module.IdentityProvider, rCfg *netconf.ResourceManagerConfig, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, - sporkID: sporkID, - addr: addr, + sporkId: sporkId, + address: address, networkKey: networkKey, createNode: DefaultCreateNodeFunc, - metrics: metrics, + metrics: metricsConfig.Metrics, resourceManagerCfg: rCfg, - gossipSubBuilder: gossipsubbuilder.NewGossipSubBuilder(logger, metrics), disallowListCacheCfg: disallowListCacheCfg, + gossipSubBuilder: gossipsubbuilder.NewGossipSubBuilder( + logger, + metricsConfig, + networkingType, + sporkId, + idProvider, + rpcInspectorCfg), } } +var _ p2p.NodeBuilder = &LibP2PNodeBuilder{} + // SetBasicResolver sets the DNS resolver for the node. func (builder *LibP2PNodeBuilder) SetBasicResolver(br madns.BasicResolver) p2p.NodeBuilder { builder.basicResolver = br @@ -188,8 +201,8 @@ func (builder *LibP2PNodeBuilder) SetGossipSubScoreTracerInterval(interval time. return builder } -func (builder *LibP2PNodeBuilder) OverrideDefaultInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) p2p.NodeBuilder { - builder.gossipSubBuilder.SetGossipSubRPCInspectorSuite(inspectorSuite) +func (builder *LibP2PNodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) p2p.NodeBuilder { + builder.gossipSubBuilder.OverrideDefaultRpcInspectorSuiteFactory(factory) return builder } @@ -274,7 +287,7 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { opts = append(opts, libp2p.ConnectionGater(builder.connGater)) } - h, err := DefaultLibP2PHost(builder.addr, builder.networkKey, opts...) + h, err := DefaultLibP2PHost(builder.address, builder.networkKey, opts...) if err != nil { return nil, err } @@ -312,7 +325,7 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { unicastManager := unicast.NewUnicastManager(builder.logger, stream.NewLibP2PStreamFactory(h), - builder.sporkID, + builder.sporkId, builder.createStreamRetryInterval, node, builder.metrics) @@ -428,8 +441,10 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, } // DefaultNodeBuilder returns a node builder. -func DefaultNodeBuilder(log zerolog.Logger, +func DefaultNodeBuilder( + logger zerolog.Logger, address string, + networkingType flownet.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, @@ -439,13 +454,13 @@ func DefaultNodeBuilder(log zerolog.Logger, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, gossipCfg *netconf.GossipSubConfig, - rpcInspectorSuite p2p.GossipSubInspectorSuite, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, rCfg *netconf.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { - connManager, err := connection.NewConnManager(log, metricsCfg.Metrics, connMgrConfig) + connManager, err := connection.NewConnManager(logger, metricsCfg.Metrics, connMgrConfig) if err != nil { return nil, fmt.Errorf("could not create connection manager: %w", err) } @@ -454,30 +469,39 @@ func DefaultNodeBuilder(log zerolog.Logger, peerFilter := notEjectedPeerFilter(idProvider) peerFilters := []p2p.PeerFilter{peerFilter} - connGater := connection.NewConnGater(log, + connGater := connection.NewConnGater(logger, idProvider, connection.WithOnInterceptPeerDialFilters(append(peerFilters, connGaterCfg.InterceptPeerDialFilters...)), connection.WithOnInterceptSecuredFilters(append(peerFilters, connGaterCfg.InterceptSecuredFilters...))) - builder := NewNodeBuilder(log, metricsCfg.Metrics, address, flowKey, sporkId, rCfg, disallowListCacheCfg). + builder := NewNodeBuilder( + logger, + metricsCfg, + networkingType, + address, + flowKey, + sporkId, + idProvider, + rCfg, + rpcInspectorCfg, + disallowListCacheCfg). SetBasicResolver(resolver). SetConnectionManager(connManager). SetConnectionGater(connGater). SetRoutingSystem(func(ctx context.Context, host host.Host) (routing.Routing, error) { - return dht.NewDHT(ctx, host, protocols.FlowDHTProtocolID(sporkId), log, metricsCfg.Metrics, dht.AsServer()) + return dht.NewDHT(ctx, host, protocols.FlowDHTProtocolID(sporkId), logger, metricsCfg.Metrics, dht.AsServer()) }). SetPeerManagerOptions(peerManagerCfg.ConnectionPruning, peerManagerCfg.UpdateInterval). SetStreamCreationRetryInterval(uniCfg.StreamRetryInterval). SetCreateNode(DefaultCreateNodeFunc). - SetRateLimiterDistributor(uniCfg.RateLimiterDistributor). - OverrideDefaultInspectorSuite(rpcInspectorSuite) + SetRateLimiterDistributor(uniCfg.RateLimiterDistributor) if gossipCfg.PeerScoring { // currently, we only enable peer scoring with default parameters. So, we set the score parameters to nil. builder.EnableGossipSubPeerScoring(idProvider, nil) } - meshTracer := tracer.NewGossipSubMeshTracer(log, metricsCfg.Metrics, idProvider, gossipCfg.LocalMeshLogInterval) + meshTracer := tracer.NewGossipSubMeshTracer(logger, metricsCfg.Metrics, idProvider, gossipCfg.LocalMeshLogInterval) builder.SetGossipSubTracer(meshTracer) builder.SetGossipSubScoreTracerInterval(gossipCfg.ScoreTracerInterval) diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index de5baf0420a..49327085b45 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -95,7 +95,7 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { idProvider, p2ptest.WithRole(flow.RoleConsensus), p2ptest.WithPeerScoringEnabled(idProvider), - p2ptest.WithGossipSubRpcInspectorSuite(inspectorSuite1)) + p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(inspectorSuite1)) node2, id2 := p2ptest.NodeFixture( t, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 668b62f5ce9..c2b097ee9d4 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -19,11 +19,13 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" + netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" @@ -31,7 +33,7 @@ import ( "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" - inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast" "github.com/onflow/flow-go/network/p2p/unicast/protocols" "github.com/onflow/flow-go/network/p2p/utils" @@ -61,23 +63,22 @@ func NodeFixture( require.NoError(t, err) logger := unittest.Logger().Level(zerolog.WarnLevel) - - rpcInspectorSuite, err := inspectorbuilder.NewGossipSubInspectorBuilder(logger, sporkID, &defaultFlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, idProvider, metrics.NewNoopCollector()). - Build() - require.NoError(t, err) - parameters := &NodeFixtureParameters{ - HandlerFunc: func(network.Stream) {}, - Unicasts: nil, - Key: NetworkingKeyFixtures(t), - Address: unittest.DefaultAddress, - Logger: logger, - Role: flow.RoleCollection, - CreateStreamRetryDelay: unicast.DefaultRetryDelay, - Metrics: metrics.NewNoopCollector(), + NetworkingType: flownet.PrivateNetwork, + HandlerFunc: func(network.Stream) {}, + Unicasts: nil, + Key: NetworkingKeyFixtures(t), + Address: unittest.DefaultAddress, + Logger: logger, + Role: flow.RoleCollection, + CreateStreamRetryDelay: unicast.DefaultRetryDelay, + MetricsCfg: &p2pconfig.MetricsConfig{ + HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), + Metrics: metrics.NewNoopCollector(), + }, ResourceManager: testutils.NewResourceManager(t), GossipSubPeerScoreTracerInterval: 0, // disabled by default - GossipSubRPCInspector: rpcInspectorSuite, + GossipSubRPCInspectorCfg: GossipSubRpcValidationInspectorConfigFixture(t), } for _, opt := range opts { @@ -91,16 +92,19 @@ func NodeFixture( logger = parameters.Logger.With().Hex("node_id", logging.ID(identity.NodeID)).Logger() - connManager, err := connection.NewConnManager(logger, parameters.Metrics, &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) + connManager, err := connection.NewConnManager(logger, parameters.MetricsCfg.Metrics, &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) require.NoError(t, err) builder := p2pbuilder.NewNodeBuilder( logger, - parameters.Metrics, + parameters.MetricsCfg, + parameters.NetworkingType, parameters.Address, parameters.Key, sporkID, + parameters.IdProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, + parameters.GossipSubRPCInspectorCfg, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), @@ -110,14 +114,17 @@ func NodeFixture( return p2pdht.NewDHT(c, h, protocol.ID(protocols.FlowDHTProtocolIDPrefix+sporkID.String()+"/"+dhtPrefix), logger, - parameters.Metrics, + parameters.MetricsCfg.Metrics, parameters.DhtOptions..., ) }). SetCreateNode(p2pbuilder.DefaultCreateNodeFunc). SetStreamCreationRetryInterval(parameters.CreateStreamRetryDelay). - SetResourceManager(parameters.ResourceManager). - OverrideDefaultInspectorSuite(parameters.GossipSubRPCInspector) + SetResourceManager(parameters.ResourceManager) + + if parameters.GossipSubRpcInspectorSuiteFactory != nil { + builder.OverrideDefaultRpcInspectorSuiteFactory(parameters.GossipSubRpcInspectorSuiteFactory) + } if parameters.ResourceManager != nil { builder.SetResourceManager(parameters.ResourceManager) @@ -171,34 +178,42 @@ func NodeFixture( type NodeFixtureParameterOption func(*NodeFixtureParameters) type NodeFixtureParameters struct { - HandlerFunc network.StreamHandler - Unicasts []protocols.ProtocolName - Key crypto.PrivateKey - Address string - DhtOptions []dht.Option - Role flow.Role - Logger zerolog.Logger - PeerScoringEnabled bool - IdProvider module.IdentityProvider - PeerScoreConfig *p2p.PeerScoringConfig - ConnectionPruning bool // peer manager parameter - UpdateInterval time.Duration // peer manager parameter - PeerProvider p2p.PeersProvider // peer manager parameter - ConnGater p2p.ConnectionGater - ConnManager connmgr.ConnManager - GossipSubFactory p2p.GossipSubFactoryFunc - GossipSubConfig p2p.GossipSubAdapterConfigFunc - Metrics module.LibP2PMetrics - ResourceManager network.ResourceManager - PubSubTracer p2p.PubSubTracer - GossipSubPeerScoreTracerInterval time.Duration // intervals at which the peer score is updated and logged. - CreateStreamRetryDelay time.Duration - GossipSubRPCInspector p2p.GossipSubInspectorSuite -} - -func WithGossipSubRpcInspectorSuite(inspectorSuite p2p.GossipSubInspectorSuite) NodeFixtureParameterOption { + HandlerFunc network.StreamHandler + NetworkingType flownet.NetworkingType + Unicasts []protocols.ProtocolName + Key crypto.PrivateKey + Address string + DhtOptions []dht.Option + Role flow.Role + Logger zerolog.Logger + PeerScoringEnabled bool + IdProvider module.IdentityProvider + PeerScoreConfig *p2p.PeerScoringConfig + ConnectionPruning bool // peer manager parameter + UpdateInterval time.Duration // peer manager parameter + PeerProvider p2p.PeersProvider // peer manager parameter + ConnGater p2p.ConnectionGater + ConnManager connmgr.ConnManager + GossipSubFactory p2p.GossipSubFactoryFunc + GossipSubConfig p2p.GossipSubAdapterConfigFunc + MetricsCfg *p2pconfig.MetricsConfig + ResourceManager network.ResourceManager + PubSubTracer p2p.PubSubTracer + GossipSubPeerScoreTracerInterval time.Duration // intervals at which the peer score is updated and logged. + CreateStreamRetryDelay time.Duration + GossipSubRPCInspectorCfg *netconf.GossipSubRPCInspectorsConfig + GossipSubRpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc +} + +func OverrideGossipSubRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) NodeFixtureParameterOption { return func(p *NodeFixtureParameters) { - p.GossipSubRPCInspector = inspectorSuite + p.GossipSubRpcInspectorSuiteFactory = factory + } +} + +func OverrideGossipSubRpcInspectorConfig(cfg *netconf.GossipSubRPCInspectorsConfig) NodeFixtureParameterOption { + return func(p *NodeFixtureParameters) { + p.GossipSubRPCInspectorCfg = cfg } } @@ -291,7 +306,7 @@ func WithLogger(logger zerolog.Logger) NodeFixtureParameterOption { func WithMetricsCollector(metrics module.NetworkMetrics) NodeFixtureParameterOption { return func(p *NodeFixtureParameters) { - p.Metrics = metrics + p.MetricsCfg.Metrics = metrics } } @@ -589,3 +604,60 @@ func PeerIdSliceFixture(t *testing.T, n int) peer.IDSlice { } return ids } + +// GossipSubRpcValidationInspectorConfigFixture returns a GossipSubRPCValidationInspectorConfigs instance for testing. +// Args: +// - t: *testing.T instance - to indicate that this is a test fixture. +// Returns: +// - *netconf.GossipSubRPCValidationInspectorConfigs: GossipSubRPCValidationInspectorConfigs instance. +// Note: the parameters in this fixture are INTENTIONALLY independent of the default values in the config file. +// This is to allow test parameters to be changed without affecting the default values in the config file. +func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *netconf.GossipSubRPCInspectorsConfig { + return &netconf.GossipSubRPCInspectorsConfig{ + GossipSubRPCValidationInspectorConfigs: netconf.GossipSubRPCValidationInspectorConfigs{ + ClusterPrefixedMessageConfig: netconf.ClusterPrefixedMessageConfig{ + ClusterPrefixHardThreshold: 100, + ClusterPrefixedControlMsgsReceivedCacheSize: 100, + ClusterPrefixedControlMsgsReceivedCacheDecay: .99, + }, + NumberOfWorkers: 5, + CacheSize: 10_000, + GraftLimits: struct { + HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-graft-hard-threshold"` + SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-graft-safety-threshold"` + RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-graft-rate-limit"` + }{ + HardThreshold: 30, + SafetyThreshold: 15, + RateLimit: 30, + }, + PruneLimits: struct { + HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-prune-hard-threshold"` + SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-prune-safety-threshold"` + RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-prune-rate-limit"` + }{ + HardThreshold: 30, + SafetyThreshold: 15, + RateLimit: 30, + }, + IHaveLimits: struct { + HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-ihave-hard-threshold"` + SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-ihave-safety-threshold"` + RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-ihave-rate-limit"` + }{ + HardThreshold: 100, + SafetyThreshold: 50, + RateLimit: 0, + }, + IHaveSyncInspectSampleSizePercentage: .25, + IHaveAsyncInspectSampleSizePercentage: .10, + IHaveInspectionMaxSampleSize: 100, + }, + GossipSubRPCMetricsInspectorConfigs: netconf.GossipSubRPCMetricsInspectorConfigs{ + NumberOfWorkers: 1, + CacheSize: 100, + }, + GossipSubRPCInspectorNotificationCacheSize: 10_000, + } + +} From 1b485691bf7dbbf8b8a48e99be7e0c288f0ed7ea Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 22 Jun 2023 13:08:22 +0300 Subject: [PATCH 08/74] changed rest metrics handler logic. --- engine/access/rest/middleware/metrics.go | 12 ++++++++---- module/metrics.go | 2 +- module/metrics/rest_api.go | 6 +++--- module/mock/access_metrics.go | 6 +++--- module/mock/rest_metrics.go | 6 +++--- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/engine/access/rest/middleware/metrics.go b/engine/access/rest/middleware/metrics.go index 4148e8ab18d..b616858b735 100644 --- a/engine/access/rest/middleware/metrics.go +++ b/engine/access/rest/middleware/metrics.go @@ -1,6 +1,7 @@ package middleware import ( + "github.com/onflow/flow-go/engine/access/rest" "net/http" "github.com/slok/go-http-metrics/middleware" @@ -12,13 +13,16 @@ import ( ) func MetricsMiddleware(restCollector module.RestMetrics) mux.MiddlewareFunc { - cfg := middleware.Config{Recorder: restCollector} - serviceID := cfg.Service - metricsMiddleware := middleware.New(cfg) + metricsMiddleware := middleware.New(middleware.Config{Recorder: restCollector}) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + routeName, err := rest.URLToRoute(req.URL.Path) + if err != nil { + return + } + // This is a custom metric being called on every http request - restCollector.AddTotalRequests(req.Context(), serviceID, req.Method) + restCollector.AddTotalRequests(req.Context(), req.Method, routeName) // Modify the writer respWriter := &responseWriter{w, http.StatusOK} diff --git a/module/metrics.go b/module/metrics.go index c77f068d0a5..e6ea28587f0 100644 --- a/module/metrics.go +++ b/module/metrics.go @@ -605,7 +605,7 @@ type RestMetrics interface { // Example recorder taken from: // https://github.com/slok/go-http-metrics/blob/master/metrics/prometheus/prometheus.go httpmetrics.Recorder - AddTotalRequests(ctx context.Context, serviceID string, method string) + AddTotalRequests(ctx context.Context, method string, routeName string) } type GRPCConnectionPoolMetrics interface { diff --git a/module/metrics/rest_api.go b/module/metrics/rest_api.go index ab277b77694..0ab08d0a3ca 100644 --- a/module/metrics/rest_api.go +++ b/module/metrics/rest_api.go @@ -81,7 +81,7 @@ func NewRestCollector(cfg metricsProm.Config) module.RestMetrics { Subsystem: "http", Name: "requests_total", Help: "The number of requests handled over time.", - }, []string{cfg.ServiceLabel, cfg.MethodLabel}), + }, []string{cfg.MethodLabel, cfg.HandlerIDLabel}), } cfg.Registry.MustRegister( @@ -108,6 +108,6 @@ func (r *RestCollector) AddInflightRequests(_ context.Context, p httpmetrics.HTT } // New custom method to track all requests made for every REST API request -func (r *RestCollector) AddTotalRequests(_ context.Context, serviceID string, method string) { - r.httpRequestsTotal.WithLabelValues(serviceID, method).Inc() +func (r *RestCollector) AddTotalRequests(_ context.Context, method string, routeName string) { + r.httpRequestsTotal.WithLabelValues(method, routeName).Inc() } diff --git a/module/mock/access_metrics.go b/module/mock/access_metrics.go index 2b686c8f7cc..3b0f68c44a5 100644 --- a/module/mock/access_metrics.go +++ b/module/mock/access_metrics.go @@ -23,9 +23,9 @@ func (_m *AccessMetrics) AddInflightRequests(ctx context.Context, props metrics. _m.Called(ctx, props, quantity) } -// AddTotalRequests provides a mock function with given fields: ctx, serviceID, method -func (_m *AccessMetrics) AddTotalRequests(ctx context.Context, serviceID string, method string) { - _m.Called(ctx, serviceID, method) +// AddTotalRequests provides a mock function with given fields: ctx, method, routeName +func (_m *AccessMetrics) AddTotalRequests(ctx context.Context, method string, routeName string) { + _m.Called(ctx, method, routeName) } // ConnectionAddedToPool provides a mock function with given fields: diff --git a/module/mock/rest_metrics.go b/module/mock/rest_metrics.go index 4d9dc09eeee..b5fbd8bc50a 100644 --- a/module/mock/rest_metrics.go +++ b/module/mock/rest_metrics.go @@ -21,9 +21,9 @@ func (_m *RestMetrics) AddInflightRequests(ctx context.Context, props metrics.HT _m.Called(ctx, props, quantity) } -// AddTotalRequests provides a mock function with given fields: ctx, serviceID, method -func (_m *RestMetrics) AddTotalRequests(ctx context.Context, serviceID string, method string) { - _m.Called(ctx, serviceID, method) +// AddTotalRequests provides a mock function with given fields: ctx, method, routeName +func (_m *RestMetrics) AddTotalRequests(ctx context.Context, method string, routeName string) { + _m.Called(ctx, method, routeName) } // ObserveHTTPRequestDuration provides a mock function with given fields: ctx, props, duration From 4b3383a83d425cfd65f962c4e7b8df6b049bff56 Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 22 Jun 2023 13:25:28 +0300 Subject: [PATCH 09/74] linted --- engine/access/rest/middleware/metrics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/access/rest/middleware/metrics.go b/engine/access/rest/middleware/metrics.go index b616858b735..e47c956a484 100644 --- a/engine/access/rest/middleware/metrics.go +++ b/engine/access/rest/middleware/metrics.go @@ -1,7 +1,6 @@ package middleware import ( - "github.com/onflow/flow-go/engine/access/rest" "net/http" "github.com/slok/go-http-metrics/middleware" @@ -9,6 +8,7 @@ import ( "github.com/gorilla/mux" + "github.com/onflow/flow-go/engine/access/rest" "github.com/onflow/flow-go/module" ) From 95cb8b9093cb73c10c33430a033fea4a546564e6 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 09:43:25 -0700 Subject: [PATCH 10/74] fixes build issue with fixtures --- network/internal/p2pfixtures/fixtures.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index 83b34e8bc6a..de942fe83dd 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -36,7 +36,6 @@ import ( "github.com/onflow/flow-go/network/p2p/keyutils" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/unicast" "github.com/onflow/flow-go/network/p2p/unicast/protocols" @@ -133,7 +132,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif SetResourceManager(testutils.NewResourceManager(t)). SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). SetGossipSubTracer(meshTracer). - SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). + SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval) for _, opt := range opts { opt(builder) From 9a7ecb2e6c29c7893ee585b2b94fd7a3a6211741 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 09:43:49 -0700 Subject: [PATCH 11/74] adds interface for collection cluster change consumer to libp2p node --- network/p2p/libp2pNode.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/network/p2p/libp2pNode.go b/network/p2p/libp2pNode.go index a5a92d5cc70..0efff130503 100644 --- a/network/p2p/libp2pNode.go +++ b/network/p2p/libp2pNode.go @@ -10,6 +10,7 @@ import ( "github.com/libp2p/go-libp2p/core/protocol" "github.com/libp2p/go-libp2p/core/routing" + "github.com/onflow/flow-go/engine/collection" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" @@ -35,6 +36,12 @@ type LibP2PNode interface { // DisallowListNotificationConsumer exposes the disallow list notification consumer API for the node so that // it will be notified when a new disallow list update is distributed. DisallowListNotificationConsumer + // CollectionClusterChangesConsumer is the interface for consuming the events of changes in the collection cluster. + // This is used to notify the node of changes in the collection cluster. + // LibP2PNode implements this interface and consumes the events to be notified of changes in the clustering channels. + // The clustering channels are used by the collection nodes of a cluster to communicate with each other. + // As the cluster (and hence their cluster channels) of collection nodes changes over time (per epoch) the node needs to be notified of these changes. + CollectionClusterChangesConsumer // DisallowListOracle exposes the disallow list oracle API for external consumers to query about the disallow list. DisallowListOracle // Start the libp2p node. @@ -93,6 +100,15 @@ type Subscriptions interface { SetUnicastManager(uniMgr UnicastManager) } +// CollectionClusterChangesConsumer is the interface for consuming the events of changes in the collection cluster. +// This is used to notify the node of changes in the collection cluster. +// LibP2PNode implements this interface and consumes the events to be notified of changes in the clustering channels. +// The clustering channels are used by the collection nodes of a cluster to communicate with each other. +// As the cluster (and hence their cluster channels) of collection nodes changes over time (per epoch) the node needs to be notified of these changes. +type CollectionClusterChangesConsumer interface { + collection.ClusterEvents +} + // PeerScore is the interface for the peer score module. It is used to expose the peer score to other // components of the node. It is also used to set the peer score exposer implementation. type PeerScore interface { From e0661b60faa69a0cb5947cd85f00a06ec5707829 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 09:44:04 -0700 Subject: [PATCH 12/74] adds implementation of collection cluster consumer --- network/p2p/p2pnode/libp2pNode.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/network/p2p/p2pnode/libp2pNode.go b/network/p2p/p2pnode/libp2pNode.go index 60a548c694b..a9920dab02a 100644 --- a/network/p2p/p2pnode/libp2pNode.go +++ b/network/p2p/p2pnode/libp2pNode.go @@ -18,6 +18,7 @@ import ( "github.com/libp2p/go-libp2p/core/routing" "github.com/rs/zerolog" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" flownet "github.com/onflow/flow-go/network" @@ -535,3 +536,8 @@ func (n *Node) OnAllowListNotification(peerId peer.ID, cause flownet.DisallowLis func (n *Node) IsDisallowListed(peerId peer.ID) ([]flownet.DisallowListedCause, bool) { return n.disallowListedCache.IsDisallowListed(peerId) } + +func (n *Node) ActiveClustersChanged(list flow.ChainIDList) { + //TODO implement me + panic("implement me") +} From 7eb4d54ec9f1b8c0cde226b87b891acc593f16fe Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 10:13:45 -0700 Subject: [PATCH 13/74] adds cluster consumer to corrupt adapter --- insecure/corruptlibp2p/libp2p_node_factory.go | 4 +-- insecure/corruptlibp2p/pubsub_adapter.go | 29 ++++++++++++++----- network/p2p/builder.go | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 8b79efeb667..4b7f775971d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -106,8 +106,8 @@ func InitCorruptLibp2pNode( // CorruptGossipSubFactory returns a factory function that creates a new instance of the forked gossipsub module from // github.com/yhassanzadeh13/go-libp2p-pubsub for the purpose of BFT testing and attack vector implementation. func CorruptGossipSubFactory(routerOpts ...func(*corrupt.GossipSubRouter)) p2p.GossipSubFactoryFunc { - factory := func(ctx context.Context, logger zerolog.Logger, host host.Host, cfg p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, error) { - adapter, router, err := NewCorruptGossipSubAdapter(ctx, logger, host, cfg) + factory := func(ctx context.Context, logger zerolog.Logger, host host.Host, cfg p2p.PubSubAdapterConfig, clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, error) { + adapter, router, err := NewCorruptGossipSubAdapter(ctx, logger, host, cfg, clusterChangeConsumer) for _, opt := range routerOpts { opt(router) } diff --git a/insecure/corruptlibp2p/pubsub_adapter.go b/insecure/corruptlibp2p/pubsub_adapter.go index c059bb0e3f1..51bbb8d15c7 100644 --- a/insecure/corruptlibp2p/pubsub_adapter.go +++ b/insecure/corruptlibp2p/pubsub_adapter.go @@ -11,6 +11,7 @@ import ( corrupt "github.com/yhassanzadeh13/go-libp2p-pubsub" "github.com/onflow/flow-go/insecure/internal" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" @@ -28,9 +29,10 @@ import ( // totally separated from the rest of the codebase. type CorruptGossipSubAdapter struct { component.Component - gossipSub *corrupt.PubSub - router *corrupt.GossipSubRouter - logger zerolog.Logger + gossipSub *corrupt.PubSub + router *corrupt.GossipSubRouter + logger zerolog.Logger + clusterChangeConsumer p2p.CollectionClusterChangesConsumer } var _ p2p.PubSubAdapter = (*CorruptGossipSubAdapter)(nil) @@ -104,7 +106,17 @@ func (c *CorruptGossipSubAdapter) ListPeers(topic string) []peer.ID { return c.gossipSub.ListPeers(topic) } -func NewCorruptGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host, cfg p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, *corrupt.GossipSubRouter, error) { +func (c *CorruptGossipSubAdapter) ActiveClustersChanged(lst flow.ChainIDList) { + c.clusterChangeConsumer.ActiveClustersChanged(lst) +} + +func NewCorruptGossipSubAdapter( + ctx context.Context, + logger zerolog.Logger, + h host.Host, + cfg p2p.PubSubAdapterConfig, + clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, *corrupt.GossipSubRouter, error) { + gossipSubConfig, ok := cfg.(*CorruptPubSubAdapterConfig) if !ok { return nil, nil, fmt.Errorf("invalid gossipsub config type: %T", cfg) @@ -126,10 +138,11 @@ func NewCorruptGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h ho }).Build() adapter := &CorruptGossipSubAdapter{ - Component: builder, - gossipSub: gossipSub, - router: router, - logger: logger, + Component: builder, + gossipSub: gossipSub, + router: router, + logger: logger, + clusterChangeConsumer: clusterChangeConsumer, } return adapter, router, nil diff --git a/network/p2p/builder.go b/network/p2p/builder.go index c16ad9a3296..f67274199d8 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -22,7 +22,7 @@ import ( "github.com/onflow/flow-go/network/channels" ) -type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig) (PubSubAdapter, error) +type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) type CreateNodeFunc func(zerolog.Logger, host.Host, ProtocolPeerCache, PeerManager, *DisallowListCacheConfig) LibP2PNode type GossipSubAdapterConfigFunc func(*BasePubSubAdapterConfig) PubSubAdapterConfig From defe219adfefe074b192543e8e750b40c3a92df9 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 12:01:25 -0700 Subject: [PATCH 14/74] wip --- network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 9 +++++++-- network/p2p/p2pnode/gossipSubAdapter.go | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 136c1e34eab..857e100b9d0 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -181,8 +181,13 @@ func NewGossipSubBuilder( } func defaultGossipSubFactory() p2p.GossipSubFactoryFunc { - return func(ctx context.Context, logger zerolog.Logger, h host.Host, cfg p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, error) { - return p2pnode.NewGossipSubAdapter(ctx, logger, h, cfg) + return func( + ctx context.Context, + logger zerolog.Logger, + h host.Host, + cfg p2p.PubSubAdapterConfig, + clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, error) { + return p2pnode.NewGossipSubAdapter(ctx, logger, h, cfg, clusterChangeConsumer) } } diff --git a/network/p2p/p2pnode/gossipSubAdapter.go b/network/p2p/p2pnode/gossipSubAdapter.go index ab72db379f9..37a0218ab91 100644 --- a/network/p2p/p2pnode/gossipSubAdapter.go +++ b/network/p2p/p2pnode/gossipSubAdapter.go @@ -9,6 +9,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/rs/zerolog" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" @@ -134,3 +135,7 @@ func (g *GossipSubAdapter) GetTopics() []string { func (g *GossipSubAdapter) ListPeers(topic string) []peer.ID { return g.gossipSub.ListPeers(topic) } + +func (g *GossipSubAdapter) ActiveClustersChanged(lst flow.ChainIDList) { + g.clusterChangeConsumer.ActiveClustersChanged(lst) +} From f6ad2ce079701cb4682959dd317325ed4bf9652d Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:45:51 -0700 Subject: [PATCH 15/74] wires in active cluster change to gossipsub adapter --- network/p2p/p2pnode/gossipSubAdapter.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2pnode/gossipSubAdapter.go b/network/p2p/p2pnode/gossipSubAdapter.go index 37a0218ab91..b5c67c466e2 100644 --- a/network/p2p/p2pnode/gossipSubAdapter.go +++ b/network/p2p/p2pnode/gossipSubAdapter.go @@ -20,8 +20,9 @@ import ( // that implements the PubSubAdapter interface for the Flow network. type GossipSubAdapter struct { component.Component - gossipSub *pubsub.PubSub - logger zerolog.Logger + gossipSub *pubsub.PubSub + logger zerolog.Logger + clusterChangeConsumer p2p.CollectionClusterChangesConsumer } var _ p2p.PubSubAdapter = (*GossipSubAdapter)(nil) From a142ae99c56866fb483c90db6333e74a4e4b762f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:51:28 -0700 Subject: [PATCH 16/74] moves networking type to p2p package --- .../node_builder/access_node_builder.go | 8 ++--- cmd/observer/node_builder/observer_builder.go | 9 +++-- cmd/scaffold.go | 8 ++--- follower/follower_builder.go | 9 +++-- insecure/cmd/corrupted_builder.go | 3 +- insecure/corruptlibp2p/libp2p_node_factory.go | 3 +- module/metrics/herocache.go | 34 +++++++++---------- network/alsp/manager/manager.go | 3 +- network/internal/p2pfixtures/fixtures.go | 3 +- network/internal/testutils/testUtil.go | 2 +- network/network.go | 13 ------- network/p2p/builder.go | 3 +- network/p2p/networkingType.go | 14 ++++++++ .../p2pbuilder/gossipsub/gossipSubBuilder.go | 7 ++-- .../inspector/rpc_inspector_builder.go | 14 ++------ network/p2p/p2pbuilder/libp2pNodeBuilder.go | 5 ++- network/p2p/test/fixtures.go | 5 ++- 17 files changed, 64 insertions(+), 79 deletions(-) create mode 100644 network/p2p/networkingType.go diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 84aff969161..7f4afd59f54 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -778,7 +778,7 @@ func (builder *FlowAccessNodeBuilder) initNetwork(nodeID module.Local, DisablePenalty: builder.FlowConfig.NetworkConfig.AlspConfig.DisablePenalty, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), }, }) @@ -1148,7 +1148,7 @@ func (builder *FlowAccessNodeBuilder) enqueuePublicNetworkInit() { top := topology.EmptyTopology{} receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { @@ -1204,7 +1204,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: networkMetrics, }, - network.PublicNetwork, + p2p.PublicNetwork, bindAddress, networkKey, builder.SporkID, @@ -1213,7 +1213,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetBasicResolver(builder.Resolver). SetSubscriptionFilter( diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index ae50cbc938d..c81bcae6f2d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -57,7 +57,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -489,7 +488,7 @@ func (builder *ObserverServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, }, }) if err != nil { @@ -716,7 +715,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - network.PublicNetwork, + p2p.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -725,7 +724,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -800,7 +799,7 @@ func (builder *ObserverServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 2de8d6c4da1..1fb6379528b 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -348,7 +348,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, - network.PrivateNetwork, + p2p.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, @@ -367,7 +367,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, &p2p.DisallowListCacheConfig{ MaxSize: fnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), }) if err != nil { @@ -457,7 +457,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( receiveCache := netcache.NewHeroReceiveCache(fnb.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, fnb.Logger, - metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork)) err := node.Metrics.Mempool.Register(metrics.ResourceNetworkingReceiveCache, receiveCache.Size) if err != nil { @@ -484,7 +484,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( HeartBeatInterval: fnb.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: fnb.Metrics.Network, HeroCacheMetricsFactory: fnb.HeroCacheMetricsFactory(), - NetworkType: network.PrivateNetwork, + NetworkType: p2p.PrivateNetwork, }, }) if err != nil { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index a801c99d2ee..36bb37aa77b 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -51,7 +51,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -390,7 +389,7 @@ func (builder *FollowerServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, }, }) if err != nil { @@ -618,7 +617,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - network.PublicNetwork, + p2p.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -627,7 +626,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -703,7 +702,7 @@ func (builder *FollowerServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/insecure/cmd/corrupted_builder.go b/insecure/cmd/corrupted_builder.go index bd85b83768b..71d604b69af 100644 --- a/insecure/cmd/corrupted_builder.go +++ b/insecure/cmd/corrupted_builder.go @@ -12,7 +12,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" @@ -105,7 +104,7 @@ func (cnb *CorruptedNodeBuilder) enqueueNetworkingLayer() { cnb.FlowConfig.NetworkConfig, &p2p.DisallowListCacheConfig{ MaxSize: cnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), network.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), }, cnb.TopicValidatorDisabled, cnb.WithPubSubMessageSigning, diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 4b7f775971d..4715f6b768d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -15,7 +15,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" @@ -76,7 +75,7 @@ func InitCorruptLibp2pNode( builder, err := p2pbuilder.DefaultNodeBuilder( log, address, - network.PrivateNetwork, + p2p.PrivateNetwork, flowKey, sporkId, idProvider, diff --git a/module/metrics/herocache.go b/module/metrics/herocache.go index 54e287bdb1b..1e5d8790bed 100644 --- a/module/metrics/herocache.go +++ b/module/metrics/herocache.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/network" + "github.com/onflow/flow-go/network/p2p" ) const subsystemHeroCache = "hero_cache" @@ -64,9 +64,9 @@ func NewNoopHeroCacheMetricsFactory() HeroCacheMetricsFactory { } } -func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingReceiveCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -79,9 +79,9 @@ func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType ne // - networkingType: the networking type of the cache, i.e., whether it is used for the public or the private network // Returns: // - a HeroCacheMetrics for the disallow list cache -func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType network.NetworkingType) module.HeroCacheMetrics { +func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingDisallowListCache - if networkingType == network.PublicNetwork { + if networkingType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -111,53 +111,53 @@ func DisallowListNotificationQueueMetricFactory(registrar prometheus.Registerer) return NewHeroCacheCollector(namespaceNetwork, ResourceNetworkingDisallowListNotificationQueue, registrar) } -func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamRecordCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamReportQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcMetricsObserverInspectorQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcValidationInspectorQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingRpcInspectorNotificationQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcClusterPrefixReceivedCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 941407e2637..9b07490ddff 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,6 +21,7 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -103,7 +104,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - NetworkType network.NetworkingType + NetworkType p2p.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index de942fe83dd..b7dd0e7c886 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,7 +26,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -115,7 +114,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - flownet.PrivateNetwork, + p2p.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 14fe9feb175..683e3ad6018 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -505,7 +505,7 @@ func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateK HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - network.PrivateNetwork, + p2p.PrivateNetwork, unittest.DefaultAddress, key, sporkID, diff --git a/network/network.go b/network/network.go index 703c5e627c8..47170c61d4d 100644 --- a/network/network.go +++ b/network/network.go @@ -9,19 +9,6 @@ import ( "github.com/onflow/flow-go/network/channels" ) -// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) -// and private (i.e., staked) networks. -type NetworkingType uint8 - -const ( - // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave - // with a staking requirement. - PrivateNetwork NetworkingType = iota + 1 - // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will - // with no staking requirement. - PublicNetwork -) - // Network represents the network layer of the node. It allows processes that // work across the peer-to-peer network to register themselves as an engine with // a unique engine ID. The returned conduit allows the process to communicate to diff --git a/network/p2p/builder.go b/network/p2p/builder.go index f67274199d8..349381e662c 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -18,7 +18,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" ) @@ -116,7 +115,7 @@ type GossipSubRpcInspectorSuiteFactoryFunc func( *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, - flownet.NetworkingType, + NetworkingType, module.IdentityProvider) (GossipSubInspectorSuite, error) // NodeBuilder is a builder pattern for creating a libp2p Node instance. diff --git a/network/p2p/networkingType.go b/network/p2p/networkingType.go new file mode 100644 index 00000000000..14df4d0037c --- /dev/null +++ b/network/p2p/networkingType.go @@ -0,0 +1,14 @@ +package p2p + +// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) +// and private (i.e., staked) networks. +type NetworkingType uint8 + +const ( + // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave + // with a staking requirement. + PrivateNetwork NetworkingType = iota + 1 + // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will + // with no staking requirement. + PublicNetwork +) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 857e100b9d0..f0e0de50003 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -17,7 +17,6 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" @@ -33,7 +32,7 @@ import ( // The Builder struct is used to configure and create a new GossipSub pubsub system. type Builder struct { - networkType network.NetworkingType + networkType p2p.NetworkingType sporkId flow.Identifier logger zerolog.Logger metricsCfg *p2pconfig.MetricsConfig @@ -160,7 +159,7 @@ func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubR func NewGossipSubBuilder( logger zerolog.Logger, metricsCfg *p2pconfig.MetricsConfig, - networkType network.NetworkingType, + networkType p2p.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, @@ -204,7 +203,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { inspectorCfg *netconf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, - networkType network.NetworkingType, + networkType p2p.NetworkingType, idProvider module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { metricsInspector := inspector.NewControlMsgMetricsInspector( logger, diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index c7a40a136ba..461dfaad13d 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -1,23 +1,15 @@ package inspector import ( - "fmt" - "github.com/rs/zerolog" netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" - "github.com/onflow/flow-go/network/p2p/inspector" - "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" - "github.com/onflow/flow-go/network/p2p/p2pnode" ) // GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following @@ -31,7 +23,7 @@ type GossipSubInspectorBuilder struct { metricsCfg *p2pconfig.MetricsConfig idProvider module.IdentityProvider inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType network.NetworkingType + networkType p2p.NetworkingType } // NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. @@ -46,7 +38,7 @@ func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier }, idProvider: provider, inspectorMetrics: inspectorMetrics, - networkType: network.PublicNetwork, + networkType: p2p.PublicNetwork, } } @@ -62,7 +54,7 @@ func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConf // - networkType: the network type. // Returns: // - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { +func (b *GossipSubInspectorBuilder) SetNetworkType(networkType p2p.NetworkingType) *GossipSubInspectorBuilder { b.networkType = networkType return b } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 1549efa1e29..3012891495a 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,7 +27,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -76,7 +75,7 @@ type LibP2PNodeBuilder struct { func NewNodeBuilder( logger zerolog.Logger, metricsConfig *p2pconfig.MetricsConfig, - networkingType flownet.NetworkingType, + networkingType p2p.NetworkingType, address string, networkKey fcrypto.PrivateKey, sporkId flow.Identifier, @@ -444,7 +443,7 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, func DefaultNodeBuilder( logger zerolog.Logger, address string, - networkingType flownet.NetworkingType, + networkingType p2p.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index c2b097ee9d4..5262fef1697 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -25,7 +25,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" @@ -64,7 +63,7 @@ func NodeFixture( logger := unittest.Logger().Level(zerolog.WarnLevel) parameters := &NodeFixtureParameters{ - NetworkingType: flownet.PrivateNetwork, + NetworkingType: p2p.PrivateNetwork, HandlerFunc: func(network.Stream) {}, Unicasts: nil, Key: NetworkingKeyFixtures(t), @@ -179,7 +178,7 @@ type NodeFixtureParameterOption func(*NodeFixtureParameters) type NodeFixtureParameters struct { HandlerFunc network.StreamHandler - NetworkingType flownet.NetworkingType + NetworkingType p2p.NetworkingType Unicasts []protocols.ProtocolName Key crypto.PrivateKey Address string From 58bcf69efa432a8c4a8b9c44d0bfe600cad393fb Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:51:28 -0700 Subject: [PATCH 17/74] Revert "moves networking type to p2p package" This reverts commit a142ae99c56866fb483c90db6333e74a4e4b762f. --- .../node_builder/access_node_builder.go | 8 ++--- cmd/observer/node_builder/observer_builder.go | 9 ++--- cmd/scaffold.go | 8 ++--- follower/follower_builder.go | 9 ++--- insecure/cmd/corrupted_builder.go | 3 +- insecure/corruptlibp2p/libp2p_node_factory.go | 3 +- module/metrics/herocache.go | 34 +++++++++---------- network/alsp/manager/manager.go | 3 +- network/internal/p2pfixtures/fixtures.go | 3 +- network/internal/testutils/testUtil.go | 2 +- network/network.go | 13 +++++++ network/p2p/builder.go | 3 +- network/p2p/networkingType.go | 14 -------- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 7 ++-- .../inspector/rpc_inspector_builder.go | 14 ++++++-- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 5 +-- network/p2p/test/fixtures.go | 5 +-- 17 files changed, 79 insertions(+), 64 deletions(-) delete mode 100644 network/p2p/networkingType.go diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 7f4afd59f54..84aff969161 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -778,7 +778,7 @@ func (builder *FlowAccessNodeBuilder) initNetwork(nodeID module.Local, DisablePenalty: builder.FlowConfig.NetworkConfig.AlspConfig.DisablePenalty, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), }, }) @@ -1148,7 +1148,7 @@ func (builder *FlowAccessNodeBuilder) enqueuePublicNetworkInit() { top := topology.EmptyTopology{} receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { @@ -1204,7 +1204,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: networkMetrics, }, - p2p.PublicNetwork, + network.PublicNetwork, bindAddress, networkKey, builder.SporkID, @@ -1213,7 +1213,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetBasicResolver(builder.Resolver). SetSubscriptionFilter( diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index c81bcae6f2d..ae50cbc938d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -57,6 +57,7 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -488,7 +489,7 @@ func (builder *ObserverServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, }, }) if err != nil { @@ -715,7 +716,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - p2p.PublicNetwork, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -724,7 +725,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -799,7 +800,7 @@ func (builder *ObserverServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 1fb6379528b..2de8d6c4da1 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -348,7 +348,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, - p2p.PrivateNetwork, + network.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, @@ -367,7 +367,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, &p2p.DisallowListCacheConfig{ MaxSize: fnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork), }) if err != nil { @@ -457,7 +457,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( receiveCache := netcache.NewHeroReceiveCache(fnb.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, fnb.Logger, - metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork)) err := node.Metrics.Mempool.Register(metrics.ResourceNetworkingReceiveCache, receiveCache.Size) if err != nil { @@ -484,7 +484,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( HeartBeatInterval: fnb.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: fnb.Metrics.Network, HeroCacheMetricsFactory: fnb.HeroCacheMetricsFactory(), - NetworkType: p2p.PrivateNetwork, + NetworkType: network.PrivateNetwork, }, }) if err != nil { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index 36bb37aa77b..a801c99d2ee 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -51,6 +51,7 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -389,7 +390,7 @@ func (builder *FollowerServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, }, }) if err != nil { @@ -617,7 +618,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - p2p.PublicNetwork, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -626,7 +627,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -702,7 +703,7 @@ func (builder *FollowerServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/insecure/cmd/corrupted_builder.go b/insecure/cmd/corrupted_builder.go index 71d604b69af..bd85b83768b 100644 --- a/insecure/cmd/corrupted_builder.go +++ b/insecure/cmd/corrupted_builder.go @@ -12,6 +12,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" @@ -104,7 +105,7 @@ func (cnb *CorruptedNodeBuilder) enqueueNetworkingLayer() { cnb.FlowConfig.NetworkConfig, &p2p.DisallowListCacheConfig{ MaxSize: cnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), network.PrivateNetwork), }, cnb.TopicValidatorDisabled, cnb.WithPubSubMessageSigning, diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 4715f6b768d..4b7f775971d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -15,6 +15,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" @@ -75,7 +76,7 @@ func InitCorruptLibp2pNode( builder, err := p2pbuilder.DefaultNodeBuilder( log, address, - p2p.PrivateNetwork, + network.PrivateNetwork, flowKey, sporkId, idProvider, diff --git a/module/metrics/herocache.go b/module/metrics/herocache.go index 1e5d8790bed..54e287bdb1b 100644 --- a/module/metrics/herocache.go +++ b/module/metrics/herocache.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network" ) const subsystemHeroCache = "hero_cache" @@ -64,9 +64,9 @@ func NewNoopHeroCacheMetricsFactory() HeroCacheMetricsFactory { } } -func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingReceiveCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -79,9 +79,9 @@ func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2 // - networkingType: the networking type of the cache, i.e., whether it is used for the public or the private network // Returns: // - a HeroCacheMetrics for the disallow list cache -func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType p2p.NetworkingType) module.HeroCacheMetrics { +func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingDisallowListCache - if networkingType == p2p.PublicNetwork { + if networkingType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -111,53 +111,53 @@ func DisallowListNotificationQueueMetricFactory(registrar prometheus.Registerer) return NewHeroCacheCollector(namespaceNetwork, ResourceNetworkingDisallowListNotificationQueue, registrar) } -func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamRecordCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamReportQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcMetricsObserverInspectorQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcValidationInspectorQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingRpcInspectorNotificationQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcClusterPrefixReceivedCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 9b07490ddff..941407e2637 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,7 +21,6 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -104,7 +103,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - NetworkType p2p.NetworkingType + NetworkType network.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index b7dd0e7c886..de942fe83dd 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,6 +26,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -114,7 +115,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - p2p.PrivateNetwork, + flownet.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 683e3ad6018..14fe9feb175 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -505,7 +505,7 @@ func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateK HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - p2p.PrivateNetwork, + network.PrivateNetwork, unittest.DefaultAddress, key, sporkID, diff --git a/network/network.go b/network/network.go index 47170c61d4d..703c5e627c8 100644 --- a/network/network.go +++ b/network/network.go @@ -9,6 +9,19 @@ import ( "github.com/onflow/flow-go/network/channels" ) +// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) +// and private (i.e., staked) networks. +type NetworkingType uint8 + +const ( + // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave + // with a staking requirement. + PrivateNetwork NetworkingType = iota + 1 + // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will + // with no staking requirement. + PublicNetwork +) + // Network represents the network layer of the node. It allows processes that // work across the peer-to-peer network to register themselves as an engine with // a unique engine ID. The returned conduit allows the process to communicate to diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 349381e662c..f67274199d8 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -18,6 +18,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" ) @@ -115,7 +116,7 @@ type GossipSubRpcInspectorSuiteFactoryFunc func( *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, - NetworkingType, + flownet.NetworkingType, module.IdentityProvider) (GossipSubInspectorSuite, error) // NodeBuilder is a builder pattern for creating a libp2p Node instance. diff --git a/network/p2p/networkingType.go b/network/p2p/networkingType.go deleted file mode 100644 index 14df4d0037c..00000000000 --- a/network/p2p/networkingType.go +++ /dev/null @@ -1,14 +0,0 @@ -package p2p - -// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) -// and private (i.e., staked) networks. -type NetworkingType uint8 - -const ( - // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave - // with a staking requirement. - PrivateNetwork NetworkingType = iota + 1 - // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will - // with no staking requirement. - PublicNetwork -) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index f0e0de50003..857e100b9d0 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -17,6 +17,7 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" @@ -32,7 +33,7 @@ import ( // The Builder struct is used to configure and create a new GossipSub pubsub system. type Builder struct { - networkType p2p.NetworkingType + networkType network.NetworkingType sporkId flow.Identifier logger zerolog.Logger metricsCfg *p2pconfig.MetricsConfig @@ -159,7 +160,7 @@ func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubR func NewGossipSubBuilder( logger zerolog.Logger, metricsCfg *p2pconfig.MetricsConfig, - networkType p2p.NetworkingType, + networkType network.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, @@ -203,7 +204,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { inspectorCfg *netconf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, - networkType p2p.NetworkingType, + networkType network.NetworkingType, idProvider module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { metricsInspector := inspector.NewControlMsgMetricsInspector( logger, diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index 461dfaad13d..c7a40a136ba 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -1,15 +1,23 @@ package inspector import ( + "fmt" + "github.com/rs/zerolog" netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" + "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" + "github.com/onflow/flow-go/network/p2p/inspector" + "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" + "github.com/onflow/flow-go/network/p2p/p2pnode" ) // GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following @@ -23,7 +31,7 @@ type GossipSubInspectorBuilder struct { metricsCfg *p2pconfig.MetricsConfig idProvider module.IdentityProvider inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType p2p.NetworkingType + networkType network.NetworkingType } // NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. @@ -38,7 +46,7 @@ func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier }, idProvider: provider, inspectorMetrics: inspectorMetrics, - networkType: p2p.PublicNetwork, + networkType: network.PublicNetwork, } } @@ -54,7 +62,7 @@ func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConf // - networkType: the network type. // Returns: // - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType p2p.NetworkingType) *GossipSubInspectorBuilder { +func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { b.networkType = networkType return b } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 3012891495a..1549efa1e29 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,6 +27,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -75,7 +76,7 @@ type LibP2PNodeBuilder struct { func NewNodeBuilder( logger zerolog.Logger, metricsConfig *p2pconfig.MetricsConfig, - networkingType p2p.NetworkingType, + networkingType flownet.NetworkingType, address string, networkKey fcrypto.PrivateKey, sporkId flow.Identifier, @@ -443,7 +444,7 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, func DefaultNodeBuilder( logger zerolog.Logger, address string, - networkingType p2p.NetworkingType, + networkingType flownet.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 5262fef1697..c2b097ee9d4 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -25,6 +25,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" @@ -63,7 +64,7 @@ func NodeFixture( logger := unittest.Logger().Level(zerolog.WarnLevel) parameters := &NodeFixtureParameters{ - NetworkingType: p2p.PrivateNetwork, + NetworkingType: flownet.PrivateNetwork, HandlerFunc: func(network.Stream) {}, Unicasts: nil, Key: NetworkingKeyFixtures(t), @@ -178,7 +179,7 @@ type NodeFixtureParameterOption func(*NodeFixtureParameters) type NodeFixtureParameters struct { HandlerFunc network.StreamHandler - NetworkingType p2p.NetworkingType + NetworkingType flownet.NetworkingType Unicasts []protocols.ProtocolName Key crypto.PrivateKey Address string From 5aa2c076053d066e00ba9676cceb41e60f5e88f6 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:51:28 -0700 Subject: [PATCH 18/74] Revert "Revert "moves networking type to p2p package"" This reverts commit 58bcf69efa432a8c4a8b9c44d0bfe600cad393fb. --- .../node_builder/access_node_builder.go | 8 ++--- cmd/observer/node_builder/observer_builder.go | 9 +++-- cmd/scaffold.go | 8 ++--- follower/follower_builder.go | 9 +++-- insecure/cmd/corrupted_builder.go | 3 +- insecure/corruptlibp2p/libp2p_node_factory.go | 3 +- module/metrics/herocache.go | 34 +++++++++---------- network/alsp/manager/manager.go | 3 +- network/internal/p2pfixtures/fixtures.go | 3 +- network/internal/testutils/testUtil.go | 2 +- network/network.go | 13 ------- network/p2p/builder.go | 3 +- network/p2p/networkingType.go | 14 ++++++++ .../p2pbuilder/gossipsub/gossipSubBuilder.go | 7 ++-- .../inspector/rpc_inspector_builder.go | 14 ++------ network/p2p/p2pbuilder/libp2pNodeBuilder.go | 5 ++- network/p2p/test/fixtures.go | 5 ++- 17 files changed, 64 insertions(+), 79 deletions(-) create mode 100644 network/p2p/networkingType.go diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 84aff969161..7f4afd59f54 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -778,7 +778,7 @@ func (builder *FlowAccessNodeBuilder) initNetwork(nodeID module.Local, DisablePenalty: builder.FlowConfig.NetworkConfig.AlspConfig.DisablePenalty, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), }, }) @@ -1148,7 +1148,7 @@ func (builder *FlowAccessNodeBuilder) enqueuePublicNetworkInit() { top := topology.EmptyTopology{} receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { @@ -1204,7 +1204,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: networkMetrics, }, - network.PublicNetwork, + p2p.PublicNetwork, bindAddress, networkKey, builder.SporkID, @@ -1213,7 +1213,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetBasicResolver(builder.Resolver). SetSubscriptionFilter( diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index ae50cbc938d..c81bcae6f2d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -57,7 +57,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -489,7 +488,7 @@ func (builder *ObserverServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, }, }) if err != nil { @@ -716,7 +715,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - network.PublicNetwork, + p2p.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -725,7 +724,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -800,7 +799,7 @@ func (builder *ObserverServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 2de8d6c4da1..1fb6379528b 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -348,7 +348,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, - network.PrivateNetwork, + p2p.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, @@ -367,7 +367,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, &p2p.DisallowListCacheConfig{ MaxSize: fnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), }) if err != nil { @@ -457,7 +457,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( receiveCache := netcache.NewHeroReceiveCache(fnb.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, fnb.Logger, - metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork)) err := node.Metrics.Mempool.Register(metrics.ResourceNetworkingReceiveCache, receiveCache.Size) if err != nil { @@ -484,7 +484,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( HeartBeatInterval: fnb.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: fnb.Metrics.Network, HeroCacheMetricsFactory: fnb.HeroCacheMetricsFactory(), - NetworkType: network.PrivateNetwork, + NetworkType: p2p.PrivateNetwork, }, }) if err != nil { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index a801c99d2ee..36bb37aa77b 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -51,7 +51,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -390,7 +389,7 @@ func (builder *FollowerServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: network.PublicNetwork, + NetworkType: p2p.PublicNetwork, }, }) if err != nil { @@ -618,7 +617,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - network.PublicNetwork, + p2p.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -627,7 +626,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -703,7 +702,7 @@ func (builder *FollowerServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/insecure/cmd/corrupted_builder.go b/insecure/cmd/corrupted_builder.go index bd85b83768b..71d604b69af 100644 --- a/insecure/cmd/corrupted_builder.go +++ b/insecure/cmd/corrupted_builder.go @@ -12,7 +12,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" @@ -105,7 +104,7 @@ func (cnb *CorruptedNodeBuilder) enqueueNetworkingLayer() { cnb.FlowConfig.NetworkConfig, &p2p.DisallowListCacheConfig{ MaxSize: cnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), network.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), }, cnb.TopicValidatorDisabled, cnb.WithPubSubMessageSigning, diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 4b7f775971d..4715f6b768d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -15,7 +15,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" @@ -76,7 +75,7 @@ func InitCorruptLibp2pNode( builder, err := p2pbuilder.DefaultNodeBuilder( log, address, - network.PrivateNetwork, + p2p.PrivateNetwork, flowKey, sporkId, idProvider, diff --git a/module/metrics/herocache.go b/module/metrics/herocache.go index 54e287bdb1b..1e5d8790bed 100644 --- a/module/metrics/herocache.go +++ b/module/metrics/herocache.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/network" + "github.com/onflow/flow-go/network/p2p" ) const subsystemHeroCache = "hero_cache" @@ -64,9 +64,9 @@ func NewNoopHeroCacheMetricsFactory() HeroCacheMetricsFactory { } } -func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingReceiveCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -79,9 +79,9 @@ func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType ne // - networkingType: the networking type of the cache, i.e., whether it is used for the public or the private network // Returns: // - a HeroCacheMetrics for the disallow list cache -func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType network.NetworkingType) module.HeroCacheMetrics { +func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingDisallowListCache - if networkingType == network.PublicNetwork { + if networkingType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -111,53 +111,53 @@ func DisallowListNotificationQueueMetricFactory(registrar prometheus.Registerer) return NewHeroCacheCollector(namespaceNetwork, ResourceNetworkingDisallowListNotificationQueue, registrar) } -func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamRecordCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamReportQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcMetricsObserverInspectorQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcValidationInspectorQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingRpcInspectorNotificationQueue - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcClusterPrefixReceivedCache - if networkType == network.PublicNetwork { + if networkType == p2p.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 941407e2637..9b07490ddff 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,6 +21,7 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -103,7 +104,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - NetworkType network.NetworkingType + NetworkType p2p.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index de942fe83dd..b7dd0e7c886 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,7 +26,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -115,7 +114,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - flownet.PrivateNetwork, + p2p.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 14fe9feb175..683e3ad6018 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -505,7 +505,7 @@ func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateK HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - network.PrivateNetwork, + p2p.PrivateNetwork, unittest.DefaultAddress, key, sporkID, diff --git a/network/network.go b/network/network.go index 703c5e627c8..47170c61d4d 100644 --- a/network/network.go +++ b/network/network.go @@ -9,19 +9,6 @@ import ( "github.com/onflow/flow-go/network/channels" ) -// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) -// and private (i.e., staked) networks. -type NetworkingType uint8 - -const ( - // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave - // with a staking requirement. - PrivateNetwork NetworkingType = iota + 1 - // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will - // with no staking requirement. - PublicNetwork -) - // Network represents the network layer of the node. It allows processes that // work across the peer-to-peer network to register themselves as an engine with // a unique engine ID. The returned conduit allows the process to communicate to diff --git a/network/p2p/builder.go b/network/p2p/builder.go index f67274199d8..349381e662c 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -18,7 +18,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" ) @@ -116,7 +115,7 @@ type GossipSubRpcInspectorSuiteFactoryFunc func( *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, - flownet.NetworkingType, + NetworkingType, module.IdentityProvider) (GossipSubInspectorSuite, error) // NodeBuilder is a builder pattern for creating a libp2p Node instance. diff --git a/network/p2p/networkingType.go b/network/p2p/networkingType.go new file mode 100644 index 00000000000..14df4d0037c --- /dev/null +++ b/network/p2p/networkingType.go @@ -0,0 +1,14 @@ +package p2p + +// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) +// and private (i.e., staked) networks. +type NetworkingType uint8 + +const ( + // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave + // with a staking requirement. + PrivateNetwork NetworkingType = iota + 1 + // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will + // with no staking requirement. + PublicNetwork +) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 857e100b9d0..f0e0de50003 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -17,7 +17,6 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" @@ -33,7 +32,7 @@ import ( // The Builder struct is used to configure and create a new GossipSub pubsub system. type Builder struct { - networkType network.NetworkingType + networkType p2p.NetworkingType sporkId flow.Identifier logger zerolog.Logger metricsCfg *p2pconfig.MetricsConfig @@ -160,7 +159,7 @@ func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubR func NewGossipSubBuilder( logger zerolog.Logger, metricsCfg *p2pconfig.MetricsConfig, - networkType network.NetworkingType, + networkType p2p.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, @@ -204,7 +203,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { inspectorCfg *netconf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, - networkType network.NetworkingType, + networkType p2p.NetworkingType, idProvider module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { metricsInspector := inspector.NewControlMsgMetricsInspector( logger, diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index c7a40a136ba..461dfaad13d 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -1,23 +1,15 @@ package inspector import ( - "fmt" - "github.com/rs/zerolog" netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" - "github.com/onflow/flow-go/network/p2p/inspector" - "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" - "github.com/onflow/flow-go/network/p2p/p2pnode" ) // GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following @@ -31,7 +23,7 @@ type GossipSubInspectorBuilder struct { metricsCfg *p2pconfig.MetricsConfig idProvider module.IdentityProvider inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType network.NetworkingType + networkType p2p.NetworkingType } // NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. @@ -46,7 +38,7 @@ func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier }, idProvider: provider, inspectorMetrics: inspectorMetrics, - networkType: network.PublicNetwork, + networkType: p2p.PublicNetwork, } } @@ -62,7 +54,7 @@ func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConf // - networkType: the network type. // Returns: // - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { +func (b *GossipSubInspectorBuilder) SetNetworkType(networkType p2p.NetworkingType) *GossipSubInspectorBuilder { b.networkType = networkType return b } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 1549efa1e29..3012891495a 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,7 +27,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -76,7 +75,7 @@ type LibP2PNodeBuilder struct { func NewNodeBuilder( logger zerolog.Logger, metricsConfig *p2pconfig.MetricsConfig, - networkingType flownet.NetworkingType, + networkingType p2p.NetworkingType, address string, networkKey fcrypto.PrivateKey, sporkId flow.Identifier, @@ -444,7 +443,7 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, func DefaultNodeBuilder( logger zerolog.Logger, address string, - networkingType flownet.NetworkingType, + networkingType p2p.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index c2b097ee9d4..5262fef1697 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -25,7 +25,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" - flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" @@ -64,7 +63,7 @@ func NodeFixture( logger := unittest.Logger().Level(zerolog.WarnLevel) parameters := &NodeFixtureParameters{ - NetworkingType: flownet.PrivateNetwork, + NetworkingType: p2p.PrivateNetwork, HandlerFunc: func(network.Stream) {}, Unicasts: nil, Key: NetworkingKeyFixtures(t), @@ -179,7 +178,7 @@ type NodeFixtureParameterOption func(*NodeFixtureParameters) type NodeFixtureParameters struct { HandlerFunc network.StreamHandler - NetworkingType flownet.NetworkingType + NetworkingType p2p.NetworkingType Unicasts []protocols.ProtocolName Key crypto.PrivateKey Address string From 7000f9c93d900fd388ddf6998f6c879dc423df6b Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:58:37 -0700 Subject: [PATCH 19/74] temp --- network/alsp/manager/manager.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 9b07490ddff..7de9cfa1349 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,7 +21,6 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -104,7 +103,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - NetworkType p2p.NetworkingType + // NetworkType p2p.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration From 2a703497751dd511fb0277129d982b88934e981c Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:58:37 -0700 Subject: [PATCH 20/74] Revert "temp" This reverts commit 7000f9c93d900fd388ddf6998f6c879dc423df6b. --- network/alsp/manager/manager.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 7de9cfa1349..9b07490ddff 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,6 +21,7 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -103,7 +104,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - // NetworkType p2p.NetworkingType + NetworkType p2p.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration From 4f7fffa3ed9ea0c50f766ef2c52cd72ac691b09f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 14:51:28 -0700 Subject: [PATCH 21/74] Revert "Revert "Revert "moves networking type to p2p package""" This reverts commit 5aa2c076053d066e00ba9676cceb41e60f5e88f6. --- .../node_builder/access_node_builder.go | 8 ++--- cmd/observer/node_builder/observer_builder.go | 9 ++--- cmd/scaffold.go | 8 ++--- follower/follower_builder.go | 9 ++--- insecure/cmd/corrupted_builder.go | 3 +- insecure/corruptlibp2p/libp2p_node_factory.go | 3 +- module/metrics/herocache.go | 34 +++++++++---------- network/alsp/manager/manager.go | 3 +- network/internal/p2pfixtures/fixtures.go | 3 +- network/internal/testutils/testUtil.go | 2 +- network/network.go | 13 +++++++ network/p2p/builder.go | 3 +- network/p2p/networkingType.go | 14 -------- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 7 ++-- .../inspector/rpc_inspector_builder.go | 14 ++++++-- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 5 +-- network/p2p/test/fixtures.go | 5 +-- 17 files changed, 79 insertions(+), 64 deletions(-) delete mode 100644 network/p2p/networkingType.go diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 7f4afd59f54..84aff969161 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -778,7 +778,7 @@ func (builder *FlowAccessNodeBuilder) initNetwork(nodeID module.Local, DisablePenalty: builder.FlowConfig.NetworkConfig.AlspConfig.DisablePenalty, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), }, }) @@ -1148,7 +1148,7 @@ func (builder *FlowAccessNodeBuilder) enqueuePublicNetworkInit() { top := topology.EmptyTopology{} receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { @@ -1204,7 +1204,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: networkMetrics, }, - p2p.PublicNetwork, + network.PublicNetwork, bindAddress, networkKey, builder.SporkID, @@ -1213,7 +1213,7 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetBasicResolver(builder.Resolver). SetSubscriptionFilter( diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index c81bcae6f2d..ae50cbc938d 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -57,6 +57,7 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -488,7 +489,7 @@ func (builder *ObserverServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, }, }) if err != nil { @@ -715,7 +716,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - p2p.PublicNetwork, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -724,7 +725,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -799,7 +800,7 @@ func (builder *ObserverServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 1fb6379528b..2de8d6c4da1 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -348,7 +348,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, - p2p.PrivateNetwork, + network.PrivateNetwork, fnb.NetworkKey, fnb.SporkID, fnb.IdentityProvider, @@ -367,7 +367,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { &fnb.FlowConfig.NetworkConfig.ConnectionManagerConfig, &p2p.DisallowListCacheConfig{ MaxSize: fnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork), }) if err != nil { @@ -457,7 +457,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( receiveCache := netcache.NewHeroReceiveCache(fnb.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, fnb.Logger, - metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(fnb.HeroCacheMetricsFactory(), network.PrivateNetwork)) err := node.Metrics.Mempool.Register(metrics.ResourceNetworkingReceiveCache, receiveCache.Size) if err != nil { @@ -484,7 +484,7 @@ func (fnb *FlowNodeBuilder) InitFlowNetworkWithConduitFactory( HeartBeatInterval: fnb.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: fnb.Metrics.Network, HeroCacheMetricsFactory: fnb.HeroCacheMetricsFactory(), - NetworkType: p2p.PrivateNetwork, + NetworkType: network.PrivateNetwork, }, }) if err != nil { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index 36bb37aa77b..a801c99d2ee 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -51,6 +51,7 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -389,7 +390,7 @@ func (builder *FollowerServiceBuilder) initNetwork(nodeID module.Local, HeartBeatInterval: builder.FlowConfig.NetworkConfig.AlspConfig.HearBeatInterval, AlspMetrics: builder.Metrics.Network, HeroCacheMetricsFactory: builder.HeroCacheMetricsFactory(), - NetworkType: p2p.PublicNetwork, + NetworkType: network.PublicNetwork, }, }) if err != nil { @@ -617,7 +618,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr HeroCacheFactory: builder.HeroCacheMetricsFactory(), Metrics: builder.Metrics.Network, }, - p2p.PublicNetwork, + network.PublicNetwork, builder.BaseConfig.BindAddr, networkKey, builder.SporkID, @@ -626,7 +627,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), }). SetSubscriptionFilter( subscription.NewRoleBasedFilter( @@ -702,7 +703,7 @@ func (builder *FollowerServiceBuilder) enqueuePublicNetworkInit() { Component("public network", func(node *cmd.NodeConfig) (module.ReadyDoneAware, error) { receiveCache := netcache.NewHeroReceiveCache(builder.FlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, builder.Logger, - metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), p2p.PublicNetwork)) + metrics.NetworkReceiveCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork)) err := node.Metrics.Mempool.Register(metrics.PrependPublicPrefix(metrics.ResourceNetworkingReceiveCache), receiveCache.Size) if err != nil { diff --git a/insecure/cmd/corrupted_builder.go b/insecure/cmd/corrupted_builder.go index 71d604b69af..bd85b83768b 100644 --- a/insecure/cmd/corrupted_builder.go +++ b/insecure/cmd/corrupted_builder.go @@ -12,6 +12,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" @@ -104,7 +105,7 @@ func (cnb *CorruptedNodeBuilder) enqueueNetworkingLayer() { cnb.FlowConfig.NetworkConfig, &p2p.DisallowListCacheConfig{ MaxSize: cnb.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, - Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), p2p.PrivateNetwork), + Metrics: metrics.DisallowListCacheMetricsFactory(cnb.HeroCacheMetricsFactory(), network.PrivateNetwork), }, cnb.TopicValidatorDisabled, cnb.WithPubSubMessageSigning, diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 4715f6b768d..4b7f775971d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -15,6 +15,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" @@ -75,7 +76,7 @@ func InitCorruptLibp2pNode( builder, err := p2pbuilder.DefaultNodeBuilder( log, address, - p2p.PrivateNetwork, + network.PrivateNetwork, flowKey, sporkId, idProvider, diff --git a/module/metrics/herocache.go b/module/metrics/herocache.go index 1e5d8790bed..54e287bdb1b 100644 --- a/module/metrics/herocache.go +++ b/module/metrics/herocache.go @@ -6,7 +6,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network" ) const subsystemHeroCache = "hero_cache" @@ -64,9 +64,9 @@ func NewNoopHeroCacheMetricsFactory() HeroCacheMetricsFactory { } } -func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingReceiveCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -79,9 +79,9 @@ func NetworkReceiveCacheMetricsFactory(f HeroCacheMetricsFactory, networkType p2 // - networkingType: the networking type of the cache, i.e., whether it is used for the public or the private network // Returns: // - a HeroCacheMetrics for the disallow list cache -func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType p2p.NetworkingType) module.HeroCacheMetrics { +func DisallowListCacheMetricsFactory(f HeroCacheMetricsFactory, networkingType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingDisallowListCache - if networkingType == p2p.PublicNetwork { + if networkingType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) @@ -111,53 +111,53 @@ func DisallowListNotificationQueueMetricFactory(registrar prometheus.Registerer) return NewHeroCacheCollector(namespaceNetwork, ResourceNetworkingDisallowListNotificationQueue, registrar) } -func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamRecordCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func ApplicationLayerSpamRecordQueueMetricsFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingApplicationLayerSpamReportQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCMetricsObserverInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcMetricsObserverInspectorQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcValidationInspectorQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func RpcInspectorNotificationQueueMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { r := ResourceNetworkingRpcInspectorNotificationQueue - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) } -func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType p2p.NetworkingType) module.HeroCacheMetrics { +func GossipSubRPCInspectorClusterPrefixedCacheMetricFactory(f HeroCacheMetricsFactory, networkType network.NetworkingType) module.HeroCacheMetrics { // we don't use the public prefix for the metrics here for sake of backward compatibility of metric name. r := ResourceNetworkingRpcClusterPrefixReceivedCache - if networkType == p2p.PublicNetwork { + if networkType == network.PublicNetwork { r = PrependPublicPrefix(r) } return f(namespaceNetwork, r) diff --git a/network/alsp/manager/manager.go b/network/alsp/manager/manager.go index 9b07490ddff..941407e2637 100644 --- a/network/alsp/manager/manager.go +++ b/network/alsp/manager/manager.go @@ -21,7 +21,6 @@ import ( "github.com/onflow/flow-go/network/alsp/internal" "github.com/onflow/flow-go/network/alsp/model" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/logging" ) @@ -104,7 +103,7 @@ type MisbehaviorReportManagerConfig struct { DisablePenalty bool // NetworkType is the type of the network it is used to determine whether the ALSP module is utilized in the // public (unstaked) or private (staked) network. - NetworkType p2p.NetworkingType + NetworkType network.NetworkingType // HeartBeatInterval is the interval between the heartbeats. Heartbeat is a recurring event that is used to // apply recurring actions, e.g., decay the penalty of the misbehaving nodes. HeartBeatInterval time.Duration diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index b7dd0e7c886..de942fe83dd 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -26,6 +26,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" "github.com/onflow/flow-go/network/internal/testutils" @@ -114,7 +115,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - p2p.PrivateNetwork, + flownet.PrivateNetwork, unittest.DefaultAddress, networkKey, sporkID, diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 683e3ad6018..14fe9feb175 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -505,7 +505,7 @@ func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateK HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - p2p.PrivateNetwork, + network.PrivateNetwork, unittest.DefaultAddress, key, sporkID, diff --git a/network/network.go b/network/network.go index 47170c61d4d..703c5e627c8 100644 --- a/network/network.go +++ b/network/network.go @@ -9,6 +9,19 @@ import ( "github.com/onflow/flow-go/network/channels" ) +// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) +// and private (i.e., staked) networks. +type NetworkingType uint8 + +const ( + // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave + // with a staking requirement. + PrivateNetwork NetworkingType = iota + 1 + // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will + // with no staking requirement. + PublicNetwork +) + // Network represents the network layer of the node. It allows processes that // work across the peer-to-peer network to register themselves as an engine with // a unique engine ID. The returned conduit allows the process to communicate to diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 349381e662c..f67274199d8 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -18,6 +18,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" ) @@ -115,7 +116,7 @@ type GossipSubRpcInspectorSuiteFactoryFunc func( *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, - NetworkingType, + flownet.NetworkingType, module.IdentityProvider) (GossipSubInspectorSuite, error) // NodeBuilder is a builder pattern for creating a libp2p Node instance. diff --git a/network/p2p/networkingType.go b/network/p2p/networkingType.go deleted file mode 100644 index 14df4d0037c..00000000000 --- a/network/p2p/networkingType.go +++ /dev/null @@ -1,14 +0,0 @@ -package p2p - -// NetworkingType is the type of the Flow networking layer. It is used to differentiate between the public (i.e., unstaked) -// and private (i.e., staked) networks. -type NetworkingType uint8 - -const ( - // PrivateNetwork indicates that the staked private-side of the Flow blockchain that nodes can only join and leave - // with a staking requirement. - PrivateNetwork NetworkingType = iota + 1 - // PublicNetwork indicates that the unstaked public-side of the Flow blockchain that nodes can join and leave at will - // with no staking requirement. - PublicNetwork -) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index f0e0de50003..857e100b9d0 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -17,6 +17,7 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" @@ -32,7 +33,7 @@ import ( // The Builder struct is used to configure and create a new GossipSub pubsub system. type Builder struct { - networkType p2p.NetworkingType + networkType network.NetworkingType sporkId flow.Identifier logger zerolog.Logger metricsCfg *p2pconfig.MetricsConfig @@ -159,7 +160,7 @@ func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubR func NewGossipSubBuilder( logger zerolog.Logger, metricsCfg *p2pconfig.MetricsConfig, - networkType p2p.NetworkingType, + networkType network.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, @@ -203,7 +204,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { inspectorCfg *netconf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, - networkType p2p.NetworkingType, + networkType network.NetworkingType, idProvider module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { metricsInspector := inspector.NewControlMsgMetricsInspector( logger, diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index 461dfaad13d..c7a40a136ba 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -1,15 +1,23 @@ package inspector import ( + "fmt" + "github.com/rs/zerolog" netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" + "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" + "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" + "github.com/onflow/flow-go/network/p2p/inspector" + "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" + "github.com/onflow/flow-go/network/p2p/p2pnode" ) // GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following @@ -23,7 +31,7 @@ type GossipSubInspectorBuilder struct { metricsCfg *p2pconfig.MetricsConfig idProvider module.IdentityProvider inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType p2p.NetworkingType + networkType network.NetworkingType } // NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. @@ -38,7 +46,7 @@ func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier }, idProvider: provider, inspectorMetrics: inspectorMetrics, - networkType: p2p.PublicNetwork, + networkType: network.PublicNetwork, } } @@ -54,7 +62,7 @@ func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConf // - networkType: the network type. // Returns: // - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType p2p.NetworkingType) *GossipSubInspectorBuilder { +func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { b.networkType = networkType return b } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 3012891495a..1549efa1e29 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,6 +27,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" @@ -75,7 +76,7 @@ type LibP2PNodeBuilder struct { func NewNodeBuilder( logger zerolog.Logger, metricsConfig *p2pconfig.MetricsConfig, - networkingType p2p.NetworkingType, + networkingType flownet.NetworkingType, address string, networkKey fcrypto.PrivateKey, sporkId flow.Identifier, @@ -443,7 +444,7 @@ func DefaultCreateNodeFunc(logger zerolog.Logger, func DefaultNodeBuilder( logger zerolog.Logger, address string, - networkingType p2p.NetworkingType, + networkingType flownet.NetworkingType, flowKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 5262fef1697..c2b097ee9d4 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -25,6 +25,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" @@ -63,7 +64,7 @@ func NodeFixture( logger := unittest.Logger().Level(zerolog.WarnLevel) parameters := &NodeFixtureParameters{ - NetworkingType: p2p.PrivateNetwork, + NetworkingType: flownet.PrivateNetwork, HandlerFunc: func(network.Stream) {}, Unicasts: nil, Key: NetworkingKeyFixtures(t), @@ -178,7 +179,7 @@ type NodeFixtureParameterOption func(*NodeFixtureParameters) type NodeFixtureParameters struct { HandlerFunc network.StreamHandler - NetworkingType p2p.NetworkingType + NetworkingType flownet.NetworkingType Unicasts []protocols.ProtocolName Key crypto.PrivateKey Address string From edb27809cc65c44c5b8bf12156c0ed846edf6c9a Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:07:53 -0700 Subject: [PATCH 22/74] moves network config to a separate package --- config/network/config.go | 12 +++++++----- insecure/rpc_inspector/validation_inspector_test.go | 2 +- network/p2p/builder.go | 2 +- {config/network => network/p2p/config}/gossipsub.go | 2 +- .../p2p/config}/gossipsub_rpc_inspectors.go | 9 +++++---- .../control_message_validation_inspector.go | 2 +- .../inspector/validation/inspect_message_request.go | 2 +- .../p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 2 +- .../p2pbuilder/inspector/rpc_inspector_builder.go | 9 +-------- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 13 +++++++------ network/p2p/test/fixtures.go | 2 +- 11 files changed, 27 insertions(+), 30 deletions(-) rename {config/network => network/p2p/config}/gossipsub.go (98%) rename {config/network => network/p2p/config}/gossipsub_rpc_inspectors.go (94%) diff --git a/config/network/config.go b/config/network/config.go index 5d015191d20..5cdd091d88f 100644 --- a/config/network/config.go +++ b/config/network/config.go @@ -6,17 +6,19 @@ import ( "time" "github.com/spf13/viper" + + "github.com/onflow/flow-go/network/p2p/config" ) // Config encapsulation of configuration structs for all components related to the Flow network. type Config struct { // UnicastRateLimitersConfig configuration for all unicast rate limiters. - UnicastRateLimitersConfig `mapstructure:",squash"` - ResourceManagerConfig `mapstructure:",squash"` - ConnectionManagerConfig `mapstructure:",squash"` + UnicastRateLimitersConfig `mapstructure:",squash"` + config.ResourceManagerConfig `mapstructure:",squash"` + ConnectionManagerConfig `mapstructure:",squash"` // GossipSubConfig core gossipsub configuration. - GossipSubConfig `mapstructure:",squash"` - AlspConfig `mapstructure:",squash"` + config.GossipSubConfig `mapstructure:",squash"` + AlspConfig `mapstructure:",squash"` // NetworkConnectionPruning determines whether connections to nodes // that are not part of protocol state should be trimmed diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index e033d713071..60910313d21 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -16,7 +16,6 @@ import ( "go.uber.org/atomic" "github.com/onflow/flow-go/config" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/insecure/corruptlibp2p" "github.com/onflow/flow-go/insecure/internal" "github.com/onflow/flow-go/model/flow" @@ -25,6 +24,7 @@ import ( "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/inspector/validation" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" diff --git a/network/p2p/builder.go b/network/p2p/builder.go index f67274199d8..3d7c929abb0 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -13,13 +13,13 @@ import ( madns "github.com/multiformats/go-multiaddr-dns" "github.com/rs/zerolog" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" + netconf "github.com/onflow/flow-go/network/p2p/config" ) type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) diff --git a/config/network/gossipsub.go b/network/p2p/config/gossipsub.go similarity index 98% rename from config/network/gossipsub.go rename to network/p2p/config/gossipsub.go index c67b1174750..1e3d300706d 100644 --- a/config/network/gossipsub.go +++ b/network/p2p/config/gossipsub.go @@ -1,4 +1,4 @@ -package network +package config import ( "time" diff --git a/config/network/gossipsub_rpc_inspectors.go b/network/p2p/config/gossipsub_rpc_inspectors.go similarity index 94% rename from config/network/gossipsub_rpc_inspectors.go rename to network/p2p/config/gossipsub_rpc_inspectors.go index 040f8a9560d..b1fa217b447 100644 --- a/config/network/gossipsub_rpc_inspectors.go +++ b/network/p2p/config/gossipsub_rpc_inspectors.go @@ -1,8 +1,9 @@ -package network +package config import ( "fmt" + "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/network/p2p" ) @@ -134,11 +135,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index e2ab265b1ed..8d0de61ff3e 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -10,7 +10,6 @@ import ( "github.com/rs/zerolog" "golang.org/x/time/rate" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/engine/common/worker" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" @@ -20,6 +19,7 @@ import ( "github.com/onflow/flow-go/module/util" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" "github.com/onflow/flow-go/state/protocol" diff --git a/network/p2p/inspector/validation/inspect_message_request.go b/network/p2p/inspector/validation/inspect_message_request.go index 08cc3ab336d..4b30b0f3f3b 100644 --- a/network/p2p/inspector/validation/inspect_message_request.go +++ b/network/p2p/inspector/validation/inspect_message_request.go @@ -6,7 +6,7 @@ import ( pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" - netconf "github.com/onflow/flow-go/config/network" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/inspector/internal" ) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 857e100b9d0..4bb3f81f02f 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -11,7 +11,6 @@ import ( "github.com/libp2p/go-libp2p/core/routing" "github.com/rs/zerolog" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/irrecoverable" @@ -20,6 +19,7 @@ import ( "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index c7a40a136ba..6f3e9598d2d 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -1,23 +1,16 @@ package inspector import ( - "fmt" - "github.com/rs/zerolog" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/distributor" - "github.com/onflow/flow-go/network/p2p/inspector" - "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" - "github.com/onflow/flow-go/network/p2p/p2pnode" ) // GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 1549efa1e29..4d41bd5db43 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -29,6 +29,7 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" + config2 "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" @@ -60,7 +61,7 @@ type LibP2PNodeBuilder struct { basicResolver madns.BasicResolver resourceManager network.ResourceManager - resourceManagerCfg *netconf.ResourceManagerConfig + resourceManagerCfg *config2.ResourceManagerConfig connManager connmgr.ConnManager connGater p2p.ConnectionGater routingFactory func(context.Context, host.Host) (routing.Routing, error) @@ -81,8 +82,8 @@ func NewNodeBuilder( networkKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, - rCfg *netconf.ResourceManagerConfig, - rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, + rCfg *config2.ResourceManagerConfig, + rpcInspectorCfg *config2.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, @@ -453,9 +454,9 @@ func DefaultNodeBuilder( role string, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, - gossipCfg *netconf.GossipSubConfig, - rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, - rCfg *netconf.ResourceManagerConfig, + gossipCfg *config2.GossipSubConfig, + rpcInspectorCfg *config2.GossipSubRPCInspectorsConfig, + rCfg *config2.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index c2b097ee9d4..638639bec50 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -19,7 +19,6 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" @@ -30,6 +29,7 @@ import ( "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" From 8424613d5aff670244d0513f3662a4e38e88e34e Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:10:14 -0700 Subject: [PATCH 23/74] moves network config to a separate package --- config/base_flags.go | 2 +- config/config.go | 8 +++----- insecure/corruptlibp2p/libp2p_node_factory.go | 2 +- network/internal/testutils/testUtil.go | 2 +- {config/network => network/netconf}/config.go | 2 +- {config/network => network/netconf}/connection_manager.go | 2 +- {config/network => network/netconf}/errors.go | 2 +- {config/network => network/netconf}/errors_test.go | 2 +- {config/network => network/netconf}/flags.go | 2 +- network/p2p/config/gossipsub_rpc_inspectors.go | 7 +++---- network/p2p/connection/connManager.go | 2 +- network/p2p/connection/connManager_test.go | 2 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 2 +- 13 files changed, 17 insertions(+), 20 deletions(-) rename {config/network => network/netconf}/config.go (99%) rename {config/network => network/netconf}/connection_manager.go (99%) rename {config/network => network/netconf}/errors.go (98%) rename {config/network => network/netconf}/errors_test.go (98%) rename {config/network => network/netconf}/flags.go (99%) diff --git a/config/base_flags.go b/config/base_flags.go index 5cc22422b40..f58fc5da4ba 100644 --- a/config/base_flags.go +++ b/config/base_flags.go @@ -3,7 +3,7 @@ package config import ( "github.com/spf13/pflag" - netconf "github.com/onflow/flow-go/config/network" + netconf "github.com/onflow/flow-go/network/network" ) const ( diff --git a/config/config.go b/config/config.go index ca9da641a2c..1ab6f0ceda7 100644 --- a/config/config.go +++ b/config/config.go @@ -13,8 +13,6 @@ import ( "github.com/rs/zerolog" "github.com/spf13/pflag" "github.com/spf13/viper" - - "github.com/onflow/flow-go/config/network" ) var ( @@ -27,8 +25,8 @@ var ( // FlowConfig Flow configuration. type FlowConfig struct { // ConfigFile used to set a path to a config.yml file used to override the default-config.yml file. - ConfigFile string `validate:"filepath" mapstructure:"config-file"` - NetworkConfig *network.Config `mapstructure:"network-config"` + ConfigFile string `validate:"filepath" mapstructure:"config-file"` + NetworkConfig *config.Config `mapstructure:"network-config"` } // Validate checks validity of the Flow config. Errors indicate that either the configuration is broken, @@ -184,7 +182,7 @@ func LogConfig(logger *zerolog.Event, flags *pflag.FlagSet) map[string]struct{} // keys do not match the CLI flags 1:1. ie: networking-connection-pruning -> network-config.networking-connection-pruning. After aliases // are set the conf store will override values with any CLI flag values that are set as expected. func setAliases() { - err := network.SetAliases(conf) + err := config.SetAliases(conf) if err != nil { panic(fmt.Errorf("failed to set network aliases: %w", err)) } diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 4b7f775971d..0d20d26ee3d 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -10,12 +10,12 @@ import ( "github.com/rs/zerolog" corrupt "github.com/yhassanzadeh13/go-libp2p-pubsub" - netconf "github.com/onflow/flow-go/config/network" fcrypto "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" + netconf "github.com/onflow/flow-go/network/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 14fe9feb175..65900dc2cb1 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -20,7 +20,6 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/model/flow/filter" @@ -36,6 +35,7 @@ import ( netcache "github.com/onflow/flow-go/network/cache" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/codec/cbor" + netconf "github.com/onflow/flow-go/network/network" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/conduit" "github.com/onflow/flow-go/network/p2p/connection" diff --git a/config/network/config.go b/network/netconf/config.go similarity index 99% rename from config/network/config.go rename to network/netconf/config.go index 5cdd091d88f..417af9d4c15 100644 --- a/config/network/config.go +++ b/network/netconf/config.go @@ -1,4 +1,4 @@ -package network +package netconf import ( "fmt" diff --git a/config/network/connection_manager.go b/network/netconf/connection_manager.go similarity index 99% rename from config/network/connection_manager.go rename to network/netconf/connection_manager.go index 92503f4f7d7..333a3f8c6e5 100644 --- a/config/network/connection_manager.go +++ b/network/netconf/connection_manager.go @@ -1,4 +1,4 @@ -package network +package netconf import "time" diff --git a/config/network/errors.go b/network/netconf/errors.go similarity index 98% rename from config/network/errors.go rename to network/netconf/errors.go index 9fee981e7d5..4ffe9635b56 100644 --- a/config/network/errors.go +++ b/network/netconf/errors.go @@ -1,4 +1,4 @@ -package network +package netconf import ( "errors" diff --git a/config/network/errors_test.go b/network/netconf/errors_test.go similarity index 98% rename from config/network/errors_test.go rename to network/netconf/errors_test.go index 604314fc83c..216a1526982 100644 --- a/config/network/errors_test.go +++ b/network/netconf/errors_test.go @@ -1,4 +1,4 @@ -package network +package netconf import ( "fmt" diff --git a/config/network/flags.go b/network/netconf/flags.go similarity index 99% rename from config/network/flags.go rename to network/netconf/flags.go index 8beb0e30dc4..971c7ae6c3e 100644 --- a/config/network/flags.go +++ b/network/netconf/flags.go @@ -1,4 +1,4 @@ -package network +package netconf import ( "fmt" diff --git a/network/p2p/config/gossipsub_rpc_inspectors.go b/network/p2p/config/gossipsub_rpc_inspectors.go index b1fa217b447..2fafa77bd75 100644 --- a/network/p2p/config/gossipsub_rpc_inspectors.go +++ b/network/p2p/config/gossipsub_rpc_inspectors.go @@ -3,7 +3,6 @@ package config import ( "fmt" - "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/network/p2p" ) @@ -135,11 +134,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return network.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } diff --git a/network/p2p/connection/connManager.go b/network/p2p/connection/connManager.go index c840201e253..5a5353ac75f 100644 --- a/network/p2p/connection/connManager.go +++ b/network/p2p/connection/connManager.go @@ -10,8 +10,8 @@ import ( libp2pconnmgr "github.com/libp2p/go-libp2p/p2p/net/connmgr" "github.com/rs/zerolog" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/module" + netconf "github.com/onflow/flow-go/network/network" "github.com/onflow/flow-go/network/p2p/connection/internal" ) diff --git a/network/p2p/connection/connManager_test.go b/network/p2p/connection/connManager_test.go index 0a17f6e9b59..4da0a86bf73 100644 --- a/network/p2p/connection/connManager_test.go +++ b/network/p2p/connection/connManager_test.go @@ -12,11 +12,11 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" - netconf "github.com/onflow/flow-go/config/network" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/internal/p2pfixtures" + netconf "github.com/onflow/flow-go/network/network" "github.com/onflow/flow-go/network/p2p/connection" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/utils" diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 4d41bd5db43..02ed9eb9554 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -21,13 +21,13 @@ import ( madns "github.com/multiformats/go-multiaddr-dns" "github.com/rs/zerolog" - netconf "github.com/onflow/flow-go/config/network" fcrypto "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" flownet "github.com/onflow/flow-go/network" + netconf "github.com/onflow/flow-go/network/network" "github.com/onflow/flow-go/network/p2p" config2 "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" From 93114a2a754ce976e9b124e3a36346357a6d1292 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:11:15 -0700 Subject: [PATCH 24/74] lint fix --- config/config.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index 1ab6f0ceda7..7b91da5f79c 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,8 @@ import ( "github.com/rs/zerolog" "github.com/spf13/pflag" "github.com/spf13/viper" + + "github.com/onflow/flow-go/network/netconf" ) var ( @@ -25,8 +27,8 @@ var ( // FlowConfig Flow configuration. type FlowConfig struct { // ConfigFile used to set a path to a config.yml file used to override the default-config.yml file. - ConfigFile string `validate:"filepath" mapstructure:"config-file"` - NetworkConfig *config.Config `mapstructure:"network-config"` + ConfigFile string `validate:"filepath" mapstructure:"config-file"` + NetworkConfig *netconf.Config `mapstructure:"network-config"` } // Validate checks validity of the Flow config. Errors indicate that either the configuration is broken, From 52e5f3ed860ccc9d421421e594995daaebafc42a Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:12:46 -0700 Subject: [PATCH 25/74] lint fix --- config/config.go | 35 ++++++++++++++++++++++++++++++++++- network/netconf/config.go | 37 ------------------------------------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/config/config.go b/config/config.go index 7b91da5f79c..bbb71ad769d 100644 --- a/config/config.go +++ b/config/config.go @@ -184,12 +184,45 @@ func LogConfig(logger *zerolog.Event, flags *pflag.FlagSet) map[string]struct{} // keys do not match the CLI flags 1:1. ie: networking-connection-pruning -> network-config.networking-connection-pruning. After aliases // are set the conf store will override values with any CLI flag values that are set as expected. func setAliases() { - err := config.SetAliases(conf) + err := SetAliases(conf) if err != nil { panic(fmt.Errorf("failed to set network aliases: %w", err)) } } +// SetAliases this func sets an aliases for each CLI flag defined for network config overrides to it's corresponding +// full key in the viper config store. This is required because in our config.yml file all configuration values for the +// Flow network are stored one level down on the network-config property. When the default config is bootstrapped viper will +// store these values with the "network-config." prefix on the config key, because we do not want to use CLI flags like --network-config.networking-connection-pruning +// to override default values we instead use cleans flags like --networking-connection-pruning and create an alias from networking-connection-pruning -> network-config.networking-connection-pruning +// to ensure overrides happen as expected. +// Args: +// *viper.Viper: instance of the viper store to register network config aliases on. +// Returns: +// error: if a flag does not have a corresponding key in the viper store. +func SetAliases(conf *viper.Viper) error { + m := make(map[string]string) + // create map of key -> full pathkey + // ie: "networking-connection-pruning" -> "network-config.networking-connection-pruning" + for _, key := range conf.AllKeys() { + s := strings.Split(key, ".") + // check len of s, we expect all network keys to have a single prefix "network-config" + // s should always contain only 2 elements + if len(s) == 2 { + m[s[1]] = key + } + } + // each flag name should correspond to exactly one key in our config store after it is loaded with the default config + for _, flagName := range netconf.AllFlagNames() { + fullKey, ok := m[flagName] + if !ok { + return fmt.Errorf("invalid network configuration missing configuration key flag name %s check config file and cli flags", flagName) + } + conf.RegisterAlias(fullKey, flagName) + } + return nil +} + // overrideConfigFile overrides the default config file by reading in the config file at the path set // by the --config-file flag in our viper config store. // diff --git a/network/netconf/config.go b/network/netconf/config.go index 417af9d4c15..25137fedb70 100644 --- a/network/netconf/config.go +++ b/network/netconf/config.go @@ -1,12 +1,8 @@ package netconf import ( - "fmt" - "strings" "time" - "github.com/spf13/viper" - "github.com/onflow/flow-go/network/p2p/config" ) @@ -72,36 +68,3 @@ type AlspConfig struct { // events that are used to perform critical ALSP tasks, such as updating the spam records cache. HearBeatInterval time.Duration `mapstructure:"alsp-heart-beat-interval"` } - -// SetAliases this func sets an aliases for each CLI flag defined for network config overrides to it's corresponding -// full key in the viper config store. This is required because in our config.yml file all configuration values for the -// Flow network are stored one level down on the network-config property. When the default config is bootstrapped viper will -// store these values with the "network-config." prefix on the config key, because we do not want to use CLI flags like --network-config.networking-connection-pruning -// to override default values we instead use cleans flags like --networking-connection-pruning and create an alias from networking-connection-pruning -> network-config.networking-connection-pruning -// to ensure overrides happen as expected. -// Args: -// *viper.Viper: instance of the viper store to register network config aliases on. -// Returns: -// error: if a flag does not have a corresponding key in the viper store. -func SetAliases(conf *viper.Viper) error { - m := make(map[string]string) - // create map of key -> full pathkey - // ie: "networking-connection-pruning" -> "network-config.networking-connection-pruning" - for _, key := range conf.AllKeys() { - s := strings.Split(key, ".") - // check len of s, we expect all network keys to have a single prefix "network-config" - // s should always contain only 2 elements - if len(s) == 2 { - m[s[1]] = key - } - } - // each flag name should correspond to exactly one key in our config store after it is loaded with the default config - for _, flagName := range AllFlagNames() { - fullKey, ok := m[flagName] - if !ok { - return fmt.Errorf("invalid network configuration missing configuration key flag name %s check config file and cli flags", flagName) - } - conf.RegisterAlias(fullKey, flagName) - } - return nil -} From acb5a9f08c1d13832cfcdbf196dcd11d038a7fcc Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:13:27 -0700 Subject: [PATCH 26/74] lint fix --- config/base_flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/base_flags.go b/config/base_flags.go index f58fc5da4ba..360c4af89b6 100644 --- a/config/base_flags.go +++ b/config/base_flags.go @@ -3,7 +3,7 @@ package config import ( "github.com/spf13/pflag" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" ) const ( From a6bcca0c98b3ef4a7f521df74531c582b8a43d31 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:14:45 -0700 Subject: [PATCH 27/74] lint fix --- network/p2p/config/gossipsub_rpc_inspectors.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/network/p2p/config/gossipsub_rpc_inspectors.go b/network/p2p/config/gossipsub_rpc_inspectors.go index 2fafa77bd75..71a5745875b 100644 --- a/network/p2p/config/gossipsub_rpc_inspectors.go +++ b/network/p2p/config/gossipsub_rpc_inspectors.go @@ -3,6 +3,7 @@ package config import ( "fmt" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" ) @@ -134,11 +135,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return config.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } From ee0a1ae86c832074e84fc70156489e2af71a4672 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:40:43 -0700 Subject: [PATCH 28/74] plumbing --- cmd/collection/main.go | 9 +---- network/p2p/consumers.go | 5 +-- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 4 +- .../p2p/p2pbuilder/inspector/suite/suite.go | 14 +++++-- network/p2p/p2pnode/gossipSubAdapter.go | 7 ++-- network/p2p/scoring/scoring_test.go | 40 +++++++++++-------- 6 files changed, 42 insertions(+), 37 deletions(-) diff --git a/cmd/collection/main.go b/cmd/collection/main.go index 6a742189180..27faa959ca2 100644 --- a/cmd/collection/main.go +++ b/cmd/collection/main.go @@ -47,7 +47,6 @@ import ( "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/state/protocol" badgerState "github.com/onflow/flow-go/state/protocol/badger" "github.com/onflow/flow-go/state/protocol/blocktimer" @@ -593,13 +592,7 @@ func main() { // register the manager for protocol events node.ProtocolEvents.AddConsumer(manager) - - for _, rpcInspector := range node.GossipSubRpcInspectorSuite.Inspectors() { - if r, ok := rpcInspector.(p2p.GossipSubMsgValidationRpcInspector); ok { - clusterEvents.AddConsumer(r) - } - } - + clusterEvents.AddConsumer(node.LibP2PNode) return manager, err }) diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index ee12521aadb..3cacd174135 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -80,6 +80,7 @@ type GossipSubInvCtrlMsgNotifConsumer interface { // It encapsulates the rpc inspectors and the notification distributors. type GossipSubInspectorSuite interface { component.Component + CollectionClusterChangesConsumer // InspectFunc returns the inspect function that is used to inspect the gossipsub rpc messages. // This function follows a dependency injection pattern, where the inspect function is injected into the gossipsu, and // is called whenever a gossipsub rpc message is received. @@ -89,7 +90,5 @@ type GossipSubInspectorSuite interface { // This consumer is notified when a misbehaving peer regarding gossipsub control messages is detected. This follows a pub/sub // pattern where the consumer is notified when a new notification is published. // A consumer is only notified once for each notification, and only receives notifications that were published after it was added. - AddInvCtrlMsgNotifConsumer(GossipSubInvCtrlMsgNotifConsumer) - // Inspectors returns all inspectors in the inspector suite. - Inspectors() []GossipSubRPCInspector + AddInvalidControlMessageConsumer(GossipSubInvCtrlMsgNotifConsumer) } diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 4bb3f81f02f..22bca367ff2 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -278,7 +278,7 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer if g.gossipSubPeerScoring { - g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(inspectorSuite.AddInvCtrlMsgNotifConsumer) + g.scoreOptionConfig.SetRegisterNotificationConsumerFunc(inspectorSuite.AddInvalidControlMessageConsumer) scoreOpt = scoring.NewScoreOption(g.scoreOptionConfig) gossipSubConfigs.WithScoreOption(scoreOpt) @@ -301,7 +301,7 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p return nil, nil, fmt.Errorf("could not create gossipsub: host is nil") } - gossipSub, err := g.gossipSubFactory(ctx, g.logger, g.h, gossipSubConfigs) + gossipSub, err := g.gossipSubFactory(ctx, g.logger, g.h, gossipSubConfigs, inspectorSuite) if err != nil { return nil, nil, fmt.Errorf("could not create gossipsub: %w", err) } diff --git a/network/p2p/p2pbuilder/inspector/suite/suite.go b/network/p2p/p2pbuilder/inspector/suite/suite.go index 6271d627cf4..97f151f9861 100644 --- a/network/p2p/p2pbuilder/inspector/suite/suite.go +++ b/network/p2p/p2pbuilder/inspector/suite/suite.go @@ -4,6 +4,7 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" @@ -17,6 +18,8 @@ type GossipSubInspectorSuite struct { ctrlMsgInspectDistributor p2p.GossipSubInspectorNotifDistributor } +var _ p2p.GossipSubInspectorSuite = (*GossipSubInspectorSuite)(nil) + // NewGossipSubInspectorSuite creates a new GossipSubInspectorSuite. // The suite is composed of the aggregated inspector, which is used to inspect the gossipsub rpc messages, and the // control message notification distributor, which is used to notify consumers when a misbehaving peer regarding gossipsub @@ -66,11 +69,14 @@ func (s *GossipSubInspectorSuite) InspectFunc() func(peer.ID, *pubsub.RPC) error // This consumer is notified when a misbehaving peer regarding gossipsub control messages is detected. This follows a pub/sub // pattern where the consumer is notified when a new notification is published. // A consumer is only notified once for each notification, and only receives notifications that were published after it was added. -func (s *GossipSubInspectorSuite) AddInvCtrlMsgNotifConsumer(c p2p.GossipSubInvCtrlMsgNotifConsumer) { +func (s *GossipSubInspectorSuite) AddInvalidControlMessageConsumer(c p2p.GossipSubInvCtrlMsgNotifConsumer) { s.ctrlMsgInspectDistributor.AddConsumer(c) } -// Inspectors returns all inspectors in the inspector suite. -func (s *GossipSubInspectorSuite) Inspectors() []p2p.GossipSubRPCInspector { - return s.aggregatedInspector.Inspectors() +func (s *GossipSubInspectorSuite) ActiveClustersChanged(list flow.ChainIDList) { + for _, rpcInspector := range s.aggregatedInspector.Inspectors() { + if r, ok := rpcInspector.(p2p.GossipSubMsgValidationRpcInspector); ok { + r.ActiveClustersChanged(list) + } + } } diff --git a/network/p2p/p2pnode/gossipSubAdapter.go b/network/p2p/p2pnode/gossipSubAdapter.go index b5c67c466e2..1ff4b3a3349 100644 --- a/network/p2p/p2pnode/gossipSubAdapter.go +++ b/network/p2p/p2pnode/gossipSubAdapter.go @@ -27,7 +27,7 @@ type GossipSubAdapter struct { var _ p2p.PubSubAdapter = (*GossipSubAdapter)(nil) -func NewGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host, cfg p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, error) { +func NewGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host, cfg p2p.PubSubAdapterConfig, clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, error) { gossipSubConfig, ok := cfg.(*GossipSubAdapterConfig) if !ok { return nil, fmt.Errorf("invalid gossipsub config type: %T", cfg) @@ -41,8 +41,9 @@ func NewGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host builder := component.NewComponentManagerBuilder() a := &GossipSubAdapter{ - gossipSub: gossipSub, - logger: logger, + gossipSub: gossipSub, + logger: logger, + clusterChangeConsumer: clusterChangeConsumer, } if scoreTracer := gossipSubConfig.ScoreTracer(); scoreTracer != nil { diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index 49327085b45..3d3bc2a7936 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -9,16 +9,21 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" + "github.com/rs/zerolog" mocktestify "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/onflow/flow-go/model/flow" + "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/id" "github.com/onflow/flow-go/module/irrecoverable" + "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/module/mock" + flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + netconf "github.com/onflow/flow-go/network/p2p/config" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -34,6 +39,14 @@ type mockInspectorSuite struct { // ensures that mockInspectorSuite implements the GossipSubInspectorSuite interface. var _ p2p.GossipSubInspectorSuite = (*mockInspectorSuite)(nil) +func (m *mockInspectorSuite) AddInvalidControlMessageConsumer(consumer p2p.GossipSubInvCtrlMsgNotifConsumer) { + require.Nil(m.t, m.consumer) + m.consumer = consumer +} +func (m *mockInspectorSuite) ActiveClustersChanged(_ flow.ChainIDList) { + // no-op +} + // newMockInspectorSuite creates a new mockInspectorSuite. // Args: // - t: the test object used for assertions. @@ -60,22 +73,6 @@ func (m *mockInspectorSuite) InspectFunc() func(peer.ID, *pubsub.RPC) error { return nil } -// AddInvCtrlMsgNotifConsumer adds a consumer for invalid control message notifications. -// In this mock implementation, the consumer is stored in the mockInspectorSuite, and is used to simulate the reception of invalid control messages. -// Args: -// - c: the consumer to add. -// Returns: -// - nil. -// Note: this function will fail the test if the consumer is already set. -func (m *mockInspectorSuite) AddInvCtrlMsgNotifConsumer(c p2p.GossipSubInvCtrlMsgNotifConsumer) { - require.Nil(m.t, m.consumer) - m.consumer = c -} - -func (m *mockInspectorSuite) Inspectors() []p2p.GossipSubRPCInspector { - return []p2p.GossipSubRPCInspector{} -} - // TestInvalidCtrlMsgScoringIntegration tests the impact of invalid control messages on the scoring and connectivity of nodes in a network. // It creates a network of 2 nodes, and sends a set of control messages with invalid topic IDs to one of the nodes. // It then checks that the node receiving the invalid control messages decreases its score for the peer spamming the invalid messages, and @@ -95,7 +92,16 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { idProvider, p2ptest.WithRole(flow.RoleConsensus), p2ptest.WithPeerScoringEnabled(idProvider), - p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(inspectorSuite1)) + p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(func(zerolog.Logger, + flow.Identifier, + *netconf.GossipSubRPCInspectorsConfig, + module.GossipSubMetrics, + metrics.HeroCacheMetricsFactory, + flownet.NetworkingType, + module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { + // override the gossipsub rpc inspector suite factory to return the mock inspector suite + return inspectorSuite1, nil + })) node2, id2 := p2ptest.NodeFixture( t, From 77659911f5c2cb0847a80c7e52a3ff35181e83a5 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:41:54 -0700 Subject: [PATCH 29/74] lint fix --- network/internal/testutils/testUtil.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 65900dc2cb1..7aad86cda66 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -35,7 +35,7 @@ import ( netcache "github.com/onflow/flow-go/network/cache" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/codec/cbor" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/conduit" "github.com/onflow/flow-go/network/p2p/connection" From 398f729931357eec55737119471a159d817edcd0 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:43:58 -0700 Subject: [PATCH 30/74] lint fix --- network/p2p/connection/connManager.go | 2 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/network/p2p/connection/connManager.go b/network/p2p/connection/connManager.go index 5a5353ac75f..54d85175cce 100644 --- a/network/p2p/connection/connManager.go +++ b/network/p2p/connection/connManager.go @@ -11,7 +11,7 @@ import ( "github.com/rs/zerolog" "github.com/onflow/flow-go/module" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p/connection/internal" ) diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 02ed9eb9554..973489387d9 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -27,7 +27,7 @@ import ( "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" flownet "github.com/onflow/flow-go/network" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" config2 "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" From 05c953439ba41cc02277b865307e463cd460a4fb Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:45:19 -0700 Subject: [PATCH 31/74] lint fix --- insecure/corruptlibp2p/libp2p_node_factory.go | 2 +- network/p2p/connection/connManager_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/insecure/corruptlibp2p/libp2p_node_factory.go b/insecure/corruptlibp2p/libp2p_node_factory.go index 0d20d26ee3d..43096e01f98 100644 --- a/insecure/corruptlibp2p/libp2p_node_factory.go +++ b/insecure/corruptlibp2p/libp2p_node_factory.go @@ -15,7 +15,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" diff --git a/network/p2p/connection/connManager_test.go b/network/p2p/connection/connManager_test.go index 4da0a86bf73..a9c66179969 100644 --- a/network/p2p/connection/connManager_test.go +++ b/network/p2p/connection/connManager_test.go @@ -16,7 +16,7 @@ import ( "github.com/onflow/flow-go/module/metrics" mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/internal/p2pfixtures" - netconf "github.com/onflow/flow-go/network/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p/connection" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/utils" From aac4486ce8c2091a45b734bc6d921e39fa60827c Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 15:47:43 -0700 Subject: [PATCH 32/74] lint fix --- insecure/rpc_inspector/validation_inspector_test.go | 2 +- network/netconf/config.go | 12 +++++------- network/{p2p/config => netconf}/gossipsub.go | 2 +- .../config => netconf}/gossipsub_rpc_inspectors.go | 9 ++++----- network/p2p/builder.go | 2 +- .../control_message_validation_inspector.go | 2 +- .../inspector/validation/inspect_message_request.go | 2 +- .../p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 2 +- .../p2pbuilder/inspector/rpc_inspector_builder.go | 2 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 13 ++++++------- network/p2p/scoring/scoring_test.go | 2 +- network/p2p/test/fixtures.go | 2 +- 12 files changed, 24 insertions(+), 28 deletions(-) rename network/{p2p/config => netconf}/gossipsub.go (98%) rename network/{p2p/config => netconf}/gossipsub_rpc_inspectors.go (94%) diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index 60910313d21..b79c0562675 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -23,8 +23,8 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/inspector/validation" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" diff --git a/network/netconf/config.go b/network/netconf/config.go index 25137fedb70..5675ca38043 100644 --- a/network/netconf/config.go +++ b/network/netconf/config.go @@ -2,19 +2,17 @@ package netconf import ( "time" - - "github.com/onflow/flow-go/network/p2p/config" ) // Config encapsulation of configuration structs for all components related to the Flow network. type Config struct { // UnicastRateLimitersConfig configuration for all unicast rate limiters. - UnicastRateLimitersConfig `mapstructure:",squash"` - config.ResourceManagerConfig `mapstructure:",squash"` - ConnectionManagerConfig `mapstructure:",squash"` + UnicastRateLimitersConfig `mapstructure:",squash"` + ResourceManagerConfig `mapstructure:",squash"` + ConnectionManagerConfig `mapstructure:",squash"` // GossipSubConfig core gossipsub configuration. - config.GossipSubConfig `mapstructure:",squash"` - AlspConfig `mapstructure:",squash"` + GossipSubConfig `mapstructure:",squash"` + AlspConfig `mapstructure:",squash"` // NetworkConnectionPruning determines whether connections to nodes // that are not part of protocol state should be trimmed diff --git a/network/p2p/config/gossipsub.go b/network/netconf/gossipsub.go similarity index 98% rename from network/p2p/config/gossipsub.go rename to network/netconf/gossipsub.go index 1e3d300706d..ca01d36a244 100644 --- a/network/p2p/config/gossipsub.go +++ b/network/netconf/gossipsub.go @@ -1,4 +1,4 @@ -package config +package netconf import ( "time" diff --git a/network/p2p/config/gossipsub_rpc_inspectors.go b/network/netconf/gossipsub_rpc_inspectors.go similarity index 94% rename from network/p2p/config/gossipsub_rpc_inspectors.go rename to network/netconf/gossipsub_rpc_inspectors.go index 71a5745875b..3177748f20c 100644 --- a/network/p2p/config/gossipsub_rpc_inspectors.go +++ b/network/netconf/gossipsub_rpc_inspectors.go @@ -1,9 +1,8 @@ -package config +package netconf import ( "fmt" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" ) @@ -135,11 +134,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 3d7c929abb0..043f467a326 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -19,7 +19,7 @@ import ( "github.com/onflow/flow-go/module/metrics" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" - netconf "github.com/onflow/flow-go/network/p2p/config" + "github.com/onflow/flow-go/network/netconf" ) type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 8d0de61ff3e..9b0511cc340 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -18,8 +18,8 @@ import ( "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/util" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" "github.com/onflow/flow-go/state/protocol" diff --git a/network/p2p/inspector/validation/inspect_message_request.go b/network/p2p/inspector/validation/inspect_message_request.go index 4b30b0f3f3b..46e35250a36 100644 --- a/network/p2p/inspector/validation/inspect_message_request.go +++ b/network/p2p/inspector/validation/inspect_message_request.go @@ -6,7 +6,7 @@ import ( pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" - netconf "github.com/onflow/flow-go/network/p2p/config" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p/inspector/internal" ) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 22bca367ff2..118b5425093 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -18,8 +18,8 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go index 6f3e9598d2d..ece8848c39b 100644 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go @@ -7,8 +7,8 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/distributor" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" ) diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 973489387d9..5d6fb43a1d3 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -29,7 +29,6 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - config2 "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" @@ -61,7 +60,7 @@ type LibP2PNodeBuilder struct { basicResolver madns.BasicResolver resourceManager network.ResourceManager - resourceManagerCfg *config2.ResourceManagerConfig + resourceManagerCfg *netconf.ResourceManagerConfig connManager connmgr.ConnManager connGater p2p.ConnectionGater routingFactory func(context.Context, host.Host) (routing.Routing, error) @@ -82,8 +81,8 @@ func NewNodeBuilder( networkKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, - rCfg *config2.ResourceManagerConfig, - rpcInspectorCfg *config2.GossipSubRPCInspectorsConfig, + rCfg *netconf.ResourceManagerConfig, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, @@ -454,9 +453,9 @@ func DefaultNodeBuilder( role string, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, - gossipCfg *config2.GossipSubConfig, - rpcInspectorCfg *config2.GossipSubRPCInspectorsConfig, - rCfg *config2.ResourceManagerConfig, + gossipCfg *netconf.GossipSubConfig, + rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, + rCfg *netconf.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index 3d3bc2a7936..0ae52257e8c 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -22,8 +22,8 @@ import ( "github.com/onflow/flow-go/module/mock" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 638639bec50..98de6827d56 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -28,8 +28,8 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - netconf "github.com/onflow/flow-go/network/p2p/config" "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" From c130132602f482f4b6625e43aab949d7dd08637f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:47:40 -0700 Subject: [PATCH 33/74] lint fix --- .../validation_inspector_test.go | 36 +++++++------- network/netconf/errors.go | 4 +- network/netconf/errors_test.go | 4 +- network/netconf/flags.go | 4 +- network/netconf/gossipsub_rpc_inspectors.go | 36 +++++++++----- network/p2p/consumers.go | 23 ++------- .../distributor/gossipsub_inspector_test.go | 3 +- .../control_message_validation_inspector.go | 48 +++++++++---------- network/p2p/inspector/validation/errors.go | 10 ++-- .../p2p/inspector/validation/errors_test.go | 6 +-- network/p2p/scoring/registry.go | 9 ++-- network/p2p/scoring/registry_test.go | 45 ++++++++--------- 12 files changed, 112 insertions(+), 116 deletions(-) diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index b79c0562675..1548c4a34ab 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -48,9 +48,9 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { inspectorConfig.PruneLimits.SafetyThreshold = safetyThreshold // expected log message logged when valid number GRAFT control messages spammed under safety threshold - graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2p.CtrlMsgGraft) + graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", netconf.CtrlMsgGraft) // expected log message logged when valid number PRUNE control messages spammed under safety threshold - pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2p.CtrlMsgGraft) + pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", netconf.CtrlMsgGraft) graftInfoLogsReceived := atomic.NewInt64(0) pruneInfoLogsReceived := atomic.NewInt64(0) // setup logger hook, we expect info log validation is skipped @@ -126,9 +126,9 @@ func TestValidationInspector_HardThreshold_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -194,7 +194,7 @@ func TestValidationInspector_HardThresholdIHave_Detection(t *testing.T) { require.Equal(t, uint64(messageCount), notification.Count) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: invIhaveNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -257,9 +257,9 @@ func TestValidationInspector_RateLimitedPeer_Detection(t *testing.T) { require.True(t, validation.IsErrRateLimitedControlMsg(notification.Err)) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -353,13 +353,13 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: require.Equal(t, uint64(ihaveMessageCount), notification.Count) invIHaveNotifCount.Inc() default: @@ -461,9 +461,9 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { require.True(t, validation.IsErrDuplicateTopic(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -538,9 +538,9 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { require.True(t, channels.IsUnknownClusterIDErr(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -608,7 +608,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -672,7 +672,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -745,9 +745,9 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { require.True(t, validation.IsErrUnstakedPeer(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") diff --git a/network/netconf/errors.go b/network/netconf/errors.go index 4ffe9635b56..206b2206341 100644 --- a/network/netconf/errors.go +++ b/network/netconf/errors.go @@ -3,8 +3,6 @@ package netconf import ( "errors" "fmt" - - "github.com/onflow/flow-go/network/p2p" ) // InvalidLimitConfigError indicates the validation limit is < 0. @@ -21,7 +19,7 @@ func (e InvalidLimitConfigError) Unwrap() error { } // NewInvalidLimitConfigErr returns a new ErrValidationLimit. -func NewInvalidLimitConfigErr(controlMsg p2p.ControlMessageType, err error) InvalidLimitConfigError { +func NewInvalidLimitConfigErr(controlMsg ControlMessageType, err error) InvalidLimitConfigError { return InvalidLimitConfigError{fmt.Errorf("invalid rpc control message %s validation limit configuration: %w", controlMsg, err)} } diff --git a/network/netconf/errors_test.go b/network/netconf/errors_test.go index 216a1526982..b5cb4626de6 100644 --- a/network/netconf/errors_test.go +++ b/network/netconf/errors_test.go @@ -5,13 +5,11 @@ import ( "testing" "github.com/stretchr/testify/assert" - - "github.com/onflow/flow-go/network/p2p" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. func TestErrInvalidLimitConfigRoundTrip(t *testing.T) { - controlMsg := p2p.CtrlMsgGraft + controlMsg := CtrlMsgGraft limit := uint64(500) e := fmt.Errorf("invalid rate limit value %d must be greater than 0", limit) diff --git a/network/netconf/flags.go b/network/netconf/flags.go index 971c7ae6c3e..36bcc18c10b 100644 --- a/network/netconf/flags.go +++ b/network/netconf/flags.go @@ -5,8 +5,6 @@ import ( "strings" "github.com/spf13/pflag" - - "github.com/onflow/flow-go/network/p2p" ) const ( @@ -137,7 +135,7 @@ func initRpcInspectorValidationLimitsFlags(flags *pflag.FlagSet, defaultNetConfi for _, ctrlMsgValidationConfig := range validationInspectorConfig.AllCtrlMsgValidationConfig() { ctrlMsgType := ctrlMsgValidationConfig.ControlMsg - if ctrlMsgValidationConfig.ControlMsg == p2p.CtrlMsgIWant { + if ctrlMsgValidationConfig.ControlMsg == CtrlMsgIWant { continue } s := strings.ToLower(ctrlMsgType.String()) diff --git a/network/netconf/gossipsub_rpc_inspectors.go b/network/netconf/gossipsub_rpc_inspectors.go index 3177748f20c..3cce29d9888 100644 --- a/network/netconf/gossipsub_rpc_inspectors.go +++ b/network/netconf/gossipsub_rpc_inspectors.go @@ -2,8 +2,20 @@ package netconf import ( "fmt" +) + +// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. +type ControlMessageType string + +func (c ControlMessageType) String() string { + return string(c) +} - "github.com/onflow/flow-go/network/p2p" +const ( + CtrlMsgIHave ControlMessageType = "IHAVE" + CtrlMsgIWant ControlMessageType = "IWANT" + CtrlMsgGraft ControlMessageType = "GRAFT" + CtrlMsgPrune ControlMessageType = "PRUNE" ) // GossipSubRPCInspectorsConfig encompasses configuration related to gossipsub RPC message inspectors. @@ -62,25 +74,25 @@ type GossipSubRPCValidationInspectorConfigs struct { } // GetCtrlMsgValidationConfig returns the CtrlMsgValidationConfig for the specified p2p.ControlMessageType. -func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg p2p.ControlMessageType) (*CtrlMsgValidationConfig, bool) { +func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg ControlMessageType) (*CtrlMsgValidationConfig, bool) { switch controlMsg { - case p2p.CtrlMsgGraft: + case CtrlMsgGraft: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgGraft, + ControlMsg: CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, true - case p2p.CtrlMsgPrune: + case CtrlMsgPrune: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgPrune, + ControlMsg: CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, true - case p2p.CtrlMsgIHave: + case CtrlMsgIHave: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgIHave, + ControlMsg: CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -93,17 +105,17 @@ func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(c // AllCtrlMsgValidationConfig returns all control message validation configs in a list. func (conf *GossipSubRPCValidationInspectorConfigs) AllCtrlMsgValidationConfig() CtrlMsgValidationConfigs { return CtrlMsgValidationConfigs{&CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgGraft, + ControlMsg: CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgPrune, + ControlMsg: CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgIHave, + ControlMsg: CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -116,7 +128,7 @@ type CtrlMsgValidationConfigs []*CtrlMsgValidationConfig // CtrlMsgValidationConfig configuration values for upper, lower threshold and rate limit. type CtrlMsgValidationConfig struct { // ControlMsg the type of RPC control message. - ControlMsg p2p.ControlMessageType + ControlMsg ControlMessageType // HardThreshold specifies the hard limit for the size of an RPC control message. // While it is generally expected that RPC messages with a size greater than HardThreshold should be dropped, // there are exceptions. For instance, if the message is an 'iHave', blocking processing is performed diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index 3cacd174135..fc3f641f928 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -5,25 +5,12 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/module/component" -) - -// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. -type ControlMessageType string - -func (c ControlMessageType) String() string { - return string(c) -} - -const ( - CtrlMsgIHave ControlMessageType = "IHAVE" - CtrlMsgIWant ControlMessageType = "IWANT" - CtrlMsgGraft ControlMessageType = "GRAFT" - CtrlMsgPrune ControlMessageType = "PRUNE" + "github.com/onflow/flow-go/network/netconf" ) // ControlMessageTypes returns list of all libp2p control message types. -func ControlMessageTypes() []ControlMessageType { - return []ControlMessageType{CtrlMsgIHave, CtrlMsgIWant, CtrlMsgGraft, CtrlMsgPrune} +func ControlMessageTypes() []netconf.ControlMessageType { + return []netconf.ControlMessageType{netconf.CtrlMsgIHave, netconf.CtrlMsgIWant, netconf.CtrlMsgGraft, netconf.CtrlMsgPrune} } // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. @@ -48,7 +35,7 @@ type InvCtrlMsgNotif struct { // PeerID is the ID of the peer that sent the invalid control message. PeerID peer.ID // MsgType is the type of control message that was received. - MsgType ControlMessageType + MsgType netconf.ControlMessageType // Count is the number of invalid control messages received from the peer that is reported in this notification. Count uint64 // Err any error associated with the invalid control message. @@ -56,7 +43,7 @@ type InvCtrlMsgNotif struct { } // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif -func NewInvalidControlMessageNotification(peerID peer.ID, msgType ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { +func NewInvalidControlMessageNotification(peerID peer.ID, msgType netconf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { return &InvCtrlMsgNotif{ PeerID: peerID, MsgType: msgType, diff --git a/network/p2p/distributor/gossipsub_inspector_test.go b/network/p2p/distributor/gossipsub_inspector_test.go index e5e94af36ce..afab4490c87 100644 --- a/network/p2p/distributor/gossipsub_inspector_test.go +++ b/network/p2p/distributor/gossipsub_inspector_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/module/irrecoverable" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" mockp2p "github.com/onflow/flow-go/network/p2p/mock" @@ -94,7 +95,7 @@ func invalidControlMessageNotificationListFixture(t *testing.T, n int) []*p2p.In func invalidControlMessageNotificationFixture(t *testing.T) *p2p.InvCtrlMsgNotif { return &p2p.InvCtrlMsgNotif{ PeerID: p2ptest.PeerIdFixture(t), - MsgType: []p2p.ControlMessageType{p2p.CtrlMsgGraft, p2p.CtrlMsgPrune, p2p.CtrlMsgIHave, p2p.CtrlMsgIWant}[rand.Intn(4)], + MsgType: []netconf.ControlMessageType{netconf.CtrlMsgGraft, netconf.CtrlMsgPrune, netconf.CtrlMsgIHave, netconf.CtrlMsgIWant}[rand.Intn(4)], Count: rand.Uint64(), } } diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 9b0511cc340..5333f049882 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -52,7 +52,7 @@ type ControlMsgValidationInspector struct { // In such cases, the inspector will allow a configured number of these messages from the corresponding peer. tracker *cache.ClusterPrefixedMessagesReceivedTracker idProvider module.IdentityProvider - rateLimiters map[p2p.ControlMessageType]p2p.BasicRateLimiter + rateLimiters map[netconf.ControlMessageType]p2p.BasicRateLimiter } var _ component.Component = (*ControlMsgValidationInspector)(nil) @@ -95,7 +95,7 @@ func NewControlMsgValidationInspector( tracker: tracker, idProvider: idProvider, metrics: inspectorMetrics, - rateLimiters: make(map[p2p.ControlMessageType]p2p.BasicRateLimiter), + rateLimiters: make(map[netconf.ControlMessageType]p2p.BasicRateLimiter), } store := queue.NewHeroStore(config.CacheSize, logger, inspectMsgQueueCacheCollector) @@ -158,7 +158,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e } switch ctrlMsgType { - case p2p.CtrlMsgGraft, p2p.CtrlMsgPrune: + case netconf.CtrlMsgGraft, netconf.CtrlMsgPrune: // normal pre-processing err := c.blockingPreprocessingRpc(from, validationConfig, control) if err != nil { @@ -167,7 +167,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e Msg("could not pre-process rpc, aborting") return fmt.Errorf("could not pre-process rpc, aborting: %w", err) } - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: // iHave specific pre-processing sampleSize := util.SampleN(len(control.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveSyncInspectSampleSizePercentage) err := c.blockingIHaveSamplePreprocessing(from, validationConfig, control, sampleSize) @@ -211,8 +211,8 @@ func (c *ControlMsgValidationInspector) ActiveClustersChanged(clusterIDList flow // // blockingPreprocessingRpc generic pre-processing validation func that ensures the RPC control message count does not exceed the configured hard threshold. func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { - if validationConfig.ControlMsg != p2p.CtrlMsgGraft && validationConfig.ControlMsg != p2p.CtrlMsgPrune { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, p2p.CtrlMsgGraft, p2p.CtrlMsgPrune) + if validationConfig.ControlMsg != netconf.CtrlMsgGraft && validationConfig.ControlMsg != netconf.CtrlMsgPrune { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, netconf.CtrlMsgGraft, netconf.CtrlMsgPrune) } count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) lg := c.logger.With(). @@ -250,10 +250,10 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, v // blockingPreprocessingSampleRpc blocking pre-processing of a sample of iHave control messages. func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - c.metrics.BlockingPreProcessingStarted(p2p.CtrlMsgIHave.String(), sampleSize) + c.metrics.BlockingPreProcessingStarted(netconf.CtrlMsgIHave.String(), sampleSize) start := time.Now() defer func() { - c.metrics.BlockingPreProcessingFinished(p2p.CtrlMsgIHave.String(), sampleSize, time.Since(start)) + c.metrics.BlockingPreProcessingFinished(netconf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) }() err := c.blockingPreprocessingSampleRpc(from, validationConfig, controlMessage, sampleSize) if err != nil { @@ -266,8 +266,8 @@ func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from pe // If the RPC control message count exceeds the configured hard threshold we perform synchronous topic validation on a subset // of the control messages. This is used for control message types that do not have an upper bound on the amount of messages a node can send. func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - if validationConfig.ControlMsg != p2p.CtrlMsgIHave && validationConfig.ControlMsg != p2p.CtrlMsgIWant { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, p2p.CtrlMsgIHave, p2p.CtrlMsgIWant) + if validationConfig.ControlMsg != netconf.CtrlMsgIHave && validationConfig.ControlMsg != netconf.CtrlMsgIWant { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, netconf.CtrlMsgIHave, netconf.CtrlMsgIWant) } activeClusterIDS := c.tracker.GetActiveClusterIds() count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) @@ -279,7 +279,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer if count > validationConfig.HardThreshold { // for iHave control message topic validation we only validate a random subset of the messages // shuffle the ihave messages to perform random validation on a subset of size sampleSize - err := c.sampleCtrlMessages(p2p.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(netconf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -305,7 +305,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // to randomize async validation to avoid data race that can occur when // performing the sampling asynchronously. // for iHave control message topic validation we only validate a random subset of the messages - err := c.sampleCtrlMessages(p2p.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(netconf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -314,9 +314,9 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // sampleCtrlMessages performs sampling on the specified control message that will randomize // the items in the control message slice up to index sampleSize-1. -func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType p2p.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { +func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType netconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { switch ctrlMsgType { - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: iHaves := ctrlMsg.GetIhave() swap := func(i, j uint) { iHaves[i], iHaves[j] = iHaves[j], iHaves[i] @@ -375,13 +375,13 @@ func (c *ControlMsgValidationInspector) processInspectMsgReq(req *InspectMsgRequ } // getCtrlMsgCount returns the amount of specified control message type in the rpc ControlMessage. -func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2p.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { +func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType netconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { switch ctrlMsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: return uint64(len(ctrlMsg.GetGraft())) - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: return uint64(len(ctrlMsg.GetPrune())) - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: return uint64(len(ctrlMsg.GetIhave())) default: return 0 @@ -395,17 +395,17 @@ func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2p.ControlM func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { activeClusterIDS := c.tracker.GetActiveClusterIds() switch validationConfig.ControlMsg { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: return c.validateGrafts(from, ctrlMsg, activeClusterIDS) - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: return c.validatePrunes(from, ctrlMsg, activeClusterIDS) - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: return c.validateIhaves(from, validationConfig, ctrlMsg, activeClusterIDS) default: // sanity check // This should never happen validateTopics is only used to validate GRAFT and PRUNE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", p2p.CtrlMsgGraft, p2p.CtrlMsgPrune, p2p.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", netconf.CtrlMsgGraft, netconf.CtrlMsgPrune, netconf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } @@ -456,7 +456,7 @@ func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationC func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { tracker := make(duplicateTopicTracker) switch validationConfig.ControlMsg { - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: for i := uint(0); i < sampleSize; i++ { topic := channels.Topic(ctrlMsg.Ihave[i].GetTopicID()) if tracker.isDuplicate(topic) { @@ -472,7 +472,7 @@ func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, valid // sanity check // This should never happen validateTopicsSample is only used to validate IHAVE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", p2p.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", netconf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } diff --git a/network/p2p/inspector/validation/errors.go b/network/p2p/inspector/validation/errors.go index 9842ac449c8..cac5e1e6185 100644 --- a/network/p2p/inspector/validation/errors.go +++ b/network/p2p/inspector/validation/errors.go @@ -5,13 +5,13 @@ import ( "fmt" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/netconf" ) // ErrHardThreshold indicates that the amount of RPC messages received exceeds hard threshold. type ErrHardThreshold struct { // controlMsg the control message type. - controlMsg p2p.ControlMessageType + controlMsg netconf.ControlMessageType // amount the amount of control messages. amount uint64 // hardThreshold configured hard threshold. @@ -23,7 +23,7 @@ func (e ErrHardThreshold) Error() string { } // NewHardThresholdErr returns a new ErrHardThreshold. -func NewHardThresholdErr(controlMsg p2p.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { +func NewHardThresholdErr(controlMsg netconf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { return ErrHardThreshold{controlMsg: controlMsg, amount: amount, hardThreshold: hardThreshold} } @@ -35,7 +35,7 @@ func IsErrHardThreshold(err error) bool { // ErrRateLimitedControlMsg indicates the specified RPC control message is rate limited for the specified peer. type ErrRateLimitedControlMsg struct { - controlMsg p2p.ControlMessageType + controlMsg netconf.ControlMessageType } func (e ErrRateLimitedControlMsg) Error() string { @@ -43,7 +43,7 @@ func (e ErrRateLimitedControlMsg) Error() string { } // NewRateLimitedControlMsgErr returns a new ErrValidationLimit. -func NewRateLimitedControlMsgErr(controlMsg p2p.ControlMessageType) ErrRateLimitedControlMsg { +func NewRateLimitedControlMsgErr(controlMsg netconf.ControlMessageType) ErrRateLimitedControlMsg { return ErrRateLimitedControlMsg{controlMsg: controlMsg} } diff --git a/network/p2p/inspector/validation/errors_test.go b/network/p2p/inspector/validation/errors_test.go index 355b403e908..c895c27490a 100644 --- a/network/p2p/inspector/validation/errors_test.go +++ b/network/p2p/inspector/validation/errors_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/netconf" ) // TestErrActiveClusterIDsNotSetRoundTrip ensures correct error formatting for ErrActiveClusterIdsNotSet. @@ -29,7 +29,7 @@ func TestErrActiveClusterIDsNotSetRoundTrip(t *testing.T) { // TestErrHardThresholdRoundTrip ensures correct error formatting for ErrHardThreshold. func TestErrHardThresholdRoundTrip(t *testing.T) { - controlMsg := p2p.CtrlMsgGraft + controlMsg := netconf.CtrlMsgGraft amount := uint64(100) hardThreshold := uint64(500) err := NewHardThresholdErr(controlMsg, amount, hardThreshold) @@ -48,7 +48,7 @@ func TestErrHardThresholdRoundTrip(t *testing.T) { // TestErrRateLimitedControlMsgRoundTrip ensures correct error formatting for ErrRateLimitedControlMsg. func TestErrRateLimitedControlMsgRoundTrip(t *testing.T) { - controlMsg := p2p.CtrlMsgGraft + controlMsg := netconf.CtrlMsgGraft err := NewRateLimitedControlMsgErr(controlMsg) // tests the error message formatting. diff --git a/network/p2p/scoring/registry.go b/network/p2p/scoring/registry.go index 15c67d55b33..0377816015e 100644 --- a/network/p2p/scoring/registry.go +++ b/network/p2p/scoring/registry.go @@ -9,6 +9,7 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" "github.com/onflow/flow-go/utils/logging" @@ -253,13 +254,13 @@ func (r *GossipSubAppSpecificScoreRegistry) OnInvalidControlMessageNotification( record, err := r.spamScoreCache.Update(notification.PeerID, func(record p2p.GossipSubSpamRecord) p2p.GossipSubSpamRecord { switch notification.MsgType { - case p2p.CtrlMsgGraft: + case netconf.CtrlMsgGraft: record.Penalty += r.penalty.Graft - case p2p.CtrlMsgPrune: + case netconf.CtrlMsgPrune: record.Penalty += r.penalty.Prune - case p2p.CtrlMsgIHave: + case netconf.CtrlMsgIHave: record.Penalty += r.penalty.IHave - case p2p.CtrlMsgIWant: + case netconf.CtrlMsgIWant: record.Penalty += r.penalty.IWant default: // the error is considered fatal as it means that we have an unsupported misbehaviour type, we should crash the node to prevent routing attack vulnerability. diff --git a/network/p2p/scoring/registry_test.go b/network/p2p/scoring/registry_test.go index 186ce7bf6bc..2a63b9ec444 100644 --- a/network/p2p/scoring/registry_test.go +++ b/network/p2p/scoring/registry_test.go @@ -13,6 +13,7 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/module/mock" + "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" mockp2p "github.com/onflow/flow-go/network/p2p/mock" @@ -48,20 +49,20 @@ func TestNoPenaltyRecord(t *testing.T) { // penalty value as the app specific score. func TestPeerWithSpamRecord(t *testing.T) { t.Run("graft", func(t *testing.T) { - testPeerWithSpamRecord(t, p2p.CtrlMsgGraft, penaltyValueFixtures().Graft) + testPeerWithSpamRecord(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testPeerWithSpamRecord(t, p2p.CtrlMsgPrune, penaltyValueFixtures().Prune) + testPeerWithSpamRecord(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testPeerWithSpamRecord(t, p2p.CtrlMsgIHave, penaltyValueFixtures().IHave) + testPeerWithSpamRecord(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testPeerWithSpamRecord(t, p2p.CtrlMsgIWant, penaltyValueFixtures().IWant) + testPeerWithSpamRecord(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } -func testPeerWithSpamRecord(t *testing.T, messageType p2p.ControlMessageType, expectedPenalty float64) { +func testPeerWithSpamRecord(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -98,22 +99,22 @@ func testPeerWithSpamRecord(t *testing.T, messageType p2p.ControlMessageType, ex func TestSpamRecord_With_UnknownIdentity(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2p.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2p.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2p.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2p.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an unknown identity. -func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2p.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithUnknownIdentity(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -149,22 +150,22 @@ func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2p.ControlMess func TestSpamRecord_With_SubscriptionPenalty(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2p.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2p.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2p.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2p.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an invalid subscription as well. -func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType p2p.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -208,7 +209,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgPrune, + MsgType: netconf.CtrlMsgPrune, Count: 1, }) @@ -216,7 +217,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgGraft, + MsgType: netconf.CtrlMsgGraft, Count: 1, }) @@ -224,7 +225,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgIHave, + MsgType: netconf.CtrlMsgIHave, Count: 1, }) @@ -232,7 +233,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgIWant, + MsgType: netconf.CtrlMsgIWant, Count: 1, }) @@ -274,7 +275,7 @@ func TestSpamPenaltyDecayToZero(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgGraft, + MsgType: netconf.CtrlMsgGraft, Count: 1, }) @@ -324,7 +325,7 @@ func TestPersistingUnknownIdentityPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgGraft, + MsgType: netconf.CtrlMsgGraft, Count: 1, }) @@ -377,7 +378,7 @@ func TestPersistingInvalidSubscriptionPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2p.CtrlMsgGraft, + MsgType: netconf.CtrlMsgGraft, Count: 1, }) From 833965f0938478619c70a6b0a0639db6c9821647 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:49:45 -0700 Subject: [PATCH 34/74] updates mocks --- .../collection_cluster_changes_consumer.go | 33 ++++++++++ network/p2p/mock/gossip_sub_builder.go | 10 +-- network/p2p/mock/gossip_sub_factory_func.go | 18 ++--- .../p2p/mock/gossip_sub_inspector_suite.go | 27 +++----- ...ip_sub_rpc_inspector_suite_factory_func.go | 66 +++++++++++++++++++ network/p2p/mock/lib_p2_p_node.go | 7 ++ network/p2p/mock/node_builder.go | 32 ++++----- 7 files changed, 145 insertions(+), 48 deletions(-) create mode 100644 network/p2p/mock/collection_cluster_changes_consumer.go create mode 100644 network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go diff --git a/network/p2p/mock/collection_cluster_changes_consumer.go b/network/p2p/mock/collection_cluster_changes_consumer.go new file mode 100644 index 00000000000..cb76577f06f --- /dev/null +++ b/network/p2p/mock/collection_cluster_changes_consumer.go @@ -0,0 +1,33 @@ +// Code generated by mockery v2.21.4. DO NOT EDIT. + +package mockp2p + +import ( + flow "github.com/onflow/flow-go/model/flow" + mock "github.com/stretchr/testify/mock" +) + +// CollectionClusterChangesConsumer is an autogenerated mock type for the CollectionClusterChangesConsumer type +type CollectionClusterChangesConsumer struct { + mock.Mock +} + +// ActiveClustersChanged provides a mock function with given fields: _a0 +func (_m *CollectionClusterChangesConsumer) ActiveClustersChanged(_a0 flow.ChainIDList) { + _m.Called(_a0) +} + +type mockConstructorTestingTNewCollectionClusterChangesConsumer interface { + mock.TestingT + Cleanup(func()) +} + +// NewCollectionClusterChangesConsumer creates a new instance of CollectionClusterChangesConsumer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewCollectionClusterChangesConsumer(t mockConstructorTestingTNewCollectionClusterChangesConsumer) *CollectionClusterChangesConsumer { + mock := &CollectionClusterChangesConsumer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/network/p2p/mock/gossip_sub_builder.go b/network/p2p/mock/gossip_sub_builder.go index e01ff021e0d..8b8a567e150 100644 --- a/network/p2p/mock/gossip_sub_builder.go +++ b/network/p2p/mock/gossip_sub_builder.go @@ -63,6 +63,11 @@ func (_m *GossipSubBuilder) Build(_a0 irrecoverable.SignalerContext) (p2p.PubSub return r0, r1, r2 } +// OverrideDefaultRpcInspectorSuiteFactory provides a mock function with given fields: _a0 +func (_m *GossipSubBuilder) OverrideDefaultRpcInspectorSuiteFactory(_a0 p2p.GossipSubRpcInspectorSuiteFactoryFunc) { + _m.Called(_a0) +} + // SetAppSpecificScoreParams provides a mock function with given fields: _a0 func (_m *GossipSubBuilder) SetAppSpecificScoreParams(_a0 func(peer.ID) float64) { _m.Called(_a0) @@ -83,11 +88,6 @@ func (_m *GossipSubBuilder) SetGossipSubPeerScoring(_a0 bool) { _m.Called(_a0) } -// SetGossipSubRPCInspectorSuite provides a mock function with given fields: _a0 -func (_m *GossipSubBuilder) SetGossipSubRPCInspectorSuite(_a0 p2p.GossipSubInspectorSuite) { - _m.Called(_a0) -} - // SetGossipSubScoreTracerInterval provides a mock function with given fields: _a0 func (_m *GossipSubBuilder) SetGossipSubScoreTracerInterval(_a0 time.Duration) { _m.Called(_a0) diff --git a/network/p2p/mock/gossip_sub_factory_func.go b/network/p2p/mock/gossip_sub_factory_func.go index 06cd0346c8c..14aa9a7cec4 100644 --- a/network/p2p/mock/gossip_sub_factory_func.go +++ b/network/p2p/mock/gossip_sub_factory_func.go @@ -18,25 +18,25 @@ type GossipSubFactoryFunc struct { mock.Mock } -// Execute provides a mock function with given fields: _a0, _a1, _a2, _a3 -func (_m *GossipSubFactoryFunc) Execute(_a0 context.Context, _a1 zerolog.Logger, _a2 host.Host, _a3 p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, error) { - ret := _m.Called(_a0, _a1, _a2, _a3) +// Execute provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 +func (_m *GossipSubFactoryFunc) Execute(_a0 context.Context, _a1 zerolog.Logger, _a2 host.Host, _a3 p2p.PubSubAdapterConfig, _a4 p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, error) { + ret := _m.Called(_a0, _a1, _a2, _a3, _a4) var r0 p2p.PubSubAdapter var r1 error - if rf, ok := ret.Get(0).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig) (p2p.PubSubAdapter, error)); ok { - return rf(_a0, _a1, _a2, _a3) + if rf, ok := ret.Get(0).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig, p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, error)); ok { + return rf(_a0, _a1, _a2, _a3, _a4) } - if rf, ok := ret.Get(0).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig) p2p.PubSubAdapter); ok { - r0 = rf(_a0, _a1, _a2, _a3) + if rf, ok := ret.Get(0).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig, p2p.CollectionClusterChangesConsumer) p2p.PubSubAdapter); ok { + r0 = rf(_a0, _a1, _a2, _a3, _a4) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(p2p.PubSubAdapter) } } - if rf, ok := ret.Get(1).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig) error); ok { - r1 = rf(_a0, _a1, _a2, _a3) + if rf, ok := ret.Get(1).(func(context.Context, zerolog.Logger, host.Host, p2p.PubSubAdapterConfig, p2p.CollectionClusterChangesConsumer) error); ok { + r1 = rf(_a0, _a1, _a2, _a3, _a4) } else { r1 = ret.Error(1) } diff --git a/network/p2p/mock/gossip_sub_inspector_suite.go b/network/p2p/mock/gossip_sub_inspector_suite.go index b9a9c0deb8b..90c7e5b15d7 100644 --- a/network/p2p/mock/gossip_sub_inspector_suite.go +++ b/network/p2p/mock/gossip_sub_inspector_suite.go @@ -3,7 +3,9 @@ package mockp2p import ( + flow "github.com/onflow/flow-go/model/flow" irrecoverable "github.com/onflow/flow-go/module/irrecoverable" + mock "github.com/stretchr/testify/mock" p2p "github.com/onflow/flow-go/network/p2p" @@ -18,8 +20,13 @@ type GossipSubInspectorSuite struct { mock.Mock } -// AddInvCtrlMsgNotifConsumer provides a mock function with given fields: _a0 -func (_m *GossipSubInspectorSuite) AddInvCtrlMsgNotifConsumer(_a0 p2p.GossipSubInvCtrlMsgNotifConsumer) { +// ActiveClustersChanged provides a mock function with given fields: _a0 +func (_m *GossipSubInspectorSuite) ActiveClustersChanged(_a0 flow.ChainIDList) { + _m.Called(_a0) +} + +// AddInvalidControlMessageConsumer provides a mock function with given fields: _a0 +func (_m *GossipSubInspectorSuite) AddInvalidControlMessageConsumer(_a0 p2p.GossipSubInvCtrlMsgNotifConsumer) { _m.Called(_a0) } @@ -55,22 +62,6 @@ func (_m *GossipSubInspectorSuite) InspectFunc() func(peer.ID, *pubsub.RPC) erro return r0 } -// Inspectors provides a mock function with given fields: -func (_m *GossipSubInspectorSuite) Inspectors() []p2p.GossipSubRPCInspector { - ret := _m.Called() - - var r0 []p2p.GossipSubRPCInspector - if rf, ok := ret.Get(0).(func() []p2p.GossipSubRPCInspector); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]p2p.GossipSubRPCInspector) - } - } - - return r0 -} - // Ready provides a mock function with given fields: func (_m *GossipSubInspectorSuite) Ready() <-chan struct{} { ret := _m.Called() diff --git a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go new file mode 100644 index 00000000000..1411c225ff8 --- /dev/null +++ b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go @@ -0,0 +1,66 @@ +// Code generated by mockery v2.21.4. DO NOT EDIT. + +package mockp2p + +import ( + flow "github.com/onflow/flow-go/model/flow" + metrics "github.com/onflow/flow-go/module/metrics" + + mock "github.com/stretchr/testify/mock" + + module "github.com/onflow/flow-go/module" + + netconf "github.com/onflow/flow-go/network/netconf" + + network "github.com/onflow/flow-go/network" + + p2p "github.com/onflow/flow-go/network/p2p" + + zerolog "github.com/rs/zerolog" +) + +// GossipSubRpcInspectorSuiteFactoryFunc is an autogenerated mock type for the GossipSubRpcInspectorSuiteFactoryFunc type +type GossipSubRpcInspectorSuiteFactoryFunc struct { + mock.Mock +} + +// Execute provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4, _a5, _a6 +func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 flow.Identifier, _a2 *netconf.GossipSubRPCInspectorsConfig, _a3 module.GossipSubMetrics, _a4 metrics.HeroCacheMetricsFactory, _a5 network.NetworkingType, _a6 module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { + ret := _m.Called(_a0, _a1, _a2, _a3, _a4, _a5, _a6) + + var r0 p2p.GossipSubInspectorSuite + var r1 error + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) (p2p.GossipSubInspectorSuite, error)); ok { + return rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) + } + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) p2p.GossipSubInspectorSuite); ok { + r0 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(p2p.GossipSubInspectorSuite) + } + } + + if rf, ok := ret.Get(1).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) error); ok { + r1 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewGossipSubRpcInspectorSuiteFactoryFunc interface { + mock.TestingT + Cleanup(func()) +} + +// NewGossipSubRpcInspectorSuiteFactoryFunc creates a new instance of GossipSubRpcInspectorSuiteFactoryFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewGossipSubRpcInspectorSuiteFactoryFunc(t mockConstructorTestingTNewGossipSubRpcInspectorSuiteFactoryFunc) *GossipSubRpcInspectorSuiteFactoryFunc { + mock := &GossipSubRpcInspectorSuiteFactoryFunc{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/network/p2p/mock/lib_p2_p_node.go b/network/p2p/mock/lib_p2_p_node.go index 6665b1a9cb2..d8bef358b74 100644 --- a/network/p2p/mock/lib_p2_p_node.go +++ b/network/p2p/mock/lib_p2_p_node.go @@ -8,6 +8,8 @@ import ( context "context" + flow "github.com/onflow/flow-go/model/flow" + flow_gonetwork "github.com/onflow/flow-go/network" host "github.com/libp2p/go-libp2p/core/host" @@ -36,6 +38,11 @@ type LibP2PNode struct { mock.Mock } +// ActiveClustersChanged provides a mock function with given fields: _a0 +func (_m *LibP2PNode) ActiveClustersChanged(_a0 flow.ChainIDList) { + _m.Called(_a0) +} + // AddPeer provides a mock function with given fields: ctx, peerInfo func (_m *LibP2PNode) AddPeer(ctx context.Context, peerInfo peer.AddrInfo) error { ret := _m.Called(ctx, peerInfo) diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index 19171dc81ba..a7f061d9b36 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -73,6 +73,22 @@ func (_m *NodeBuilder) EnableGossipSubPeerScoring(_a0 module.IdentityProvider, _ return r0 } +// OverrideDefaultRpcInspectorSuiteFactory provides a mock function with given fields: _a0 +func (_m *NodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(_a0 p2p.GossipSubRpcInspectorSuiteFactoryFunc) p2p.NodeBuilder { + ret := _m.Called(_a0) + + var r0 p2p.NodeBuilder + if rf, ok := ret.Get(0).(func(p2p.GossipSubRpcInspectorSuiteFactoryFunc) p2p.NodeBuilder); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(p2p.NodeBuilder) + } + } + + return r0 +} + // SetBasicResolver provides a mock function with given fields: _a0 func (_m *NodeBuilder) SetBasicResolver(_a0 madns.BasicResolver) p2p.NodeBuilder { ret := _m.Called(_a0) @@ -153,22 +169,6 @@ func (_m *NodeBuilder) SetGossipSubFactory(_a0 p2p.GossipSubFactoryFunc, _a1 p2p return r0 } -// SetGossipSubRpcInspectorSuite provides a mock function with given fields: _a0 -func (_m *NodeBuilder) OverrideDefaultRpcInspectorSuiteFactory(_a0 p2p.GossipSubInspectorSuite) p2p.NodeBuilder { - ret := _m.Called(_a0) - - var r0 p2p.NodeBuilder - if rf, ok := ret.Get(0).(func(p2p.GossipSubInspectorSuite) p2p.NodeBuilder); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(p2p.NodeBuilder) - } - } - - return r0 -} - // SetGossipSubScoreTracerInterval provides a mock function with given fields: _a0 func (_m *NodeBuilder) SetGossipSubScoreTracerInterval(_a0 time.Duration) p2p.NodeBuilder { ret := _m.Called(_a0) From a9b9b3057b596f9c12110bcf504f0d491b053609 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:52:45 -0700 Subject: [PATCH 35/74] removes inspector suite builder and moves the logic to parent package --- .../inspector/{suite => }/aggregate.go | 0 .../inspector/rpc_inspector_builder.go | 85 ------------------- .../p2pbuilder/inspector/{suite => }/suite.go | 0 3 files changed, 85 deletions(-) rename network/p2p/p2pbuilder/inspector/{suite => }/aggregate.go (100%) delete mode 100644 network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go rename network/p2p/p2pbuilder/inspector/{suite => }/suite.go (100%) diff --git a/network/p2p/p2pbuilder/inspector/suite/aggregate.go b/network/p2p/p2pbuilder/inspector/aggregate.go similarity index 100% rename from network/p2p/p2pbuilder/inspector/suite/aggregate.go rename to network/p2p/p2pbuilder/inspector/aggregate.go diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go deleted file mode 100644 index ece8848c39b..00000000000 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ /dev/null @@ -1,85 +0,0 @@ -package inspector - -import ( - "github.com/rs/zerolog" - - "github.com/onflow/flow-go/model/flow" - "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" - "github.com/onflow/flow-go/network/netconf" - "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/distributor" - p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" -) - -// GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following -// rpc inspectors are created with this builder. -// - validation inspector: performs validation on all control messages. -// - metrics inspector: observes metrics for each rpc message received. -type GossipSubInspectorBuilder struct { - logger zerolog.Logger - sporkID flow.Identifier - inspectorsConfig *netconf.GossipSubRPCInspectorsConfig - metricsCfg *p2pconfig.MetricsConfig - idProvider module.IdentityProvider - inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType network.NetworkingType -} - -// NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. -func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier, inspectorsConfig *netconf.GossipSubRPCInspectorsConfig, provider module.IdentityProvider, inspectorMetrics module.GossipSubRpcValidationInspectorMetrics) *GossipSubInspectorBuilder { - return &GossipSubInspectorBuilder{ - logger: logger, - sporkID: sporkID, - inspectorsConfig: inspectorsConfig, - metricsCfg: &p2pconfig.MetricsConfig{ - Metrics: metrics.NewNoopCollector(), - HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), - }, - idProvider: provider, - inspectorMetrics: inspectorMetrics, - networkType: network.PublicNetwork, - } -} - -// SetMetrics sets the network metrics and registry. -func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConfig) *GossipSubInspectorBuilder { - b.metricsCfg = metricsCfg - return b -} - -// SetNetworkType sets the network type for the inspector. -// This is used to determine if the node is running on a public or private network. -// Args: -// - networkType: the network type. -// Returns: -// - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { - b.networkType = networkType - return b -} - -// buildGossipSubMetricsInspector builds the gossipsub rpc metrics inspector. -func (b *GossipSubInspectorBuilder) buildGossipSubMetricsInspector() p2p.GossipSubRPCInspector { - - return metricsInspector -} - -// buildGossipSubValidationInspector builds the gossipsub rpc validation inspector. -func (b *GossipSubInspectorBuilder) buildGossipSubValidationInspector() (p2p.GossipSubRPCInspector, *distributor.GossipSubInspectorNotifDistributor, error) { - - return rpcValidationInspector, notificationDistributor, nil -} - -// Build builds the rpc inspectors used by gossipsub. -// Any returned error from this func indicates a problem setting up rpc inspectors. -// In libp2p node setup, the returned error should be treated as a fatal error. -func (b *GossipSubInspectorBuilder) Build() (p2p.GossipSubInspectorSuite, error) { - metricsInspector := b.buildGossipSubMetricsInspector() - validationInspector, notificationDistributor, err := b.buildGossipSubValidationInspector() - if err != nil { - return nil, err - } - return , nil -} diff --git a/network/p2p/p2pbuilder/inspector/suite/suite.go b/network/p2p/p2pbuilder/inspector/suite.go similarity index 100% rename from network/p2p/p2pbuilder/inspector/suite/suite.go rename to network/p2p/p2pbuilder/inspector/suite.go From e7c0f7cf39ac36d1d649f46cfcbdd45a074ba52d Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:52:45 -0700 Subject: [PATCH 36/74] removes inspector suite builder and moves the logic to parent package --- cmd/node_builder.go | 3 - cmd/scaffold.go | 2 - .../p2pbuilder/gossipsub/gossipSubBuilder.go | 4 +- .../inspector/{suite => }/aggregate.go | 2 +- .../inspector/rpc_inspector_builder.go | 85 ------------------- .../p2pbuilder/inspector/{suite => }/suite.go | 2 +- 6 files changed, 4 insertions(+), 94 deletions(-) rename network/p2p/p2pbuilder/inspector/{suite => }/aggregate.go (98%) delete mode 100644 network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go rename network/p2p/p2pbuilder/inspector/{suite => }/suite.go (99%) diff --git a/cmd/node_builder.go b/cmd/node_builder.go index 1b944db832b..9fb490d3f02 100644 --- a/cmd/node_builder.go +++ b/cmd/node_builder.go @@ -223,9 +223,6 @@ type NodeConfig struct { // UnicastRateLimiterDistributor notifies consumers when a peer's unicast message is rate limited. UnicastRateLimiterDistributor p2p.UnicastRateLimiterDistributor - - // GossipSubRpcInspectorSuite rpc inspector suite. - GossipSubRpcInspectorSuite p2p.GossipSubInspectorSuite } // StateExcerptAtBoot stores information about the root snapshot and latest finalized block for use in bootstrapping. diff --git a/cmd/scaffold.go b/cmd/scaffold.go index 2de8d6c4da1..bacce0e22ab 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -343,8 +343,6 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { myAddr = fnb.BaseConfig.BindAddr } - fnb.GossipSubRpcInspectorSuite = rpcInspectorSuite - builder, err := p2pbuilder.DefaultNodeBuilder( fnb.Logger, myAddr, diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 118b5425093..bc81344983c 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -24,7 +24,7 @@ import ( "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector/suite" + inspector2 "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/network/p2p/tracer" @@ -236,7 +236,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return nil, fmt.Errorf("failed to create new control message valiadation inspector: %w", err) } - return suite.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, rpcValidationInspector}, notificationDistributor), nil + return inspector2.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, rpcValidationInspector}, notificationDistributor), nil } } diff --git a/network/p2p/p2pbuilder/inspector/suite/aggregate.go b/network/p2p/p2pbuilder/inspector/aggregate.go similarity index 98% rename from network/p2p/p2pbuilder/inspector/suite/aggregate.go rename to network/p2p/p2pbuilder/inspector/aggregate.go index 9c774f40291..604a888fb45 100644 --- a/network/p2p/p2pbuilder/inspector/suite/aggregate.go +++ b/network/p2p/p2pbuilder/inspector/aggregate.go @@ -1,4 +1,4 @@ -package suite +package inspector import ( "github.com/hashicorp/go-multierror" diff --git a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go b/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go deleted file mode 100644 index ece8848c39b..00000000000 --- a/network/p2p/p2pbuilder/inspector/rpc_inspector_builder.go +++ /dev/null @@ -1,85 +0,0 @@ -package inspector - -import ( - "github.com/rs/zerolog" - - "github.com/onflow/flow-go/model/flow" - "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/module/metrics" - "github.com/onflow/flow-go/network" - "github.com/onflow/flow-go/network/netconf" - "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/distributor" - p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" -) - -// GossipSubInspectorBuilder builder that constructs all rpc inspectors used by gossip sub. The following -// rpc inspectors are created with this builder. -// - validation inspector: performs validation on all control messages. -// - metrics inspector: observes metrics for each rpc message received. -type GossipSubInspectorBuilder struct { - logger zerolog.Logger - sporkID flow.Identifier - inspectorsConfig *netconf.GossipSubRPCInspectorsConfig - metricsCfg *p2pconfig.MetricsConfig - idProvider module.IdentityProvider - inspectorMetrics module.GossipSubRpcValidationInspectorMetrics - networkType network.NetworkingType -} - -// NewGossipSubInspectorBuilder returns new *GossipSubInspectorBuilder. -func NewGossipSubInspectorBuilder(logger zerolog.Logger, sporkID flow.Identifier, inspectorsConfig *netconf.GossipSubRPCInspectorsConfig, provider module.IdentityProvider, inspectorMetrics module.GossipSubRpcValidationInspectorMetrics) *GossipSubInspectorBuilder { - return &GossipSubInspectorBuilder{ - logger: logger, - sporkID: sporkID, - inspectorsConfig: inspectorsConfig, - metricsCfg: &p2pconfig.MetricsConfig{ - Metrics: metrics.NewNoopCollector(), - HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), - }, - idProvider: provider, - inspectorMetrics: inspectorMetrics, - networkType: network.PublicNetwork, - } -} - -// SetMetrics sets the network metrics and registry. -func (b *GossipSubInspectorBuilder) SetMetrics(metricsCfg *p2pconfig.MetricsConfig) *GossipSubInspectorBuilder { - b.metricsCfg = metricsCfg - return b -} - -// SetNetworkType sets the network type for the inspector. -// This is used to determine if the node is running on a public or private network. -// Args: -// - networkType: the network type. -// Returns: -// - *GossipSubInspectorBuilder: the builder. -func (b *GossipSubInspectorBuilder) SetNetworkType(networkType network.NetworkingType) *GossipSubInspectorBuilder { - b.networkType = networkType - return b -} - -// buildGossipSubMetricsInspector builds the gossipsub rpc metrics inspector. -func (b *GossipSubInspectorBuilder) buildGossipSubMetricsInspector() p2p.GossipSubRPCInspector { - - return metricsInspector -} - -// buildGossipSubValidationInspector builds the gossipsub rpc validation inspector. -func (b *GossipSubInspectorBuilder) buildGossipSubValidationInspector() (p2p.GossipSubRPCInspector, *distributor.GossipSubInspectorNotifDistributor, error) { - - return rpcValidationInspector, notificationDistributor, nil -} - -// Build builds the rpc inspectors used by gossipsub. -// Any returned error from this func indicates a problem setting up rpc inspectors. -// In libp2p node setup, the returned error should be treated as a fatal error. -func (b *GossipSubInspectorBuilder) Build() (p2p.GossipSubInspectorSuite, error) { - metricsInspector := b.buildGossipSubMetricsInspector() - validationInspector, notificationDistributor, err := b.buildGossipSubValidationInspector() - if err != nil { - return nil, err - } - return , nil -} diff --git a/network/p2p/p2pbuilder/inspector/suite/suite.go b/network/p2p/p2pbuilder/inspector/suite.go similarity index 99% rename from network/p2p/p2pbuilder/inspector/suite/suite.go rename to network/p2p/p2pbuilder/inspector/suite.go index 97f151f9861..a3daf213def 100644 --- a/network/p2p/p2pbuilder/inspector/suite/suite.go +++ b/network/p2p/p2pbuilder/inspector/suite.go @@ -1,4 +1,4 @@ -package suite +package inspector import ( pubsub "github.com/libp2p/go-libp2p-pubsub" From e4e96ecb85b6af20f682105229bddee6c7fac586 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:56:30 -0700 Subject: [PATCH 37/74] lint fix --- network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index bc81344983c..a11d306ffb6 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -274,6 +274,9 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p g.networkType, g.idProvider) gossipSubConfigs.WithInspectorSuite(inspectorSuite) + if err != nil { + return nil, nil, fmt.Errorf("could not create gossipsub inspector suite: %w", err) + } var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer From 256c6c2f7c3196df7dfac389f59d465636cd527e Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 16:58:12 -0700 Subject: [PATCH 38/74] lint fix --- cmd/observer/node_builder/observer_builder.go | 1 - cmd/util/cmd/execution-state-extract/export_report.json | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 cmd/util/cmd/execution-state-extract/export_report.json diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index ae50cbc938d..c0a6d62b2b4 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -57,7 +57,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json new file mode 100644 index 00000000000..8f2934f91bb --- /dev/null +++ b/cmd/util/cmd/execution-state-extract/export_report.json @@ -0,0 +1,6 @@ +{ + "EpochCounter": 0, + "PreviousStateCommitment": "4952fff1587f52d2aef47a3d5fd01b78b14520b8366cd1f28fc9d5ab3c830ed4", + "CurrentStateCommitment": "4952fff1587f52d2aef47a3d5fd01b78b14520b8366cd1f28fc9d5ab3c830ed4", + "ReportSucceeded": true +} \ No newline at end of file From 8d656b6d6e3c60bbf44e1759e42ca02f3a82048f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 17:01:50 -0700 Subject: [PATCH 39/74] lint fix --- follower/follower_builder.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/follower/follower_builder.go b/follower/follower_builder.go index a801c99d2ee..1650fa15799 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -51,7 +51,6 @@ import ( "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" "github.com/onflow/flow-go/network/p2p/translator" @@ -645,9 +644,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). - OverrideDefaultRpcInspectorSuiteFactory(rpcInspectorSuite). Build() - if err != nil { return nil, fmt.Errorf("could not build public libp2p node: %w", err) } From 8f46c9f4b11a41e1a9f7841b85e1ce854a82601a Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 17:31:31 -0700 Subject: [PATCH 40/74] lint fix --- .../execution-state-extract/export_report.json | 4 ++-- network/p2p/builder.go | 6 +----- network/p2p/mock/node_builder.go | 2 +- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 17 +++-------------- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 6 ++---- network/p2p/scoring/score_option.go | 11 ++--------- network/p2p/test/fixtures.go | 2 +- 7 files changed, 12 insertions(+), 36 deletions(-) diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json index 8f2934f91bb..0739dff2b55 100644 --- a/cmd/util/cmd/execution-state-extract/export_report.json +++ b/cmd/util/cmd/execution-state-extract/export_report.json @@ -1,6 +1,6 @@ { "EpochCounter": 0, - "PreviousStateCommitment": "4952fff1587f52d2aef47a3d5fd01b78b14520b8366cd1f28fc9d5ab3c830ed4", - "CurrentStateCommitment": "4952fff1587f52d2aef47a3d5fd01b78b14520b8366cd1f28fc9d5ab3c830ed4", + "PreviousStateCommitment": "4d773fa4f66bfbb4ed3b1f425d2e4d5b71482adfa33a0f258634f9ac83a0b2b7", + "CurrentStateCommitment": "4d773fa4f66bfbb4ed3b1f425d2e4d5b71482adfa33a0f258634f9ac83a0b2b7", "ReportSucceeded": true } \ No newline at end of file diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 043f467a326..797ca77377f 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -57,10 +57,6 @@ type GossipSubBuilder interface { // If the gossipsub tracer has already been set, a fatal error is logged. SetGossipSubTracer(PubSubTracer) - // SetIDProvider sets the identity provider of the builder. - // If the identity provider has already been set, a fatal error is logged. - SetIDProvider(module.IdentityProvider) - // SetRoutingSystem sets the routing system of the builder. // If the routing system has already been set, a fatal error is logged. SetRoutingSystem(routing.Routing) @@ -133,7 +129,7 @@ type NodeBuilder interface { // Arguments: // - module.IdentityProvider: the identity provider for the node (must be set before calling this method). // - *PeerScoringConfig: the peer scoring configuration for the GossipSub pubsub system. If nil, the default configuration is used. - EnableGossipSubPeerScoring(module.IdentityProvider, *PeerScoringConfig) NodeBuilder + EnableGossipSubPeerScoring(*PeerScoringConfig) NodeBuilder SetCreateNode(CreateNodeFunc) NodeBuilder SetGossipSubFactory(GossipSubFactoryFunc, GossipSubAdapterConfigFunc) NodeBuilder SetStreamCreationRetryInterval(time.Duration) NodeBuilder diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index a7f061d9b36..63f046c56f8 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -58,7 +58,7 @@ func (_m *NodeBuilder) Build() (p2p.LibP2PNode, error) { } // EnableGossipSubPeerScoring provides a mock function with given fields: _a0, _a1 -func (_m *NodeBuilder) EnableGossipSubPeerScoring(_a0 module.IdentityProvider, _a1 *p2p.PeerScoringConfig) p2p.NodeBuilder { +func (_m *NodeBuilder) EnableGossipSubPeerScoring(_a1 *p2p.PeerScoringConfig) p2p.NodeBuilder { ret := _m.Called(_a0, _a1) var r0 p2p.NodeBuilder diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index a11d306ffb6..cc3faacdb5b 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -122,18 +122,6 @@ func (g *Builder) SetGossipSubTracer(gossipSubTracer p2p.PubSubTracer) { g.gossipSubTracer = gossipSubTracer } -// SetIDProvider sets the identity provider of the builder. -// If the identity provider has already been set, a fatal error is logged. -func (g *Builder) SetIDProvider(idProvider module.IdentityProvider) { - if g.idProvider != nil { - g.logger.Fatal().Msg("id provider has already been set") - return - } - - g.idProvider = idProvider - g.scoreOptionConfig.SetProvider(idProvider) -} - // SetRoutingSystem sets the routing system of the builder. // If the routing system has already been set, a fatal error is logged. func (g *Builder) SetRoutingSystem(routingSystem routing.Routing) { @@ -166,7 +154,7 @@ func NewGossipSubBuilder( rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, ) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() - return &Builder{ + b := &Builder{ logger: lg, metricsCfg: metricsCfg, sporkId: sporkId, @@ -174,10 +162,11 @@ func NewGossipSubBuilder( idProvider: idProvider, gossipSubFactory: defaultGossipSubFactory(), gossipSubConfigFunc: defaultGossipSubAdapterConfig(), - scoreOptionConfig: scoring.NewScoreOptionConfig(lg), + scoreOptionConfig: scoring.NewScoreOptionConfig(lg, idProvider), rpcInspectorConfig: rpcInspectorConfig, rpcInspectorSuiteFactory: defaultInspectorSuite(), } + return b } func defaultGossipSubFactory() p2p.GossipSubFactoryFunc { diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 5d6fb43a1d3..d789dd96782 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -149,11 +149,9 @@ func (builder *LibP2PNodeBuilder) SetGossipSubFactory(gf p2p.GossipSubFactoryFun // EnableGossipSubPeerScoring enables peer scoring for the GossipSub pubsub system. // Arguments: -// - module.IdentityProvider: the identity provider for the node (must be set before calling this method). // - *PeerScoringConfig: the peer scoring configuration for the GossipSub pubsub system. If nil, the default configuration is used. -func (builder *LibP2PNodeBuilder) EnableGossipSubPeerScoring(provider module.IdentityProvider, config *p2p.PeerScoringConfig) p2p.NodeBuilder { +func (builder *LibP2PNodeBuilder) EnableGossipSubPeerScoring(config *p2p.PeerScoringConfig) p2p.NodeBuilder { builder.gossipSubBuilder.SetGossipSubPeerScoring(true) - builder.gossipSubBuilder.SetIDProvider(provider) if config != nil { if config.AppSpecificScoreParams != nil { builder.gossipSubBuilder.SetAppSpecificScoreParams(config.AppSpecificScoreParams) @@ -498,7 +496,7 @@ func DefaultNodeBuilder( if gossipCfg.PeerScoring { // currently, we only enable peer scoring with default parameters. So, we set the score parameters to nil. - builder.EnableGossipSubPeerScoring(idProvider, nil) + builder.EnableGossipSubPeerScoring(nil) } meshTracer := tracer.NewGossipSubMeshTracer(logger, metricsCfg.Metrics, idProvider, gossipCfg.LocalMeshLogInterval) diff --git a/network/p2p/scoring/score_option.go b/network/p2p/scoring/score_option.go index c6bf52a21be..e10b678745c 100644 --- a/network/p2p/scoring/score_option.go +++ b/network/p2p/scoring/score_option.go @@ -126,23 +126,16 @@ type ScoreOptionConfig struct { registerNotificationConsumerFunc func(p2p.GossipSubInvCtrlMsgNotifConsumer) } -func NewScoreOptionConfig(logger zerolog.Logger) *ScoreOptionConfig { +func NewScoreOptionConfig(logger zerolog.Logger, idProvider module.IdentityProvider) *ScoreOptionConfig { return &ScoreOptionConfig{ logger: logger, + provider: idProvider, cacheSize: defaultScoreCacheSize, cacheMetrics: metrics.NewNoopCollector(), // no metrics by default topicParams: make([]func(map[string]*pubsub.TopicScoreParams), 0), } } -// SetProvider sets the identity provider for the penalty option. -// It is used to retrieve the identity of a peer when calculating the app specific penalty. -// If the provider is not set, the penalty registry will crash. This is a required field. -// It is safe to call this method multiple times, the last call will be used. -func (c *ScoreOptionConfig) SetProvider(provider module.IdentityProvider) { - c.provider = provider -} - // SetCacheSize sets the size of the cache used to store the app specific penalty of peers. // If the cache size is not set, the default value will be used. // It is safe to call this method multiple times, the last call will be used. diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 98de6827d56..932057f2e66 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -135,7 +135,7 @@ func NodeFixture( } if parameters.PeerScoringEnabled { - builder.EnableGossipSubPeerScoring(parameters.IdProvider, parameters.PeerScoreConfig) + builder.EnableGossipSubPeerScoring(parameters.PeerScoreConfig) } if parameters.UpdateInterval != 0 { From 8db84e481b08d4393262a5523797f88f597d8d55 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 22 Jun 2023 17:47:57 -0700 Subject: [PATCH 41/74] lint fix --- network/p2p/mock/gossip_sub_builder.go | 7 ------- network/p2p/mock/node_builder.go | 12 +++++------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/network/p2p/mock/gossip_sub_builder.go b/network/p2p/mock/gossip_sub_builder.go index 8b8a567e150..b5c5f1241ea 100644 --- a/network/p2p/mock/gossip_sub_builder.go +++ b/network/p2p/mock/gossip_sub_builder.go @@ -10,8 +10,6 @@ import ( mock "github.com/stretchr/testify/mock" - module "github.com/onflow/flow-go/module" - p2p "github.com/onflow/flow-go/network/p2p" peer "github.com/libp2p/go-libp2p/core/peer" @@ -103,11 +101,6 @@ func (_m *GossipSubBuilder) SetHost(_a0 host.Host) { _m.Called(_a0) } -// SetIDProvider provides a mock function with given fields: _a0 -func (_m *GossipSubBuilder) SetIDProvider(_a0 module.IdentityProvider) { - _m.Called(_a0) -} - // SetRoutingSystem provides a mock function with given fields: _a0 func (_m *GossipSubBuilder) SetRoutingSystem(_a0 routing.Routing) { _m.Called(_a0) diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index 63f046c56f8..dbe0302bb9d 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -13,8 +13,6 @@ import ( mock "github.com/stretchr/testify/mock" - module "github.com/onflow/flow-go/module" - network "github.com/libp2p/go-libp2p/core/network" p2p "github.com/onflow/flow-go/network/p2p" @@ -57,13 +55,13 @@ func (_m *NodeBuilder) Build() (p2p.LibP2PNode, error) { return r0, r1 } -// EnableGossipSubPeerScoring provides a mock function with given fields: _a0, _a1 -func (_m *NodeBuilder) EnableGossipSubPeerScoring(_a1 *p2p.PeerScoringConfig) p2p.NodeBuilder { - ret := _m.Called(_a0, _a1) +// EnableGossipSubPeerScoring provides a mock function with given fields: _a0 +func (_m *NodeBuilder) EnableGossipSubPeerScoring(_a0 *p2p.PeerScoringConfig) p2p.NodeBuilder { + ret := _m.Called(_a0) var r0 p2p.NodeBuilder - if rf, ok := ret.Get(0).(func(module.IdentityProvider, *p2p.PeerScoringConfig) p2p.NodeBuilder); ok { - r0 = rf(_a0, _a1) + if rf, ok := ret.Get(0).(func(*p2p.PeerScoringConfig) p2p.NodeBuilder); ok { + r0 = rf(_a0) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(p2p.NodeBuilder) From 5e4b50d9030f072f275b7d40f40bd928338044f9 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 09:36:23 -0700 Subject: [PATCH 42/74] removes json --- cmd/util/cmd/execution-state-extract/export_report.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 cmd/util/cmd/execution-state-extract/export_report.json diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json deleted file mode 100644 index 0739dff2b55..00000000000 --- a/cmd/util/cmd/execution-state-extract/export_report.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "EpochCounter": 0, - "PreviousStateCommitment": "4d773fa4f66bfbb4ed3b1f425d2e4d5b71482adfa33a0f258634f9ac83a0b2b7", - "CurrentStateCommitment": "4d773fa4f66bfbb4ed3b1f425d2e4d5b71482adfa33a0f258634f9ac83a0b2b7", - "ReportSucceeded": true -} \ No newline at end of file From f88f3dd37c8c6fabf5ddc0dacec1810aaa4c6d6c Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:08:25 -0700 Subject: [PATCH 43/74] extends godocs --- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index cc3faacdb5b..3dfb5b8f4de 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -132,19 +132,39 @@ func (g *Builder) SetRoutingSystem(routingSystem routing.Routing) { g.routingSystem = routingSystem } +// SetTopicScoreParams sets the topic score params of the builder. +// There is a default topic score parameters that is used if this function is not called for a topic. +// However, if this function is called multiple times for a topic, the last topic score params will be used. +// Note: calling this function will override the default topic score params for the topic. Don't call this function +// unless you know what you are doing. func (g *Builder) SetTopicScoreParams(topic channels.Topic, topicScoreParams *pubsub.TopicScoreParams) { g.scoreOptionConfig.SetTopicScoreParams(topic, topicScoreParams) } +// SetAppSpecificScoreParams sets the app specific score params of the builder. +// There is no default app specific score function. However, if this function is called multiple times, the last function will be used. func (g *Builder) SetAppSpecificScoreParams(f func(peer.ID) float64) { g.scoreOptionConfig.SetAppSpecificScoreFunction(f) } +// OverrideDefaultRpcInspectorSuiteFactory overrides the default rpc inspector suite factory. +// Note: this function should only be used for testing purposes. Never override the default rpc inspector suite factory unless you know what you are doing. func (g *Builder) OverrideDefaultRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) { g.logger.Warn().Msg("overriding default rpc inspector suite factory") g.rpcInspectorSuiteFactory = factory } +// NewGossipSubBuilder returns a new gossipsub builder. +// Args: +// - logger: the logger of the node. +// - metricsCfg: the metrics config of the node. +// - networkType: the network type of the node. +// - sporkId: the spork id of the node. +// - idProvider: the identity provider of the node. +// - rpcInspectorConfig: the rpc inspector config of the node. +// Returns: +// - a new gossipsub builder. +// Note: the builder is not thread-safe. It should only be used in the main thread. func NewGossipSubBuilder( logger zerolog.Logger, metricsCfg *p2pconfig.MetricsConfig, @@ -169,6 +189,8 @@ func NewGossipSubBuilder( return b } +// defaultGossipSubFactory returns the default gossipsub factory function. It is used to create the default gossipsub factory. +// Note: always use the default gossipsub factory function to create the gossipsub factory (unless you know what you are doing). func defaultGossipSubFactory() p2p.GossipSubFactoryFunc { return func( ctx context.Context, @@ -180,12 +202,17 @@ func defaultGossipSubFactory() p2p.GossipSubFactoryFunc { } } +// defaultGossipSubAdapterConfig returns the default gossipsub config function. It is used to create the default gossipsub config. +// Note: always use the default gossipsub config function to create the gossipsub config (unless you know what you are doing). func defaultGossipSubAdapterConfig() p2p.GossipSubAdapterConfigFunc { return func(cfg *p2p.BasePubSubAdapterConfig) p2p.PubSubAdapterConfig { return p2pnode.NewGossipSubAdapterConfig(cfg) } } +// defaultInspectorSuite returns the default inspector suite factory function. It is used to create the default inspector suite. +// Inspector suite is utilized to inspect the incoming gossipsub rpc messages from different perspectives. +// Note: always use the default inspector suite factory function to create the inspector suite (unless you know what you are doing). func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return func( logger zerolog.Logger, From 3689d4ff73e595cabf2ab088d910465972723281 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:12:22 -0700 Subject: [PATCH 44/74] moves gossipsub config to conf package of libp2p --- .../validation_inspector_test.go | 40 +++++------ network/message/gossipsub.go | 1 + network/netconf/config.go | 12 ++-- network/netconf/errors.go | 4 +- network/netconf/errors_test.go | 4 +- network/netconf/flags.go | 4 +- network/p2p/builder.go | 4 +- network/{netconf => p2p/conf}/gossipsub.go | 2 +- .../conf}/gossipsub_rpc_inspectors.go | 10 +-- network/p2p/consumers.go | 10 +-- .../distributor/gossipsub_inspector_test.go | 4 +- .../control_message_validation_inspector.go | 66 +++++++++---------- network/p2p/inspector/validation/errors.go | 10 +-- .../p2p/inspector/validation/errors_test.go | 6 +- .../validation/inspect_message_request.go | 6 +- ...ip_sub_rpc_inspector_suite_factory_func.go | 3 +- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 8 +-- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 13 ++-- network/p2p/scoring/registry.go | 10 +-- network/p2p/scoring/registry_test.go | 46 ++++++------- network/p2p/scoring/scoring_test.go | 4 +- network/p2p/test/fixtures.go | 16 ++--- 22 files changed, 147 insertions(+), 136 deletions(-) create mode 100644 network/message/gossipsub.go rename network/{netconf => p2p/conf}/gossipsub.go (98%) rename network/{netconf => p2p/conf}/gossipsub_rpc_inspectors.go (94%) diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index 1548c4a34ab..b8692812535 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -23,8 +23,8 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/validation" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -48,9 +48,9 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { inspectorConfig.PruneLimits.SafetyThreshold = safetyThreshold // expected log message logged when valid number GRAFT control messages spammed under safety threshold - graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", netconf.CtrlMsgGraft) + graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", conf.CtrlMsgGraft) // expected log message logged when valid number PRUNE control messages spammed under safety threshold - pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", netconf.CtrlMsgGraft) + pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", conf.CtrlMsgGraft) graftInfoLogsReceived := atomic.NewInt64(0) pruneInfoLogsReceived := atomic.NewInt64(0) // setup logger hook, we expect info log validation is skipped @@ -126,9 +126,9 @@ func TestValidationInspector_HardThreshold_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -194,7 +194,7 @@ func TestValidationInspector_HardThresholdIHave_Detection(t *testing.T) { require.Equal(t, uint64(messageCount), notification.Count) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: invIhaveNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -257,9 +257,9 @@ func TestValidationInspector_RateLimitedPeer_Detection(t *testing.T) { require.True(t, validation.IsErrRateLimitedControlMsg(notification.Err)) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -353,13 +353,13 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: require.Equal(t, uint64(ihaveMessageCount), notification.Count) invIHaveNotifCount.Inc() default: @@ -461,9 +461,9 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { require.True(t, validation.IsErrDuplicateTopic(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -538,9 +538,9 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { require.True(t, channels.IsUnknownClusterIDErr(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -608,7 +608,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -672,7 +672,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -745,9 +745,9 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { require.True(t, validation.IsErrUnstakedPeer(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: invGraftNotifCount.Inc() - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -805,7 +805,7 @@ func withExpectedNotificationDissemination(expectedNumOfTotalNotif int, f onNoti } // setupTest sets up common components of RPC inspector test. -func setupTest(t *testing.T, logger zerolog.Logger, role flow.Role, sporkID flow.Identifier, inspectorConfig *netconf.GossipSubRPCValidationInspectorConfigs, mockDistributorOpts ...mockDistributorOption) (*irrecoverable.MockSignalerContext, context.CancelFunc, *corruptlibp2p.GossipSubRouterSpammer, p2p.LibP2PNode, flow.Identity, *mockp2p.GossipSubInspectorNotificationDistributor, *validation.ControlMsgValidationInspector, *mock.IdentityProvider) { +func setupTest(t *testing.T, logger zerolog.Logger, role flow.Role, sporkID flow.Identifier, inspectorConfig *conf.GossipSubRPCValidationInspectorConfigs, mockDistributorOpts ...mockDistributorOption) (*irrecoverable.MockSignalerContext, context.CancelFunc, *corruptlibp2p.GossipSubRouterSpammer, p2p.LibP2PNode, flow.Identity, *mockp2p.GossipSubInspectorNotificationDistributor, *validation.ControlMsgValidationInspector, *mock.IdentityProvider) { idProvider := mock.NewIdentityProvider(t) spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) ctx, cancel := context.WithCancel(context.Background()) diff --git a/network/message/gossipsub.go b/network/message/gossipsub.go new file mode 100644 index 00000000000..ede1b09878e --- /dev/null +++ b/network/message/gossipsub.go @@ -0,0 +1 @@ +package message diff --git a/network/netconf/config.go b/network/netconf/config.go index 5675ca38043..f7a0fd2b4ad 100644 --- a/network/netconf/config.go +++ b/network/netconf/config.go @@ -2,17 +2,19 @@ package netconf import ( "time" + + "github.com/onflow/flow-go/network/p2p/conf" ) // Config encapsulation of configuration structs for all components related to the Flow network. type Config struct { // UnicastRateLimitersConfig configuration for all unicast rate limiters. - UnicastRateLimitersConfig `mapstructure:",squash"` - ResourceManagerConfig `mapstructure:",squash"` - ConnectionManagerConfig `mapstructure:",squash"` + UnicastRateLimitersConfig `mapstructure:",squash"` + conf.ResourceManagerConfig `mapstructure:",squash"` + ConnectionManagerConfig `mapstructure:",squash"` // GossipSubConfig core gossipsub configuration. - GossipSubConfig `mapstructure:",squash"` - AlspConfig `mapstructure:",squash"` + conf.GossipSubConfig `mapstructure:",squash"` + AlspConfig `mapstructure:",squash"` // NetworkConnectionPruning determines whether connections to nodes // that are not part of protocol state should be trimmed diff --git a/network/netconf/errors.go b/network/netconf/errors.go index 206b2206341..534c13b9dfd 100644 --- a/network/netconf/errors.go +++ b/network/netconf/errors.go @@ -3,6 +3,8 @@ package netconf import ( "errors" "fmt" + + "github.com/onflow/flow-go/network/p2p/conf" ) // InvalidLimitConfigError indicates the validation limit is < 0. @@ -19,7 +21,7 @@ func (e InvalidLimitConfigError) Unwrap() error { } // NewInvalidLimitConfigErr returns a new ErrValidationLimit. -func NewInvalidLimitConfigErr(controlMsg ControlMessageType, err error) InvalidLimitConfigError { +func NewInvalidLimitConfigErr(controlMsg conf.ControlMessageType, err error) InvalidLimitConfigError { return InvalidLimitConfigError{fmt.Errorf("invalid rpc control message %s validation limit configuration: %w", controlMsg, err)} } diff --git a/network/netconf/errors_test.go b/network/netconf/errors_test.go index b5cb4626de6..f5c3a6dbc96 100644 --- a/network/netconf/errors_test.go +++ b/network/netconf/errors_test.go @@ -5,11 +5,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/onflow/flow-go/network/p2p/conf" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. func TestErrInvalidLimitConfigRoundTrip(t *testing.T) { - controlMsg := CtrlMsgGraft + controlMsg := conf.CtrlMsgGraft limit := uint64(500) e := fmt.Errorf("invalid rate limit value %d must be greater than 0", limit) diff --git a/network/netconf/flags.go b/network/netconf/flags.go index 36bcc18c10b..2e74a6c4644 100644 --- a/network/netconf/flags.go +++ b/network/netconf/flags.go @@ -5,6 +5,8 @@ import ( "strings" "github.com/spf13/pflag" + + "github.com/onflow/flow-go/network/p2p/conf" ) const ( @@ -135,7 +137,7 @@ func initRpcInspectorValidationLimitsFlags(flags *pflag.FlagSet, defaultNetConfi for _, ctrlMsgValidationConfig := range validationInspectorConfig.AllCtrlMsgValidationConfig() { ctrlMsgType := ctrlMsgValidationConfig.ControlMsg - if ctrlMsgValidationConfig.ControlMsg == CtrlMsgIWant { + if ctrlMsgValidationConfig.ControlMsg == conf.CtrlMsgIWant { continue } s := strings.ToLower(ctrlMsgType.String()) diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 797ca77377f..d053575902d 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -19,7 +19,7 @@ import ( "github.com/onflow/flow-go/module/metrics" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" + "github.com/onflow/flow-go/network/p2p/conf" ) type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) @@ -109,7 +109,7 @@ type PeerScoringBuilder interface { type GossipSubRpcInspectorSuiteFactoryFunc func( zerolog.Logger, flow.Identifier, - *netconf.GossipSubRPCInspectorsConfig, + *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, flownet.NetworkingType, diff --git a/network/netconf/gossipsub.go b/network/p2p/conf/gossipsub.go similarity index 98% rename from network/netconf/gossipsub.go rename to network/p2p/conf/gossipsub.go index ca01d36a244..cc1d5ea0b2a 100644 --- a/network/netconf/gossipsub.go +++ b/network/p2p/conf/gossipsub.go @@ -1,4 +1,4 @@ -package netconf +package conf import ( "time" diff --git a/network/netconf/gossipsub_rpc_inspectors.go b/network/p2p/conf/gossipsub_rpc_inspectors.go similarity index 94% rename from network/netconf/gossipsub_rpc_inspectors.go rename to network/p2p/conf/gossipsub_rpc_inspectors.go index 3cce29d9888..bd9e22d9746 100644 --- a/network/netconf/gossipsub_rpc_inspectors.go +++ b/network/p2p/conf/gossipsub_rpc_inspectors.go @@ -1,7 +1,9 @@ -package netconf +package conf import ( "fmt" + + "github.com/onflow/flow-go/network/netconf" ) // ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. @@ -146,11 +148,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index fc3f641f928..916a370b9e2 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -5,12 +5,12 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/module/component" - "github.com/onflow/flow-go/network/netconf" + "github.com/onflow/flow-go/network/p2p/conf" ) // ControlMessageTypes returns list of all libp2p control message types. -func ControlMessageTypes() []netconf.ControlMessageType { - return []netconf.ControlMessageType{netconf.CtrlMsgIHave, netconf.CtrlMsgIWant, netconf.CtrlMsgGraft, netconf.CtrlMsgPrune} +func ControlMessageTypes() []conf.ControlMessageType { + return []conf.ControlMessageType{conf.CtrlMsgIHave, conf.CtrlMsgIWant, conf.CtrlMsgGraft, conf.CtrlMsgPrune} } // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. @@ -35,7 +35,7 @@ type InvCtrlMsgNotif struct { // PeerID is the ID of the peer that sent the invalid control message. PeerID peer.ID // MsgType is the type of control message that was received. - MsgType netconf.ControlMessageType + MsgType conf.ControlMessageType // Count is the number of invalid control messages received from the peer that is reported in this notification. Count uint64 // Err any error associated with the invalid control message. @@ -43,7 +43,7 @@ type InvCtrlMsgNotif struct { } // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif -func NewInvalidControlMessageNotification(peerID peer.ID, msgType netconf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { +func NewInvalidControlMessageNotification(peerID peer.ID, msgType conf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { return &InvCtrlMsgNotif{ PeerID: peerID, MsgType: msgType, diff --git a/network/p2p/distributor/gossipsub_inspector_test.go b/network/p2p/distributor/gossipsub_inspector_test.go index afab4490c87..bca0e250830 100644 --- a/network/p2p/distributor/gossipsub_inspector_test.go +++ b/network/p2p/distributor/gossipsub_inspector_test.go @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/module/irrecoverable" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/distributor" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -95,7 +95,7 @@ func invalidControlMessageNotificationListFixture(t *testing.T, n int) []*p2p.In func invalidControlMessageNotificationFixture(t *testing.T) *p2p.InvCtrlMsgNotif { return &p2p.InvCtrlMsgNotif{ PeerID: p2ptest.PeerIdFixture(t), - MsgType: []netconf.ControlMessageType{netconf.CtrlMsgGraft, netconf.CtrlMsgPrune, netconf.CtrlMsgIHave, netconf.CtrlMsgIWant}[rand.Intn(4)], + MsgType: []conf.ControlMessageType{conf.CtrlMsgGraft, conf.CtrlMsgPrune, conf.CtrlMsgIHave, conf.CtrlMsgIWant}[rand.Intn(4)], Count: rand.Uint64(), } } diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 5333f049882..ca738b6b51e 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -18,8 +18,8 @@ import ( "github.com/onflow/flow-go/module/mempool/queue" "github.com/onflow/flow-go/module/util" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" "github.com/onflow/flow-go/state/protocol" @@ -37,7 +37,7 @@ type ControlMsgValidationInspector struct { sporkID flow.Identifier metrics module.GossipSubRpcValidationInspectorMetrics // config control message validation configurations. - config *netconf.GossipSubRPCValidationInspectorConfigs + config *conf.GossipSubRPCValidationInspectorConfigs // distributor used to disseminate invalid RPC message notifications. distributor p2p.GossipSubInspectorNotifDistributor // workerPool queue that stores *InspectMsgRequest that will be processed by component workers. @@ -52,7 +52,7 @@ type ControlMsgValidationInspector struct { // In such cases, the inspector will allow a configured number of these messages from the corresponding peer. tracker *cache.ClusterPrefixedMessagesReceivedTracker idProvider module.IdentityProvider - rateLimiters map[netconf.ControlMessageType]p2p.BasicRateLimiter + rateLimiters map[conf.ControlMessageType]p2p.BasicRateLimiter } var _ component.Component = (*ControlMsgValidationInspector)(nil) @@ -74,7 +74,7 @@ var _ protocol.Consumer = (*ControlMsgValidationInspector)(nil) func NewControlMsgValidationInspector( logger zerolog.Logger, sporkID flow.Identifier, - config *netconf.GossipSubRPCValidationInspectorConfigs, + config *conf.GossipSubRPCValidationInspectorConfigs, distributor p2p.GossipSubInspectorNotifDistributor, inspectMsgQueueCacheCollector module.HeroCacheMetrics, clusterPrefixedCacheCollector module.HeroCacheMetrics, @@ -95,7 +95,7 @@ func NewControlMsgValidationInspector( tracker: tracker, idProvider: idProvider, metrics: inspectorMetrics, - rateLimiters: make(map[netconf.ControlMessageType]p2p.BasicRateLimiter), + rateLimiters: make(map[conf.ControlMessageType]p2p.BasicRateLimiter), } store := queue.NewHeroStore(config.CacheSize, logger, inspectMsgQueueCacheCollector) @@ -158,7 +158,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e } switch ctrlMsgType { - case netconf.CtrlMsgGraft, netconf.CtrlMsgPrune: + case conf.CtrlMsgGraft, conf.CtrlMsgPrune: // normal pre-processing err := c.blockingPreprocessingRpc(from, validationConfig, control) if err != nil { @@ -167,7 +167,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e Msg("could not pre-process rpc, aborting") return fmt.Errorf("could not pre-process rpc, aborting: %w", err) } - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: // iHave specific pre-processing sampleSize := util.SampleN(len(control.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveSyncInspectSampleSizePercentage) err := c.blockingIHaveSamplePreprocessing(from, validationConfig, control, sampleSize) @@ -210,9 +210,9 @@ func (c *ControlMsgValidationInspector) ActiveClustersChanged(clusterIDList flow // - ErrDiscardThreshold: if control message count exceeds the configured discard threshold. // // blockingPreprocessingRpc generic pre-processing validation func that ensures the RPC control message count does not exceed the configured hard threshold. -func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { - if validationConfig.ControlMsg != netconf.CtrlMsgGraft && validationConfig.ControlMsg != netconf.CtrlMsgPrune { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, netconf.CtrlMsgGraft, netconf.CtrlMsgPrune) +func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { + if validationConfig.ControlMsg != conf.CtrlMsgGraft && validationConfig.ControlMsg != conf.CtrlMsgPrune { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, conf.CtrlMsgGraft, conf.CtrlMsgPrune) } count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) lg := c.logger.With(). @@ -249,11 +249,11 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, v } // blockingPreprocessingSampleRpc blocking pre-processing of a sample of iHave control messages. -func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - c.metrics.BlockingPreProcessingStarted(netconf.CtrlMsgIHave.String(), sampleSize) +func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { + c.metrics.BlockingPreProcessingStarted(conf.CtrlMsgIHave.String(), sampleSize) start := time.Now() defer func() { - c.metrics.BlockingPreProcessingFinished(netconf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) + c.metrics.BlockingPreProcessingFinished(conf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) }() err := c.blockingPreprocessingSampleRpc(from, validationConfig, controlMessage, sampleSize) if err != nil { @@ -265,9 +265,9 @@ func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from pe // blockingPreprocessingSampleRpc blocking pre-processing validation func that performs some pre-validation of RPC control messages. // If the RPC control message count exceeds the configured hard threshold we perform synchronous topic validation on a subset // of the control messages. This is used for control message types that do not have an upper bound on the amount of messages a node can send. -func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - if validationConfig.ControlMsg != netconf.CtrlMsgIHave && validationConfig.ControlMsg != netconf.CtrlMsgIWant { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, netconf.CtrlMsgIHave, netconf.CtrlMsgIWant) +func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { + if validationConfig.ControlMsg != conf.CtrlMsgIHave && validationConfig.ControlMsg != conf.CtrlMsgIWant { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, conf.CtrlMsgIHave, conf.CtrlMsgIWant) } activeClusterIDS := c.tracker.GetActiveClusterIds() count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) @@ -279,7 +279,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer if count > validationConfig.HardThreshold { // for iHave control message topic validation we only validate a random subset of the messages // shuffle the ihave messages to perform random validation on a subset of size sampleSize - err := c.sampleCtrlMessages(netconf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(conf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -305,7 +305,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // to randomize async validation to avoid data race that can occur when // performing the sampling asynchronously. // for iHave control message topic validation we only validate a random subset of the messages - err := c.sampleCtrlMessages(netconf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(conf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -314,9 +314,9 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // sampleCtrlMessages performs sampling on the specified control message that will randomize // the items in the control message slice up to index sampleSize-1. -func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType netconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { +func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType conf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { switch ctrlMsgType { - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: iHaves := ctrlMsg.GetIhave() swap := func(i, j uint) { iHaves[i], iHaves[j] = iHaves[j], iHaves[i] @@ -375,13 +375,13 @@ func (c *ControlMsgValidationInspector) processInspectMsgReq(req *InspectMsgRequ } // getCtrlMsgCount returns the amount of specified control message type in the rpc ControlMessage. -func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType netconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { +func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType conf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { switch ctrlMsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: return uint64(len(ctrlMsg.GetGraft())) - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: return uint64(len(ctrlMsg.GetPrune())) - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: return uint64(len(ctrlMsg.GetIhave())) default: return 0 @@ -392,20 +392,20 @@ func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType netconf.Cont // Expected error returns during normal operations: // - channels.InvalidTopicErr: if topic is invalid. // - ErrDuplicateTopic: if a duplicate topic ID is encountered. -func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { +func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { activeClusterIDS := c.tracker.GetActiveClusterIds() switch validationConfig.ControlMsg { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: return c.validateGrafts(from, ctrlMsg, activeClusterIDS) - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: return c.validatePrunes(from, ctrlMsg, activeClusterIDS) - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: return c.validateIhaves(from, validationConfig, ctrlMsg, activeClusterIDS) default: // sanity check // This should never happen validateTopics is only used to validate GRAFT and PRUNE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", netconf.CtrlMsgGraft, netconf.CtrlMsgPrune, netconf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", conf.CtrlMsgGraft, conf.CtrlMsgPrune, conf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } @@ -445,7 +445,7 @@ func (c *ControlMsgValidationInspector) validatePrunes(from peer.ID, ctrlMsg *pu } // validateIhaves performs topic validation on all ihaves in the control message using the provided validateTopic func while tracking duplicates. -func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList) error { +func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList) error { sampleSize := util.SampleN(len(ctrlMsg.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveAsyncInspectSampleSizePercentage) return c.validateTopicsSample(from, validationConfig, ctrlMsg, activeClusterIDS, sampleSize) } @@ -453,10 +453,10 @@ func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationC // validateTopicsSample samples a subset of topics from the specified control message and ensures the sample contains only valid flow topic/channel and no duplicate topics exist. // Sample size ensures liveness of the network when validating messages with no upper bound on the amount of messages that may be received. // All errors returned from this function can be considered benign. -func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { +func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { tracker := make(duplicateTopicTracker) switch validationConfig.ControlMsg { - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: for i := uint(0); i < sampleSize; i++ { topic := channels.Topic(ctrlMsg.Ihave[i].GetTopicID()) if tracker.isDuplicate(topic) { @@ -472,7 +472,7 @@ func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, valid // sanity check // This should never happen validateTopicsSample is only used to validate IHAVE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", netconf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", conf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } diff --git a/network/p2p/inspector/validation/errors.go b/network/p2p/inspector/validation/errors.go index cac5e1e6185..7ceb4f842b4 100644 --- a/network/p2p/inspector/validation/errors.go +++ b/network/p2p/inspector/validation/errors.go @@ -5,13 +5,13 @@ import ( "fmt" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" + "github.com/onflow/flow-go/network/p2p/conf" ) // ErrHardThreshold indicates that the amount of RPC messages received exceeds hard threshold. type ErrHardThreshold struct { // controlMsg the control message type. - controlMsg netconf.ControlMessageType + controlMsg conf.ControlMessageType // amount the amount of control messages. amount uint64 // hardThreshold configured hard threshold. @@ -23,7 +23,7 @@ func (e ErrHardThreshold) Error() string { } // NewHardThresholdErr returns a new ErrHardThreshold. -func NewHardThresholdErr(controlMsg netconf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { +func NewHardThresholdErr(controlMsg conf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { return ErrHardThreshold{controlMsg: controlMsg, amount: amount, hardThreshold: hardThreshold} } @@ -35,7 +35,7 @@ func IsErrHardThreshold(err error) bool { // ErrRateLimitedControlMsg indicates the specified RPC control message is rate limited for the specified peer. type ErrRateLimitedControlMsg struct { - controlMsg netconf.ControlMessageType + controlMsg conf.ControlMessageType } func (e ErrRateLimitedControlMsg) Error() string { @@ -43,7 +43,7 @@ func (e ErrRateLimitedControlMsg) Error() string { } // NewRateLimitedControlMsgErr returns a new ErrValidationLimit. -func NewRateLimitedControlMsgErr(controlMsg netconf.ControlMessageType) ErrRateLimitedControlMsg { +func NewRateLimitedControlMsgErr(controlMsg conf.ControlMessageType) ErrRateLimitedControlMsg { return ErrRateLimitedControlMsg{controlMsg: controlMsg} } diff --git a/network/p2p/inspector/validation/errors_test.go b/network/p2p/inspector/validation/errors_test.go index c895c27490a..62d9f3b7d40 100644 --- a/network/p2p/inspector/validation/errors_test.go +++ b/network/p2p/inspector/validation/errors_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" + "github.com/onflow/flow-go/network/p2p/conf" ) // TestErrActiveClusterIDsNotSetRoundTrip ensures correct error formatting for ErrActiveClusterIdsNotSet. @@ -29,7 +29,7 @@ func TestErrActiveClusterIDsNotSetRoundTrip(t *testing.T) { // TestErrHardThresholdRoundTrip ensures correct error formatting for ErrHardThreshold. func TestErrHardThresholdRoundTrip(t *testing.T) { - controlMsg := netconf.CtrlMsgGraft + controlMsg := conf.CtrlMsgGraft amount := uint64(100) hardThreshold := uint64(500) err := NewHardThresholdErr(controlMsg, amount, hardThreshold) @@ -48,7 +48,7 @@ func TestErrHardThresholdRoundTrip(t *testing.T) { // TestErrRateLimitedControlMsgRoundTrip ensures correct error formatting for ErrRateLimitedControlMsg. func TestErrRateLimitedControlMsgRoundTrip(t *testing.T) { - controlMsg := netconf.CtrlMsgGraft + controlMsg := conf.CtrlMsgGraft err := NewRateLimitedControlMsgErr(controlMsg) // tests the error message formatting. diff --git a/network/p2p/inspector/validation/inspect_message_request.go b/network/p2p/inspector/validation/inspect_message_request.go index 46e35250a36..0dcd5a40829 100644 --- a/network/p2p/inspector/validation/inspect_message_request.go +++ b/network/p2p/inspector/validation/inspect_message_request.go @@ -6,7 +6,7 @@ import ( pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" - "github.com/onflow/flow-go/network/netconf" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/internal" ) @@ -18,11 +18,11 @@ type InspectMsgRequest struct { Peer peer.ID // CtrlMsg the control message that will be inspected. ctrlMsg *pubsub_pb.ControlMessage - validationConfig *netconf.CtrlMsgValidationConfig + validationConfig *conf.CtrlMsgValidationConfig } // NewInspectMsgRequest returns a new *InspectMsgRequest. -func NewInspectMsgRequest(from peer.ID, validationConfig *netconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) (*InspectMsgRequest, error) { +func NewInspectMsgRequest(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) (*InspectMsgRequest, error) { nonce, err := internal.Nonce() if err != nil { return nil, fmt.Errorf("failed to get inspect message request nonce: %w", err) diff --git a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go index 1411c225ff8..8f532afb7b3 100644 --- a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go +++ b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go @@ -5,13 +5,12 @@ package mockp2p import ( flow "github.com/onflow/flow-go/model/flow" metrics "github.com/onflow/flow-go/module/metrics" + netconf "github.com/onflow/flow-go/network/p2p/conf" mock "github.com/stretchr/testify/mock" module "github.com/onflow/flow-go/module" - netconf "github.com/onflow/flow-go/network/netconf" - network "github.com/onflow/flow-go/network" p2p "github.com/onflow/flow-go/network/p2p" diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 3dfb5b8f4de..1ab40416398 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -18,8 +18,8 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" @@ -49,7 +49,7 @@ type Builder struct { scoreOptionConfig *scoring.ScoreOptionConfig idProvider module.IdentityProvider routingSystem routing.Routing - rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig + rpcInspectorConfig *conf.GossipSubRPCInspectorsConfig rpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } @@ -171,7 +171,7 @@ func NewGossipSubBuilder( networkType network.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, - rpcInspectorConfig *netconf.GossipSubRPCInspectorsConfig, + rpcInspectorConfig *conf.GossipSubRPCInspectorsConfig, ) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() b := &Builder{ @@ -217,7 +217,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return func( logger zerolog.Logger, sporkId flow.Identifier, - inspectorCfg *netconf.GossipSubRPCInspectorsConfig, + inspectorCfg *conf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, networkType network.NetworkingType, diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index d789dd96782..185794e0f17 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -29,6 +29,7 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" @@ -60,7 +61,7 @@ type LibP2PNodeBuilder struct { basicResolver madns.BasicResolver resourceManager network.ResourceManager - resourceManagerCfg *netconf.ResourceManagerConfig + resourceManagerCfg *conf.ResourceManagerConfig connManager connmgr.ConnManager connGater p2p.ConnectionGater routingFactory func(context.Context, host.Host) (routing.Routing, error) @@ -81,8 +82,8 @@ func NewNodeBuilder( networkKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, - rCfg *netconf.ResourceManagerConfig, - rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, + rCfg *conf.ResourceManagerConfig, + rpcInspectorCfg *conf.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, @@ -451,9 +452,9 @@ func DefaultNodeBuilder( role string, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, - gossipCfg *netconf.GossipSubConfig, - rpcInspectorCfg *netconf.GossipSubRPCInspectorsConfig, - rCfg *netconf.ResourceManagerConfig, + gossipCfg *conf.GossipSubConfig, + rpcInspectorCfg *conf.GossipSubRPCInspectorsConfig, + rCfg *conf.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { diff --git a/network/p2p/scoring/registry.go b/network/p2p/scoring/registry.go index 0377816015e..e076ffe9f16 100644 --- a/network/p2p/scoring/registry.go +++ b/network/p2p/scoring/registry.go @@ -9,9 +9,9 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/utils/logging" ) @@ -254,13 +254,13 @@ func (r *GossipSubAppSpecificScoreRegistry) OnInvalidControlMessageNotification( record, err := r.spamScoreCache.Update(notification.PeerID, func(record p2p.GossipSubSpamRecord) p2p.GossipSubSpamRecord { switch notification.MsgType { - case netconf.CtrlMsgGraft: + case conf.CtrlMsgGraft: record.Penalty += r.penalty.Graft - case netconf.CtrlMsgPrune: + case conf.CtrlMsgPrune: record.Penalty += r.penalty.Prune - case netconf.CtrlMsgIHave: + case conf.CtrlMsgIHave: record.Penalty += r.penalty.IHave - case netconf.CtrlMsgIWant: + case conf.CtrlMsgIWant: record.Penalty += r.penalty.IWant default: // the error is considered fatal as it means that we have an unsupported misbehaviour type, we should crash the node to prevent routing attack vulnerability. diff --git a/network/p2p/scoring/registry_test.go b/network/p2p/scoring/registry_test.go index 2a63b9ec444..a7a9e047b63 100644 --- a/network/p2p/scoring/registry_test.go +++ b/network/p2p/scoring/registry_test.go @@ -13,9 +13,9 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/module/mock" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" + "github.com/onflow/flow-go/network/p2p/conf" mockp2p "github.com/onflow/flow-go/network/p2p/mock" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/utils/unittest" @@ -49,20 +49,20 @@ func TestNoPenaltyRecord(t *testing.T) { // penalty value as the app specific score. func TestPeerWithSpamRecord(t *testing.T) { t.Run("graft", func(t *testing.T) { - testPeerWithSpamRecord(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testPeerWithSpamRecord(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testPeerWithSpamRecord(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testPeerWithSpamRecord(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testPeerWithSpamRecord(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testPeerWithSpamRecord(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testPeerWithSpamRecord(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testPeerWithSpamRecord(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } -func testPeerWithSpamRecord(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { +func testPeerWithSpamRecord(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -99,22 +99,22 @@ func testPeerWithSpamRecord(t *testing.T, messageType netconf.ControlMessageType func TestSpamRecord_With_UnknownIdentity(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an unknown identity. -func testSpamRecordWithUnknownIdentity(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithUnknownIdentity(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -150,22 +150,22 @@ func testSpamRecordWithUnknownIdentity(t *testing.T, messageType netconf.Control func TestSpamRecord_With_SubscriptionPenalty(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, netconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an invalid subscription as well. -func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType netconf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -209,7 +209,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgPrune, + MsgType: conf.CtrlMsgPrune, Count: 1, }) @@ -217,7 +217,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgGraft, + MsgType: conf.CtrlMsgGraft, Count: 1, }) @@ -225,7 +225,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgIHave, + MsgType: conf.CtrlMsgIHave, Count: 1, }) @@ -233,7 +233,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgIWant, + MsgType: conf.CtrlMsgIWant, Count: 1, }) @@ -275,7 +275,7 @@ func TestSpamPenaltyDecayToZero(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgGraft, + MsgType: conf.CtrlMsgGraft, Count: 1, }) @@ -325,7 +325,7 @@ func TestPersistingUnknownIdentityPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgGraft, + MsgType: conf.CtrlMsgGraft, Count: 1, }) @@ -378,7 +378,7 @@ func TestPersistingInvalidSubscriptionPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: netconf.CtrlMsgGraft, + MsgType: conf.CtrlMsgGraft, Count: 1, }) diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index 0ae52257e8c..5aa83dfc75e 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -22,8 +22,8 @@ import ( "github.com/onflow/flow-go/module/mock" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -94,7 +94,7 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { p2ptest.WithPeerScoringEnabled(idProvider), p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(func(zerolog.Logger, flow.Identifier, - *netconf.GossipSubRPCInspectorsConfig, + *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, flownet.NetworkingType, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 932057f2e66..7a9cc0cd264 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -28,8 +28,8 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" - "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" @@ -201,7 +201,7 @@ type NodeFixtureParameters struct { PubSubTracer p2p.PubSubTracer GossipSubPeerScoreTracerInterval time.Duration // intervals at which the peer score is updated and logged. CreateStreamRetryDelay time.Duration - GossipSubRPCInspectorCfg *netconf.GossipSubRPCInspectorsConfig + GossipSubRPCInspectorCfg *conf.GossipSubRPCInspectorsConfig GossipSubRpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } @@ -211,7 +211,7 @@ func OverrideGossipSubRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspector } } -func OverrideGossipSubRpcInspectorConfig(cfg *netconf.GossipSubRPCInspectorsConfig) NodeFixtureParameterOption { +func OverrideGossipSubRpcInspectorConfig(cfg *conf.GossipSubRPCInspectorsConfig) NodeFixtureParameterOption { return func(p *NodeFixtureParameters) { p.GossipSubRPCInspectorCfg = cfg } @@ -612,10 +612,10 @@ func PeerIdSliceFixture(t *testing.T, n int) peer.IDSlice { // - *netconf.GossipSubRPCValidationInspectorConfigs: GossipSubRPCValidationInspectorConfigs instance. // Note: the parameters in this fixture are INTENTIONALLY independent of the default values in the config file. // This is to allow test parameters to be changed without affecting the default values in the config file. -func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *netconf.GossipSubRPCInspectorsConfig { - return &netconf.GossipSubRPCInspectorsConfig{ - GossipSubRPCValidationInspectorConfigs: netconf.GossipSubRPCValidationInspectorConfigs{ - ClusterPrefixedMessageConfig: netconf.ClusterPrefixedMessageConfig{ +func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *conf.GossipSubRPCInspectorsConfig { + return &conf.GossipSubRPCInspectorsConfig{ + GossipSubRPCValidationInspectorConfigs: conf.GossipSubRPCValidationInspectorConfigs{ + ClusterPrefixedMessageConfig: conf.ClusterPrefixedMessageConfig{ ClusterPrefixHardThreshold: 100, ClusterPrefixedControlMsgsReceivedCacheSize: 100, ClusterPrefixedControlMsgsReceivedCacheDecay: .99, @@ -653,7 +653,7 @@ func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *netconf.GossipS IHaveAsyncInspectSampleSizePercentage: .10, IHaveInspectionMaxSampleSize: 100, }, - GossipSubRPCMetricsInspectorConfigs: netconf.GossipSubRPCMetricsInspectorConfigs{ + GossipSubRPCMetricsInspectorConfigs: conf.GossipSubRPCMetricsInspectorConfigs{ NumberOfWorkers: 1, CacheSize: 100, }, From 0f4e3ea95454cc1f5d49168af0907b08b48d48df Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:14:21 -0700 Subject: [PATCH 45/74] mock fix --- .../gossip_sub_rpc_inspector_suite_factory_func.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go index 8f532afb7b3..825465addff 100644 --- a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go +++ b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go @@ -4,8 +4,9 @@ package mockp2p import ( flow "github.com/onflow/flow-go/model/flow" + conf "github.com/onflow/flow-go/network/p2p/conf" + metrics "github.com/onflow/flow-go/module/metrics" - netconf "github.com/onflow/flow-go/network/p2p/conf" mock "github.com/stretchr/testify/mock" @@ -24,15 +25,15 @@ type GossipSubRpcInspectorSuiteFactoryFunc struct { } // Execute provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4, _a5, _a6 -func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 flow.Identifier, _a2 *netconf.GossipSubRPCInspectorsConfig, _a3 module.GossipSubMetrics, _a4 metrics.HeroCacheMetricsFactory, _a5 network.NetworkingType, _a6 module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { +func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 flow.Identifier, _a2 *conf.GossipSubRPCInspectorsConfig, _a3 module.GossipSubMetrics, _a4 metrics.HeroCacheMetricsFactory, _a5 network.NetworkingType, _a6 module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { ret := _m.Called(_a0, _a1, _a2, _a3, _a4, _a5, _a6) var r0 p2p.GossipSubInspectorSuite var r1 error - if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) (p2p.GossipSubInspectorSuite, error)); ok { + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) (p2p.GossipSubInspectorSuite, error)); ok { return rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } - if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) p2p.GossipSubInspectorSuite); ok { + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) p2p.GossipSubInspectorSuite); ok { r0 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } else { if ret.Get(0) != nil { @@ -40,7 +41,7 @@ func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 } } - if rf, ok := ret.Get(1).(func(zerolog.Logger, flow.Identifier, *netconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) error); ok { + if rf, ok := ret.Get(1).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) error); ok { r1 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } else { r1 = ret.Error(1) From 2cc22e0fa59359291525240a71f74a873eba8134 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:16:09 -0700 Subject: [PATCH 46/74] removes import cycle --- network/netconf/{ => error}/errors.go | 2 +- network/netconf/{ => error}/errors_test.go | 2 +- network/p2p/conf/gossipsub_rpc_inspectors.go | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) rename network/netconf/{ => error}/errors.go (98%) rename network/netconf/{ => error}/errors_test.go (98%) diff --git a/network/netconf/errors.go b/network/netconf/error/errors.go similarity index 98% rename from network/netconf/errors.go rename to network/netconf/error/errors.go index 534c13b9dfd..edf4998ab37 100644 --- a/network/netconf/errors.go +++ b/network/netconf/error/errors.go @@ -1,4 +1,4 @@ -package netconf +package error import ( "errors" diff --git a/network/netconf/errors_test.go b/network/netconf/error/errors_test.go similarity index 98% rename from network/netconf/errors_test.go rename to network/netconf/error/errors_test.go index f5c3a6dbc96..704d229b9f7 100644 --- a/network/netconf/errors_test.go +++ b/network/netconf/error/errors_test.go @@ -1,4 +1,4 @@ -package netconf +package error import ( "fmt" diff --git a/network/p2p/conf/gossipsub_rpc_inspectors.go b/network/p2p/conf/gossipsub_rpc_inspectors.go index bd9e22d9746..03cba0258d2 100644 --- a/network/p2p/conf/gossipsub_rpc_inspectors.go +++ b/network/p2p/conf/gossipsub_rpc_inspectors.go @@ -3,7 +3,7 @@ package conf import ( "fmt" - "github.com/onflow/flow-go/network/netconf" + error2 "github.com/onflow/flow-go/network/netconf/error" ) // ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. @@ -148,11 +148,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return netconf.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } From 8b85fe3851234fc9274b05b002e764dfd7706a4f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:18:23 -0700 Subject: [PATCH 47/74] fixes improt cycle --- network/{netconf/error => p2p/conf}/errors.go | 6 ++---- network/{netconf/error => p2p/conf}/errors_test.go | 6 ++---- network/p2p/conf/gossipsub_rpc_inspectors.go | 8 +++----- 3 files changed, 7 insertions(+), 13 deletions(-) rename network/{netconf/error => p2p/conf}/errors.go (80%) rename network/{netconf/error => p2p/conf}/errors_test.go (91%) diff --git a/network/netconf/error/errors.go b/network/p2p/conf/errors.go similarity index 80% rename from network/netconf/error/errors.go rename to network/p2p/conf/errors.go index edf4998ab37..51f95a92272 100644 --- a/network/netconf/error/errors.go +++ b/network/p2p/conf/errors.go @@ -1,10 +1,8 @@ -package error +package conf import ( "errors" "fmt" - - "github.com/onflow/flow-go/network/p2p/conf" ) // InvalidLimitConfigError indicates the validation limit is < 0. @@ -21,7 +19,7 @@ func (e InvalidLimitConfigError) Unwrap() error { } // NewInvalidLimitConfigErr returns a new ErrValidationLimit. -func NewInvalidLimitConfigErr(controlMsg conf.ControlMessageType, err error) InvalidLimitConfigError { +func NewInvalidLimitConfigErr(controlMsg ControlMessageType, err error) InvalidLimitConfigError { return InvalidLimitConfigError{fmt.Errorf("invalid rpc control message %s validation limit configuration: %w", controlMsg, err)} } diff --git a/network/netconf/error/errors_test.go b/network/p2p/conf/errors_test.go similarity index 91% rename from network/netconf/error/errors_test.go rename to network/p2p/conf/errors_test.go index 704d229b9f7..5058730db92 100644 --- a/network/netconf/error/errors_test.go +++ b/network/p2p/conf/errors_test.go @@ -1,17 +1,15 @@ -package error +package conf import ( "fmt" "testing" "github.com/stretchr/testify/assert" - - "github.com/onflow/flow-go/network/p2p/conf" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. func TestErrInvalidLimitConfigRoundTrip(t *testing.T) { - controlMsg := conf.CtrlMsgGraft + controlMsg := CtrlMsgGraft limit := uint64(500) e := fmt.Errorf("invalid rate limit value %d must be greater than 0", limit) diff --git a/network/p2p/conf/gossipsub_rpc_inspectors.go b/network/p2p/conf/gossipsub_rpc_inspectors.go index 03cba0258d2..a814b0dcf0e 100644 --- a/network/p2p/conf/gossipsub_rpc_inspectors.go +++ b/network/p2p/conf/gossipsub_rpc_inspectors.go @@ -2,8 +2,6 @@ package conf import ( "fmt" - - error2 "github.com/onflow/flow-go/network/netconf/error" ) // ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. @@ -148,11 +146,11 @@ func (c *CtrlMsgValidationConfig) Validate() error { // check common config values used by all control message types switch { case c.RateLimit < 0: - return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid rate limit value %d must be greater than 0", c.RateLimit)) case c.HardThreshold <= 0: - return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid hard threshold value %d must be greater than 0", c.HardThreshold)) case c.SafetyThreshold <= 0: - return error2.NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) + return NewInvalidLimitConfigErr(c.ControlMsg, fmt.Errorf("invalid safety threshold value %d must be greater than 0", c.SafetyThreshold)) } return nil } From a8b44dafecbdb5360733676a5898407ba360073f Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:20:38 -0700 Subject: [PATCH 48/74] renames a package --- .../validation_inspector_test.go | 39 ++++++----- network/netconf/config.go | 12 ++-- network/netconf/flags.go | 4 +- network/p2p/builder.go | 3 +- network/p2p/consumers.go | 9 ++- .../distributor/gossipsub_inspector_test.go | 3 +- .../control_message_validation_inspector.go | 65 +++++++++---------- network/p2p/inspector/validation/errors.go | 9 ++- .../p2p/inspector/validation/errors_test.go | 5 +- .../validation/inspect_message_request.go | 5 +- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 7 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 13 ++-- network/p2p/{conf => p2pconf}/errors.go | 2 +- network/p2p/{conf => p2pconf}/errors_test.go | 2 +- network/p2p/{conf => p2pconf}/gossipsub.go | 2 +- .../gossipsub_rpc_inspectors.go | 2 +- network/p2p/scoring/registry.go | 9 ++- network/p2p/scoring/registry_test.go | 45 +++++++------ network/p2p/scoring/scoring_test.go | 3 +- network/p2p/test/fixtures.go | 15 ++--- 20 files changed, 118 insertions(+), 136 deletions(-) rename network/p2p/{conf => p2pconf}/errors.go (97%) rename network/p2p/{conf => p2pconf}/errors_test.go (98%) rename network/p2p/{conf => p2pconf}/gossipsub.go (98%) rename network/p2p/{conf => p2pconf}/gossipsub_rpc_inspectors.go (99%) diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index b8692812535..3ec26252d19 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -24,7 +24,6 @@ import ( "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/validation" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -48,9 +47,9 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { inspectorConfig.PruneLimits.SafetyThreshold = safetyThreshold // expected log message logged when valid number GRAFT control messages spammed under safety threshold - graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", conf.CtrlMsgGraft) + graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pconf.CtrlMsgGraft) // expected log message logged when valid number PRUNE control messages spammed under safety threshold - pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", conf.CtrlMsgGraft) + pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pconf.CtrlMsgGraft) graftInfoLogsReceived := atomic.NewInt64(0) pruneInfoLogsReceived := atomic.NewInt64(0) // setup logger hook, we expect info log validation is skipped @@ -126,9 +125,9 @@ func TestValidationInspector_HardThreshold_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -194,7 +193,7 @@ func TestValidationInspector_HardThresholdIHave_Detection(t *testing.T) { require.Equal(t, uint64(messageCount), notification.Count) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: invIhaveNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -257,9 +256,9 @@ func TestValidationInspector_RateLimitedPeer_Detection(t *testing.T) { require.True(t, validation.IsErrRateLimitedControlMsg(notification.Err)) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -353,13 +352,13 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: require.Equal(t, uint64(ihaveMessageCount), notification.Count) invIHaveNotifCount.Inc() default: @@ -461,9 +460,9 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { require.True(t, validation.IsErrDuplicateTopic(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -538,9 +537,9 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { require.True(t, channels.IsUnknownClusterIDErr(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -608,7 +607,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -672,7 +671,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -745,9 +744,9 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { require.True(t, validation.IsErrUnstakedPeer(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: invGraftNotifCount.Inc() - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -805,7 +804,7 @@ func withExpectedNotificationDissemination(expectedNumOfTotalNotif int, f onNoti } // setupTest sets up common components of RPC inspector test. -func setupTest(t *testing.T, logger zerolog.Logger, role flow.Role, sporkID flow.Identifier, inspectorConfig *conf.GossipSubRPCValidationInspectorConfigs, mockDistributorOpts ...mockDistributorOption) (*irrecoverable.MockSignalerContext, context.CancelFunc, *corruptlibp2p.GossipSubRouterSpammer, p2p.LibP2PNode, flow.Identity, *mockp2p.GossipSubInspectorNotificationDistributor, *validation.ControlMsgValidationInspector, *mock.IdentityProvider) { +func setupTest(t *testing.T, logger zerolog.Logger, role flow.Role, sporkID flow.Identifier, inspectorConfig *p2pconf.GossipSubRPCValidationInspectorConfigs, mockDistributorOpts ...mockDistributorOption) (*irrecoverable.MockSignalerContext, context.CancelFunc, *corruptlibp2p.GossipSubRouterSpammer, p2p.LibP2PNode, flow.Identity, *mockp2p.GossipSubInspectorNotificationDistributor, *validation.ControlMsgValidationInspector, *mock.IdentityProvider) { idProvider := mock.NewIdentityProvider(t) spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) ctx, cancel := context.WithCancel(context.Background()) diff --git a/network/netconf/config.go b/network/netconf/config.go index f7a0fd2b4ad..5c6fa4507f9 100644 --- a/network/netconf/config.go +++ b/network/netconf/config.go @@ -2,19 +2,17 @@ package netconf import ( "time" - - "github.com/onflow/flow-go/network/p2p/conf" ) // Config encapsulation of configuration structs for all components related to the Flow network. type Config struct { // UnicastRateLimitersConfig configuration for all unicast rate limiters. - UnicastRateLimitersConfig `mapstructure:",squash"` - conf.ResourceManagerConfig `mapstructure:",squash"` - ConnectionManagerConfig `mapstructure:",squash"` + UnicastRateLimitersConfig `mapstructure:",squash"` + p2pconf.ResourceManagerConfig `mapstructure:",squash"` + ConnectionManagerConfig `mapstructure:",squash"` // GossipSubConfig core gossipsub configuration. - conf.GossipSubConfig `mapstructure:",squash"` - AlspConfig `mapstructure:",squash"` + p2pconf.GossipSubConfig `mapstructure:",squash"` + AlspConfig `mapstructure:",squash"` // NetworkConnectionPruning determines whether connections to nodes // that are not part of protocol state should be trimmed diff --git a/network/netconf/flags.go b/network/netconf/flags.go index 2e74a6c4644..8e5992229aa 100644 --- a/network/netconf/flags.go +++ b/network/netconf/flags.go @@ -5,8 +5,6 @@ import ( "strings" "github.com/spf13/pflag" - - "github.com/onflow/flow-go/network/p2p/conf" ) const ( @@ -137,7 +135,7 @@ func initRpcInspectorValidationLimitsFlags(flags *pflag.FlagSet, defaultNetConfi for _, ctrlMsgValidationConfig := range validationInspectorConfig.AllCtrlMsgValidationConfig() { ctrlMsgType := ctrlMsgValidationConfig.ControlMsg - if ctrlMsgValidationConfig.ControlMsg == conf.CtrlMsgIWant { + if ctrlMsgValidationConfig.ControlMsg == p2pconf.CtrlMsgIWant { continue } s := strings.ToLower(ctrlMsgType.String()) diff --git a/network/p2p/builder.go b/network/p2p/builder.go index d053575902d..bb90c389715 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/module/metrics" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p/conf" ) type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) @@ -109,7 +108,7 @@ type PeerScoringBuilder interface { type GossipSubRpcInspectorSuiteFactoryFunc func( zerolog.Logger, flow.Identifier, - *conf.GossipSubRPCInspectorsConfig, + *p2pconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, flownet.NetworkingType, diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index 916a370b9e2..82800027a12 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -5,12 +5,11 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/module/component" - "github.com/onflow/flow-go/network/p2p/conf" ) // ControlMessageTypes returns list of all libp2p control message types. -func ControlMessageTypes() []conf.ControlMessageType { - return []conf.ControlMessageType{conf.CtrlMsgIHave, conf.CtrlMsgIWant, conf.CtrlMsgGraft, conf.CtrlMsgPrune} +func ControlMessageTypes() []p2pconf.ControlMessageType { + return []p2pconf.ControlMessageType{p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant, p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune} } // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. @@ -35,7 +34,7 @@ type InvCtrlMsgNotif struct { // PeerID is the ID of the peer that sent the invalid control message. PeerID peer.ID // MsgType is the type of control message that was received. - MsgType conf.ControlMessageType + MsgType p2pconf.ControlMessageType // Count is the number of invalid control messages received from the peer that is reported in this notification. Count uint64 // Err any error associated with the invalid control message. @@ -43,7 +42,7 @@ type InvCtrlMsgNotif struct { } // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif -func NewInvalidControlMessageNotification(peerID peer.ID, msgType conf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { +func NewInvalidControlMessageNotification(peerID peer.ID, msgType p2pconf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { return &InvCtrlMsgNotif{ PeerID: peerID, MsgType: msgType, diff --git a/network/p2p/distributor/gossipsub_inspector_test.go b/network/p2p/distributor/gossipsub_inspector_test.go index bca0e250830..b76406b5a1e 100644 --- a/network/p2p/distributor/gossipsub_inspector_test.go +++ b/network/p2p/distributor/gossipsub_inspector_test.go @@ -13,7 +13,6 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/distributor" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -95,7 +94,7 @@ func invalidControlMessageNotificationListFixture(t *testing.T, n int) []*p2p.In func invalidControlMessageNotificationFixture(t *testing.T) *p2p.InvCtrlMsgNotif { return &p2p.InvCtrlMsgNotif{ PeerID: p2ptest.PeerIdFixture(t), - MsgType: []conf.ControlMessageType{conf.CtrlMsgGraft, conf.CtrlMsgPrune, conf.CtrlMsgIHave, conf.CtrlMsgIWant}[rand.Intn(4)], + MsgType: []p2pconf.ControlMessageType{p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune, p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant}[rand.Intn(4)], Count: rand.Uint64(), } } diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index ca738b6b51e..c3831e8272e 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/module/util" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" "github.com/onflow/flow-go/state/protocol" @@ -37,7 +36,7 @@ type ControlMsgValidationInspector struct { sporkID flow.Identifier metrics module.GossipSubRpcValidationInspectorMetrics // config control message validation configurations. - config *conf.GossipSubRPCValidationInspectorConfigs + config *p2pconf.GossipSubRPCValidationInspectorConfigs // distributor used to disseminate invalid RPC message notifications. distributor p2p.GossipSubInspectorNotifDistributor // workerPool queue that stores *InspectMsgRequest that will be processed by component workers. @@ -52,7 +51,7 @@ type ControlMsgValidationInspector struct { // In such cases, the inspector will allow a configured number of these messages from the corresponding peer. tracker *cache.ClusterPrefixedMessagesReceivedTracker idProvider module.IdentityProvider - rateLimiters map[conf.ControlMessageType]p2p.BasicRateLimiter + rateLimiters map[p2pconf.ControlMessageType]p2p.BasicRateLimiter } var _ component.Component = (*ControlMsgValidationInspector)(nil) @@ -74,7 +73,7 @@ var _ protocol.Consumer = (*ControlMsgValidationInspector)(nil) func NewControlMsgValidationInspector( logger zerolog.Logger, sporkID flow.Identifier, - config *conf.GossipSubRPCValidationInspectorConfigs, + config *p2pconf.GossipSubRPCValidationInspectorConfigs, distributor p2p.GossipSubInspectorNotifDistributor, inspectMsgQueueCacheCollector module.HeroCacheMetrics, clusterPrefixedCacheCollector module.HeroCacheMetrics, @@ -95,7 +94,7 @@ func NewControlMsgValidationInspector( tracker: tracker, idProvider: idProvider, metrics: inspectorMetrics, - rateLimiters: make(map[conf.ControlMessageType]p2p.BasicRateLimiter), + rateLimiters: make(map[p2pconf.ControlMessageType]p2p.BasicRateLimiter), } store := queue.NewHeroStore(config.CacheSize, logger, inspectMsgQueueCacheCollector) @@ -158,7 +157,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e } switch ctrlMsgType { - case conf.CtrlMsgGraft, conf.CtrlMsgPrune: + case p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune: // normal pre-processing err := c.blockingPreprocessingRpc(from, validationConfig, control) if err != nil { @@ -167,7 +166,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e Msg("could not pre-process rpc, aborting") return fmt.Errorf("could not pre-process rpc, aborting: %w", err) } - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: // iHave specific pre-processing sampleSize := util.SampleN(len(control.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveSyncInspectSampleSizePercentage) err := c.blockingIHaveSamplePreprocessing(from, validationConfig, control, sampleSize) @@ -210,9 +209,9 @@ func (c *ControlMsgValidationInspector) ActiveClustersChanged(clusterIDList flow // - ErrDiscardThreshold: if control message count exceeds the configured discard threshold. // // blockingPreprocessingRpc generic pre-processing validation func that ensures the RPC control message count does not exceed the configured hard threshold. -func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { - if validationConfig.ControlMsg != conf.CtrlMsgGraft && validationConfig.ControlMsg != conf.CtrlMsgPrune { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, conf.CtrlMsgGraft, conf.CtrlMsgPrune) +func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { + if validationConfig.ControlMsg != p2pconf.CtrlMsgGraft && validationConfig.ControlMsg != p2pconf.CtrlMsgPrune { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune) } count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) lg := c.logger.With(). @@ -249,11 +248,11 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, v } // blockingPreprocessingSampleRpc blocking pre-processing of a sample of iHave control messages. -func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - c.metrics.BlockingPreProcessingStarted(conf.CtrlMsgIHave.String(), sampleSize) +func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { + c.metrics.BlockingPreProcessingStarted(p2pconf.CtrlMsgIHave.String(), sampleSize) start := time.Now() defer func() { - c.metrics.BlockingPreProcessingFinished(conf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) + c.metrics.BlockingPreProcessingFinished(p2pconf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) }() err := c.blockingPreprocessingSampleRpc(from, validationConfig, controlMessage, sampleSize) if err != nil { @@ -265,9 +264,9 @@ func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from pe // blockingPreprocessingSampleRpc blocking pre-processing validation func that performs some pre-validation of RPC control messages. // If the RPC control message count exceeds the configured hard threshold we perform synchronous topic validation on a subset // of the control messages. This is used for control message types that do not have an upper bound on the amount of messages a node can send. -func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - if validationConfig.ControlMsg != conf.CtrlMsgIHave && validationConfig.ControlMsg != conf.CtrlMsgIWant { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, conf.CtrlMsgIHave, conf.CtrlMsgIWant) +func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { + if validationConfig.ControlMsg != p2pconf.CtrlMsgIHave && validationConfig.ControlMsg != p2pconf.CtrlMsgIWant { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant) } activeClusterIDS := c.tracker.GetActiveClusterIds() count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) @@ -279,7 +278,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer if count > validationConfig.HardThreshold { // for iHave control message topic validation we only validate a random subset of the messages // shuffle the ihave messages to perform random validation on a subset of size sampleSize - err := c.sampleCtrlMessages(conf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(p2pconf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -305,7 +304,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // to randomize async validation to avoid data race that can occur when // performing the sampling asynchronously. // for iHave control message topic validation we only validate a random subset of the messages - err := c.sampleCtrlMessages(conf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(p2pconf.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -314,9 +313,9 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // sampleCtrlMessages performs sampling on the specified control message that will randomize // the items in the control message slice up to index sampleSize-1. -func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType conf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { +func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType p2pconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { switch ctrlMsgType { - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: iHaves := ctrlMsg.GetIhave() swap := func(i, j uint) { iHaves[i], iHaves[j] = iHaves[j], iHaves[i] @@ -375,13 +374,13 @@ func (c *ControlMsgValidationInspector) processInspectMsgReq(req *InspectMsgRequ } // getCtrlMsgCount returns the amount of specified control message type in the rpc ControlMessage. -func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType conf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { +func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2pconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { switch ctrlMsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: return uint64(len(ctrlMsg.GetGraft())) - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: return uint64(len(ctrlMsg.GetPrune())) - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: return uint64(len(ctrlMsg.GetIhave())) default: return 0 @@ -392,20 +391,20 @@ func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType conf.Control // Expected error returns during normal operations: // - channels.InvalidTopicErr: if topic is invalid. // - ErrDuplicateTopic: if a duplicate topic ID is encountered. -func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { +func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { activeClusterIDS := c.tracker.GetActiveClusterIds() switch validationConfig.ControlMsg { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: return c.validateGrafts(from, ctrlMsg, activeClusterIDS) - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: return c.validatePrunes(from, ctrlMsg, activeClusterIDS) - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: return c.validateIhaves(from, validationConfig, ctrlMsg, activeClusterIDS) default: // sanity check // This should never happen validateTopics is only used to validate GRAFT and PRUNE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", conf.CtrlMsgGraft, conf.CtrlMsgPrune, conf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune, p2pconf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } @@ -445,7 +444,7 @@ func (c *ControlMsgValidationInspector) validatePrunes(from peer.ID, ctrlMsg *pu } // validateIhaves performs topic validation on all ihaves in the control message using the provided validateTopic func while tracking duplicates. -func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList) error { +func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList) error { sampleSize := util.SampleN(len(ctrlMsg.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveAsyncInspectSampleSizePercentage) return c.validateTopicsSample(from, validationConfig, ctrlMsg, activeClusterIDS, sampleSize) } @@ -453,10 +452,10 @@ func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationC // validateTopicsSample samples a subset of topics from the specified control message and ensures the sample contains only valid flow topic/channel and no duplicate topics exist. // Sample size ensures liveness of the network when validating messages with no upper bound on the amount of messages that may be received. // All errors returned from this function can be considered benign. -func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { +func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { tracker := make(duplicateTopicTracker) switch validationConfig.ControlMsg { - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: for i := uint(0); i < sampleSize; i++ { topic := channels.Topic(ctrlMsg.Ihave[i].GetTopicID()) if tracker.isDuplicate(topic) { @@ -472,7 +471,7 @@ func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, valid // sanity check // This should never happen validateTopicsSample is only used to validate IHAVE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", conf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", p2pconf.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } diff --git a/network/p2p/inspector/validation/errors.go b/network/p2p/inspector/validation/errors.go index 7ceb4f842b4..68eb16500e1 100644 --- a/network/p2p/inspector/validation/errors.go +++ b/network/p2p/inspector/validation/errors.go @@ -5,13 +5,12 @@ import ( "fmt" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p/conf" ) // ErrHardThreshold indicates that the amount of RPC messages received exceeds hard threshold. type ErrHardThreshold struct { // controlMsg the control message type. - controlMsg conf.ControlMessageType + controlMsg p2pconf.ControlMessageType // amount the amount of control messages. amount uint64 // hardThreshold configured hard threshold. @@ -23,7 +22,7 @@ func (e ErrHardThreshold) Error() string { } // NewHardThresholdErr returns a new ErrHardThreshold. -func NewHardThresholdErr(controlMsg conf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { +func NewHardThresholdErr(controlMsg p2pconf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { return ErrHardThreshold{controlMsg: controlMsg, amount: amount, hardThreshold: hardThreshold} } @@ -35,7 +34,7 @@ func IsErrHardThreshold(err error) bool { // ErrRateLimitedControlMsg indicates the specified RPC control message is rate limited for the specified peer. type ErrRateLimitedControlMsg struct { - controlMsg conf.ControlMessageType + controlMsg p2pconf.ControlMessageType } func (e ErrRateLimitedControlMsg) Error() string { @@ -43,7 +42,7 @@ func (e ErrRateLimitedControlMsg) Error() string { } // NewRateLimitedControlMsgErr returns a new ErrValidationLimit. -func NewRateLimitedControlMsgErr(controlMsg conf.ControlMessageType) ErrRateLimitedControlMsg { +func NewRateLimitedControlMsgErr(controlMsg p2pconf.ControlMessageType) ErrRateLimitedControlMsg { return ErrRateLimitedControlMsg{controlMsg: controlMsg} } diff --git a/network/p2p/inspector/validation/errors_test.go b/network/p2p/inspector/validation/errors_test.go index 62d9f3b7d40..73736d46516 100644 --- a/network/p2p/inspector/validation/errors_test.go +++ b/network/p2p/inspector/validation/errors_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/onflow/flow-go/network/channels" - "github.com/onflow/flow-go/network/p2p/conf" ) // TestErrActiveClusterIDsNotSetRoundTrip ensures correct error formatting for ErrActiveClusterIdsNotSet. @@ -29,7 +28,7 @@ func TestErrActiveClusterIDsNotSetRoundTrip(t *testing.T) { // TestErrHardThresholdRoundTrip ensures correct error formatting for ErrHardThreshold. func TestErrHardThresholdRoundTrip(t *testing.T) { - controlMsg := conf.CtrlMsgGraft + controlMsg := p2pconf.CtrlMsgGraft amount := uint64(100) hardThreshold := uint64(500) err := NewHardThresholdErr(controlMsg, amount, hardThreshold) @@ -48,7 +47,7 @@ func TestErrHardThresholdRoundTrip(t *testing.T) { // TestErrRateLimitedControlMsgRoundTrip ensures correct error formatting for ErrRateLimitedControlMsg. func TestErrRateLimitedControlMsgRoundTrip(t *testing.T) { - controlMsg := conf.CtrlMsgGraft + controlMsg := p2pconf.CtrlMsgGraft err := NewRateLimitedControlMsgErr(controlMsg) // tests the error message formatting. diff --git a/network/p2p/inspector/validation/inspect_message_request.go b/network/p2p/inspector/validation/inspect_message_request.go index 0dcd5a40829..8d73f9fdc0f 100644 --- a/network/p2p/inspector/validation/inspect_message_request.go +++ b/network/p2p/inspector/validation/inspect_message_request.go @@ -6,7 +6,6 @@ import ( pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/inspector/internal" ) @@ -18,11 +17,11 @@ type InspectMsgRequest struct { Peer peer.ID // CtrlMsg the control message that will be inspected. ctrlMsg *pubsub_pb.ControlMessage - validationConfig *conf.CtrlMsgValidationConfig + validationConfig *p2pconf.CtrlMsgValidationConfig } // NewInspectMsgRequest returns a new *InspectMsgRequest. -func NewInspectMsgRequest(from peer.ID, validationConfig *conf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) (*InspectMsgRequest, error) { +func NewInspectMsgRequest(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) (*InspectMsgRequest, error) { nonce, err := internal.Nonce() if err != nil { return nil, fmt.Errorf("failed to get inspect message request nonce: %w", err) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 1ab40416398..34bded0cc73 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/distributor" "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" @@ -49,7 +48,7 @@ type Builder struct { scoreOptionConfig *scoring.ScoreOptionConfig idProvider module.IdentityProvider routingSystem routing.Routing - rpcInspectorConfig *conf.GossipSubRPCInspectorsConfig + rpcInspectorConfig *p2pconf.GossipSubRPCInspectorsConfig rpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } @@ -171,7 +170,7 @@ func NewGossipSubBuilder( networkType network.NetworkingType, sporkId flow.Identifier, idProvider module.IdentityProvider, - rpcInspectorConfig *conf.GossipSubRPCInspectorsConfig, + rpcInspectorConfig *p2pconf.GossipSubRPCInspectorsConfig, ) *Builder { lg := logger.With().Str("component", "gossipsub").Logger() b := &Builder{ @@ -217,7 +216,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return func( logger zerolog.Logger, sporkId flow.Identifier, - inspectorCfg *conf.GossipSubRPCInspectorsConfig, + inspectorCfg *p2pconf.GossipSubRPCInspectorsConfig, gossipSubMetrics module.GossipSubMetrics, heroCacheMetricsFactory metrics.HeroCacheMetricsFactory, networkType network.NetworkingType, diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 185794e0f17..025945bdc01 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -29,7 +29,6 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/keyutils" @@ -61,7 +60,7 @@ type LibP2PNodeBuilder struct { basicResolver madns.BasicResolver resourceManager network.ResourceManager - resourceManagerCfg *conf.ResourceManagerConfig + resourceManagerCfg *p2pconf.ResourceManagerConfig connManager connmgr.ConnManager connGater p2p.ConnectionGater routingFactory func(context.Context, host.Host) (routing.Routing, error) @@ -82,8 +81,8 @@ func NewNodeBuilder( networkKey fcrypto.PrivateKey, sporkId flow.Identifier, idProvider module.IdentityProvider, - rCfg *conf.ResourceManagerConfig, - rpcInspectorCfg *conf.GossipSubRPCInspectorsConfig, + rCfg *p2pconf.ResourceManagerConfig, + rpcInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, @@ -452,9 +451,9 @@ func DefaultNodeBuilder( role string, connGaterCfg *p2pconfig.ConnectionGaterConfig, peerManagerCfg *p2pconfig.PeerManagerConfig, - gossipCfg *conf.GossipSubConfig, - rpcInspectorCfg *conf.GossipSubRPCInspectorsConfig, - rCfg *conf.ResourceManagerConfig, + gossipCfg *p2pconf.GossipSubConfig, + rpcInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig, + rCfg *p2pconf.ResourceManagerConfig, uniCfg *p2pconfig.UnicastConfig, connMgrConfig *netconf.ConnectionManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) (p2p.NodeBuilder, error) { diff --git a/network/p2p/conf/errors.go b/network/p2p/p2pconf/errors.go similarity index 97% rename from network/p2p/conf/errors.go rename to network/p2p/p2pconf/errors.go index 51f95a92272..24b10167c56 100644 --- a/network/p2p/conf/errors.go +++ b/network/p2p/p2pconf/errors.go @@ -1,4 +1,4 @@ -package conf +package p2pconf import ( "errors" diff --git a/network/p2p/conf/errors_test.go b/network/p2p/p2pconf/errors_test.go similarity index 98% rename from network/p2p/conf/errors_test.go rename to network/p2p/p2pconf/errors_test.go index 5058730db92..2cf0a2144dc 100644 --- a/network/p2p/conf/errors_test.go +++ b/network/p2p/p2pconf/errors_test.go @@ -1,4 +1,4 @@ -package conf +package p2pconf import ( "fmt" diff --git a/network/p2p/conf/gossipsub.go b/network/p2p/p2pconf/gossipsub.go similarity index 98% rename from network/p2p/conf/gossipsub.go rename to network/p2p/p2pconf/gossipsub.go index cc1d5ea0b2a..f9155129efd 100644 --- a/network/p2p/conf/gossipsub.go +++ b/network/p2p/p2pconf/gossipsub.go @@ -1,4 +1,4 @@ -package conf +package p2pconf import ( "time" diff --git a/network/p2p/conf/gossipsub_rpc_inspectors.go b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go similarity index 99% rename from network/p2p/conf/gossipsub_rpc_inspectors.go rename to network/p2p/p2pconf/gossipsub_rpc_inspectors.go index a814b0dcf0e..59ea398cbc0 100644 --- a/network/p2p/conf/gossipsub_rpc_inspectors.go +++ b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go @@ -1,4 +1,4 @@ -package conf +package p2pconf import ( "fmt" diff --git a/network/p2p/scoring/registry.go b/network/p2p/scoring/registry.go index e076ffe9f16..8eb7666278b 100644 --- a/network/p2p/scoring/registry.go +++ b/network/p2p/scoring/registry.go @@ -11,7 +11,6 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/utils/logging" ) @@ -254,13 +253,13 @@ func (r *GossipSubAppSpecificScoreRegistry) OnInvalidControlMessageNotification( record, err := r.spamScoreCache.Update(notification.PeerID, func(record p2p.GossipSubSpamRecord) p2p.GossipSubSpamRecord { switch notification.MsgType { - case conf.CtrlMsgGraft: + case p2pconf.CtrlMsgGraft: record.Penalty += r.penalty.Graft - case conf.CtrlMsgPrune: + case p2pconf.CtrlMsgPrune: record.Penalty += r.penalty.Prune - case conf.CtrlMsgIHave: + case p2pconf.CtrlMsgIHave: record.Penalty += r.penalty.IHave - case conf.CtrlMsgIWant: + case p2pconf.CtrlMsgIWant: record.Penalty += r.penalty.IWant default: // the error is considered fatal as it means that we have an unsupported misbehaviour type, we should crash the node to prevent routing attack vulnerability. diff --git a/network/p2p/scoring/registry_test.go b/network/p2p/scoring/registry_test.go index a7a9e047b63..5e69abd8a0a 100644 --- a/network/p2p/scoring/registry_test.go +++ b/network/p2p/scoring/registry_test.go @@ -15,7 +15,6 @@ import ( "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" - "github.com/onflow/flow-go/network/p2p/conf" mockp2p "github.com/onflow/flow-go/network/p2p/mock" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/utils/unittest" @@ -49,20 +48,20 @@ func TestNoPenaltyRecord(t *testing.T) { // penalty value as the app specific score. func TestPeerWithSpamRecord(t *testing.T) { t.Run("graft", func(t *testing.T) { - testPeerWithSpamRecord(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testPeerWithSpamRecord(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testPeerWithSpamRecord(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testPeerWithSpamRecord(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testPeerWithSpamRecord(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testPeerWithSpamRecord(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testPeerWithSpamRecord(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testPeerWithSpamRecord(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } -func testPeerWithSpamRecord(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { +func testPeerWithSpamRecord(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -99,22 +98,22 @@ func testPeerWithSpamRecord(t *testing.T, messageType conf.ControlMessageType, e func TestSpamRecord_With_UnknownIdentity(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an unknown identity. -func testSpamRecordWithUnknownIdentity(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -150,22 +149,22 @@ func testSpamRecordWithUnknownIdentity(t *testing.T, messageType conf.ControlMes func TestSpamRecord_With_SubscriptionPenalty(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, conf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an invalid subscription as well. -func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType conf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -209,7 +208,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgPrune, + MsgType: p2pconf.CtrlMsgPrune, Count: 1, }) @@ -217,7 +216,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgGraft, + MsgType: p2pconf.CtrlMsgGraft, Count: 1, }) @@ -225,7 +224,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgIHave, + MsgType: p2pconf.CtrlMsgIHave, Count: 1, }) @@ -233,7 +232,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgIWant, + MsgType: p2pconf.CtrlMsgIWant, Count: 1, }) @@ -275,7 +274,7 @@ func TestSpamPenaltyDecayToZero(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgGraft, + MsgType: p2pconf.CtrlMsgGraft, Count: 1, }) @@ -325,7 +324,7 @@ func TestPersistingUnknownIdentityPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgGraft, + MsgType: p2pconf.CtrlMsgGraft, Count: 1, }) @@ -378,7 +377,7 @@ func TestPersistingInvalidSubscriptionPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: conf.CtrlMsgGraft, + MsgType: p2pconf.CtrlMsgGraft, Count: 1, }) diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index 5aa83dfc75e..d0b252d7195 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -23,7 +23,6 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -94,7 +93,7 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { p2ptest.WithPeerScoringEnabled(idProvider), p2ptest.OverrideGossipSubRpcInspectorSuiteFactory(func(zerolog.Logger, flow.Identifier, - *conf.GossipSubRPCInspectorsConfig, + *p2pconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, flownet.NetworkingType, diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 7a9cc0cd264..4c753e33b44 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -29,7 +29,6 @@ import ( "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/conf" "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" @@ -201,7 +200,7 @@ type NodeFixtureParameters struct { PubSubTracer p2p.PubSubTracer GossipSubPeerScoreTracerInterval time.Duration // intervals at which the peer score is updated and logged. CreateStreamRetryDelay time.Duration - GossipSubRPCInspectorCfg *conf.GossipSubRPCInspectorsConfig + GossipSubRPCInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig GossipSubRpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc } @@ -211,7 +210,7 @@ func OverrideGossipSubRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspector } } -func OverrideGossipSubRpcInspectorConfig(cfg *conf.GossipSubRPCInspectorsConfig) NodeFixtureParameterOption { +func OverrideGossipSubRpcInspectorConfig(cfg *p2pconf.GossipSubRPCInspectorsConfig) NodeFixtureParameterOption { return func(p *NodeFixtureParameters) { p.GossipSubRPCInspectorCfg = cfg } @@ -612,10 +611,10 @@ func PeerIdSliceFixture(t *testing.T, n int) peer.IDSlice { // - *netconf.GossipSubRPCValidationInspectorConfigs: GossipSubRPCValidationInspectorConfigs instance. // Note: the parameters in this fixture are INTENTIONALLY independent of the default values in the config file. // This is to allow test parameters to be changed without affecting the default values in the config file. -func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *conf.GossipSubRPCInspectorsConfig { - return &conf.GossipSubRPCInspectorsConfig{ - GossipSubRPCValidationInspectorConfigs: conf.GossipSubRPCValidationInspectorConfigs{ - ClusterPrefixedMessageConfig: conf.ClusterPrefixedMessageConfig{ +func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *p2pconf.GossipSubRPCInspectorsConfig { + return &p2pconf.GossipSubRPCInspectorsConfig{ + GossipSubRPCValidationInspectorConfigs: p2pconf.GossipSubRPCValidationInspectorConfigs{ + ClusterPrefixedMessageConfig: p2pconf.ClusterPrefixedMessageConfig{ ClusterPrefixHardThreshold: 100, ClusterPrefixedControlMsgsReceivedCacheSize: 100, ClusterPrefixedControlMsgsReceivedCacheDecay: .99, @@ -653,7 +652,7 @@ func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *conf.GossipSubR IHaveAsyncInspectSampleSizePercentage: .10, IHaveInspectionMaxSampleSize: 100, }, - GossipSubRPCMetricsInspectorConfigs: conf.GossipSubRPCMetricsInspectorConfigs{ + GossipSubRPCMetricsInspectorConfigs: p2pconf.GossipSubRPCMetricsInspectorConfigs{ NumberOfWorkers: 1, CacheSize: 100, }, From 1763c407b2c2f526bd692222cbecc4b8fa2f8816 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:24:10 -0700 Subject: [PATCH 49/74] repackages message types --- network/p2p/consumers.go | 9 ++--- network/p2p/p2pconf/errors.go | 4 ++- network/p2p/p2pconf/errors_test.go | 4 ++- .../p2p/p2pconf/gossipsub_rpc_inspectors.go | 36 +++++++------------ network/p2p/pubsub.go | 19 ++++++++++ 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index 82800027a12..7cac52c0ef2 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -7,11 +7,6 @@ import ( "github.com/onflow/flow-go/module/component" ) -// ControlMessageTypes returns list of all libp2p control message types. -func ControlMessageTypes() []p2pconf.ControlMessageType { - return []p2pconf.ControlMessageType{p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant, p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune} -} - // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. // It is used to distribute notifications to the consumers in an asynchronous manner and non-blocking manner. // The implementation should guarantee that all registered consumers are called upon distribution of a new event. @@ -34,7 +29,7 @@ type InvCtrlMsgNotif struct { // PeerID is the ID of the peer that sent the invalid control message. PeerID peer.ID // MsgType is the type of control message that was received. - MsgType p2pconf.ControlMessageType + MsgType ControlMessageType // Count is the number of invalid control messages received from the peer that is reported in this notification. Count uint64 // Err any error associated with the invalid control message. @@ -42,7 +37,7 @@ type InvCtrlMsgNotif struct { } // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif -func NewInvalidControlMessageNotification(peerID peer.ID, msgType p2pconf.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { +func NewInvalidControlMessageNotification(peerID peer.ID, msgType ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { return &InvCtrlMsgNotif{ PeerID: peerID, MsgType: msgType, diff --git a/network/p2p/p2pconf/errors.go b/network/p2p/p2pconf/errors.go index 24b10167c56..3d5f7c37dde 100644 --- a/network/p2p/p2pconf/errors.go +++ b/network/p2p/p2pconf/errors.go @@ -3,6 +3,8 @@ package p2pconf import ( "errors" "fmt" + + "github.com/onflow/flow-go/network/p2p" ) // InvalidLimitConfigError indicates the validation limit is < 0. @@ -19,7 +21,7 @@ func (e InvalidLimitConfigError) Unwrap() error { } // NewInvalidLimitConfigErr returns a new ErrValidationLimit. -func NewInvalidLimitConfigErr(controlMsg ControlMessageType, err error) InvalidLimitConfigError { +func NewInvalidLimitConfigErr(controlMsg p2p.ControlMessageType, err error) InvalidLimitConfigError { return InvalidLimitConfigError{fmt.Errorf("invalid rpc control message %s validation limit configuration: %w", controlMsg, err)} } diff --git a/network/p2p/p2pconf/errors_test.go b/network/p2p/p2pconf/errors_test.go index 2cf0a2144dc..4419b6f7045 100644 --- a/network/p2p/p2pconf/errors_test.go +++ b/network/p2p/p2pconf/errors_test.go @@ -5,11 +5,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/onflow/flow-go/network/p2p" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. func TestErrInvalidLimitConfigRoundTrip(t *testing.T) { - controlMsg := CtrlMsgGraft + controlMsg := p2p.CtrlMsgGraft limit := uint64(500) e := fmt.Errorf("invalid rate limit value %d must be greater than 0", limit) diff --git a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go index 59ea398cbc0..486639565df 100644 --- a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go +++ b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go @@ -2,20 +2,8 @@ package p2pconf import ( "fmt" -) - -// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. -type ControlMessageType string - -func (c ControlMessageType) String() string { - return string(c) -} -const ( - CtrlMsgIHave ControlMessageType = "IHAVE" - CtrlMsgIWant ControlMessageType = "IWANT" - CtrlMsgGraft ControlMessageType = "GRAFT" - CtrlMsgPrune ControlMessageType = "PRUNE" + "github.com/onflow/flow-go/network/p2p" ) // GossipSubRPCInspectorsConfig encompasses configuration related to gossipsub RPC message inspectors. @@ -74,25 +62,25 @@ type GossipSubRPCValidationInspectorConfigs struct { } // GetCtrlMsgValidationConfig returns the CtrlMsgValidationConfig for the specified p2p.ControlMessageType. -func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg ControlMessageType) (*CtrlMsgValidationConfig, bool) { +func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg p2p.ControlMessageType) (*CtrlMsgValidationConfig, bool) { switch controlMsg { - case CtrlMsgGraft: + case p2p.CtrlMsgGraft: return &CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgGraft, + ControlMsg: p2p.CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, true - case CtrlMsgPrune: + case p2p.CtrlMsgPrune: return &CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgPrune, + ControlMsg: p2p.CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, true - case CtrlMsgIHave: + case p2p.CtrlMsgIHave: return &CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgIHave, + ControlMsg: p2p.CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -105,17 +93,17 @@ func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(c // AllCtrlMsgValidationConfig returns all control message validation configs in a list. func (conf *GossipSubRPCValidationInspectorConfigs) AllCtrlMsgValidationConfig() CtrlMsgValidationConfigs { return CtrlMsgValidationConfigs{&CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgGraft, + ControlMsg: p2p.CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgPrune, + ControlMsg: p2p.CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: CtrlMsgIHave, + ControlMsg: p2p.CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -128,7 +116,7 @@ type CtrlMsgValidationConfigs []*CtrlMsgValidationConfig // CtrlMsgValidationConfig configuration values for upper, lower threshold and rate limit. type CtrlMsgValidationConfig struct { // ControlMsg the type of RPC control message. - ControlMsg ControlMessageType + ControlMsg p2p.ControlMessageType // HardThreshold specifies the hard limit for the size of an RPC control message. // While it is generally expected that RPC messages with a size greater than HardThreshold should be dropped, // there are exceptions. For instance, if the message is an 'iHave', blocking processing is performed diff --git a/network/p2p/pubsub.go b/network/p2p/pubsub.go index 3f19c892c75..a5a9129fc7d 100644 --- a/network/p2p/pubsub.go +++ b/network/p2p/pubsub.go @@ -259,3 +259,22 @@ type PeerScoreExposer interface { // The returned map is keyed by topic name. GetTopicScores(peerID peer.ID) (map[string]TopicScoreSnapshot, bool) } + +// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. +type ControlMessageType string + +func (c ControlMessageType) String() string { + return string(c) +} + +const ( + CtrlMsgIHave ControlMessageType = "IHAVE" + CtrlMsgIWant ControlMessageType = "IWANT" + CtrlMsgGraft ControlMessageType = "GRAFT" + CtrlMsgPrune ControlMessageType = "PRUNE" +) + +// ControlMessageTypes returns list of all libp2p control message types. +func ControlMessageTypes() []ControlMessageType { + return []ControlMessageType{CtrlMsgIHave, CtrlMsgIWant, CtrlMsgGraft, CtrlMsgPrune} +} From 4e8833c35da909d1f85ef6e7da5b28a1435fa68d Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:26:23 -0700 Subject: [PATCH 50/74] fixes dependencies --- network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go | 1 - network/p2p/p2pbuilder/libp2pNodeBuilder.go | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go index 825465addff..c03f7c87df9 100644 --- a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go +++ b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go @@ -4,7 +4,6 @@ package mockp2p import ( flow "github.com/onflow/flow-go/model/flow" - conf "github.com/onflow/flow-go/network/p2p/conf" metrics "github.com/onflow/flow-go/module/metrics" diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index 025945bdc01..cccd1962141 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -34,6 +34,7 @@ import ( "github.com/onflow/flow-go/network/p2p/keyutils" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" gossipsubbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/gossipsub" + "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/subscription" "github.com/onflow/flow-go/network/p2p/tracer" From 52bdd977cbc3371fe915a9ea3c3816fe30be1280 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:27:36 -0700 Subject: [PATCH 51/74] fixes lint --- network/p2p/builder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/network/p2p/builder.go b/network/p2p/builder.go index bb90c389715..88a94e52a5f 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -19,6 +19,7 @@ import ( "github.com/onflow/flow-go/module/metrics" flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/p2p/p2pconf" ) type GossipSubFactoryFunc func(context.Context, zerolog.Logger, host.Host, PubSubAdapterConfig, CollectionClusterChangesConsumer) (PubSubAdapter, error) From b9ce59c81dd32da14d1ce3c7d6fc42241072f92e Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:31:26 -0700 Subject: [PATCH 52/74] fixes import cycle --- network/p2p/consumers.go | 5 ++-- .../control_message_validation_inspector.go | 3 ++- network/p2p/message/types.go | 20 ++++++++++++++++ network/p2p/p2pconf/errors.go | 4 ++-- network/p2p/p2pconf/errors_test.go | 4 ++-- .../p2p/p2pconf/gossipsub_rpc_inspectors.go | 24 +++++++++---------- network/p2p/pubsub.go | 19 --------------- network/p2p/scoring/scoring_test.go | 3 ++- 8 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 network/p2p/message/types.go diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index 7cac52c0ef2..676cd53db1a 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -5,6 +5,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/module/component" + "github.com/onflow/flow-go/network/p2p/message" ) // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. @@ -29,7 +30,7 @@ type InvCtrlMsgNotif struct { // PeerID is the ID of the peer that sent the invalid control message. PeerID peer.ID // MsgType is the type of control message that was received. - MsgType ControlMessageType + MsgType p2pmsg.ControlMessageType // Count is the number of invalid control messages received from the peer that is reported in this notification. Count uint64 // Err any error associated with the invalid control message. @@ -37,7 +38,7 @@ type InvCtrlMsgNotif struct { } // NewInvalidControlMessageNotification returns a new *InvCtrlMsgNotif -func NewInvalidControlMessageNotification(peerID peer.ID, msgType ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { +func NewInvalidControlMessageNotification(peerID peer.ID, msgType p2pmsg.ControlMessageType, count uint64, err error) *InvCtrlMsgNotif { return &InvCtrlMsgNotif{ PeerID: peerID, MsgType: msgType, diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index c3831e8272e..574b5bc1a71 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -21,6 +21,7 @@ import ( "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" + "github.com/onflow/flow-go/network/p2p/message" "github.com/onflow/flow-go/state/protocol" "github.com/onflow/flow-go/state/protocol/events" "github.com/onflow/flow-go/utils/logging" @@ -146,7 +147,7 @@ func NewControlMsgValidationInspector( // The returned error is returned to the gossipsub node which causes the rejection of rpc (for non-nil errors). func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) error { control := rpc.GetControl() - for _, ctrlMsgType := range p2p.ControlMessageTypes() { + for _, ctrlMsgType := range p2pmsg.ControlMessageTypes() { lg := c.logger.With(). Str("peer_id", from.String()). Str("ctrl_msg_type", string(ctrlMsgType)).Logger() diff --git a/network/p2p/message/types.go b/network/p2p/message/types.go new file mode 100644 index 00000000000..087cbd21455 --- /dev/null +++ b/network/p2p/message/types.go @@ -0,0 +1,20 @@ +package p2pmsg + +// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. +type ControlMessageType string + +func (c ControlMessageType) String() string { + return string(c) +} + +const ( + CtrlMsgIHave ControlMessageType = "IHAVE" + CtrlMsgIWant ControlMessageType = "IWANT" + CtrlMsgGraft ControlMessageType = "GRAFT" + CtrlMsgPrune ControlMessageType = "PRUNE" +) + +// ControlMessageTypes returns list of all libp2p control message types. +func ControlMessageTypes() []ControlMessageType { + return []ControlMessageType{CtrlMsgIHave, CtrlMsgIWant, CtrlMsgGraft, CtrlMsgPrune} +} diff --git a/network/p2p/p2pconf/errors.go b/network/p2p/p2pconf/errors.go index 3d5f7c37dde..64fe445ab0a 100644 --- a/network/p2p/p2pconf/errors.go +++ b/network/p2p/p2pconf/errors.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/message" ) // InvalidLimitConfigError indicates the validation limit is < 0. @@ -21,7 +21,7 @@ func (e InvalidLimitConfigError) Unwrap() error { } // NewInvalidLimitConfigErr returns a new ErrValidationLimit. -func NewInvalidLimitConfigErr(controlMsg p2p.ControlMessageType, err error) InvalidLimitConfigError { +func NewInvalidLimitConfigErr(controlMsg p2pmsg.ControlMessageType, err error) InvalidLimitConfigError { return InvalidLimitConfigError{fmt.Errorf("invalid rpc control message %s validation limit configuration: %w", controlMsg, err)} } diff --git a/network/p2p/p2pconf/errors_test.go b/network/p2p/p2pconf/errors_test.go index 4419b6f7045..8733e739b4a 100644 --- a/network/p2p/p2pconf/errors_test.go +++ b/network/p2p/p2pconf/errors_test.go @@ -6,12 +6,12 @@ import ( "github.com/stretchr/testify/assert" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/message" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. func TestErrInvalidLimitConfigRoundTrip(t *testing.T) { - controlMsg := p2p.CtrlMsgGraft + controlMsg := p2pmsg.CtrlMsgGraft limit := uint64(500) e := fmt.Errorf("invalid rate limit value %d must be greater than 0", limit) diff --git a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go index 486639565df..04a3fd983b9 100644 --- a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go +++ b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go @@ -3,7 +3,7 @@ package p2pconf import ( "fmt" - "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/message" ) // GossipSubRPCInspectorsConfig encompasses configuration related to gossipsub RPC message inspectors. @@ -62,25 +62,25 @@ type GossipSubRPCValidationInspectorConfigs struct { } // GetCtrlMsgValidationConfig returns the CtrlMsgValidationConfig for the specified p2p.ControlMessageType. -func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg p2p.ControlMessageType) (*CtrlMsgValidationConfig, bool) { +func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(controlMsg p2pmsg.ControlMessageType) (*CtrlMsgValidationConfig, bool) { switch controlMsg { - case p2p.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgGraft, + ControlMsg: p2pmsg.CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, true - case p2p.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgPrune, + ControlMsg: p2pmsg.CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, true - case p2p.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: return &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgIHave, + ControlMsg: p2pmsg.CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -93,17 +93,17 @@ func (conf *GossipSubRPCValidationInspectorConfigs) GetCtrlMsgValidationConfig(c // AllCtrlMsgValidationConfig returns all control message validation configs in a list. func (conf *GossipSubRPCValidationInspectorConfigs) AllCtrlMsgValidationConfig() CtrlMsgValidationConfigs { return CtrlMsgValidationConfigs{&CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgGraft, + ControlMsg: p2pmsg.CtrlMsgGraft, HardThreshold: conf.GraftLimits.HardThreshold, SafetyThreshold: conf.GraftLimits.SafetyThreshold, RateLimit: conf.GraftLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgPrune, + ControlMsg: p2pmsg.CtrlMsgPrune, HardThreshold: conf.PruneLimits.HardThreshold, SafetyThreshold: conf.PruneLimits.SafetyThreshold, RateLimit: conf.PruneLimits.RateLimit, }, &CtrlMsgValidationConfig{ - ControlMsg: p2p.CtrlMsgIHave, + ControlMsg: p2pmsg.CtrlMsgIHave, HardThreshold: conf.IHaveLimits.HardThreshold, SafetyThreshold: conf.IHaveLimits.SafetyThreshold, RateLimit: conf.IHaveLimits.RateLimit, @@ -116,7 +116,7 @@ type CtrlMsgValidationConfigs []*CtrlMsgValidationConfig // CtrlMsgValidationConfig configuration values for upper, lower threshold and rate limit. type CtrlMsgValidationConfig struct { // ControlMsg the type of RPC control message. - ControlMsg p2p.ControlMessageType + ControlMsg p2pmsg.ControlMessageType // HardThreshold specifies the hard limit for the size of an RPC control message. // While it is generally expected that RPC messages with a size greater than HardThreshold should be dropped, // there are exceptions. For instance, if the message is an 'iHave', blocking processing is performed diff --git a/network/p2p/pubsub.go b/network/p2p/pubsub.go index a5a9129fc7d..3f19c892c75 100644 --- a/network/p2p/pubsub.go +++ b/network/p2p/pubsub.go @@ -259,22 +259,3 @@ type PeerScoreExposer interface { // The returned map is keyed by topic name. GetTopicScores(peerID peer.ID) (map[string]TopicScoreSnapshot, bool) } - -// ControlMessageType is the type of control message, as defined in the libp2p pubsub spec. -type ControlMessageType string - -func (c ControlMessageType) String() string { - return string(c) -} - -const ( - CtrlMsgIHave ControlMessageType = "IHAVE" - CtrlMsgIWant ControlMessageType = "IWANT" - CtrlMsgGraft ControlMessageType = "GRAFT" - CtrlMsgPrune ControlMessageType = "PRUNE" -) - -// ControlMessageTypes returns list of all libp2p control message types. -func ControlMessageTypes() []ControlMessageType { - return []ControlMessageType{CtrlMsgIHave, CtrlMsgIWant, CtrlMsgGraft, CtrlMsgPrune} -} diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index d0b252d7195..e280e426143 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -23,6 +23,7 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/message" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -137,7 +138,7 @@ func TestInvalidCtrlMsgScoringIntegration(t *testing.T) { for i := 0; i < 30; i++ { inspectorSuite1.consumer.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: node2.Host().ID(), - MsgType: p2p.ControlMessageTypes()[rand.Intn(len(p2p.ControlMessageTypes()))], + MsgType: p2pmsg.ControlMessageTypes()[rand.Intn(len(p2pmsg.ControlMessageTypes()))], Count: 1, Err: fmt.Errorf("invalid control message"), }) From 5b03689bd57c3433ef0d1dae0c357b8c75b90472 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:32:28 -0700 Subject: [PATCH 53/74] lint fix --- network/netconf/config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/network/netconf/config.go b/network/netconf/config.go index 5c6fa4507f9..f3bcfed1f93 100644 --- a/network/netconf/config.go +++ b/network/netconf/config.go @@ -2,6 +2,8 @@ package netconf import ( "time" + + "github.com/onflow/flow-go/network/p2p/p2pconf" ) // Config encapsulation of configuration structs for all components related to the Flow network. From c26090602df06fa8dbe663e8ce9dae57b5a3852d Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:33:44 -0700 Subject: [PATCH 54/74] updates mocks --- network/p2p/consumers.go | 2 +- .../gossip_sub_rpc_inspector_suite_factory_func.go | 11 ++++++----- network/p2p/p2pconf/errors.go | 2 +- network/p2p/p2pconf/errors_test.go | 2 +- network/p2p/p2pconf/gossipsub_rpc_inspectors.go | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/network/p2p/consumers.go b/network/p2p/consumers.go index 676cd53db1a..356bb410d81 100644 --- a/network/p2p/consumers.go +++ b/network/p2p/consumers.go @@ -5,7 +5,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/module/component" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // GossipSubInspectorNotifDistributor is the interface for the distributor that distributes gossip sub inspector notifications. diff --git a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go index c03f7c87df9..03ea2329d85 100644 --- a/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go +++ b/network/p2p/mock/gossip_sub_rpc_inspector_suite_factory_func.go @@ -4,7 +4,6 @@ package mockp2p import ( flow "github.com/onflow/flow-go/model/flow" - metrics "github.com/onflow/flow-go/module/metrics" mock "github.com/stretchr/testify/mock" @@ -15,6 +14,8 @@ import ( p2p "github.com/onflow/flow-go/network/p2p" + p2pconf "github.com/onflow/flow-go/network/p2p/p2pconf" + zerolog "github.com/rs/zerolog" ) @@ -24,15 +25,15 @@ type GossipSubRpcInspectorSuiteFactoryFunc struct { } // Execute provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4, _a5, _a6 -func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 flow.Identifier, _a2 *conf.GossipSubRPCInspectorsConfig, _a3 module.GossipSubMetrics, _a4 metrics.HeroCacheMetricsFactory, _a5 network.NetworkingType, _a6 module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { +func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 flow.Identifier, _a2 *p2pconf.GossipSubRPCInspectorsConfig, _a3 module.GossipSubMetrics, _a4 metrics.HeroCacheMetricsFactory, _a5 network.NetworkingType, _a6 module.IdentityProvider) (p2p.GossipSubInspectorSuite, error) { ret := _m.Called(_a0, _a1, _a2, _a3, _a4, _a5, _a6) var r0 p2p.GossipSubInspectorSuite var r1 error - if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) (p2p.GossipSubInspectorSuite, error)); ok { + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *p2pconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) (p2p.GossipSubInspectorSuite, error)); ok { return rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } - if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) p2p.GossipSubInspectorSuite); ok { + if rf, ok := ret.Get(0).(func(zerolog.Logger, flow.Identifier, *p2pconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) p2p.GossipSubInspectorSuite); ok { r0 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } else { if ret.Get(0) != nil { @@ -40,7 +41,7 @@ func (_m *GossipSubRpcInspectorSuiteFactoryFunc) Execute(_a0 zerolog.Logger, _a1 } } - if rf, ok := ret.Get(1).(func(zerolog.Logger, flow.Identifier, *conf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) error); ok { + if rf, ok := ret.Get(1).(func(zerolog.Logger, flow.Identifier, *p2pconf.GossipSubRPCInspectorsConfig, module.GossipSubMetrics, metrics.HeroCacheMetricsFactory, network.NetworkingType, module.IdentityProvider) error); ok { r1 = rf(_a0, _a1, _a2, _a3, _a4, _a5, _a6) } else { r1 = ret.Error(1) diff --git a/network/p2p/p2pconf/errors.go b/network/p2p/p2pconf/errors.go index 64fe445ab0a..88417ced914 100644 --- a/network/p2p/p2pconf/errors.go +++ b/network/p2p/p2pconf/errors.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // InvalidLimitConfigError indicates the validation limit is < 0. diff --git a/network/p2p/p2pconf/errors_test.go b/network/p2p/p2pconf/errors_test.go index 8733e739b4a..681d839a5fa 100644 --- a/network/p2p/p2pconf/errors_test.go +++ b/network/p2p/p2pconf/errors_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // TestErrInvalidLimitConfigRoundTrip ensures correct error formatting for ErrInvalidLimitConfig. diff --git a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go index 04a3fd983b9..43c041eb1a8 100644 --- a/network/p2p/p2pconf/gossipsub_rpc_inspectors.go +++ b/network/p2p/p2pconf/gossipsub_rpc_inspectors.go @@ -3,7 +3,7 @@ package p2pconf import ( "fmt" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // GossipSubRPCInspectorsConfig encompasses configuration related to gossipsub RPC message inspectors. From d5512c59baa8937f1fe77ed6f043f683356964f0 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:41:05 -0700 Subject: [PATCH 55/74] fixes lint --- network/netconf/flags.go | 4 +++- network/p2p/scoring/registry.go | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/network/netconf/flags.go b/network/netconf/flags.go index 8e5992229aa..2b76042e6c8 100644 --- a/network/netconf/flags.go +++ b/network/netconf/flags.go @@ -5,6 +5,8 @@ import ( "strings" "github.com/spf13/pflag" + + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) const ( @@ -135,7 +137,7 @@ func initRpcInspectorValidationLimitsFlags(flags *pflag.FlagSet, defaultNetConfi for _, ctrlMsgValidationConfig := range validationInspectorConfig.AllCtrlMsgValidationConfig() { ctrlMsgType := ctrlMsgValidationConfig.ControlMsg - if ctrlMsgValidationConfig.ControlMsg == p2pconf.CtrlMsgIWant { + if ctrlMsgValidationConfig.ControlMsg == p2pmsg.CtrlMsgIWant { continue } s := strings.ToLower(ctrlMsgType.String()) diff --git a/network/p2p/scoring/registry.go b/network/p2p/scoring/registry.go index 8eb7666278b..30e28b02096 100644 --- a/network/p2p/scoring/registry.go +++ b/network/p2p/scoring/registry.go @@ -11,6 +11,7 @@ import ( "github.com/onflow/flow-go/module" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" "github.com/onflow/flow-go/utils/logging" ) @@ -253,9 +254,9 @@ func (r *GossipSubAppSpecificScoreRegistry) OnInvalidControlMessageNotification( record, err := r.spamScoreCache.Update(notification.PeerID, func(record p2p.GossipSubSpamRecord) p2p.GossipSubSpamRecord { switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: record.Penalty += r.penalty.Graft - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: record.Penalty += r.penalty.Prune case p2pconf.CtrlMsgIHave: record.Penalty += r.penalty.IHave From 152fe90afebe26c5466762211e0147d1b434053b Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:42:10 -0700 Subject: [PATCH 56/74] fixes lint --- network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 1 + network/p2p/scoring/registry.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 34bded0cc73..191935ee00b 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -24,6 +24,7 @@ import ( "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" inspector2 "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" + "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/network/p2p/tracer" diff --git a/network/p2p/scoring/registry.go b/network/p2p/scoring/registry.go index 30e28b02096..9009b86f41a 100644 --- a/network/p2p/scoring/registry.go +++ b/network/p2p/scoring/registry.go @@ -258,9 +258,9 @@ func (r *GossipSubAppSpecificScoreRegistry) OnInvalidControlMessageNotification( record.Penalty += r.penalty.Graft case p2pmsg.CtrlMsgPrune: record.Penalty += r.penalty.Prune - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: record.Penalty += r.penalty.IHave - case p2pconf.CtrlMsgIWant: + case p2pmsg.CtrlMsgIWant: record.Penalty += r.penalty.IWant default: // the error is considered fatal as it means that we have an unsupported misbehaviour type, we should crash the node to prevent routing attack vulnerability. From 0b0720b16d1ffdd056843f2230a761d5dcf16b76 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:42:48 -0700 Subject: [PATCH 57/74] fixes lint --- network/p2p/test/fixtures.go | 1 + 1 file changed, 1 insertion(+) diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index 4c753e33b44..d8bb88c2f5d 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -33,6 +33,7 @@ import ( p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/p2pbuilder" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/network/p2p/unicast" "github.com/onflow/flow-go/network/p2p/unicast/protocols" "github.com/onflow/flow-go/network/p2p/utils" From cd466a627b80ad962ccec03a19868a0cb19faea7 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:44:04 -0700 Subject: [PATCH 58/74] fixes lint --- network/p2p/distributor/gossipsub_inspector_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/p2p/distributor/gossipsub_inspector_test.go b/network/p2p/distributor/gossipsub_inspector_test.go index b76406b5a1e..23323d7282c 100644 --- a/network/p2p/distributor/gossipsub_inspector_test.go +++ b/network/p2p/distributor/gossipsub_inspector_test.go @@ -14,6 +14,7 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/distributor" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" mockp2p "github.com/onflow/flow-go/network/p2p/mock" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" @@ -94,7 +95,7 @@ func invalidControlMessageNotificationListFixture(t *testing.T, n int) []*p2p.In func invalidControlMessageNotificationFixture(t *testing.T) *p2p.InvCtrlMsgNotif { return &p2p.InvCtrlMsgNotif{ PeerID: p2ptest.PeerIdFixture(t), - MsgType: []p2pconf.ControlMessageType{p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune, p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant}[rand.Intn(4)], + MsgType: []p2pmsg.ControlMessageType{p2pmsg.CtrlMsgGraft, p2pmsg.CtrlMsgPrune, p2pmsg.CtrlMsgIHave, p2pmsg.CtrlMsgIWant}[rand.Intn(4)], Count: rand.Uint64(), } } From 4a1520b26772e9f6e2518cf6d76b425bca72d6a4 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:45:11 -0700 Subject: [PATCH 59/74] fixes lint --- .../validation/control_message_validation_inspector.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 574b5bc1a71..88c62ead56d 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -22,6 +22,7 @@ import ( "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" "github.com/onflow/flow-go/network/p2p/message" + "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/state/protocol" "github.com/onflow/flow-go/state/protocol/events" "github.com/onflow/flow-go/utils/logging" @@ -52,7 +53,7 @@ type ControlMsgValidationInspector struct { // In such cases, the inspector will allow a configured number of these messages from the corresponding peer. tracker *cache.ClusterPrefixedMessagesReceivedTracker idProvider module.IdentityProvider - rateLimiters map[p2pconf.ControlMessageType]p2p.BasicRateLimiter + rateLimiters map[p2pmsg.ControlMessageType]p2p.BasicRateLimiter } var _ component.Component = (*ControlMsgValidationInspector)(nil) From df1f8ad949acf9bdaa43311a70016db8a707077e Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:50:19 -0700 Subject: [PATCH 60/74] fixes lint --- .../control_message_validation_inspector.go | 46 +++++++++---------- .../validation/inspect_message_request.go | 1 + 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 88c62ead56d..711a1253c2c 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -96,7 +96,7 @@ func NewControlMsgValidationInspector( tracker: tracker, idProvider: idProvider, metrics: inspectorMetrics, - rateLimiters: make(map[p2pconf.ControlMessageType]p2p.BasicRateLimiter), + rateLimiters: make(map[p2pmsg.ControlMessageType]p2p.BasicRateLimiter), } store := queue.NewHeroStore(config.CacheSize, logger, inspectMsgQueueCacheCollector) @@ -159,7 +159,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e } switch ctrlMsgType { - case p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgGraft, p2pmsg.CtrlMsgPrune: // normal pre-processing err := c.blockingPreprocessingRpc(from, validationConfig, control) if err != nil { @@ -168,7 +168,7 @@ func (c *ControlMsgValidationInspector) Inspect(from peer.ID, rpc *pubsub.RPC) e Msg("could not pre-process rpc, aborting") return fmt.Errorf("could not pre-process rpc, aborting: %w", err) } - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: // iHave specific pre-processing sampleSize := util.SampleN(len(control.GetIhave()), c.config.IHaveInspectionMaxSampleSize, c.config.IHaveSyncInspectSampleSizePercentage) err := c.blockingIHaveSamplePreprocessing(from, validationConfig, control, sampleSize) @@ -212,8 +212,8 @@ func (c *ControlMsgValidationInspector) ActiveClustersChanged(clusterIDList flow // // blockingPreprocessingRpc generic pre-processing validation func that ensures the RPC control message count does not exceed the configured hard threshold. func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage) error { - if validationConfig.ControlMsg != p2pconf.CtrlMsgGraft && validationConfig.ControlMsg != p2pconf.CtrlMsgPrune { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune) + if validationConfig.ControlMsg != p2pmsg.CtrlMsgGraft && validationConfig.ControlMsg != p2pmsg.CtrlMsgPrune { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing rpc, expected %s or %s", validationConfig.ControlMsg, p2pmsg.CtrlMsgGraft, p2pmsg.CtrlMsgPrune) } count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) lg := c.logger.With(). @@ -251,10 +251,10 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingRpc(from peer.ID, v // blockingPreprocessingSampleRpc blocking pre-processing of a sample of iHave control messages. func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - c.metrics.BlockingPreProcessingStarted(p2pconf.CtrlMsgIHave.String(), sampleSize) + c.metrics.BlockingPreProcessingStarted(p2pmsg.CtrlMsgIHave.String(), sampleSize) start := time.Now() defer func() { - c.metrics.BlockingPreProcessingFinished(p2pconf.CtrlMsgIHave.String(), sampleSize, time.Since(start)) + c.metrics.BlockingPreProcessingFinished(p2pmsg.CtrlMsgIHave.String(), sampleSize, time.Since(start)) }() err := c.blockingPreprocessingSampleRpc(from, validationConfig, controlMessage, sampleSize) if err != nil { @@ -267,8 +267,8 @@ func (c *ControlMsgValidationInspector) blockingIHaveSamplePreprocessing(from pe // If the RPC control message count exceeds the configured hard threshold we perform synchronous topic validation on a subset // of the control messages. This is used for control message types that do not have an upper bound on the amount of messages a node can send. func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, controlMessage *pubsub_pb.ControlMessage, sampleSize uint) error { - if validationConfig.ControlMsg != p2pconf.CtrlMsgIHave && validationConfig.ControlMsg != p2pconf.CtrlMsgIWant { - return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, p2pconf.CtrlMsgIHave, p2pconf.CtrlMsgIWant) + if validationConfig.ControlMsg != p2pmsg.CtrlMsgIHave && validationConfig.ControlMsg != p2pmsg.CtrlMsgIWant { + return fmt.Errorf("unexpected control message type %s encountered during blocking pre-processing sample rpc, expected %s or %s", validationConfig.ControlMsg, p2pmsg.CtrlMsgIHave, p2pmsg.CtrlMsgIWant) } activeClusterIDS := c.tracker.GetActiveClusterIds() count := c.getCtrlMsgCount(validationConfig.ControlMsg, controlMessage) @@ -280,7 +280,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer if count > validationConfig.HardThreshold { // for iHave control message topic validation we only validate a random subset of the messages // shuffle the ihave messages to perform random validation on a subset of size sampleSize - err := c.sampleCtrlMessages(p2pconf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(p2pmsg.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -306,7 +306,7 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // to randomize async validation to avoid data race that can occur when // performing the sampling asynchronously. // for iHave control message topic validation we only validate a random subset of the messages - err := c.sampleCtrlMessages(p2pconf.CtrlMsgIHave, controlMessage, sampleSize) + err := c.sampleCtrlMessages(p2pmsg.CtrlMsgIHave, controlMessage, sampleSize) if err != nil { return fmt.Errorf("failed to sample ihave messages: %w", err) } @@ -315,9 +315,9 @@ func (c *ControlMsgValidationInspector) blockingPreprocessingSampleRpc(from peer // sampleCtrlMessages performs sampling on the specified control message that will randomize // the items in the control message slice up to index sampleSize-1. -func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType p2pconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { +func (c *ControlMsgValidationInspector) sampleCtrlMessages(ctrlMsgType p2pmsg.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage, sampleSize uint) error { switch ctrlMsgType { - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: iHaves := ctrlMsg.GetIhave() swap := func(i, j uint) { iHaves[i], iHaves[j] = iHaves[j], iHaves[i] @@ -376,13 +376,13 @@ func (c *ControlMsgValidationInspector) processInspectMsgReq(req *InspectMsgRequ } // getCtrlMsgCount returns the amount of specified control message type in the rpc ControlMessage. -func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2pconf.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { +func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2pmsg.ControlMessageType, ctrlMsg *pubsub_pb.ControlMessage) uint64 { switch ctrlMsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: return uint64(len(ctrlMsg.GetGraft())) - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: return uint64(len(ctrlMsg.GetPrune())) - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: return uint64(len(ctrlMsg.GetIhave())) default: return 0 @@ -396,17 +396,17 @@ func (c *ControlMsgValidationInspector) getCtrlMsgCount(ctrlMsgType p2pconf.Cont func (c *ControlMsgValidationInspector) validateTopics(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage) error { activeClusterIDS := c.tracker.GetActiveClusterIds() switch validationConfig.ControlMsg { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: return c.validateGrafts(from, ctrlMsg, activeClusterIDS) - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: return c.validatePrunes(from, ctrlMsg, activeClusterIDS) - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: return c.validateIhaves(from, validationConfig, ctrlMsg, activeClusterIDS) default: // sanity check // This should never happen validateTopics is only used to validate GRAFT and PRUNE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", p2pconf.CtrlMsgGraft, p2pconf.CtrlMsgPrune, p2pconf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics expected %s, %s or %s got %s", p2pmsg.CtrlMsgGraft, p2pmsg.CtrlMsgPrune, p2pmsg.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } @@ -457,7 +457,7 @@ func (c *ControlMsgValidationInspector) validateIhaves(from peer.ID, validationC func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, validationConfig *p2pconf.CtrlMsgValidationConfig, ctrlMsg *pubsub_pb.ControlMessage, activeClusterIDS flow.ChainIDList, sampleSize uint) error { tracker := make(duplicateTopicTracker) switch validationConfig.ControlMsg { - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: for i := uint(0); i < sampleSize; i++ { topic := channels.Topic(ctrlMsg.Ihave[i].GetTopicID()) if tracker.isDuplicate(topic) { @@ -473,7 +473,7 @@ func (c *ControlMsgValidationInspector) validateTopicsSample(from peer.ID, valid // sanity check // This should never happen validateTopicsSample is only used to validate IHAVE control message types // if any other control message type is encountered here this indicates invalid state irrecoverable error. - c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", p2pconf.CtrlMsgIHave, validationConfig.ControlMsg)) + c.logger.Fatal().Msg(fmt.Sprintf("encountered invalid control message type in validate topics sample expected %s got %s", p2pmsg.CtrlMsgIHave, validationConfig.ControlMsg)) } return nil } diff --git a/network/p2p/inspector/validation/inspect_message_request.go b/network/p2p/inspector/validation/inspect_message_request.go index 8d73f9fdc0f..bbd68878428 100644 --- a/network/p2p/inspector/validation/inspect_message_request.go +++ b/network/p2p/inspector/validation/inspect_message_request.go @@ -7,6 +7,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/onflow/flow-go/network/p2p/inspector/internal" + "github.com/onflow/flow-go/network/p2p/p2pconf" ) // InspectMsgRequest represents a short digest of an RPC control message. It is used for further message inspection by component workers. From 6616442acafb6f64f453de74cfbab03a20df90a2 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:54:40 -0700 Subject: [PATCH 61/74] fixes lint --- .../validation_inspector_test.go | 38 +++++++++-------- .../p2p/inspector/validation/errors_test.go | 5 ++- network/p2p/scoring/registry_test.go | 41 ++++++++++--------- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/rpc_inspector/validation_inspector_test.go index 3ec26252d19..73ef79e86e9 100644 --- a/insecure/rpc_inspector/validation_inspector_test.go +++ b/insecure/rpc_inspector/validation_inspector_test.go @@ -25,7 +25,9 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/inspector/validation" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" mockp2p "github.com/onflow/flow-go/network/p2p/mock" + "github.com/onflow/flow-go/network/p2p/p2pconf" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -47,9 +49,9 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { inspectorConfig.PruneLimits.SafetyThreshold = safetyThreshold // expected log message logged when valid number GRAFT control messages spammed under safety threshold - graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pconf.CtrlMsgGraft) + graftExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pmsg.CtrlMsgGraft) // expected log message logged when valid number PRUNE control messages spammed under safety threshold - pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pconf.CtrlMsgGraft) + pruneExpectedMessageStr := fmt.Sprintf("control message %s inspection passed 5 is below configured safety threshold", p2pmsg.CtrlMsgGraft) graftInfoLogsReceived := atomic.NewInt64(0) pruneInfoLogsReceived := atomic.NewInt64(0) // setup logger hook, we expect info log validation is skipped @@ -125,9 +127,9 @@ func TestValidationInspector_HardThreshold_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -193,7 +195,7 @@ func TestValidationInspector_HardThresholdIHave_Detection(t *testing.T) { require.Equal(t, uint64(messageCount), notification.Count) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: invIhaveNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -256,9 +258,9 @@ func TestValidationInspector_RateLimitedPeer_Detection(t *testing.T) { require.True(t, validation.IsErrRateLimitedControlMsg(notification.Err)) require.Equal(t, uint64(messageCount), notification.Count) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -352,13 +354,13 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) require.True(t, channels.IsInvalidTopicErr(notification.Err)) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() require.Equal(t, messageCount, notification.Count) - case p2pconf.CtrlMsgIHave: + case p2pmsg.CtrlMsgIHave: require.Equal(t, uint64(ihaveMessageCount), notification.Count) invIHaveNotifCount.Inc() default: @@ -460,9 +462,9 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { require.True(t, validation.IsErrDuplicateTopic(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -537,9 +539,9 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { require.True(t, channels.IsUnknownClusterIDErr(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -607,7 +609,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -671,7 +673,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T require.True(t, validation.IsErrActiveClusterIDsNotSet(notification.Err)) require.Equal(t, spammer.SpammerNode.Host().ID(), notification.PeerID) switch notification.MsgType { - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") @@ -744,9 +746,9 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { require.True(t, validation.IsErrUnstakedPeer(notification.Err)) require.Equal(t, messageCount, notification.Count) switch notification.MsgType { - case p2pconf.CtrlMsgGraft: + case p2pmsg.CtrlMsgGraft: invGraftNotifCount.Inc() - case p2pconf.CtrlMsgPrune: + case p2pmsg.CtrlMsgPrune: invPruneNotifCount.Inc() default: require.Fail(t, "unexpected control message type") diff --git a/network/p2p/inspector/validation/errors_test.go b/network/p2p/inspector/validation/errors_test.go index 73736d46516..9bef259fd41 100644 --- a/network/p2p/inspector/validation/errors_test.go +++ b/network/p2p/inspector/validation/errors_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/onflow/flow-go/network/channels" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // TestErrActiveClusterIDsNotSetRoundTrip ensures correct error formatting for ErrActiveClusterIdsNotSet. @@ -28,7 +29,7 @@ func TestErrActiveClusterIDsNotSetRoundTrip(t *testing.T) { // TestErrHardThresholdRoundTrip ensures correct error formatting for ErrHardThreshold. func TestErrHardThresholdRoundTrip(t *testing.T) { - controlMsg := p2pconf.CtrlMsgGraft + controlMsg := p2pmsg.CtrlMsgGraft amount := uint64(100) hardThreshold := uint64(500) err := NewHardThresholdErr(controlMsg, amount, hardThreshold) @@ -47,7 +48,7 @@ func TestErrHardThresholdRoundTrip(t *testing.T) { // TestErrRateLimitedControlMsgRoundTrip ensures correct error formatting for ErrRateLimitedControlMsg. func TestErrRateLimitedControlMsgRoundTrip(t *testing.T) { - controlMsg := p2pconf.CtrlMsgGraft + controlMsg := p2pmsg.CtrlMsgGraft err := NewRateLimitedControlMsgErr(controlMsg) // tests the error message formatting. diff --git a/network/p2p/scoring/registry_test.go b/network/p2p/scoring/registry_test.go index 5e69abd8a0a..d1feb8a80c2 100644 --- a/network/p2p/scoring/registry_test.go +++ b/network/p2p/scoring/registry_test.go @@ -15,6 +15,7 @@ import ( "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" mockp2p "github.com/onflow/flow-go/network/p2p/mock" "github.com/onflow/flow-go/network/p2p/scoring" "github.com/onflow/flow-go/utils/unittest" @@ -48,20 +49,20 @@ func TestNoPenaltyRecord(t *testing.T) { // penalty value as the app specific score. func TestPeerWithSpamRecord(t *testing.T) { t.Run("graft", func(t *testing.T) { - testPeerWithSpamRecord(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testPeerWithSpamRecord(t, p2pmsg.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testPeerWithSpamRecord(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testPeerWithSpamRecord(t, p2pmsg.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testPeerWithSpamRecord(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testPeerWithSpamRecord(t, p2pmsg.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testPeerWithSpamRecord(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testPeerWithSpamRecord(t, p2pmsg.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } -func testPeerWithSpamRecord(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { +func testPeerWithSpamRecord(t *testing.T, messageType p2pmsg.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -98,16 +99,16 @@ func testPeerWithSpamRecord(t *testing.T, messageType p2pconf.ControlMessageType func TestSpamRecord_With_UnknownIdentity(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithUnknownIdentity(t, p2pmsg.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithUnknownIdentity(t, p2pmsg.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithUnknownIdentity(t, p2pmsg.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithUnknownIdentity(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithUnknownIdentity(t, p2pmsg.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } @@ -149,16 +150,16 @@ func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2pconf.Control func TestSpamRecord_With_SubscriptionPenalty(t *testing.T) { t.Run("graft", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgGraft, penaltyValueFixtures().Graft) + testSpamRecordWithSubscriptionPenalty(t, p2pmsg.CtrlMsgGraft, penaltyValueFixtures().Graft) }) t.Run("prune", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgPrune, penaltyValueFixtures().Prune) + testSpamRecordWithSubscriptionPenalty(t, p2pmsg.CtrlMsgPrune, penaltyValueFixtures().Prune) }) t.Run("ihave", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgIHave, penaltyValueFixtures().IHave) + testSpamRecordWithSubscriptionPenalty(t, p2pmsg.CtrlMsgIHave, penaltyValueFixtures().IHave) }) t.Run("iwant", func(t *testing.T) { - testSpamRecordWithSubscriptionPenalty(t, p2pconf.CtrlMsgIWant, penaltyValueFixtures().IWant) + testSpamRecordWithSubscriptionPenalty(t, p2pmsg.CtrlMsgIWant, penaltyValueFixtures().IWant) }) } @@ -208,7 +209,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgPrune, + MsgType: p2pmsg.CtrlMsgPrune, Count: 1, }) @@ -216,7 +217,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgGraft, + MsgType: p2pmsg.CtrlMsgGraft, Count: 1, }) @@ -224,7 +225,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgIHave, + MsgType: p2pmsg.CtrlMsgIHave, Count: 1, }) @@ -232,7 +233,7 @@ func TestSpamPenaltyDecaysInCache(t *testing.T) { reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgIWant, + MsgType: p2pmsg.CtrlMsgIWant, Count: 1, }) @@ -274,7 +275,7 @@ func TestSpamPenaltyDecayToZero(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgGraft, + MsgType: p2pmsg.CtrlMsgGraft, Count: 1, }) @@ -324,7 +325,7 @@ func TestPersistingUnknownIdentityPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgGraft, + MsgType: p2pmsg.CtrlMsgGraft, Count: 1, }) @@ -377,7 +378,7 @@ func TestPersistingInvalidSubscriptionPenalty(t *testing.T) { // report a misbehavior for the peer id. reg.OnInvalidControlMessageNotification(&p2p.InvCtrlMsgNotif{ PeerID: peerID, - MsgType: p2pconf.CtrlMsgGraft, + MsgType: p2pmsg.CtrlMsgGraft, Count: 1, }) From d782422deff79800293654d8334aaa4e2e28855c Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:55:43 -0700 Subject: [PATCH 62/74] lint fix --- network/p2p/inspector/validation/errors.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/network/p2p/inspector/validation/errors.go b/network/p2p/inspector/validation/errors.go index 68eb16500e1..231fe979498 100644 --- a/network/p2p/inspector/validation/errors.go +++ b/network/p2p/inspector/validation/errors.go @@ -5,12 +5,13 @@ import ( "fmt" "github.com/onflow/flow-go/network/channels" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" ) // ErrHardThreshold indicates that the amount of RPC messages received exceeds hard threshold. type ErrHardThreshold struct { // controlMsg the control message type. - controlMsg p2pconf.ControlMessageType + controlMsg p2pmsg.ControlMessageType // amount the amount of control messages. amount uint64 // hardThreshold configured hard threshold. @@ -22,7 +23,7 @@ func (e ErrHardThreshold) Error() string { } // NewHardThresholdErr returns a new ErrHardThreshold. -func NewHardThresholdErr(controlMsg p2pconf.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { +func NewHardThresholdErr(controlMsg p2pmsg.ControlMessageType, amount, hardThreshold uint64) ErrHardThreshold { return ErrHardThreshold{controlMsg: controlMsg, amount: amount, hardThreshold: hardThreshold} } @@ -34,7 +35,7 @@ func IsErrHardThreshold(err error) bool { // ErrRateLimitedControlMsg indicates the specified RPC control message is rate limited for the specified peer. type ErrRateLimitedControlMsg struct { - controlMsg p2pconf.ControlMessageType + controlMsg p2pmsg.ControlMessageType } func (e ErrRateLimitedControlMsg) Error() string { @@ -42,7 +43,7 @@ func (e ErrRateLimitedControlMsg) Error() string { } // NewRateLimitedControlMsgErr returns a new ErrValidationLimit. -func NewRateLimitedControlMsgErr(controlMsg p2pconf.ControlMessageType) ErrRateLimitedControlMsg { +func NewRateLimitedControlMsgErr(controlMsg p2pmsg.ControlMessageType) ErrRateLimitedControlMsg { return ErrRateLimitedControlMsg{controlMsg: controlMsg} } From 6973b693907a332e4a00147329932525210de3fe Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:56:36 -0700 Subject: [PATCH 63/74] lint fix --- network/p2p/scoring/registry_test.go | 4 ++-- network/p2p/scoring/scoring_test.go | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/network/p2p/scoring/registry_test.go b/network/p2p/scoring/registry_test.go index d1feb8a80c2..843ec2d87ae 100644 --- a/network/p2p/scoring/registry_test.go +++ b/network/p2p/scoring/registry_test.go @@ -114,7 +114,7 @@ func TestSpamRecord_With_UnknownIdentity(t *testing.T) { // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an unknown identity. -func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithUnknownIdentity(t *testing.T, messageType p2pmsg.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, @@ -165,7 +165,7 @@ func TestSpamRecord_With_SubscriptionPenalty(t *testing.T) { // testSpamRecordWithUnknownIdentity tests the app specific penalty computation of the node when there is a spam record for the peer id and // the peer id has an invalid subscription as well. -func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType p2pconf.ControlMessageType, expectedPenalty float64) { +func testSpamRecordWithSubscriptionPenalty(t *testing.T, messageType p2pmsg.ControlMessageType, expectedPenalty float64) { peerID := peer.ID("peer-1") reg, spamRecords := newGossipSubAppSpecificScoreRegistry( t, diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index e280e426143..35d633c0055 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -24,6 +24,7 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/message" + "github.com/onflow/flow-go/network/p2p/p2pconf" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) From 37bbe481a428da1ac7ae0bc9210b3eb4b8dd9f86 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 10:57:25 -0700 Subject: [PATCH 64/74] lint fix --- .../validation/control_message_validation_inspector.go | 2 +- network/p2p/scoring/scoring_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/network/p2p/inspector/validation/control_message_validation_inspector.go b/network/p2p/inspector/validation/control_message_validation_inspector.go index 711a1253c2c..7daf3f38599 100644 --- a/network/p2p/inspector/validation/control_message_validation_inspector.go +++ b/network/p2p/inspector/validation/control_message_validation_inspector.go @@ -21,7 +21,7 @@ import ( "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/inspector/internal/cache" "github.com/onflow/flow-go/network/p2p/inspector/internal/ratelimit" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/state/protocol" "github.com/onflow/flow-go/state/protocol/events" diff --git a/network/p2p/scoring/scoring_test.go b/network/p2p/scoring/scoring_test.go index 35d633c0055..db43c59a055 100644 --- a/network/p2p/scoring/scoring_test.go +++ b/network/p2p/scoring/scoring_test.go @@ -23,7 +23,7 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" - "github.com/onflow/flow-go/network/p2p/message" + p2pmsg "github.com/onflow/flow-go/network/p2p/message" "github.com/onflow/flow-go/network/p2p/p2pconf" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" From 6de273964f69ebf447f187c8a68f689f09b98e3d Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 11:02:20 -0700 Subject: [PATCH 65/74] adds a godoc --- cmd/util/cmd/execution-state-extract/export_report.json | 6 ++++++ network/p2p/p2pbuilder/inspector/suite.go | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 cmd/util/cmd/execution-state-extract/export_report.json diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json new file mode 100644 index 00000000000..9ba56715ad2 --- /dev/null +++ b/cmd/util/cmd/execution-state-extract/export_report.json @@ -0,0 +1,6 @@ +{ + "EpochCounter": 0, + "PreviousStateCommitment": "ef8ccf6bb2bc341ba3fbf92f259d0c08db912f8e6915297145abb227489006b8", + "CurrentStateCommitment": "ef8ccf6bb2bc341ba3fbf92f259d0c08db912f8e6915297145abb227489006b8", + "ReportSucceeded": true +} \ No newline at end of file diff --git a/network/p2p/p2pbuilder/inspector/suite.go b/network/p2p/p2pbuilder/inspector/suite.go index a3daf213def..eda1d68089b 100644 --- a/network/p2p/p2pbuilder/inspector/suite.go +++ b/network/p2p/p2pbuilder/inspector/suite.go @@ -65,7 +65,7 @@ func (s *GossipSubInspectorSuite) InspectFunc() func(peer.ID, *pubsub.RPC) error return s.aggregatedInspector.Inspect } -// AddInvalidCtrlMsgNotificationConsumer adds a consumer to the invalid control message notification distributor. +// AddInvalidControlMessageConsumer adds a consumer to the invalid control message notification distributor. // This consumer is notified when a misbehaving peer regarding gossipsub control messages is detected. This follows a pub/sub // pattern where the consumer is notified when a new notification is published. // A consumer is only notified once for each notification, and only receives notifications that were published after it was added. @@ -73,6 +73,9 @@ func (s *GossipSubInspectorSuite) AddInvalidControlMessageConsumer(c p2p.GossipS s.ctrlMsgInspectDistributor.AddConsumer(c) } +// ActiveClustersChanged is called when the list of active collection nodes cluster is changed. +// GossipSubInspectorSuite consumes this event and forwards it to all the respective rpc inspectors, that are +// concerned with this cluster-based topics (i.e., channels), so that they can update their internal state. func (s *GossipSubInspectorSuite) ActiveClustersChanged(list flow.ChainIDList) { for _, rpcInspector := range s.aggregatedInspector.Inspectors() { if r, ok := rpcInspector.(p2p.GossipSubMsgValidationRpcInspector); ok { From 272f7a875e9cf86f6c3c735626c121102e4b72cb Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 12:26:49 -0700 Subject: [PATCH 66/74] wires pubsub active cluster change --- .../cmd/execution-state-extract/export_report.json | 6 ------ network/p2p/mock/pub_sub_adapter.go | 7 +++++++ network/p2p/p2pnode/libp2pNode.go | 10 ++++++++-- network/p2p/pubsub.go | 6 ++++++ 4 files changed, 21 insertions(+), 8 deletions(-) delete mode 100644 cmd/util/cmd/execution-state-extract/export_report.json diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json deleted file mode 100644 index 9ba56715ad2..00000000000 --- a/cmd/util/cmd/execution-state-extract/export_report.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "EpochCounter": 0, - "PreviousStateCommitment": "ef8ccf6bb2bc341ba3fbf92f259d0c08db912f8e6915297145abb227489006b8", - "CurrentStateCommitment": "ef8ccf6bb2bc341ba3fbf92f259d0c08db912f8e6915297145abb227489006b8", - "ReportSucceeded": true -} \ No newline at end of file diff --git a/network/p2p/mock/pub_sub_adapter.go b/network/p2p/mock/pub_sub_adapter.go index d8f2cf533a2..ad0d7e8f9c6 100644 --- a/network/p2p/mock/pub_sub_adapter.go +++ b/network/p2p/mock/pub_sub_adapter.go @@ -3,7 +3,9 @@ package mockp2p import ( + flow "github.com/onflow/flow-go/model/flow" irrecoverable "github.com/onflow/flow-go/module/irrecoverable" + mock "github.com/stretchr/testify/mock" p2p "github.com/onflow/flow-go/network/p2p" @@ -16,6 +18,11 @@ type PubSubAdapter struct { mock.Mock } +// ActiveClustersChanged provides a mock function with given fields: _a0 +func (_m *PubSubAdapter) ActiveClustersChanged(_a0 flow.ChainIDList) { + _m.Called(_a0) +} + // Done provides a mock function with given fields: func (_m *PubSubAdapter) Done() <-chan struct{} { ret := _m.Called() diff --git a/network/p2p/p2pnode/libp2pNode.go b/network/p2p/p2pnode/libp2pNode.go index a9920dab02a..168849d1761 100644 --- a/network/p2p/p2pnode/libp2pNode.go +++ b/network/p2p/p2pnode/libp2pNode.go @@ -537,7 +537,13 @@ func (n *Node) IsDisallowListed(peerId peer.ID) ([]flownet.DisallowListedCause, return n.disallowListedCache.IsDisallowListed(peerId) } +// ActiveClustersChanged is called when the active clusters list of the collection clusters has changed. +// The LibP2PNode implementation directly calls the ActiveClustersChanged method of the pubsub implementation, as +// the pubsub implementation is responsible for the actual handling of the event. +// Args: +// - list: the new active clusters list. +// Returns: +// - none func (n *Node) ActiveClustersChanged(list flow.ChainIDList) { - //TODO implement me - panic("implement me") + n.pubSub.ActiveClustersChanged(list) } diff --git a/network/p2p/pubsub.go b/network/p2p/pubsub.go index 3f19c892c75..7ccc0aa6ca7 100644 --- a/network/p2p/pubsub.go +++ b/network/p2p/pubsub.go @@ -27,6 +27,12 @@ type TopicValidatorFunc func(context.Context, peer.ID, *pubsub.Message) Validati // PubSubAdapter is the abstraction of the underlying pubsub logic that is used by the Flow network. type PubSubAdapter interface { component.Component + // CollectionClusterChangesConsumer is the interface for consuming the events of changes in the collection cluster. + // This is used to notify the node of changes in the collection cluster. + // PubSubAdapter implements this interface and consumes the events to be notified of changes in the clustering channels. + // The clustering channels are used by the collection nodes of a cluster to communicate with each other. + // As the cluster (and hence their cluster channels) of collection nodes changes over time (per epoch) the node needs to be notified of these changes. + CollectionClusterChangesConsumer // RegisterTopicValidator registers a validator for topic. RegisterTopicValidator(topic string, topicValidator TopicValidatorFunc) error From 0933c33190e62762f70b77a84b11da781f9d9879 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 12:33:40 -0700 Subject: [PATCH 67/74] adds godoc --- network/p2p/p2pnode/gossipSubAdapter.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2pnode/gossipSubAdapter.go b/network/p2p/p2pnode/gossipSubAdapter.go index 1ff4b3a3349..5a14501d012 100644 --- a/network/p2p/p2pnode/gossipSubAdapter.go +++ b/network/p2p/p2pnode/gossipSubAdapter.go @@ -20,8 +20,11 @@ import ( // that implements the PubSubAdapter interface for the Flow network. type GossipSubAdapter struct { component.Component - gossipSub *pubsub.PubSub - logger zerolog.Logger + gossipSub *pubsub.PubSub + logger zerolog.Logger + // clusterChangeConsumer is a callback that is invoked when the set of active clusters of collection nodes changes. + // This callback is implemented by the rpc inspector suite of the GossipSubAdapter, and consumes the cluster changes + // to update the rpc inspector state of the recent topics (i.e., channels). clusterChangeConsumer p2p.CollectionClusterChangesConsumer } @@ -138,6 +141,13 @@ func (g *GossipSubAdapter) ListPeers(topic string) []peer.ID { return g.gossipSub.ListPeers(topic) } +// ActiveClustersChanged is called when the active clusters of collection nodes changes. +// GossipSubAdapter implements this method to forward the call to the clusterChangeConsumer (rpc inspector), +// which will then update the cluster state of the rpc inspector. +// Args: +// - lst: the list of active clusters +// Returns: +// - void func (g *GossipSubAdapter) ActiveClustersChanged(lst flow.ChainIDList) { g.clusterChangeConsumer.ActiveClustersChanged(lst) } From 27cef004b184e4724658e17180acde923195d88e Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 23 Jun 2023 12:36:24 -0700 Subject: [PATCH 68/74] removes the unused method --- network/p2p/test/fixtures.go | 59 +----------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index d8bb88c2f5d..d2d8ebfac9c 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -78,7 +78,7 @@ func NodeFixture( }, ResourceManager: testutils.NewResourceManager(t), GossipSubPeerScoreTracerInterval: 0, // disabled by default - GossipSubRPCInspectorCfg: GossipSubRpcValidationInspectorConfigFixture(t), + GossipSubRPCInspectorCfg: &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, } for _, opt := range opts { @@ -604,60 +604,3 @@ func PeerIdSliceFixture(t *testing.T, n int) peer.IDSlice { } return ids } - -// GossipSubRpcValidationInspectorConfigFixture returns a GossipSubRPCValidationInspectorConfigs instance for testing. -// Args: -// - t: *testing.T instance - to indicate that this is a test fixture. -// Returns: -// - *netconf.GossipSubRPCValidationInspectorConfigs: GossipSubRPCValidationInspectorConfigs instance. -// Note: the parameters in this fixture are INTENTIONALLY independent of the default values in the config file. -// This is to allow test parameters to be changed without affecting the default values in the config file. -func GossipSubRpcValidationInspectorConfigFixture(_ *testing.T) *p2pconf.GossipSubRPCInspectorsConfig { - return &p2pconf.GossipSubRPCInspectorsConfig{ - GossipSubRPCValidationInspectorConfigs: p2pconf.GossipSubRPCValidationInspectorConfigs{ - ClusterPrefixedMessageConfig: p2pconf.ClusterPrefixedMessageConfig{ - ClusterPrefixHardThreshold: 100, - ClusterPrefixedControlMsgsReceivedCacheSize: 100, - ClusterPrefixedControlMsgsReceivedCacheDecay: .99, - }, - NumberOfWorkers: 5, - CacheSize: 10_000, - GraftLimits: struct { - HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-graft-hard-threshold"` - SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-graft-safety-threshold"` - RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-graft-rate-limit"` - }{ - HardThreshold: 30, - SafetyThreshold: 15, - RateLimit: 30, - }, - PruneLimits: struct { - HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-prune-hard-threshold"` - SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-prune-safety-threshold"` - RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-prune-rate-limit"` - }{ - HardThreshold: 30, - SafetyThreshold: 15, - RateLimit: 30, - }, - IHaveLimits: struct { - HardThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-ihave-hard-threshold"` - SafetyThreshold uint64 `validate:"gt=0" mapstructure:"gossipsub-rpc-ihave-safety-threshold"` - RateLimit int `validate:"gte=0" mapstructure:"gossipsub-rpc-ihave-rate-limit"` - }{ - HardThreshold: 100, - SafetyThreshold: 50, - RateLimit: 0, - }, - IHaveSyncInspectSampleSizePercentage: .25, - IHaveAsyncInspectSampleSizePercentage: .10, - IHaveInspectionMaxSampleSize: 100, - }, - GossipSubRPCMetricsInspectorConfigs: p2pconf.GossipSubRPCMetricsInspectorConfigs{ - NumberOfWorkers: 1, - CacheSize: 100, - }, - GossipSubRPCInspectorNotificationCacheSize: 10_000, - } - -} From a3b4bd5463d4beec976e7fc9475b8cc09c2a9833 Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 29 Jun 2023 02:33:23 +0300 Subject: [PATCH 69/74] Fixed cyclic dependency and regexp lint. --- engine/access/rest/middleware/metrics.go | 5 ++--- engine/access/rest/router.go | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/engine/access/rest/middleware/metrics.go b/engine/access/rest/middleware/metrics.go index e47c956a484..da555d41c67 100644 --- a/engine/access/rest/middleware/metrics.go +++ b/engine/access/rest/middleware/metrics.go @@ -8,15 +8,14 @@ import ( "github.com/gorilla/mux" - "github.com/onflow/flow-go/engine/access/rest" "github.com/onflow/flow-go/module" ) -func MetricsMiddleware(restCollector module.RestMetrics) mux.MiddlewareFunc { +func MetricsMiddleware(restCollector module.RestMetrics, urlToRoute func(string) (string, error)) mux.MiddlewareFunc { metricsMiddleware := middleware.New(middleware.Config{Recorder: restCollector}) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - routeName, err := rest.URLToRoute(req.URL.Path) + routeName, err := urlToRoute(req.URL.Path) if err != nil { return } diff --git a/engine/access/rest/router.go b/engine/access/rest/router.go index 9bee63560b0..f51f1c65f3e 100644 --- a/engine/access/rest/router.go +++ b/engine/access/rest/router.go @@ -24,7 +24,7 @@ func newRouter(backend access.API, logger zerolog.Logger, chain flow.Chain, rest v1SubRouter.Use(middleware.LoggingMiddleware(logger)) v1SubRouter.Use(middleware.QueryExpandable()) v1SubRouter.Use(middleware.QuerySelect()) - v1SubRouter.Use(middleware.MetricsMiddleware(restCollector)) + v1SubRouter.Use(middleware.MetricsMiddleware(restCollector, URLToRoute)) linkGenerator := models.NewLinkGeneratorImpl(v1SubRouter) @@ -119,7 +119,7 @@ var Routes = []route{{ }} var routeUrlMap = map[string]string{} -var routeRE = regexp.MustCompile("/v1/([\\w]+)(/([\\w]+)(/([\\w]+))?)?") +var routeRE = regexp.MustCompile(`(?i)/v1/(\w+)(/(\w+)(/(\w+))?)?`) func init() { for _, r := range Routes { From 2f94bd6c2da2ec5c7dbf6b83105a858a2c1f5af6 Mon Sep 17 00:00:00 2001 From: Andrii Slisarchuk Date: Thu, 29 Jun 2023 22:53:40 +0300 Subject: [PATCH 70/74] Change error handling in rest metrics. --- engine/access/rest/middleware/metrics.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/access/rest/middleware/metrics.go b/engine/access/rest/middleware/metrics.go index da555d41c67..25f82bf4277 100644 --- a/engine/access/rest/middleware/metrics.go +++ b/engine/access/rest/middleware/metrics.go @@ -15,9 +15,11 @@ func MetricsMiddleware(restCollector module.RestMetrics, urlToRoute func(string) metricsMiddleware := middleware.New(middleware.Config{Recorder: restCollector}) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + //urlToRoute transforms specific URL to generic url pattern routeName, err := urlToRoute(req.URL.Path) if err != nil { - return + // In case of an error, an empty route name filled with "unknown" + routeName = "unknown" } // This is a custom metric being called on every http request From 38ed00e2f89e21065bfecb4996d3fadb9384ed63 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 29 Jun 2023 14:00:41 -0700 Subject: [PATCH 71/74] restructures the code --- network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 191935ee00b..441c46632f9 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -289,10 +289,10 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p g.metricsCfg.HeroCacheFactory, g.networkType, g.idProvider) - gossipSubConfigs.WithInspectorSuite(inspectorSuite) if err != nil { return nil, nil, fmt.Errorf("could not create gossipsub inspector suite: %w", err) } + gossipSubConfigs.WithInspectorSuite(inspectorSuite) var scoreOpt *scoring.ScoreOption var scoreTracer p2p.PeerScoreTracer From 4eff362ee754bf332e9ca0b621e47657c52a7ee8 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Thu, 29 Jun 2023 14:06:55 -0700 Subject: [PATCH 72/74] renames package name --- network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index 441c46632f9..a8efac21944 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -23,7 +23,7 @@ import ( "github.com/onflow/flow-go/network/p2p/inspector" "github.com/onflow/flow-go/network/p2p/inspector/validation" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" - inspector2 "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" + inspectorbuilder "github.com/onflow/flow-go/network/p2p/p2pbuilder/inspector" "github.com/onflow/flow-go/network/p2p/p2pconf" "github.com/onflow/flow-go/network/p2p/p2pnode" "github.com/onflow/flow-go/network/p2p/scoring" @@ -252,7 +252,7 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { return nil, fmt.Errorf("failed to create new control message valiadation inspector: %w", err) } - return inspector2.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, rpcValidationInspector}, notificationDistributor), nil + return inspectorbuilder.NewGossipSubInspectorSuite([]p2p.GossipSubRPCInspector{metricsInspector, rpcValidationInspector}, notificationDistributor), nil } } From 91da6d0b24d1d5a5e156c3616f1179b4951d19a6 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Fri, 30 Jun 2023 13:04:06 -0700 Subject: [PATCH 73/74] [Routing Attacks] Mitigates invalid message delivery (#4492) --- .../export_report.json | 6 + insecure/cmd/mods_override.sh | 2 +- insecure/corruptlibp2p/gossipsub_spammer.go | 26 +-- insecure/corruptlibp2p/pubsub_adapter.go | 51 ++++-- .../corruptlibp2p/pubsub_adapter_config.go | 104 ++++++++++- insecure/go.mod | 2 +- insecure/go.sum | 4 +- .../rpc_inspector/metrics_inspector_test.go | 0 .../test/gossipsub}/rpc_inspector/utils.go | 0 .../validation_inspector_test.go | 0 .../test/gossipsub/scoring/scoring_test.go | 173 ++++++++++++++++++ .../{test => tests}/composability_test.go | 2 +- .../{test => tests}/mock_orchestrator.go | 2 +- integration/go.mod | 2 +- integration/go.sum | 4 +- network/p2p/builder.go | 3 +- network/p2p/libp2pNode.go | 6 +- network/p2p/mock/gossip_sub_builder.go | 21 +-- network/p2p/mock/lib_p2_p_node.go | 19 +- network/p2p/mock/peer_score.go | 19 +- network/p2p/mock/pub_sub_adapter.go | 16 ++ network/p2p/mock/score_option_builder.go | 36 +++- .../p2pbuilder/gossipsub/gossipSubBuilder.go | 16 +- network/p2p/p2pbuilder/libp2pNodeBuilder.go | 5 +- network/p2p/p2pnode/gossipSubAdapter.go | 50 ++++- network/p2p/p2pnode/gossipSubAdapterConfig.go | 23 ++- network/p2p/p2pnode/libp2pNode.go | 40 ++-- network/p2p/pubsub.go | 15 +- network/p2p/scoring/README.md | 20 ++ network/p2p/scoring/score_option.go | 108 ++++++++--- network/p2p/test/message.go | 65 +++++++ .../p2p/tracer/gossipSubScoreTracer_test.go | 4 +- network/p2p/utils/logger.go | 33 ++++ utils/unittest/bytes.go | 20 ++ utils/unittest/strings.go | 36 ++++ 35 files changed, 759 insertions(+), 174 deletions(-) create mode 100644 cmd/util/cmd/execution-state-extract/export_report.json rename insecure/{ => integration/functional/test/gossipsub}/rpc_inspector/metrics_inspector_test.go (100%) rename insecure/{ => integration/functional/test/gossipsub}/rpc_inspector/utils.go (100%) rename insecure/{ => integration/functional/test/gossipsub}/rpc_inspector/validation_inspector_test.go (100%) create mode 100644 insecure/integration/functional/test/gossipsub/scoring/scoring_test.go rename insecure/integration/{test => tests}/composability_test.go (99%) rename insecure/integration/{test => tests}/mock_orchestrator.go (99%) create mode 100644 network/p2p/test/message.go create mode 100644 network/p2p/utils/logger.go create mode 100644 utils/unittest/bytes.go create mode 100644 utils/unittest/strings.go diff --git a/cmd/util/cmd/execution-state-extract/export_report.json b/cmd/util/cmd/execution-state-extract/export_report.json new file mode 100644 index 00000000000..2cbadb698d0 --- /dev/null +++ b/cmd/util/cmd/execution-state-extract/export_report.json @@ -0,0 +1,6 @@ +{ + "EpochCounter": 0, + "PreviousStateCommitment": "18eb0e8beef7ce851e552ecd29c813fde0a9e6f0c5614d7615642076602a48cf", + "CurrentStateCommitment": "18eb0e8beef7ce851e552ecd29c813fde0a9e6f0c5614d7615642076602a48cf", + "ReportSucceeded": true +} \ No newline at end of file diff --git a/insecure/cmd/mods_override.sh b/insecure/cmd/mods_override.sh index 6f6b4d4a6a7..d1877ac7b5c 100755 --- a/insecure/cmd/mods_override.sh +++ b/insecure/cmd/mods_override.sh @@ -6,7 +6,7 @@ cp ./go.mod ./go2.mod cp ./go.sum ./go2.sum # inject forked libp2p-pubsub into main module to allow building corrupt Docker images -echo "require github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee" >> ./go.mod +echo "require github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg" >> ./go.mod # update go.sum since added new dependency go mod tidy diff --git a/insecure/corruptlibp2p/gossipsub_spammer.go b/insecure/corruptlibp2p/gossipsub_spammer.go index 11a651c5d1a..2ec81a89e53 100644 --- a/insecure/corruptlibp2p/gossipsub_spammer.go +++ b/insecure/corruptlibp2p/gossipsub_spammer.go @@ -8,6 +8,7 @@ import ( pb "github.com/libp2p/go-libp2p-pubsub/pb" "github.com/libp2p/go-libp2p/core/peer" "github.com/stretchr/testify/require" + corrupt "github.com/yhassanzadeh13/go-libp2p-pubsub" "github.com/onflow/flow-go/insecure/internal" @@ -26,8 +27,8 @@ type GossipSubRouterSpammer struct { } // NewGossipSubRouterSpammer is the main method tests call for spamming attacks. -func NewGossipSubRouterSpammer(t *testing.T, sporkId flow.Identifier, role flow.Role, provider module.IdentityProvider) *GossipSubRouterSpammer { - spammerNode, spammerId, router := createSpammerNode(t, sporkId, role, provider) +func NewGossipSubRouterSpammer(t *testing.T, sporkId flow.Identifier, role flow.Role, provider module.IdentityProvider, opts ...p2ptest.NodeFixtureParameterOption) *GossipSubRouterSpammer { + spammerNode, spammerId, router := createSpammerNode(t, sporkId, role, provider, opts...) return &GossipSubRouterSpammer{ router: router, SpammerNode: spammerNode, @@ -37,9 +38,9 @@ func NewGossipSubRouterSpammer(t *testing.T, sporkId flow.Identifier, role flow. // SpamControlMessage spams the victim with junk control messages. // ctlMessages is the list of spam messages to send to the victim node. -func (s *GossipSubRouterSpammer) SpamControlMessage(t *testing.T, victim p2p.LibP2PNode, ctlMessages []pb.ControlMessage) { +func (s *GossipSubRouterSpammer) SpamControlMessage(t *testing.T, victim p2p.LibP2PNode, ctlMessages []pb.ControlMessage, msgs ...*pb.Message) { for _, ctlMessage := range ctlMessages { - require.True(t, s.router.Get().SendControl(victim.Host().ID(), &ctlMessage)) + require.True(t, s.router.Get().SendControl(victim.Host().ID(), &ctlMessage, msgs...)) } } @@ -64,14 +65,9 @@ func (s *GossipSubRouterSpammer) Start(t *testing.T) { s.router.set(s.router.Get()) } -func createSpammerNode(t *testing.T, sporkId flow.Identifier, role flow.Role, provider module.IdentityProvider) (p2p.LibP2PNode, flow.Identity, *atomicRouter) { +func createSpammerNode(t *testing.T, sporkId flow.Identifier, role flow.Role, provider module.IdentityProvider, opts ...p2ptest.NodeFixtureParameterOption) (p2p.LibP2PNode, flow.Identity, *atomicRouter) { router := newAtomicRouter() - spammerNode, spammerId := p2ptest.NodeFixture( - t, - sporkId, - t.Name(), - provider, - p2ptest.WithRole(role), + opts = append(opts, p2ptest.WithRole(role), internal.WithCorruptGossipSub(CorruptGossipSubFactory(func(r *corrupt.GossipSubRouter) { require.NotNil(t, r) router.set(r) @@ -79,7 +75,13 @@ func createSpammerNode(t *testing.T, sporkId flow.Identifier, role flow.Role, pr CorruptGossipSubConfigFactoryWithInspector(func(id peer.ID, rpc *corrupt.RPC) error { // here we can inspect the incoming RPC message to the spammer node return nil - })), + }))) + spammerNode, spammerId := p2ptest.NodeFixture( + t, + sporkId, + t.Name(), + provider, + opts..., ) return spammerNode, spammerId, router } diff --git a/insecure/corruptlibp2p/pubsub_adapter.go b/insecure/corruptlibp2p/pubsub_adapter.go index 51bbb8d15c7..f9d08eed50e 100644 --- a/insecure/corruptlibp2p/pubsub_adapter.go +++ b/insecure/corruptlibp2p/pubsub_adapter.go @@ -33,6 +33,7 @@ type CorruptGossipSubAdapter struct { router *corrupt.GossipSubRouter logger zerolog.Logger clusterChangeConsumer p2p.CollectionClusterChangesConsumer + peerScoreExposer p2p.PeerScoreExposer } var _ p2p.PubSubAdapter = (*CorruptGossipSubAdapter)(nil) @@ -110,13 +111,22 @@ func (c *CorruptGossipSubAdapter) ActiveClustersChanged(lst flow.ChainIDList) { c.clusterChangeConsumer.ActiveClustersChanged(lst) } -func NewCorruptGossipSubAdapter( - ctx context.Context, - logger zerolog.Logger, - h host.Host, - cfg p2p.PubSubAdapterConfig, - clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, *corrupt.GossipSubRouter, error) { +// PeerScoreExposer returns the peer score exposer for the gossipsub adapter. The exposer is a read-only interface +// for querying peer scores and returns the local scoring table of the underlying gossipsub node. +// The exposer is only available if the gossipsub adapter was configured with a score tracer. +// If the gossipsub adapter was not configured with a score tracer, the exposer will be nil. +// Args: +// +// None. +// +// Returns: +// +// The peer score exposer for the gossipsub adapter. +func (c *CorruptGossipSubAdapter) PeerScoreExposer() p2p.PeerScoreExposer { + return c.peerScoreExposer +} +func NewCorruptGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host, cfg p2p.PubSubAdapterConfig, clusterChangeConsumer p2p.CollectionClusterChangesConsumer) (p2p.PubSubAdapter, *corrupt.GossipSubRouter, error) { gossipSubConfig, ok := cfg.(*CorruptPubSubAdapterConfig) if !ok { return nil, nil, fmt.Errorf("invalid gossipsub config type: %T", cfg) @@ -131,19 +141,34 @@ func NewCorruptGossipSubAdapter( return nil, nil, fmt.Errorf("failed to create corrupt gossipsub: %w", err) } - builder := component.NewComponentManagerBuilder(). - AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { - ready() - <-ctx.Done() - }).Build() - + builder := component.NewComponentManagerBuilder() adapter := &CorruptGossipSubAdapter{ - Component: builder, gossipSub: gossipSub, router: router, logger: logger, clusterChangeConsumer: clusterChangeConsumer, } + if scoreTracer := gossipSubConfig.ScoreTracer(); scoreTracer != nil { + builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { + ready() + logger.Debug().Str("component", "corrupt-gossipsub_score_tracer").Msg("starting score tracer") + scoreTracer.Start(ctx) + logger.Debug().Str("component", "corrupt-gossipsub_score_tracer").Msg("score tracer started") + + <-scoreTracer.Done() + logger.Debug().Str("component", "corrupt-gossipsub_score_tracer").Msg("score tracer stopped") + }) + adapter.peerScoreExposer = scoreTracer + } + builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { + ready() + // it is likely that this adapter is configured without a score tracer, so we need to + // wait for the context to be done in order to prevent immature shutdown. + <-ctx.Done() + }) + + adapter.Component = builder.Build() + return adapter, router, nil } diff --git a/insecure/corruptlibp2p/pubsub_adapter_config.go b/insecure/corruptlibp2p/pubsub_adapter_config.go index 002e18608e0..1bae78dd872 100644 --- a/insecure/corruptlibp2p/pubsub_adapter_config.go +++ b/insecure/corruptlibp2p/pubsub_adapter_config.go @@ -24,6 +24,7 @@ type CorruptPubSubAdapterConfig struct { inspector func(peer.ID, *corrupt.RPC) error withMessageSigning bool withStrictSignatureVerification bool + scoreTracer p2p.PeerScoreTracer } type CorruptPubSubAdapterConfigOption func(config *CorruptPubSubAdapterConfig) @@ -78,8 +79,56 @@ func (c *CorruptPubSubAdapterConfig) WithSubscriptionFilter(filter p2p.Subscript c.options = append(c.options, corrupt.WithSubscriptionFilter(filter)) } -func (c *CorruptPubSubAdapterConfig) WithScoreOption(_ p2p.ScoreOptionBuilder) { - // CorruptPubSub does not support score options. This is a no-op. +func (c *CorruptPubSubAdapterConfig) WithScoreOption(option p2p.ScoreOptionBuilder) { + params, thresholds := option.BuildFlowPubSubScoreOption() + // convert flow pubsub score option to corrupt pubsub score option + corruptParams := &corrupt.PeerScoreParams{ + SkipAtomicValidation: params.SkipAtomicValidation, + TopicScoreCap: params.TopicScoreCap, + AppSpecificScore: params.AppSpecificScore, + AppSpecificWeight: params.AppSpecificWeight, + IPColocationFactorWeight: params.IPColocationFactorWeight, + IPColocationFactorThreshold: params.IPColocationFactorThreshold, + IPColocationFactorWhitelist: params.IPColocationFactorWhitelist, + BehaviourPenaltyWeight: params.BehaviourPenaltyWeight, + BehaviourPenaltyThreshold: params.BehaviourPenaltyThreshold, + BehaviourPenaltyDecay: params.BehaviourPenaltyDecay, + DecayInterval: params.DecayInterval, + DecayToZero: params.DecayToZero, + RetainScore: params.RetainScore, + SeenMsgTTL: params.SeenMsgTTL, + } + corruptThresholds := &corrupt.PeerScoreThresholds{ + SkipAtomicValidation: thresholds.SkipAtomicValidation, + GossipThreshold: thresholds.GossipThreshold, + PublishThreshold: thresholds.PublishThreshold, + GraylistThreshold: thresholds.GraylistThreshold, + AcceptPXThreshold: thresholds.AcceptPXThreshold, + OpportunisticGraftThreshold: thresholds.OpportunisticGraftThreshold, + } + for topic, topicParams := range params.Topics { + corruptParams.Topics[topic] = &corrupt.TopicScoreParams{ + SkipAtomicValidation: topicParams.SkipAtomicValidation, + TopicWeight: topicParams.TopicWeight, + TimeInMeshWeight: topicParams.TimeInMeshWeight, + TimeInMeshQuantum: topicParams.TimeInMeshQuantum, + TimeInMeshCap: topicParams.TimeInMeshCap, + FirstMessageDeliveriesWeight: topicParams.FirstMessageDeliveriesWeight, + FirstMessageDeliveriesDecay: topicParams.FirstMessageDeliveriesDecay, + FirstMessageDeliveriesCap: topicParams.FirstMessageDeliveriesCap, + MeshMessageDeliveriesWeight: topicParams.MeshMessageDeliveriesWeight, + MeshMessageDeliveriesDecay: topicParams.MeshMessageDeliveriesDecay, + MeshMessageDeliveriesCap: topicParams.MeshMessageDeliveriesCap, + MeshMessageDeliveriesThreshold: topicParams.MeshMessageDeliveriesThreshold, + MeshMessageDeliveriesWindow: topicParams.MeshMessageDeliveriesWindow, + MeshMessageDeliveriesActivation: topicParams.MeshMessageDeliveriesActivation, + MeshFailurePenaltyWeight: topicParams.MeshFailurePenaltyWeight, + MeshFailurePenaltyDecay: topicParams.MeshFailurePenaltyDecay, + InvalidMessageDeliveriesWeight: topicParams.InvalidMessageDeliveriesWeight, + InvalidMessageDeliveriesDecay: topicParams.InvalidMessageDeliveriesDecay, + } + } + c.options = append(c.options, corrupt.WithPeerScore(corruptParams, corruptThresholds)) } func (c *CorruptPubSubAdapterConfig) WithTracer(_ p2p.PubSubTracer) { @@ -93,8 +142,15 @@ func (c *CorruptPubSubAdapterConfig) WithMessageIdFunction(f func([]byte) string })) } -func (c *CorruptPubSubAdapterConfig) WithScoreTracer(_ p2p.PeerScoreTracer) { - // CorruptPubSub does not support score tracer. This is a no-op. +func (c *CorruptPubSubAdapterConfig) WithScoreTracer(tracer p2p.PeerScoreTracer) { + c.scoreTracer = tracer + c.options = append(c.options, corrupt.WithPeerScoreInspect(func(snapshot map[peer.ID]*corrupt.PeerScoreSnapshot) { + tracer.UpdatePeerScoreSnapshots(convertPeerScoreSnapshots(snapshot)) + }, tracer.UpdateInterval())) +} + +func (c *CorruptPubSubAdapterConfig) ScoreTracer() p2p.PeerScoreTracer { + return c.scoreTracer } func (c *CorruptPubSubAdapterConfig) WithInspectorSuite(_ p2p.GossipSubInspectorSuite) { @@ -112,3 +168,43 @@ func defaultCorruptPubsubOptions(base *p2p.BasePubSubAdapterConfig, withMessageS corrupt.WithMaxMessageSize(base.MaxMessageSize), } } + +// convertPeerScoreSnapshots converts a libp2p pubsub peer score snapshot to a Flow peer score snapshot. +// Args: +// - snapshot: the libp2p pubsub peer score snapshot. +// +// Returns: +// - map[peer.ID]*p2p.PeerScoreSnapshot: the Flow peer score snapshot. +func convertPeerScoreSnapshots(snapshot map[peer.ID]*corrupt.PeerScoreSnapshot) map[peer.ID]*p2p.PeerScoreSnapshot { + newSnapshot := make(map[peer.ID]*p2p.PeerScoreSnapshot) + for id, snap := range snapshot { + newSnapshot[id] = &p2p.PeerScoreSnapshot{ + Topics: convertTopicScoreSnapshot(snap.Topics), + Score: snap.Score, + AppSpecificScore: snap.AppSpecificScore, + BehaviourPenalty: snap.BehaviourPenalty, + IPColocationFactor: snap.IPColocationFactor, + } + } + return newSnapshot +} + +// convertTopicScoreSnapshot converts a libp2p pubsub topic score snapshot to a Flow topic score snapshot. +// Args: +// - snapshot: the libp2p pubsub topic score snapshot. +// +// Returns: +// - map[string]*p2p.TopicScoreSnapshot: the Flow topic score snapshot. +func convertTopicScoreSnapshot(snapshot map[string]*corrupt.TopicScoreSnapshot) map[string]*p2p.TopicScoreSnapshot { + newSnapshot := make(map[string]*p2p.TopicScoreSnapshot) + for topic, snap := range snapshot { + newSnapshot[topic] = &p2p.TopicScoreSnapshot{ + TimeInMesh: snap.TimeInMesh, + FirstMessageDeliveries: snap.FirstMessageDeliveries, + MeshMessageDeliveries: snap.MeshMessageDeliveries, + InvalidMessageDeliveries: snap.InvalidMessageDeliveries, + } + } + + return newSnapshot +} diff --git a/insecure/go.mod b/insecure/go.mod index e3748bc6c3d..121b45694a5 100644 --- a/insecure/go.mod +++ b/insecure/go.mod @@ -14,7 +14,7 @@ require ( github.com/rs/zerolog v1.29.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.2 - github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee + github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg go.uber.org/atomic v1.10.0 google.golang.org/grpc v1.53.0 google.golang.org/protobuf v1.30.0 diff --git a/insecure/go.sum b/insecure/go.sum index 614d1513e79..dceda2bb27e 100644 --- a/insecure/go.sum +++ b/insecure/go.sum @@ -1481,8 +1481,8 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee h1:yFB2xjfswpuRh8FHagdBMKcBMltjr5u/XKzX6fkJO5E= -github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee/go.mod h1:Tylw4k1H86gbJx84i3r7qahN/mBaeMpUBvHY0Igshfw= +github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg h1:CtmNcsXmPNYnpzogVjrIy99if5Hvh79kd+ecoQgA7Vg= +github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg/go.mod h1:Tylw4k1H86gbJx84i3r7qahN/mBaeMpUBvHY0Igshfw= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/insecure/rpc_inspector/metrics_inspector_test.go b/insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go similarity index 100% rename from insecure/rpc_inspector/metrics_inspector_test.go rename to insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go diff --git a/insecure/rpc_inspector/utils.go b/insecure/integration/functional/test/gossipsub/rpc_inspector/utils.go similarity index 100% rename from insecure/rpc_inspector/utils.go rename to insecure/integration/functional/test/gossipsub/rpc_inspector/utils.go diff --git a/insecure/rpc_inspector/validation_inspector_test.go b/insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go similarity index 100% rename from insecure/rpc_inspector/validation_inspector_test.go rename to insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go diff --git a/insecure/integration/functional/test/gossipsub/scoring/scoring_test.go b/insecure/integration/functional/test/gossipsub/scoring/scoring_test.go new file mode 100644 index 00000000000..ec024775cf0 --- /dev/null +++ b/insecure/integration/functional/test/gossipsub/scoring/scoring_test.go @@ -0,0 +1,173 @@ +package scoring + +import ( + "context" + "testing" + "time" + + pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/require" + + "github.com/onflow/flow-go/insecure/corruptlibp2p" + "github.com/onflow/flow-go/model/flow" + "github.com/onflow/flow-go/module/irrecoverable" + "github.com/onflow/flow-go/module/mock" + "github.com/onflow/flow-go/network/channels" + "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/scoring" + p2ptest "github.com/onflow/flow-go/network/p2p/test" + "github.com/onflow/flow-go/utils/unittest" +) + +// TestGossipSubInvalidMessageDelivery_Integration tests that when a victim peer is spammed with invalid messages from +// a spammer peer, the victim will eventually penalize the spammer and stop receiving messages from them. +// Note: the term integration is used here because it requires integrating all components of the libp2p stack. +func TestGossipSubInvalidMessageDelivery_Integration(t *testing.T) { + tt := []struct { + name string + spamMsgFactory func(spammerId peer.ID, victimId peer.ID, topic channels.Topic) *pubsub_pb.Message + }{ + { + name: "unknown peer, invalid signature", + spamMsgFactory: func(spammerId peer.ID, _ peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithTopic(topic.String())) + }, + }, + { + name: "unknown peer, missing signature", + spamMsgFactory: func(spammerId peer.ID, _ peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithTopic(topic.String()), p2ptest.WithoutSignature()) + }, + }, + { + name: "known peer, invalid signature", + spamMsgFactory: func(spammerId peer.ID, _ peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithFrom(spammerId), p2ptest.WithTopic(topic.String())) + }, + }, + { + name: "known peer, missing signature", + spamMsgFactory: func(spammerId peer.ID, _ peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithFrom(spammerId), p2ptest.WithTopic(topic.String()), p2ptest.WithoutSignature()) + }, + }, + { + name: "self-origin, invalid signature", // bounce back our own messages + spamMsgFactory: func(_ peer.ID, victimId peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithFrom(victimId), p2ptest.WithTopic(topic.String())) + }, + }, + { + name: "self-origin, no signature", // bounce back our own messages + spamMsgFactory: func(_ peer.ID, victimId peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithFrom(victimId), p2ptest.WithTopic(topic.String()), p2ptest.WithoutSignature()) + }, + }, + { + name: "no sender", + spamMsgFactory: func(_ peer.ID, victimId peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithoutSignerId(), p2ptest.WithTopic(topic.String())) + }, + }, + { + name: "no sender, missing signature", + spamMsgFactory: func(_ peer.ID, victimId peer.ID, topic channels.Topic) *pubsub_pb.Message { + return p2ptest.PubsubMessageFixture(t, p2ptest.WithoutSignerId(), p2ptest.WithTopic(topic.String()), p2ptest.WithoutSignature()) + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + testGossipSubInvalidMessageDeliveryScoring(t, tc.spamMsgFactory) + }) + } +} + +// testGossipSubInvalidMessageDeliveryScoring tests that when a victim peer is spammed with invalid messages from +// a spammer peer, the victim will eventually penalize the spammer and stop receiving messages from them. +// Args: +// - t: the test instance. +// - spamMsgFactory: a function that creates unique invalid messages to spam the victim with. +func testGossipSubInvalidMessageDeliveryScoring(t *testing.T, spamMsgFactory func(peer.ID, peer.ID, channels.Topic) *pubsub_pb.Message) { + role := flow.RoleConsensus + sporkId := unittest.IdentifierFixture() + blockTopic := channels.TopicFromChannel(channels.PushBlocks, sporkId) + + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkId, role, idProvider) + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkId, + t.Name(), + idProvider, + p2ptest.WithRole(role), + p2ptest.WithPeerScoreTracerInterval(1*time.Second), + p2ptest.WithPeerScoringEnabled(idProvider), + ) + + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() + ids := flow.IdentityList{&spammer.SpammerId, &victimIdentity} + nodes := []p2p.LibP2PNode{spammer.SpammerNode, victimNode} + + p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) + defer p2ptest.StopNodes(t, nodes, cancel, 2*time.Second) + + p2ptest.LetNodesDiscoverEachOther(t, ctx, nodes, ids) + p2ptest.TryConnectionAndEnsureConnected(t, ctx, nodes) + + // checks end-to-end message delivery works on GossipSub + p2ptest.EnsurePubsubMessageExchange(t, ctx, nodes, func() (interface{}, channels.Topic) { + return unittest.ProposalFixture(), blockTopic + }) + + totalSpamMessages := 20 + for i := 0; i <= totalSpamMessages; i++ { + spammer.SpamControlMessage(t, victimNode, + spammer.GenerateCtlMessages(1), + spamMsgFactory(spammer.SpammerNode.Host().ID(), victimNode.Host().ID(), blockTopic)) + } + + // wait for at most 3 seconds for the victim node to penalize the spammer node. + // Each heartbeat is 1 second, so 3 heartbeats should be enough to penalize the spammer node. + // Ideally, we should wait for 1 heartbeat, but the score may not be updated immediately after the heartbeat. + require.Eventually(t, func() bool { + spammerScore, ok := victimNode.PeerScoreExposer().GetScore(spammer.SpammerNode.Host().ID()) + if !ok { + return false + } + if spammerScore >= scoring.DefaultGossipThreshold { + // ensure the score is low enough so that no gossip is routed by victim node to spammer node. + return false + } + if spammerScore >= scoring.DefaultPublishThreshold { + // ensure the score is low enough so that non of the published messages of the victim node are routed to the spammer node. + return false + } + if spammerScore >= scoring.DefaultGraylistThreshold { + // ensure the score is low enough so that the victim node does not accept RPC messages from the spammer node. + return false + } + + return true + }, 3*time.Second, 100*time.Millisecond) + + topicsSnapshot, ok := victimNode.PeerScoreExposer().GetTopicScores(spammer.SpammerNode.Host().ID()) + require.True(t, ok) + require.NotNil(t, topicsSnapshot, "topic scores must not be nil") + require.NotEmpty(t, topicsSnapshot, "topic scores must not be empty") + blkTopicSnapshot, ok := topicsSnapshot[blockTopic.String()] + require.True(t, ok) + + // ensure that the topic snapshot of the spammer contains a record of at least (60%) of the spam messages sent. The 60% is to account for the messages that were delivered before the score was updated, after the spammer is PRUNED, as well as to account for decay. + require.True(t, blkTopicSnapshot.InvalidMessageDeliveries > 0.6*float64(totalSpamMessages), "invalid message deliveries must be greater than %f. invalid message deliveries: %f", 0.9*float64(totalSpamMessages), blkTopicSnapshot.InvalidMessageDeliveries) + + p2ptest.EnsureNoPubsubExchangeBetweenGroups(t, ctx, []p2p.LibP2PNode{victimNode}, []p2p.LibP2PNode{spammer.SpammerNode}, func() (interface{}, channels.Topic) { + return unittest.ProposalFixture(), blockTopic + }) +} diff --git a/insecure/integration/test/composability_test.go b/insecure/integration/tests/composability_test.go similarity index 99% rename from insecure/integration/test/composability_test.go rename to insecure/integration/tests/composability_test.go index c7ba04d3b7a..4bac2aeb0c5 100644 --- a/insecure/integration/test/composability_test.go +++ b/insecure/integration/tests/composability_test.go @@ -1,4 +1,4 @@ -package test +package tests import ( "context" diff --git a/insecure/integration/test/mock_orchestrator.go b/insecure/integration/tests/mock_orchestrator.go similarity index 99% rename from insecure/integration/test/mock_orchestrator.go rename to insecure/integration/tests/mock_orchestrator.go index b992e1d6c20..5d11879d6df 100644 --- a/insecure/integration/test/mock_orchestrator.go +++ b/insecure/integration/tests/mock_orchestrator.go @@ -1,4 +1,4 @@ -package test +package tests import ( "github.com/onflow/flow-go/insecure" diff --git a/integration/go.mod b/integration/go.mod index 629b5e458ab..4be06e9a9cf 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -287,7 +287,7 @@ require ( github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee // indirect + github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zeebo/blake3 v0.2.3 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect diff --git a/integration/go.sum b/integration/go.sum index 374df68f7cf..3545b49110c 100644 --- a/integration/go.sum +++ b/integration/go.sum @@ -1733,8 +1733,8 @@ github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee h1:yFB2xjfswpuRh8FHagdBMKcBMltjr5u/XKzX6fkJO5E= -github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.2-0.20221208234712-b44d9133e4ee/go.mod h1:Tylw4k1H86gbJx84i3r7qahN/mBaeMpUBvHY0Igshfw= +github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg h1:CtmNcsXmPNYnpzogVjrIy99if5Hvh79kd+ecoQgA7Vg= +github.com/yhassanzadeh13/go-libp2p-pubsub v0.6.11-flow-expose-msg/go.mod h1:Tylw4k1H86gbJx84i3r7qahN/mBaeMpUBvHY0Igshfw= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 88a94e52a5f..9e6eac022e6 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -76,10 +76,9 @@ type GossipSubBuilder interface { // // Returns: // - PubSubAdapter: a GossipSub pubsub system for the libp2p node. - // - PeerScoreTracer: a peer score tracer for the GossipSub pubsub system (if enabled, otherwise nil). // - error: if an error occurs during the creation of the GossipSub pubsub system, it is returned. Otherwise, nil is returned. // Note that on happy path, the returned error is nil. Any error returned is unexpected and should be handled as irrecoverable. - Build(irrecoverable.SignalerContext) (PubSubAdapter, PeerScoreTracer, error) + Build(irrecoverable.SignalerContext) (PubSubAdapter, error) } type PeerScoringBuilder interface { diff --git a/network/p2p/libp2pNode.go b/network/p2p/libp2pNode.go index 0efff130503..061e45a43ff 100644 --- a/network/p2p/libp2pNode.go +++ b/network/p2p/libp2pNode.go @@ -112,13 +112,9 @@ type CollectionClusterChangesConsumer interface { // PeerScore is the interface for the peer score module. It is used to expose the peer score to other // components of the node. It is also used to set the peer score exposer implementation. type PeerScore interface { - // SetPeerScoreExposer sets the node's peer score exposer implementation. - // SetPeerScoreExposer may be called at most once. It is an irrecoverable error to call this - // method if the node's peer score exposer has already been set. - SetPeerScoreExposer(e PeerScoreExposer) // PeerScoreExposer returns the node's peer score exposer implementation. // If the node's peer score exposer has not been set, the second return value will be false. - PeerScoreExposer() (PeerScoreExposer, bool) + PeerScoreExposer() PeerScoreExposer } // PeerConnections subset of funcs related to underlying libp2p host connections. diff --git a/network/p2p/mock/gossip_sub_builder.go b/network/p2p/mock/gossip_sub_builder.go index b5c5f1241ea..2146f922c9b 100644 --- a/network/p2p/mock/gossip_sub_builder.go +++ b/network/p2p/mock/gossip_sub_builder.go @@ -27,13 +27,12 @@ type GossipSubBuilder struct { } // Build provides a mock function with given fields: _a0 -func (_m *GossipSubBuilder) Build(_a0 irrecoverable.SignalerContext) (p2p.PubSubAdapter, p2p.PeerScoreTracer, error) { +func (_m *GossipSubBuilder) Build(_a0 irrecoverable.SignalerContext) (p2p.PubSubAdapter, error) { ret := _m.Called(_a0) var r0 p2p.PubSubAdapter - var r1 p2p.PeerScoreTracer - var r2 error - if rf, ok := ret.Get(0).(func(irrecoverable.SignalerContext) (p2p.PubSubAdapter, p2p.PeerScoreTracer, error)); ok { + var r1 error + if rf, ok := ret.Get(0).(func(irrecoverable.SignalerContext) (p2p.PubSubAdapter, error)); ok { return rf(_a0) } if rf, ok := ret.Get(0).(func(irrecoverable.SignalerContext) p2p.PubSubAdapter); ok { @@ -44,21 +43,13 @@ func (_m *GossipSubBuilder) Build(_a0 irrecoverable.SignalerContext) (p2p.PubSub } } - if rf, ok := ret.Get(1).(func(irrecoverable.SignalerContext) p2p.PeerScoreTracer); ok { + if rf, ok := ret.Get(1).(func(irrecoverable.SignalerContext) error); ok { r1 = rf(_a0) } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(p2p.PeerScoreTracer) - } - } - - if rf, ok := ret.Get(2).(func(irrecoverable.SignalerContext) error); ok { - r2 = rf(_a0) - } else { - r2 = ret.Error(2) + r1 = ret.Error(1) } - return r0, r1, r2 + return r0, r1 } // OverrideDefaultRpcInspectorSuiteFactory provides a mock function with given fields: _a0 diff --git a/network/p2p/mock/lib_p2_p_node.go b/network/p2p/mock/lib_p2_p_node.go index d8bef358b74..5813983110e 100644 --- a/network/p2p/mock/lib_p2_p_node.go +++ b/network/p2p/mock/lib_p2_p_node.go @@ -269,14 +269,10 @@ func (_m *LibP2PNode) PeerManagerComponent() component.Component { } // PeerScoreExposer provides a mock function with given fields: -func (_m *LibP2PNode) PeerScoreExposer() (p2p.PeerScoreExposer, bool) { +func (_m *LibP2PNode) PeerScoreExposer() p2p.PeerScoreExposer { ret := _m.Called() var r0 p2p.PeerScoreExposer - var r1 bool - if rf, ok := ret.Get(0).(func() (p2p.PeerScoreExposer, bool)); ok { - return rf() - } if rf, ok := ret.Get(0).(func() p2p.PeerScoreExposer); ok { r0 = rf() } else { @@ -285,13 +281,7 @@ func (_m *LibP2PNode) PeerScoreExposer() (p2p.PeerScoreExposer, bool) { } } - if rf, ok := ret.Get(1).(func() bool); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(bool) - } - - return r0, r1 + return r0 } // Publish provides a mock function with given fields: ctx, topic, data @@ -380,11 +370,6 @@ func (_m *LibP2PNode) SetComponentManager(cm *component.ComponentManager) { _m.Called(cm) } -// SetPeerScoreExposer provides a mock function with given fields: e -func (_m *LibP2PNode) SetPeerScoreExposer(e p2p.PeerScoreExposer) { - _m.Called(e) -} - // SetPubSub provides a mock function with given fields: ps func (_m *LibP2PNode) SetPubSub(ps p2p.PubSubAdapter) { _m.Called(ps) diff --git a/network/p2p/mock/peer_score.go b/network/p2p/mock/peer_score.go index 374d03d6749..81ea79ec570 100644 --- a/network/p2p/mock/peer_score.go +++ b/network/p2p/mock/peer_score.go @@ -13,14 +13,10 @@ type PeerScore struct { } // PeerScoreExposer provides a mock function with given fields: -func (_m *PeerScore) PeerScoreExposer() (p2p.PeerScoreExposer, bool) { +func (_m *PeerScore) PeerScoreExposer() p2p.PeerScoreExposer { ret := _m.Called() var r0 p2p.PeerScoreExposer - var r1 bool - if rf, ok := ret.Get(0).(func() (p2p.PeerScoreExposer, bool)); ok { - return rf() - } if rf, ok := ret.Get(0).(func() p2p.PeerScoreExposer); ok { r0 = rf() } else { @@ -29,18 +25,7 @@ func (_m *PeerScore) PeerScoreExposer() (p2p.PeerScoreExposer, bool) { } } - if rf, ok := ret.Get(1).(func() bool); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(bool) - } - - return r0, r1 -} - -// SetPeerScoreExposer provides a mock function with given fields: e -func (_m *PeerScore) SetPeerScoreExposer(e p2p.PeerScoreExposer) { - _m.Called(e) + return r0 } type mockConstructorTestingTNewPeerScore interface { diff --git a/network/p2p/mock/pub_sub_adapter.go b/network/p2p/mock/pub_sub_adapter.go index ad0d7e8f9c6..ec05980dea1 100644 --- a/network/p2p/mock/pub_sub_adapter.go +++ b/network/p2p/mock/pub_sub_adapter.go @@ -97,6 +97,22 @@ func (_m *PubSubAdapter) ListPeers(topic string) []peer.ID { return r0 } +// PeerScoreExposer provides a mock function with given fields: +func (_m *PubSubAdapter) PeerScoreExposer() p2p.PeerScoreExposer { + ret := _m.Called() + + var r0 p2p.PeerScoreExposer + if rf, ok := ret.Get(0).(func() p2p.PeerScoreExposer); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(p2p.PeerScoreExposer) + } + } + + return r0 +} + // Ready provides a mock function with given fields: func (_m *PubSubAdapter) Ready() <-chan struct{} { ret := _m.Called() diff --git a/network/p2p/mock/score_option_builder.go b/network/p2p/mock/score_option_builder.go index eabe096b50a..d0f437bfc12 100644 --- a/network/p2p/mock/score_option_builder.go +++ b/network/p2p/mock/score_option_builder.go @@ -14,15 +14,43 @@ type ScoreOptionBuilder struct { } // BuildFlowPubSubScoreOption provides a mock function with given fields: -func (_m *ScoreOptionBuilder) BuildFlowPubSubScoreOption() pubsub.Option { +func (_m *ScoreOptionBuilder) BuildFlowPubSubScoreOption() (*pubsub.PeerScoreParams, *pubsub.PeerScoreThresholds) { ret := _m.Called() - var r0 pubsub.Option - if rf, ok := ret.Get(0).(func() pubsub.Option); ok { + var r0 *pubsub.PeerScoreParams + var r1 *pubsub.PeerScoreThresholds + if rf, ok := ret.Get(0).(func() (*pubsub.PeerScoreParams, *pubsub.PeerScoreThresholds)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *pubsub.PeerScoreParams); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(pubsub.Option) + r0 = ret.Get(0).(*pubsub.PeerScoreParams) + } + } + + if rf, ok := ret.Get(1).(func() *pubsub.PeerScoreThresholds); ok { + r1 = rf() + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*pubsub.PeerScoreThresholds) + } + } + + return r0, r1 +} + +// TopicScoreParams provides a mock function with given fields: _a0 +func (_m *ScoreOptionBuilder) TopicScoreParams(_a0 *pubsub.Topic) *pubsub.TopicScoreParams { + ret := _m.Called(_a0) + + var r0 *pubsub.TopicScoreParams + if rf, ok := ret.Get(0).(func(*pubsub.Topic) *pubsub.TopicScoreParams); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*pubsub.TopicScoreParams) } } diff --git a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go index a8efac21944..89b1351691f 100644 --- a/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go +++ b/network/p2p/p2pbuilder/gossipsub/gossipSubBuilder.go @@ -138,7 +138,7 @@ func (g *Builder) SetRoutingSystem(routingSystem routing.Routing) { // Note: calling this function will override the default topic score params for the topic. Don't call this function // unless you know what you are doing. func (g *Builder) SetTopicScoreParams(topic channels.Topic, topicScoreParams *pubsub.TopicScoreParams) { - g.scoreOptionConfig.SetTopicScoreParams(topic, topicScoreParams) + g.scoreOptionConfig.OverrideTopicScoreParams(topic, topicScoreParams) } // SetAppSpecificScoreParams sets the app specific score params of the builder. @@ -266,14 +266,14 @@ func defaultInspectorSuite() p2p.GossipSubRpcInspectorSuiteFactoryFunc { // - p2p.PeerScoreTracer: a peer score tracer for the GossipSub pubsub system (if enabled, otherwise nil). // - error: if an error occurs during the creation of the GossipSub pubsub system, it is returned. Otherwise, nil is returned. // Note that on happy path, the returned error is nil. Any error returned is unexpected and should be handled as irrecoverable. -func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p2p.PeerScoreTracer, error) { +func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, error) { gossipSubConfigs := g.gossipSubConfigFunc(&p2p.BasePubSubAdapterConfig{ MaxMessageSize: p2pnode.DefaultMaxPubSubMsgSize, }) gossipSubConfigs.WithMessageIdFunction(utils.MessageID) if g.routingSystem == nil { - return nil, nil, fmt.Errorf("could not create gossipsub: routing system is nil") + return nil, fmt.Errorf("could not create gossipsub: routing system is nil") } gossipSubConfigs.WithRoutingDiscovery(g.routingSystem) @@ -290,7 +290,7 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p g.networkType, g.idProvider) if err != nil { - return nil, nil, fmt.Errorf("could not create gossipsub inspector suite: %w", err) + return nil, fmt.Errorf("could not create gossipsub inspector suite: %w", err) } gossipSubConfigs.WithInspectorSuite(inspectorSuite) @@ -317,20 +317,20 @@ func (g *Builder) Build(ctx irrecoverable.SignalerContext) (p2p.PubSubAdapter, p } if g.h == nil { - return nil, nil, fmt.Errorf("could not create gossipsub: host is nil") + return nil, fmt.Errorf("could not create gossipsub: host is nil") } gossipSub, err := g.gossipSubFactory(ctx, g.logger, g.h, gossipSubConfigs, inspectorSuite) if err != nil { - return nil, nil, fmt.Errorf("could not create gossipsub: %w", err) + return nil, fmt.Errorf("could not create gossipsub: %w", err) } if scoreOpt != nil { err := scoreOpt.SetSubscriptionProvider(scoring.NewSubscriptionProvider(g.logger, gossipSub)) if err != nil { - return nil, nil, fmt.Errorf("could not set subscription provider: %w", err) + return nil, fmt.Errorf("could not set subscription provider: %w", err) } } - return gossipSub, scoreTracer, nil + return gossipSub, nil } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index cccd1962141..bf61b8b0054 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -341,13 +341,10 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { builder.gossipSubBuilder.SetRoutingSystem(routingSystem) // gossipsub is created here, because it needs to be created during the node startup. - gossipSub, scoreTracer, err := builder.gossipSubBuilder.Build(ctx) + gossipSub, err := builder.gossipSubBuilder.Build(ctx) if err != nil { ctx.Throw(fmt.Errorf("could not create gossipsub: %w", err)) } - if scoreTracer != nil { - node.SetPeerScoreExposer(scoreTracer) - } node.SetPubSub(gossipSub) gossipSub.Start(ctx) ready() diff --git a/network/p2p/p2pnode/gossipSubAdapter.go b/network/p2p/p2pnode/gossipSubAdapter.go index 5a14501d012..861093993cc 100644 --- a/network/p2p/p2pnode/gossipSubAdapter.go +++ b/network/p2p/p2pnode/gossipSubAdapter.go @@ -13,6 +13,7 @@ import ( "github.com/onflow/flow-go/module/component" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/utils" "github.com/onflow/flow-go/utils/logging" ) @@ -21,7 +22,15 @@ import ( type GossipSubAdapter struct { component.Component gossipSub *pubsub.PubSub - logger zerolog.Logger + // topicScoreParamFunc is a function that returns the topic score params for a given topic. + // If no function is provided the node will join the topic with no scoring params. As the + // node will not be able to score other peers in the topic, it may be vulnerable to routing + // attacks on the topic that may also affect the overall function of the node. + // It is not recommended to use this adapter without a topicScoreParamFunc. Also in mature + // implementations of the Flow network, the topicScoreParamFunc must be a required parameter. + topicScoreParamFunc func(topic *pubsub.Topic) *pubsub.TopicScoreParams + logger zerolog.Logger + peerScoreExposer p2p.PeerScoreExposer // clusterChangeConsumer is a callback that is invoked when the set of active clusters of collection nodes changes. // This callback is implemented by the rpc inspector suite of the GossipSubAdapter, and consumes the cluster changes // to update the rpc inspector state of the recent topics (i.e., channels). @@ -45,10 +54,17 @@ func NewGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host a := &GossipSubAdapter{ gossipSub: gossipSub, - logger: logger, + logger: logger.With().Str("component", "gossipsub-adapter").Logger(), clusterChangeConsumer: clusterChangeConsumer, } + topicScoreParamFunc, ok := gossipSubConfig.TopicScoreParamFunc() + if ok { + a.topicScoreParamFunc = topicScoreParamFunc + } else { + a.logger.Warn().Msg("no topic score param func provided") + } + if scoreTracer := gossipSubConfig.ScoreTracer(); scoreTracer != nil { builder.AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { ready() @@ -59,6 +75,7 @@ func NewGossipSubAdapter(ctx context.Context, logger zerolog.Logger, h host.Host <-scoreTracer.Done() a.logger.Debug().Str("component", "gossipsub_score_tracer").Msg("score tracer stopped") }) + a.peerScoreExposer = scoreTracer } if tracer := gossipSubConfig.PubSubTracer(); tracer != nil { @@ -130,6 +147,20 @@ func (g *GossipSubAdapter) Join(topic string) (p2p.Topic, error) { if err != nil { return nil, fmt.Errorf("could not join topic %s: %w", topic, err) } + + if g.topicScoreParamFunc != nil { + topicParams := g.topicScoreParamFunc(t) + err = t.SetScoreParams(topicParams) + if err != nil { + return nil, fmt.Errorf("could not set score params for topic %s: %w", topic, err) + } + topicParamsLogger := utils.TopicScoreParamsLogger(g.logger, topic, topicParams) + topicParamsLogger.Info().Msg("joined topic with score params set") + } else { + g.logger.Warn(). + Str("topic", topic). + Msg("joining topic without score params, this is not recommended from a security perspective") + } return NewGossipSubTopic(t), nil } @@ -141,6 +172,21 @@ func (g *GossipSubAdapter) ListPeers(topic string) []peer.ID { return g.gossipSub.ListPeers(topic) } +// PeerScoreExposer returns the peer score exposer for the gossipsub adapter. The exposer is a read-only interface +// for querying peer scores and returns the local scoring table of the underlying gossipsub node. +// The exposer is only available if the gossipsub adapter was configured with a score tracer. +// If the gossipsub adapter was not configured with a score tracer, the exposer will be nil. +// Args: +// +// None. +// +// Returns: +// +// The peer score exposer for the gossipsub adapter. +func (g *GossipSubAdapter) PeerScoreExposer() p2p.PeerScoreExposer { + return g.peerScoreExposer +} + // ActiveClustersChanged is called when the active clusters of collection nodes changes. // GossipSubAdapter implements this method to forward the call to the clusterChangeConsumer (rpc inspector), // which will then update the cluster state of the rpc inspector. diff --git a/network/p2p/p2pnode/gossipSubAdapterConfig.go b/network/p2p/p2pnode/gossipSubAdapterConfig.go index c5fafd20dbe..a2dbe59289f 100644 --- a/network/p2p/p2pnode/gossipSubAdapterConfig.go +++ b/network/p2p/p2pnode/gossipSubAdapterConfig.go @@ -16,6 +16,7 @@ import ( type GossipSubAdapterConfig struct { options []pubsub.Option scoreTracer p2p.PeerScoreTracer + scoreOption p2p.ScoreOptionBuilder pubsubTracer p2p.PubSubTracer inspectorSuite p2p.GossipSubInspectorSuite // currently only used to manage the lifecycle. } @@ -60,7 +61,9 @@ func (g *GossipSubAdapterConfig) WithSubscriptionFilter(filter p2p.SubscriptionF // Returns: // -None func (g *GossipSubAdapterConfig) WithScoreOption(option p2p.ScoreOptionBuilder) { - g.options = append(g.options, option.BuildFlowPubSubScoreOption()) + params, thresholds := option.BuildFlowPubSubScoreOption() + g.scoreOption = option + g.options = append(g.options, pubsub.WithPeerScore(params, thresholds)) } // WithMessageIdFunction adds a message ID function option to the config. @@ -177,6 +180,24 @@ func convertTopicScoreSnapshot(snapshot map[string]*pubsub.TopicScoreSnapshot) m return newSnapshot } +// TopicScoreParamFunc returns the topic score param function. This function is used to get the topic score params for a topic. +// The topic score params are used to set the topic parameters in GossipSub at the time of joining the topic. +// Args: +// - None +// +// Returns: +// - func(topic *pubsub.Topic) *pubsub.TopicScoreParams: the topic score param function if set, nil otherwise. +// - bool: true if the topic score param function is set, false otherwise. +func (g *GossipSubAdapterConfig) TopicScoreParamFunc() (func(topic *pubsub.Topic) *pubsub.TopicScoreParams, bool) { + if g.scoreOption != nil { + return func(topic *pubsub.Topic) *pubsub.TopicScoreParams { + return g.scoreOption.TopicScoreParams(topic) + }, true + } + + return nil, false +} + // Build returns the libp2p pubsub options. // Args: // - None diff --git a/network/p2p/p2pnode/libp2pNode.go b/network/p2p/p2pnode/libp2pNode.go index 168849d1761..38746521430 100644 --- a/network/p2p/p2pnode/libp2pNode.go +++ b/network/p2p/p2pnode/libp2pNode.go @@ -54,16 +54,15 @@ var _ p2p.LibP2PNode = (*Node)(nil) type Node struct { component.Component sync.RWMutex - uniMgr p2p.UnicastManager - host host.Host // reference to the libp2p host (https://godoc.org/github.com/libp2p/go-libp2p/core/host) - pubSub p2p.PubSubAdapter - logger zerolog.Logger // used to provide logging - topics map[channels.Topic]p2p.Topic // map of a topic string to an actual topic instance - subs map[channels.Topic]p2p.Subscription // map of a topic string to an actual subscription - routing routing.Routing - pCache p2p.ProtocolPeerCache - peerManager p2p.PeerManager - peerScoreExposer p2p.PeerScoreExposer + uniMgr p2p.UnicastManager + host host.Host // reference to the libp2p host (https://godoc.org/github.com/libp2p/go-libp2p/core/host) + pubSub p2p.PubSubAdapter + logger zerolog.Logger // used to provide logging + topics map[channels.Topic]p2p.Topic // map of a topic string to an actual topic instance + subs map[channels.Topic]p2p.Subscription // map of a topic string to an actual subscription + routing routing.Routing + pCache p2p.ProtocolPeerCache + peerManager p2p.PeerManager // Cache of temporary disallow-listed peers, when a peer is disallow-listed, the connections to that peer // are closed and further connections are not allowed till the peer is removed from the disallow-list. disallowListedCache p2p.DisallowListCache @@ -92,7 +91,7 @@ func NewNode( } } -var _ component.Component = (*Node)(nil) +var _ p2p.LibP2PNode = (*Node)(nil) func (n *Node) Start(ctx irrecoverable.SignalerContext) { n.Component.Start(ctx) @@ -429,25 +428,10 @@ func (n *Node) Routing() routing.Routing { return n.routing } -// SetPeerScoreExposer sets the node's peer score exposer implementation. -// SetPeerScoreExposer may be called at most once. It is an irrecoverable error to call this -// method if the node's peer score exposer has already been set. -func (n *Node) SetPeerScoreExposer(e p2p.PeerScoreExposer) { - if n.peerScoreExposer != nil { - n.logger.Fatal().Msg("peer score exposer already set") - } - - n.peerScoreExposer = e -} - // PeerScoreExposer returns the node's peer score exposer implementation. // If the node's peer score exposer has not been set, the second return value will be false. -func (n *Node) PeerScoreExposer() (p2p.PeerScoreExposer, bool) { - if n.peerScoreExposer == nil { - return nil, false - } - - return n.peerScoreExposer, true +func (n *Node) PeerScoreExposer() p2p.PeerScoreExposer { + return n.pubSub.PeerScoreExposer() } // SetPubSub sets the node's pubsub implementation. diff --git a/network/p2p/pubsub.go b/network/p2p/pubsub.go index 7ccc0aa6ca7..3e8e030ad8c 100644 --- a/network/p2p/pubsub.go +++ b/network/p2p/pubsub.go @@ -53,6 +53,16 @@ type PubSubAdapter interface { // For example, if current peer has subscribed to topics A and B, then ListPeers only return // subscribed peers for topics A and B, and querying for topic C will return an empty list. ListPeers(topic string) []peer.ID + + // PeerScoreExposer returns the peer score exposer for the gossipsub adapter. The exposer is a read-only interface + // for querying peer scores and returns the local scoring table of the underlying gossipsub node. + // The exposer is only available if the gossipsub adapter was configured with a score tracer. + // If the gossipsub adapter was not configured with a score tracer, the exposer will be nil. + // Args: + // None. + // Returns: + // The peer score exposer for the gossipsub adapter. + PeerScoreExposer() PeerScoreExposer } // PubSubAdapterConfig abstracts the configuration for the underlying pubsub implementation. @@ -119,7 +129,10 @@ type Topic interface { // ScoreOptionBuilder abstracts the configuration for the underlying pubsub score implementation. type ScoreOptionBuilder interface { // BuildFlowPubSubScoreOption builds the pubsub score options as pubsub.Option for the Flow network. - BuildFlowPubSubScoreOption() pubsub.Option + BuildFlowPubSubScoreOption() (*pubsub.PeerScoreParams, *pubsub.PeerScoreThresholds) + // TopicScoreParams returns the topic score params for the given topic. + // If the topic score params for the given topic does not exist, it will return the default topic score params. + TopicScoreParams(*pubsub.Topic) *pubsub.TopicScoreParams } // Subscription is the abstraction of the underlying pubsub subscription that is used by the Flow network. diff --git a/network/p2p/scoring/README.md b/network/p2p/scoring/README.md index a965d324052..622ecadd3fe 100644 --- a/network/p2p/scoring/README.md +++ b/network/p2p/scoring/README.md @@ -73,6 +73,26 @@ scoreOption := NewScoreOption(config) 5. `AcceptPXThreshold`: The threshold above which a peer's score will result in accepting PX information with a prune from that peer. PX stands for "Peer Exchange" in the context of libp2p's gossipsub protocol. When a peer sends a PRUNE control message to another peer, it can include a list of other peers as PX information. The purpose of this is to help the pruned peer find new peers to replace the ones that have been pruned from its mesh. When a node receives a PRUNE message containing PX information, it can decide whether to connect to the suggested peers based on its own criteria. In this package, the `DefaultAcceptPXThreshold` is used to determine if the originating peer's penalty score is good enough to accept the PX information. If the originating peer's penalty score exceeds the threshold, the node will consider connecting to the suggested peers. 6. `OpportunisticGraftThreshold`: The threshold below which the median peer score in the mesh may result in selecting more peers with a higher score for opportunistic grafting. +### Flow Specific Scoring Parameters and Thresholds +# GossipSub Scoring Parameters Explained +1. `DefaultAppSpecificScoreWeight = 1`: This is the default weight for application-specific scoring. It basically tells us how important the application-specific score is in comparison to other scores. +2. `MaxAppSpecificPenalty = -100` and `MinAppSpecificPenalty = -1`: These values define the range for application-specific penalties. A peer can have a maximum penalty of -100 and a minimum penalty of -1. +3. `MaxAppSpecificReward = 100`: This is the maximum reward a peer can earn for good behavior. +4. `DefaultStakedIdentityReward = MaxAppSpecificReward`: This reward is given to peers that contribute positively to the network (i.e., no misbehavior). It’s to encourage them and prioritize them in neighbor selection. +5. `DefaultUnknownIdentityPenalty = MaxAppSpecificPenalty`: This penalty is given to a peer if it's not in the identity list. It's to discourage anonymity. +6. `DefaultInvalidSubscriptionPenalty = MaxAppSpecificPenalty`: This penalty is for peers that subscribe to topics they are not authorized to subscribe to. +7. `DefaultGossipThreshold = -99`: If a peer's penalty goes below this threshold, the peer is ignored for gossip. It means no gossip is sent to or received from that peer. +8. `DefaultPublishThreshold = -99`: If a peer's penalty goes below this threshold, self-published messages will not be sent to this peer. +9. `DefaultGraylistThreshold = -99`: If a peer's penalty goes below this threshold, it is graylisted. This means all incoming messages from this peer are ignored. +10. `DefaultAcceptPXThreshold = 99`: This is a threshold for accepting peers. If a peer sends information and its score is above this threshold, the information is accepted. +11. `DefaultOpportunisticGraftThreshold = MaxAppSpecificReward + 1`: This value is used to selectively connect to new peers if the median score of the current peers drops below this threshold. +12. `defaultScoreCacheSize = 1000`: Sets the default size of the cache used to store the application-specific penalty of peers. +13. `defaultDecayInterval = 1 * time.Minute`: Sets the default interval at which the score of a peer will be decayed. +14. `defaultDecayToZero = 0.01`: This is a threshold below which a decayed score is reset to zero. It prevents the score from decaying to a very small value. +15. `defaultTopicTimeInMeshQuantum` is a parameter in the GossipSub scoring system that represents a fixed time interval used to count the amount of time a peer stays in a topic mesh. It is set to 1 hour, meaning that for each hour a peer remains in a topic mesh, its time-in-mesh counter increases by 1, contributing to its availability score. This is to reward peers that stay in the mesh for longer durations and discourage those that frequently join and leave. +16. `defaultTopicInvalidMessageDeliveriesWeight` is set to -1.0 and is used to penalize peers that send invalid messages by applying it to the square of the number of such messages. A message is considered invalid if it is not properly signed. A peer will be disconnected if it sends around 14 invalid messages within a gossipsub heartbeat interval. +17. `defaultTopicInvalidMessageDeliveriesDecay` is a decay factor set to 0.99. It is used to reduce the number of invalid message deliveries counted against a peer by 1% at each heartbeat interval. This prevents the peer from being disconnected if it stops sending invalid messages. The heartbeat interval in the gossipsub scoring system is set to 1 minute by default. + ## Customization The scoring mechanism can be easily customized to suit the needs of the Flow network. This includes changing the scoring parameters, thresholds, and the scoring function itself. You can customize the scoring parameters and thresholds by using the various setter methods provided in the `ScoreOptionConfig` object. Additionally, you can provide a custom app-specific scoring function through the `SetAppSpecificScoreFunction` method. diff --git a/network/p2p/scoring/score_option.go b/network/p2p/scoring/score_option.go index e10b678745c..c743b3efa33 100644 --- a/network/p2p/scoring/score_option.go +++ b/network/p2p/scoring/score_option.go @@ -12,6 +12,7 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" netcache "github.com/onflow/flow-go/network/p2p/cache" + "github.com/onflow/flow-go/network/p2p/utils" "github.com/onflow/flow-go/utils/logging" ) @@ -93,9 +94,9 @@ const ( defaultScoreCacheSize = 1000 // defaultDecayInterval is the default decay interval for the overall score of a peer at the GossipSub scoring - // system. It is the interval over which we decay the effect of past behavior. So that the effect of past behavior - // is not permanent. - defaultDecayInterval = 1 * time.Hour + // system. We set it to 1 minute so that it is not too short so that a malicious node can recover from a penalty + // and is not too long so that a well-behaved node can't recover from a penalty. + defaultDecayInterval = 1 * time.Minute // defaultDecayToZero is the default decay to zero for the overall score of a peer at the GossipSub scoring system. // It defines the maximum value below which a peer scoring counter is reset to zero. @@ -104,6 +105,43 @@ const ( // When a counter hits the DecayToZero threshold, it means that the peer did not exhibit the behavior // for a long time, and we can reset the counter. defaultDecayToZero = 0.01 + + // defaultTopicSkipAtomicValidation is the default value for the skip atomic validation flag for topics. + // We set it to true, which means gossipsub parameter validation will not fail if we leave some of the + // topic parameters at their default values, i.e., zero. This is because we are not setting all + // topic parameters at the current implementation. + defaultTopicSkipAtomicValidation = true + + // defaultTopicInvalidMessageDeliveriesWeight this value is applied to the square of the number of invalid message deliveries on a topic. + // It is used to penalize peers that send invalid messages. By an invalid message, we mean a message that is not signed by the + // publisher, or a message that is not signed by the peer that sent it. We set it to -1.0, which means that with around 14 invalid + // message deliveries within a gossipsub heartbeat interval, the peer will be disconnected. + // The supporting math is as follows: + // - each staked (i.e., authorized) peer is rewarded by the fixed reward of 100 (i.e., DefaultStakedIdentityReward). + // - x invalid message deliveries will result in a penalty of x^2 * DefaultTopicInvalidMessageDeliveriesWeight, i.e., -x^2. + // - the peer will be disconnected when its penalty reaches -100 (i.e., MaxAppSpecificPenalty). + // - so, the maximum number of invalid message deliveries that a peer can have before being disconnected is sqrt(200/DefaultTopicInvalidMessageDeliveriesWeight) ~ 14. + defaultTopicInvalidMessageDeliveriesWeight = -1.0 + + // defaultTopicInvalidMessageDeliveriesDecay decay factor used to decay the number of invalid message deliveries. + // The total number of invalid message deliveries is multiplied by this factor at each heartbeat interval to + // decay the number of invalid message deliveries, and prevent the peer from being disconnected if it stops + // sending invalid messages. We set it to 0.99, which means that the number of invalid message deliveries will + // decay by 1% at each heartbeat interval. + // The decay heartbeats are defined by the heartbeat interval of the gossipsub scoring system, which is 1 Minute (defaultDecayInterval). + defaultTopicInvalidMessageDeliveriesDecay = .99 + + // defaultTopicTimeInMeshQuantum is the default time in mesh quantum for the GossipSub scoring system. It is used to gauge + // a discrete time interval for the time in mesh counter. We set it to 1 hour, which means that every one complete hour a peer is + // in a topic mesh, the time in mesh counter will be incremented by 1 and is counted towards the availability score of the peer in that topic mesh. + // The reason of setting it to 1 hour is that we want to reward peers that are in a topic mesh for a long time, and we want to avoid rewarding peers that + // are churners, i.e., peers that join and leave a topic mesh frequently. + defaultTopicTimeInMesh = time.Hour + + // defaultTopicWeight is the default weight of a topic in the GossipSub scoring system. The overall score of a peer in a topic mesh is + // multiplied by the weight of the topic when calculating the overall score of the peer. + // We set it to 1.0, which means that the overall score of a peer in a topic mesh is not affected by the weight of the topic. + defaultTopicWeight = 1.0 ) // ScoreOption is a functional option for configuring the peer scoring system. @@ -160,10 +198,10 @@ func (c *ScoreOptionConfig) SetAppSpecificScoreFunction(appSpecificScoreFunction c.appScoreFunc = appSpecificScoreFunction } -// SetTopicScoreParams adds the topic penalty parameters to the peer penalty parameters. -// It is used to configure the topic penalty parameters for the pubsub system. -// If there is already a topic penalty parameter for the given topic, the last call will be used. -func (c *ScoreOptionConfig) SetTopicScoreParams(topic channels.Topic, topicScoreParams *pubsub.TopicScoreParams) { +// OverrideTopicScoreParams overrides the topic score parameters for the given topic. +// It is used to override the default topic score parameters for a specific topic. +// If the topic score parameters are not set, the default ones will be used. +func (c *ScoreOptionConfig) OverrideTopicScoreParams(topic channels.Topic, topicScoreParams *pubsub.TopicScoreParams) { c.topicParams = append(c.topicParams, func(topics map[string]*pubsub.TopicScoreParams) { topics[topic.String()] = topicScoreParams }) @@ -222,7 +260,6 @@ func NewScoreOption(cfg *ScoreOptionConfig) *ScoreOption { for _, topicParams := range cfg.topicParams { topicParams(s.peerScoreParams.Topics) } - return s } @@ -230,7 +267,7 @@ func (s *ScoreOption) SetSubscriptionProvider(provider *SubscriptionProvider) er return s.validator.RegisterSubscriptionProvider(provider) } -func (s *ScoreOption) BuildFlowPubSubScoreOption() pubsub.Option { +func (s *ScoreOption) BuildFlowPubSubScoreOption() (*pubsub.PeerScoreParams, *pubsub.PeerScoreThresholds) { s.preparePeerScoreThresholds() s.logger.Info(). @@ -239,12 +276,15 @@ func (s *ScoreOption) BuildFlowPubSubScoreOption() pubsub.Option { Float64("graylist_threshold", s.peerThresholdParams.GraylistThreshold). Float64("accept_px_threshold", s.peerThresholdParams.AcceptPXThreshold). Float64("opportunistic_graft_threshold", s.peerThresholdParams.OpportunisticGraftThreshold). - Msg("peer penalty thresholds configured") + Msg("pubsub score thresholds are set") - return pubsub.WithPeerScore( - s.peerScoreParams, - s.peerThresholdParams, - ) + for topic, topicParams := range s.peerScoreParams.Topics { + topicScoreParamLogger := utils.TopicScoreParamsLogger(s.logger, topic, topicParams) + topicScoreParamLogger.Info(). + Msg("pubsub score topic parameters are set for topic") + } + + return s.peerScoreParams, s.peerThresholdParams } func (s *ScoreOption) preparePeerScoreThresholds() { @@ -257,6 +297,22 @@ func (s *ScoreOption) preparePeerScoreThresholds() { } } +// TopicScoreParams returns the topic score parameters for the given topic. If the topic +// score parameters are not set, it returns the default topic score parameters. +// The custom topic parameters are set at the initialization of the score option. +// Args: +// - topic: the topic for which the score parameters are requested. +// Returns: +// - the topic score parameters for the given topic, or the default topic score parameters if +// the topic score parameters are not set. +func (s *ScoreOption) TopicScoreParams(topic *pubsub.Topic) *pubsub.TopicScoreParams { + params, exists := s.peerScoreParams.Topics[topic.String()] + if !exists { + return defaultTopicScoreParams() + } + return params +} + func defaultPeerScoreParams() *pubsub.PeerScoreParams { return &pubsub.PeerScoreParams{ Topics: make(map[string]*pubsub.TopicScoreParams), @@ -276,19 +332,13 @@ func defaultPeerScoreParams() *pubsub.PeerScoreParams { } } -func (s *ScoreOption) BuildGossipSubScoreOption() pubsub.Option { - s.preparePeerScoreThresholds() - - s.logger.Info(). - Float64("gossip_threshold", s.peerThresholdParams.GossipThreshold). - Float64("publish_threshold", s.peerThresholdParams.PublishThreshold). - Float64("graylist_threshold", s.peerThresholdParams.GraylistThreshold). - Float64("accept_px_threshold", s.peerThresholdParams.AcceptPXThreshold). - Float64("opportunistic_graft_threshold", s.peerThresholdParams.OpportunisticGraftThreshold). - Msg("peer penalty thresholds configured") - - return pubsub.WithPeerScore( - s.peerScoreParams, - s.peerThresholdParams, - ) +// defaultTopicScoreParams returns the default score params for topics. +func defaultTopicScoreParams() *pubsub.TopicScoreParams { + return &pubsub.TopicScoreParams{ + TopicWeight: defaultTopicWeight, + SkipAtomicValidation: defaultTopicSkipAtomicValidation, + InvalidMessageDeliveriesWeight: defaultTopicInvalidMessageDeliveriesWeight, + InvalidMessageDeliveriesDecay: defaultTopicInvalidMessageDeliveriesDecay, + TimeInMeshQuantum: defaultTopicTimeInMesh, + } } diff --git a/network/p2p/test/message.go b/network/p2p/test/message.go new file mode 100644 index 00000000000..cb2d762393d --- /dev/null +++ b/network/p2p/test/message.go @@ -0,0 +1,65 @@ +package p2ptest + +import ( + "testing" + + pb "github.com/libp2p/go-libp2p-pubsub/pb" + "github.com/libp2p/go-libp2p/core/peer" + + "github.com/onflow/flow-go/utils/unittest" +) + +// WithFrom is a test helper that returns a function that sets the from field of a pubsub message to the given peer id. +func WithFrom(from peer.ID) func(*pb.Message) { + return func(m *pb.Message) { + m.From = []byte(from) + } +} + +// WithTopic is a test helper that returns a function that sets the topic of a pubsub message to the given topic. +func WithTopic(topic string) func(*pb.Message) { + return func(m *pb.Message) { + m.Topic = &topic + } +} + +// WithoutSignature is a test helper that returns a function that sets the signature of a pubsub message to nil, effectively removing the signature. +func WithoutSignature() func(*pb.Message) { + return func(m *pb.Message) { + m.Signature = nil + } +} + +// WithoutSignerId is a test helper that returns a function that sets the from field of a pubsub message to nil, effectively removing the signer id. +func WithoutSignerId() func(*pb.Message) { + return func(m *pb.Message) { + m.From = nil + } +} + +// PubsubMessageFixture is a test helper that returns a random pubsub message with the given options applied. +// If no options are provided, the message will be random. +// Args: +// +// t: testing.T +// +// opt: variadic list of options to apply to the message +// Returns: +// *pb.Message: pubsub message +func PubsubMessageFixture(t *testing.T, opts ...func(*pb.Message)) *pb.Message { + topic := unittest.RandomStringFixture(t, 10) + + m := &pb.Message{ + Data: unittest.RandomByteSlice(t, 100), + Topic: &topic, + Signature: unittest.RandomByteSlice(t, 100), + From: unittest.RandomByteSlice(t, 100), + Seqno: unittest.RandomByteSlice(t, 100), + } + + for _, opt := range opts { + opt(m) + } + + return m +} diff --git a/network/p2p/tracer/gossipSubScoreTracer_test.go b/network/p2p/tracer/gossipSubScoreTracer_test.go index 269e2c1099f..a759cc2b46f 100644 --- a/network/p2p/tracer/gossipSubScoreTracer_test.go +++ b/network/p2p/tracer/gossipSubScoreTracer_test.go @@ -190,9 +190,7 @@ func TestGossipSubScoreTracer(t *testing.T) { // IP score, and an existing mesh score. assert.Eventually(t, func() bool { // we expect the tracerNode to have the consensusNodes and accessNodes with the correct app scores. - exposer, ok := tracerNode.PeerScoreExposer() - require.True(t, ok) - + exposer := tracerNode.PeerScoreExposer() score, ok := exposer.GetAppScore(consensusNode.Host().ID()) if !ok || score != consensusScore { return false diff --git a/network/p2p/utils/logger.go b/network/p2p/utils/logger.go new file mode 100644 index 00000000000..b535d567ccd --- /dev/null +++ b/network/p2p/utils/logger.go @@ -0,0 +1,33 @@ +package utils + +import ( + pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/rs/zerolog" +) + +// TopicScoreParamsLogger is a helper function that returns a logger with the topic score params added as fields. +// Args: +// logger: zerolog.Logger - logger to add fields to +// topicName: string - name of the topic +// params: pubsub.TopicScoreParams - topic score params +func TopicScoreParamsLogger(logger zerolog.Logger, topicName string, topicParams *pubsub.TopicScoreParams) zerolog.Logger { + return logger.With().Str("topic", topicName). + Bool("atomic_validation", topicParams.SkipAtomicValidation). + Float64("topic_weight", topicParams.TopicWeight). + Float64("time_in_mesh_weight", topicParams.TimeInMeshWeight). + Dur("time_in_mesh_quantum", topicParams.TimeInMeshQuantum). + Float64("time_in_mesh_cap", topicParams.TimeInMeshCap). + Float64("first_message_deliveries_weight", topicParams.FirstMessageDeliveriesWeight). + Float64("first_message_deliveries_decay", topicParams.FirstMessageDeliveriesDecay). + Float64("first_message_deliveries_cap", topicParams.FirstMessageDeliveriesCap). + Float64("mesh_message_deliveries_weight", topicParams.MeshMessageDeliveriesWeight). + Float64("mesh_message_deliveries_decay", topicParams.MeshMessageDeliveriesDecay). + Float64("mesh_message_deliveries_cap", topicParams.MeshMessageDeliveriesCap). + Float64("mesh_message_deliveries_threshold", topicParams.MeshMessageDeliveriesThreshold). + Dur("mesh_message_deliveries_window", topicParams.MeshMessageDeliveriesWindow). + Dur("mesh_message_deliveries_activation", topicParams.MeshMessageDeliveriesActivation). + Float64("mesh_failure_penalty_weight", topicParams.MeshFailurePenaltyWeight). + Float64("mesh_failure_penalty_decay", topicParams.MeshFailurePenaltyDecay). + Float64("invalid_message_deliveries_weight", topicParams.InvalidMessageDeliveriesWeight). + Float64("invalid_message_deliveries_decay", topicParams.InvalidMessageDeliveriesDecay).Logger() +} diff --git a/utils/unittest/bytes.go b/utils/unittest/bytes.go new file mode 100644 index 00000000000..96238cc7ae0 --- /dev/null +++ b/utils/unittest/bytes.go @@ -0,0 +1,20 @@ +package unittest + +import ( + "crypto/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +// RandomByteSlice is a test helper that generates a cryptographically secure random byte slice of size n. +func RandomByteSlice(t *testing.T, n int) []byte { + require.Greater(t, n, 0, "size should be positive") + + byteSlice := make([]byte, n) + n, err := rand.Read(byteSlice) + require.NoErrorf(t, err, "failed to generate random byte slice of size %d", n) + require.Equalf(t, n, len(byteSlice), "failed to generate random byte slice of size %d", n) + + return byteSlice +} diff --git a/utils/unittest/strings.go b/utils/unittest/strings.go new file mode 100644 index 00000000000..9c7b39839af --- /dev/null +++ b/utils/unittest/strings.go @@ -0,0 +1,36 @@ +package unittest + +import ( + "crypto/rand" + "encoding/base64" + "testing" + + "github.com/stretchr/testify/require" +) + +// RandomStringFixture is a test helper that generates a cryptographically secure random string of size n. +func RandomStringFixture(t *testing.T, n int) string { + require.Greater(t, n, 0, "size should be positive") + + // The base64 encoding uses 64 different characters to represent data in + // strings, which makes it possible to represent 6 bits of data with each + // character (as 2^6 is 64). This means that every 3 bytes (24 bits) of + // input data will be represented by 4 characters (4 * 6 bits) in the + // base64 encoding. Consequently, base64 encoding increases the size of + // the data by approximately 1/3 compared to the original input data. + // + // 1. (n+3) / 4 - This calculates how many groups of 4 characters are needed + // in the base64 encoded output to represent at least 'n' characters. + // The +3 ensures rounding up, as integer division truncates the result. + // + // 2. ... * 3 - Each group of 4 base64 characters represents 3 bytes + // of input data. This multiplication calculates the number of bytes + // needed to produce the required length of the base64 string. + byteSlice := make([]byte, (n+3)/4*3) + n, err := rand.Read(byteSlice) + require.NoError(t, err) + require.Equal(t, n, len(byteSlice)) + + encodedString := base64.URLEncoding.EncodeToString(byteSlice) + return encodedString[:n] +} From 6c51ddf72e48b4faebd428484c880b01529fc722 Mon Sep 17 00:00:00 2001 From: Yahya Hassanzadeh Date: Mon, 3 Jul 2023 15:42:44 -0700 Subject: [PATCH 74/74] [Testing] Refactoring Network Test Fixtures for Enhanced Customizability and Maintenance (#4524) * performs refactorings * refactors p2p manager config * disables peer manager by default * lint fix * updates mocks * fixes tests * removes consumer off the network fixtures * fixes panic issue * fixes tests * cleans up redundant parameters * removes zerolong logger * lint fix * dissolves generate ids and middlewares * removes subscription manager * removes subscription manager * removes generate id middleware network * removes generate id and middleware * removes generate libp2p nodes func * fixes tests * sets connection gater and peer manager default * fixes spork tests * fixes tests * fixes tests * fixes tests * fixes tests * fixes tests * fixes tests * fixes lint * removes json file * updates test helpers * updates documentation * removes commented code * adds zero jitter and zero backoff * makes jitter zero * renames libp2p node fixture * fixes insecure tests * lint fix * wip * lint fix * lint fix * lint fix * fixes nil pointer exception * fixes insecure package tests * adds a todo for enabling pruning in the public network * removes a commented line * Update network/internal/testutils/testUtil.go Co-authored-by: Misha * extends a todo * fixes nil panic --------- Co-authored-by: Misha --- .../node_builder/access_node_builder.go | 8 +- cmd/observer/node_builder/observer_builder.go | 1 + cmd/scaffold.go | 2 + follower/follower_builder.go | 1 + insecure/cmd/corrupted_builder.go | 2 + insecure/corruptlibp2p/spam_test.go | 7 +- .../rpc_inspector/metrics_inspector_test.go | 7 +- .../validation_inspector_test.go | 341 +++++++++++++-- network/alsp/manager/manager_test.go | 48 +-- network/internal/p2pfixtures/fixtures.go | 4 +- network/internal/testutils/testUtil.go | 403 ++++-------------- network/mocknetwork/connector.go | 6 +- network/mocknetwork/connector_factory.go | 56 +++ network/p2p/builder.go | 1 - network/p2p/connection/connManager_test.go | 6 +- .../p2p/connection/connection_gater_test.go | 25 +- network/p2p/connection/connector.go | 45 +- network/p2p/connection/connector_factory.go | 6 +- network/p2p/connection/peerManager.go | 4 +- .../peerManager_integration_test.go | 24 +- network/p2p/connection/peerManager_test.go | 42 +- network/p2p/connector.go | 22 +- network/p2p/dht/dht_test.go | 9 +- network/p2p/mock/connector.go | 6 +- network/p2p/mock/connector_factory.go | 56 +++ network/p2p/mock/node_builder.go | 16 - network/p2p/mock/peer_updater.go | 36 ++ network/p2p/p2pbuilder/config/config.go | 11 + network/p2p/p2pbuilder/libp2pNodeBuilder.go | 32 +- network/p2p/p2pnode/disallow_listing_test.go | 10 +- network/p2p/p2pnode/libp2pNode_test.go | 20 +- network/p2p/p2pnode/libp2pStream_test.go | 47 +- network/p2p/test/fixtures.go | 99 ++++- network/p2p/test/sporking_test.go | 32 +- network/p2p/unicast/manager.go | 4 +- network/test/blob_service_test.go | 34 +- network/test/echoengine_test.go | 18 +- network/test/epochtransition_test.go | 11 +- network/test/meshengine_test.go | 13 +- network/test/middleware_test.go | 81 ++-- network/test/unicast_authorization_test.go | 8 +- .../unittest}/updatable_provider.go | 2 +- 42 files changed, 911 insertions(+), 695 deletions(-) create mode 100644 network/mocknetwork/connector_factory.go create mode 100644 network/p2p/mock/connector_factory.go create mode 100644 network/p2p/mock/peer_updater.go rename {network/internal/testutils => utils/unittest}/updatable_provider.go (98%) diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index 84aff969161..bf7a52047b4 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -1211,6 +1211,13 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, + &p2pconfig.PeerManagerConfig{ + // TODO: eventually, we need pruning enabled even on public network. However, it needs a modified version of + // the peer manager that also operate on the public identities. + ConnectionPruning: connection.PruningDisabled, + UpdateInterval: builder.FlowConfig.NetworkConfig.PeerUpdateInterval, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + }, &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), @@ -1233,7 +1240,6 @@ func (builder *FlowAccessNodeBuilder) initPublicLibp2pNode(networkKey crypto.Pri ) }). // disable connection pruning for the access node which supports the observer - SetPeerManagerOptions(connection.PruningDisabled, builder.FlowConfig.NetworkConfig.PeerUpdateInterval). SetStreamCreationRetryInterval(builder.FlowConfig.NetworkConfig.UnicastCreateStreamRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(builder.FlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval). diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index c0a6d62b2b4..be518249714 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -722,6 +722,7 @@ func (builder *ObserverServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, + p2pconfig.PeerManagerDisableConfig(), // disable peer manager for observer node. &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), diff --git a/cmd/scaffold.go b/cmd/scaffold.go index bacce0e22ab..32114adb25e 100644 --- a/cmd/scaffold.go +++ b/cmd/scaffold.go @@ -50,6 +50,7 @@ import ( "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/cache" "github.com/onflow/flow-go/network/p2p/conduit" + "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dns" "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pbuilder" @@ -335,6 +336,7 @@ func (fnb *FlowNodeBuilder) EnqueueNetworkInit() { peerManagerCfg := &p2pconfig.PeerManagerConfig{ ConnectionPruning: fnb.FlowConfig.NetworkConfig.NetworkConnectionPruning, UpdateInterval: fnb.FlowConfig.NetworkConfig.PeerUpdateInterval, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), } fnb.Component(LibP2PNodeComponent, func(node *NodeConfig) (module.ReadyDoneAware, error) { diff --git a/follower/follower_builder.go b/follower/follower_builder.go index 1650fa15799..36486907d1c 100644 --- a/follower/follower_builder.go +++ b/follower/follower_builder.go @@ -624,6 +624,7 @@ func (builder *FollowerServiceBuilder) initPublicLibp2pNode(networkKey crypto.Pr builder.IdentityProvider, &builder.FlowConfig.NetworkConfig.ResourceManagerConfig, &builder.FlowConfig.NetworkConfig.GossipSubConfig.GossipSubRPCInspectorsConfig, + p2pconfig.PeerManagerDisableConfig(), // disable peer manager for follower &p2p.DisallowListCacheConfig{ MaxSize: builder.FlowConfig.NetworkConfig.DisallowListNotificationCacheSize, Metrics: metrics.DisallowListCacheMetricsFactory(builder.HeroCacheMetricsFactory(), network.PublicNetwork), diff --git a/insecure/cmd/corrupted_builder.go b/insecure/cmd/corrupted_builder.go index bd85b83768b..34de857fda5 100644 --- a/insecure/cmd/corrupted_builder.go +++ b/insecure/cmd/corrupted_builder.go @@ -14,6 +14,7 @@ import ( "github.com/onflow/flow-go/module/metrics" "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/connection" p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" "github.com/onflow/flow-go/utils/logging" @@ -85,6 +86,7 @@ func (cnb *CorruptedNodeBuilder) enqueueNetworkingLayer() { peerManagerCfg := &p2pconfig.PeerManagerConfig{ ConnectionPruning: cnb.FlowConfig.NetworkConfig.NetworkConnectionPruning, UpdateInterval: cnb.FlowConfig.NetworkConfig.PeerUpdateInterval, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), } // create default libp2p factory if corrupt node should enable the topic validator diff --git a/insecure/corruptlibp2p/spam_test.go b/insecure/corruptlibp2p/spam_test.go index cd759fd52e9..06f6183c03e 100644 --- a/insecure/corruptlibp2p/spam_test.go +++ b/insecure/corruptlibp2p/spam_test.go @@ -19,7 +19,6 @@ import ( "github.com/onflow/flow-go/insecure/corruptlibp2p" "github.com/onflow/flow-go/insecure/internal" "github.com/onflow/flow-go/module/irrecoverable" - mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/p2p" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" @@ -32,8 +31,8 @@ func TestSpam_IHave(t *testing.T) { const messagesToSpam = 3 sporkId := unittest.IdentifierFixture() role := flow.RoleConsensus - idProvider := mockmodule.NewIdentityProvider(t) - gsrSpammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkId, role, nil) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) + gsrSpammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkId, role, idProvider) allSpamIHavesReceived := sync.WaitGroup{} allSpamIHavesReceived.Add(messagesToSpam) @@ -57,7 +56,7 @@ func TestSpam_IHave(t *testing.T) { return nil })), ) - idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&victimIdentity, &gsrSpammer.SpammerId}) // starts nodes ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) diff --git a/insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go b/insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go index 38078dd6993..c62cfba2f8b 100644 --- a/insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go +++ b/insecure/integration/functional/test/gossipsub/rpc_inspector/metrics_inspector_test.go @@ -15,7 +15,6 @@ import ( "github.com/onflow/flow-go/insecure/internal" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/irrecoverable" - mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/inspector" @@ -29,7 +28,8 @@ func TestMetricsInspector_ObserveRPC(t *testing.T) { t.Parallel() role := flow.RoleConsensus sporkID := unittest.IdentifierFixture() - spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, nil) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) @@ -57,7 +57,6 @@ func TestMetricsInspector_ObserveRPC(t *testing.T) { }) metricsInspector := inspector.NewControlMsgMetricsInspector(unittest.Logger(), mockMetricsObserver, 2) corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(metricsInspector) - idProvider := mockmodule.NewIdentityProvider(t) victimNode, victimIdentity := p2ptest.NodeFixture( t, sporkID, @@ -67,7 +66,7 @@ func TestMetricsInspector_ObserveRPC(t *testing.T) { internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), ) - idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&victimIdentity, &spammer.SpammerId}) metricsInspector.Start(signalerCtx) nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) diff --git a/insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go b/insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go index 73ef79e86e9..5917ceee31e 100644 --- a/insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go +++ b/insecure/integration/functional/test/gossipsub/rpc_inspector/validation_inspector_test.go @@ -68,7 +68,36 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { }) logger := zerolog.New(os.Stdout).Hook(hook) - signalerCtx, cancelFunc, spammer, victimNode, _, distributor, validationInspector, _ := setupTest(t, logger, role, sporkID, &inspectorConfig) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + validationInspector, err := validation.NewControlMsgValidationInspector( + logger, + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() messageCount := 5 controlMessageCount := int64(2) @@ -80,7 +109,7 @@ func TestValidationInspector_SafetyThreshold(t *testing.T) { nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages ctlMsgs := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(messageCount, channels.PushBlocks.String()), @@ -140,13 +169,43 @@ func TestValidationInspector_HardThreshold_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, _ := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(2, inspectDisseminatedNotif)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(2, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() validationInspector.Start(signalerCtx) nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages graftCtlMsgs := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(messageCount, channels.PushBlocks.String())) @@ -206,13 +265,43 @@ func TestValidationInspector_HardThresholdIHave_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, _ := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(1, inspectDisseminatedNotif)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(1, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() validationInspector.Start(signalerCtx) nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // add an unknown topic to each of our ihave control messages, this will ensure // that whatever random sample of topic ids that are inspected cause validation @@ -271,13 +360,43 @@ func TestValidationInspector_RateLimitedPeer_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, _ := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(4, inspectDisseminatedNotif)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(4, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() validationInspector.Start(signalerCtx) nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // the first time we spam this message it will be processed completely so we need to ensure // all topics are valid and no duplicates exists. @@ -372,7 +491,37 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, _ := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() // create unknown topic unknownTopic := channels.Topic(fmt.Sprintf("%s/%s", corruptlibp2p.GossipSubTopicIdFixture(), sporkID)) @@ -385,7 +534,7 @@ func TestValidationInspector_InvalidTopicId_Detection(t *testing.T) { nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages graftCtlMsgsWithUnknownTopic := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(int(messageCount), unknownTopic.String())) @@ -475,7 +624,37 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, _ := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Maybe() // a topics spork ID is considered invalid if it does not match the current spork ID duplicateTopic := channels.Topic(fmt.Sprintf("%s/%s", channels.PushBlocks, sporkID)) @@ -484,7 +663,7 @@ func TestValidationInspector_DuplicateTopicId_Detection(t *testing.T) { nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages graftCtlMsgsDuplicateTopic := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(int(messageCount), duplicateTopic.String())) @@ -552,8 +731,36 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, idProvider := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) - idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Twice() + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Times(3) // setup cluster prefixed topic with an invalid cluster ID unknownClusterID := channels.Topic(channels.SyncCluster("unknown-cluster-ID")) @@ -564,7 +771,7 @@ func TestValidationInspector_UnknownClusterId_Detection(t *testing.T) { nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages graftCtlMsgsDuplicateTopic := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(int(messageCount), unknownClusterID.String())) @@ -621,8 +828,36 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, idProvider := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) - idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Times(int(controlMessageCount)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Times(int(controlMessageCount + 1)) // we deliberately avoid setting the cluster IDs so that we eventually receive errors after we have exceeded the allowed cluster // prefixed hard threshold @@ -630,7 +865,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Graft_Detection(t *testing.T nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // generate multiple control messages with GRAFT's for randomly generated // cluster prefixed channels, this ensures we do not encounter duplicate topic ID errors ctlMsgs := spammer.GenerateCtlMessages(int(controlMessageCount), @@ -685,8 +920,36 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, idProvider := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) - idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Times(int(controlMessageCount)) + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(&spammer.SpammerId, true).Times(int(controlMessageCount + 1)) // we deliberately avoid setting the cluster IDs so that we eventually receive errors after we have exceeded the allowed cluster // prefixed hard threshold @@ -694,7 +957,7 @@ func TestValidationInspector_ActiveClusterIdsNotSet_Prune_Detection(t *testing.T nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // generate multiple control messages with GRAFT's for randomly generated // cluster prefixed channels, this ensures we do not encounter duplicate topic ID errors ctlMsgs := spammer.GenerateCtlMessages(int(controlMessageCount), @@ -759,8 +1022,36 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { } } - signalerCtx, cancelFunc, spammer, victimNode, _, _, validationInspector, idProvider := setupTest(t, unittest.Logger(), role, sporkID, &inspectorConfig, withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)) - idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(nil, false).Twice() + idProvider := mock.NewIdentityProvider(t) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, role, idProvider) + ctx, cancel := context.WithCancel(context.Background()) + signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) + + distributor := mockp2p.NewGossipSubInspectorNotificationDistributor(t) + mockDistributorReadyDoneAware(distributor) + withExpectedNotificationDissemination(expectedNumOfTotalNotif, inspectDisseminatedNotif)(distributor, spammer) + validationInspector, err := validation.NewControlMsgValidationInspector( + unittest.Logger(), + sporkID, + &inspectorConfig, + distributor, + metrics.NewNoopCollector(), + metrics.NewNoopCollector(), + idProvider, + metrics.NewNoopCollector()) + require.NoError(t, err) + corruptInspectorFunc := corruptlibp2p.CorruptInspectorFunc(validationInspector) + victimNode, victimIdentity := p2ptest.NodeFixture( + t, + sporkID, + t.Name(), + idProvider, + p2ptest.WithRole(role), + internal.WithCorruptGossipSub(corruptlibp2p.CorruptGossipSubFactory(), + corruptlibp2p.CorruptGossipSubConfigFactoryWithInspector(corruptInspectorFunc)), + ) + idProvider.On("ByPeerID", victimNode.Host().ID()).Return(&victimIdentity, true).Maybe() + idProvider.On("ByPeerID", spammer.SpammerNode.Host().ID()).Return(nil, false).Times(3) // setup cluster prefixed topic with an invalid cluster ID clusterID := flow.ChainID("known-cluster-id") @@ -772,7 +1063,7 @@ func TestValidationInspector_UnstakedNode_Detection(t *testing.T) { nodes := []p2p.LibP2PNode{victimNode, spammer.SpammerNode} startNodesAndEnsureConnected(t, signalerCtx, nodes, sporkID) spammer.Start(t) - defer stopNodesAndInspector(t, cancelFunc, nodes, validationInspector) + defer stopNodesAndInspector(t, cancel, nodes, validationInspector) // prepare to spam - generate control messages graftCtlMsgsDuplicateTopic := spammer.GenerateCtlMessages(int(controlMessageCount), corruptlibp2p.WithGraft(int(messageCount), clusterIDTopic.String())) @@ -844,7 +1135,7 @@ func TestGossipSubSpamMitigationIntegration(t *testing.T) { t.Parallel() idProvider := mock.NewIdentityProvider(t) sporkID := unittest.IdentifierFixture() - spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, flow.RoleConsensus, nil) + spammer := corruptlibp2p.NewGossipSubRouterSpammer(t, sporkID, flow.RoleConsensus, idProvider) ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) diff --git a/network/alsp/manager/manager_test.go b/network/alsp/manager/manager_test.go index dbe5207e431..03f012bb206 100644 --- a/network/alsp/manager/manager_test.go +++ b/network/alsp/manager/manager_test.go @@ -53,16 +53,10 @@ func TestNetworkPassesReportedMisbehavior(t *testing.T) { misbehaviorReportManger.On("Ready").Return(readyDoneChan).Once() misbehaviorReportManger.On("Done").Return(readyDoneChan).Once() + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(t, 1) + mws, _ := testutils.MiddlewareFixtures(t, ids, nodes, testutils.MiddlewareConfigFixture(t)) - ids, nodes, mws, _, _ := testutils.GenerateIDsAndMiddlewares( - t, - 1, - unittest.Logger(), - unittest.NetworkCodec(), - unittest.NetworkSlashingViolationsConsumer(unittest.Logger(), metrics.NewNoopCollector())) - sms := testutils.GenerateSubscriptionManagers(t, mws) - - networkCfg := testutils.NetworkConfigFixture(t, unittest.Logger(), *ids[0], ids, mws[0], sms[0]) + networkCfg := testutils.NetworkConfigFixture(t, *ids[0], ids, mws[0]) net, err := p2p.NewNetwork(networkCfg, p2p.WithAlspManager(misbehaviorReportManger)) require.NoError(t, err) @@ -116,15 +110,9 @@ func TestHandleReportedMisbehavior_Cache_Integration(t *testing.T) { return cache }), } - - ids, nodes, mws, _, _ := testutils.GenerateIDsAndMiddlewares( - t, - 1, - unittest.Logger(), - unittest.NetworkCodec(), - unittest.NetworkSlashingViolationsConsumer(unittest.Logger(), metrics.NewNoopCollector())) - sms := testutils.GenerateSubscriptionManagers(t, mws) - networkCfg := testutils.NetworkConfigFixture(t, unittest.Logger(), *ids[0], ids, mws[0], sms[0], p2p.WithAlspConfig(cfg)) + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(t, 1) + mws, _ := testutils.MiddlewareFixtures(t, ids, nodes, testutils.MiddlewareConfigFixture(t)) + networkCfg := testutils.NetworkConfigFixture(t, *ids[0], ids, mws[0], p2p.WithAlspConfig(cfg)) net, err := p2p.NewNetwork(networkCfg) require.NoError(t, err) @@ -216,14 +204,10 @@ func TestHandleReportedMisbehavior_And_DisallowListing_Integration(t *testing.T) }), } - ids, nodes, mws, _, _ := testutils.GenerateIDsAndMiddlewares( - t, - 3, - unittest.Logger(), - unittest.NetworkCodec(), - unittest.NetworkSlashingViolationsConsumer(unittest.Logger(), metrics.NewNoopCollector())) - sms := testutils.GenerateSubscriptionManagers(t, mws) - networkCfg := testutils.NetworkConfigFixture(t, unittest.Logger(), *ids[0], ids, mws[0], sms[0], p2p.WithAlspConfig(cfg)) + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(t, 3, + p2ptest.WithPeerManagerEnabled(p2ptest.PeerManagerConfigFixture(), nil)) + mws, _ := testutils.MiddlewareFixtures(t, ids, nodes, testutils.MiddlewareConfigFixture(t)) + networkCfg := testutils.NetworkConfigFixture(t, *ids[0], ids, mws[0], p2p.WithAlspConfig(cfg)) victimNetwork, err := p2p.NewNetwork(networkCfg) require.NoError(t, err) @@ -294,15 +278,9 @@ func TestMisbehaviorReportMetrics(t *testing.T) { alspMetrics := mockmodule.NewAlspMetrics(t) cfg.AlspMetrics = alspMetrics - ids, nodes, mws, _, _ := testutils.GenerateIDsAndMiddlewares( - t, - 1, - unittest.Logger(), - unittest.NetworkCodec(), - unittest.NetworkSlashingViolationsConsumer(unittest.Logger(), metrics.NewNoopCollector())) - sms := testutils.GenerateSubscriptionManagers(t, mws) - - networkCfg := testutils.NetworkConfigFixture(t, unittest.Logger(), *ids[0], ids, mws[0], sms[0], p2p.WithAlspConfig(cfg)) + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(t, 1) + mws, _ := testutils.MiddlewareFixtures(t, ids, nodes, testutils.MiddlewareConfigFixture(t)) + networkCfg := testutils.NetworkConfigFixture(t, *ids[0], ids, mws[0], p2p.WithAlspConfig(cfg)) net, err := p2p.NewNetwork(networkCfg) require.NoError(t, err) diff --git a/network/internal/p2pfixtures/fixtures.go b/network/internal/p2pfixtures/fixtures.go index de942fe83dd..40229337dfa 100644 --- a/network/internal/p2pfixtures/fixtures.go +++ b/network/internal/p2pfixtures/fixtures.go @@ -29,7 +29,6 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2putils" - "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/message" "github.com/onflow/flow-go/network/p2p" p2pdht "github.com/onflow/flow-go/network/p2p/dht" @@ -122,6 +121,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif idProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, + p2pconfig.PeerManagerDisableConfig(), &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), @@ -129,7 +129,7 @@ func CreateNode(t *testing.T, networkKey crypto.PrivateKey, sporkID flow.Identif SetRoutingSystem(func(c context.Context, h host.Host) (routing.Routing, error) { return p2pdht.NewDHT(c, h, protocols.FlowDHTProtocolID(sporkID), zerolog.Nop(), metrics.NewNoopCollector()) }). - SetResourceManager(testutils.NewResourceManager(t)). + SetResourceManager(&network.NullResourceManager{}). SetStreamCreationRetryInterval(unicast.DefaultRetryDelay). SetGossipSubTracer(meshTracer). SetGossipSubScoreTracerInterval(defaultFlowConfig.NetworkConfig.GossipSubConfig.ScoreTracerInterval) diff --git a/network/internal/testutils/testUtil.go b/network/internal/testutils/testUtil.go index 7aad86cda66..2457c7c6af7 100644 --- a/network/internal/testutils/testUtil.go +++ b/network/internal/testutils/testUtil.go @@ -1,7 +1,6 @@ package testutils import ( - "context" "fmt" "reflect" "runtime" @@ -10,17 +9,11 @@ import ( "testing" "time" - dht "github.com/libp2p/go-libp2p-kad-dht" - "github.com/libp2p/go-libp2p/core/host" - p2pNetwork "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" - pc "github.com/libp2p/go-libp2p/core/protocol" - "github.com/libp2p/go-libp2p/core/routing" "github.com/rs/zerolog" "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" - "github.com/onflow/flow-go/crypto" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/model/flow/filter" libp2pmessage "github.com/onflow/flow-go/model/libp2p/message" @@ -35,20 +28,15 @@ import ( netcache "github.com/onflow/flow-go/network/cache" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/codec/cbor" + "github.com/onflow/flow-go/network/mocknetwork" "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/conduit" "github.com/onflow/flow-go/network/p2p/connection" - p2pdht "github.com/onflow/flow-go/network/p2p/dht" "github.com/onflow/flow-go/network/p2p/middleware" - "github.com/onflow/flow-go/network/p2p/p2pbuilder" - p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" "github.com/onflow/flow-go/network/p2p/subscription" + p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/translator" - "github.com/onflow/flow-go/network/p2p/unicast" - "github.com/onflow/flow-go/network/p2p/unicast/protocols" - "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" - "github.com/onflow/flow-go/network/slashing" "github.com/onflow/flow-go/utils/unittest" ) @@ -126,121 +114,108 @@ func NewTagWatchingConnManager(log zerolog.Logger, metrics module.LibP2PConnecti }, nil } -// GenerateIDs is a test helper that generate flow identities with a valid port and libp2p nodes. -func GenerateIDs(t *testing.T, logger zerolog.Logger, n int, opts ...func(*optsConfig)) (flow.IdentityList, - []p2p.LibP2PNode, - []observable.Observable) { - libP2PNodes := make([]p2p.LibP2PNode, n) - tagObservables := make([]observable.Observable, n) - - identities := unittest.IdentityListFixture(n, unittest.WithAllRoles()) - idProvider := NewUpdatableIDProvider(identities) - o := &optsConfig{ - peerUpdateInterval: connection.DefaultPeerUpdateInterval, - unicastRateLimiterDistributor: ratelimit.NewUnicastRateLimiterDistributor(), - connectionGaterFactory: func() p2p.ConnectionGater { - return NewConnectionGater(idProvider, func(p peer.ID) error { - return nil - }) - }, - createStreamRetryInterval: unicast.DefaultRetryDelay, - } - for _, opt := range opts { - opt(o) - } - - for _, identity := range identities { - for _, idOpt := range o.idOpts { - idOpt(identity) - } - } - - // generates keys and address for the node - for i, identity := range identities { - // generate key - key, err := generateNetworkingKey(identity.NodeID) - require.NoError(t, err) - - var opts []nodeBuilderOption - - opts = append(opts, withDHT(o.dhtPrefix, o.dhtOpts...)) - opts = append(opts, withPeerManagerOptions(connection.PruningEnabled, o.peerUpdateInterval)) - opts = append(opts, withRateLimiterDistributor(o.unicastRateLimiterDistributor)) - opts = append(opts, withConnectionGater(o.connectionGaterFactory())) - opts = append(opts, withUnicastManagerOpts(o.createStreamRetryInterval)) +// LibP2PNodeForMiddlewareFixture is a test helper that generate flow identities with a valid port and libp2p nodes. +// Note that the LibP2PNode created by this fixture is meant to used with a middleware component. +// If you want to create a standalone LibP2PNode without network and middleware components, please use p2ptest.NodeFixture. +// Args: +// +// t: testing.T- the test object +// +// n: int - number of nodes to create +// opts: []p2ptest.NodeFixtureParameterOption - options to configure the nodes +// Returns: +// +// flow.IdentityList - list of identities created for the nodes, one for each node. +// +// []p2p.LibP2PNode - list of libp2p nodes created. +// []observable.Observable - list of observables created for each node. +func LibP2PNodeForMiddlewareFixture(t *testing.T, n int, opts ...p2ptest.NodeFixtureParameterOption) (flow.IdentityList, []p2p.LibP2PNode, []observable.Observable) { + + libP2PNodes := make([]p2p.LibP2PNode, 0) + identities := make(flow.IdentityList, 0) + tagObservables := make([]observable.Observable, 0) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) + defaultFlowConfig, err := config.DefaultConfig() + require.NoError(t, err) - libP2PNodes[i], tagObservables[i] = generateLibP2PNode(t, logger, key, idProvider, opts...) + opts = append(opts, p2ptest.WithUnicastHandlerFunc(nil)) - _, port, err := libP2PNodes[i].GetIPPort() + for i := 0; i < n; i++ { + // TODO: generating a tag watching connection manager can be moved to a separate function, as only a few tests need this. + // For the rest of tests, the node can run on the default connection manager without setting and option. + connManager, err := NewTagWatchingConnManager(unittest.Logger(), metrics.NewNoopCollector(), &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) require.NoError(t, err) - identities[i].Address = unittest.IPPort(port) - identities[i].NetworkPubKey = key.PublicKey() - } - + opts = append(opts, p2ptest.WithConnectionManager(connManager)) + node, nodeId := p2ptest.NodeFixture(t, + sporkID, + t.Name(), + idProvider, + opts...) + libP2PNodes = append(libP2PNodes, node) + identities = append(identities, &nodeId) + tagObservables = append(tagObservables, connManager) + } + idProvider.SetIdentities(identities) return identities, libP2PNodes, tagObservables } -// GenerateMiddlewares creates and initializes middleware instances for all the identities -func GenerateMiddlewares(t *testing.T, - logger zerolog.Logger, - identities flow.IdentityList, - libP2PNodes []p2p.LibP2PNode, - codec network.Codec, - consumer slashing.ViolationsConsumer, - opts ...func(*optsConfig)) ([]network.Middleware, []*UpdatableIDProvider) { +// MiddlewareConfigFixture is a test helper that generates a middleware config for testing. +// Args: +// - t: the test instance. +// Returns: +// - a middleware config. +func MiddlewareConfigFixture(t *testing.T) *middleware.Config { + return &middleware.Config{ + Logger: unittest.Logger(), + BitSwapMetrics: metrics.NewNoopCollector(), + RootBlockID: sporkID, + UnicastMessageTimeout: middleware.DefaultUnicastTimeout, + Codec: unittest.NetworkCodec(), + SlashingViolationsConsumer: mocknetwork.NewViolationsConsumer(t), + } +} + +// MiddlewareFixtures is a test helper that generates middlewares with the given identities and libp2p nodes. +// It also generates a list of UpdatableIDProvider that can be used to update the identities of the middlewares. +// The number of identities and libp2p nodes must be the same. +// Args: +// - identities: a list of flow identities that correspond to the libp2p nodes. +// - libP2PNodes: a list of libp2p nodes that correspond to the identities. +// - cfg: the middleware config. +// - opts: a list of middleware option functions. +// Returns: +// - a list of middlewares - one for each identity. +// - a list of UpdatableIDProvider - one for each identity. +func MiddlewareFixtures(t *testing.T, identities flow.IdentityList, libP2PNodes []p2p.LibP2PNode, cfg *middleware.Config, opts ...middleware.OptionFn) ([]network.Middleware, []*unittest.UpdatableIDProvider) { + require.Equal(t, len(identities), len(libP2PNodes)) + mws := make([]network.Middleware, len(identities)) - idProviders := make([]*UpdatableIDProvider, len(identities)) - bitswapmet := metrics.NewNoopCollector() - o := &optsConfig{ - peerUpdateInterval: connection.DefaultPeerUpdateInterval, - unicastRateLimiters: ratelimit.NoopRateLimiters(), - networkMetrics: metrics.NewNoopCollector(), - peerManagerFilters: []p2p.PeerFilter{}, - } + idProviders := make([]*unittest.UpdatableIDProvider, len(identities)) - for _, opt := range opts { - opt(o) - } + for i := 0; i < len(identities); i++ { + i := i + cfg.Libp2pNode = libP2PNodes[i] + cfg.FlowId = identities[i].NodeID + idProviders[i] = unittest.NewUpdatableIDProvider(identities) + cfg.IdTranslator = translator.NewIdentityProviderIDTranslator(idProviders[i]) - total := len(identities) - for i := 0; i < total; i++ { - // casts libP2PNode instance to a local variable to avoid closure - node := libP2PNodes[i] - nodeId := identities[i].NodeID - - idProviders[i] = NewUpdatableIDProvider(identities) - - // creating middleware of nodes - mws[i] = middleware.NewMiddleware(&middleware.Config{ - Logger: logger, - Libp2pNode: node, - FlowId: nodeId, - BitSwapMetrics: bitswapmet, - RootBlockID: sporkID, - UnicastMessageTimeout: middleware.DefaultUnicastTimeout, - IdTranslator: translator.NewIdentityProviderIDTranslator(idProviders[i]), - Codec: codec, - SlashingViolationsConsumer: consumer, - }, - middleware.WithUnicastRateLimiters(o.unicastRateLimiters), - middleware.WithPeerManagerFilters(o.peerManagerFilters)) + mws[i] = middleware.NewMiddleware(cfg, opts...) } return mws, idProviders } // NetworksFixture generates the network for the given middlewares func NetworksFixture(t *testing.T, - log zerolog.Logger, ids flow.IdentityList, - mws []network.Middleware, - sms []network.SubscriptionManager) []network.Network { + mws []network.Middleware) []network.Network { count := len(ids) nets := make([]network.Network, 0) for i := 0; i < count; i++ { - params := NetworkConfigFixture(t, log, *ids[i], ids, mws[i], sms[i]) + + params := NetworkConfigFixture(t, *ids[i], ids, mws[i]) net, err := p2p.NewNetwork(params) require.NoError(t, err) @@ -252,11 +227,10 @@ func NetworksFixture(t *testing.T, func NetworkConfigFixture( t *testing.T, - logger zerolog.Logger, myId flow.Identity, allIds flow.IdentityList, mw network.Middleware, - subMgr network.SubscriptionManager, opts ...p2p.NetworkConfigOption) *p2p.NetworkConfig { + opts ...p2p.NetworkConfigOption) *p2p.NetworkConfig { me := mock.NewLocal(t) me.On("NodeID").Return(myId.NodeID).Maybe() @@ -266,10 +240,14 @@ func NetworkConfigFixture( defaultFlowConfig, err := config.DefaultConfig() require.NoError(t, err) - receiveCache := netcache.NewHeroReceiveCache(defaultFlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, logger, metrics.NewNoopCollector()) + receiveCache := netcache.NewHeroReceiveCache( + defaultFlowConfig.NetworkConfig.NetworkReceivedMessageCacheSize, + unittest.Logger(), + metrics.NewNoopCollector()) + subMgr := subscription.NewChannelSubscriptionManager(mw) params := &p2p.NetworkConfig{ - Logger: logger, - Codec: cbor.NewCodec(), + Logger: unittest.Logger(), + Codec: unittest.NetworkCodec(), Me: me, MiddlewareFactory: func() (network.Middleware, error) { return mw, nil }, Topology: unittest.NetworkTopology(), @@ -295,100 +273,6 @@ func NetworkConfigFixture( return params } -// GenerateIDsAndMiddlewares returns nodeIDs, libp2pNodes, middlewares, and observables which can be subscirbed to in order to witness protect events from pubsub -func GenerateIDsAndMiddlewares(t *testing.T, - n int, - logger zerolog.Logger, - codec network.Codec, - consumer slashing.ViolationsConsumer, - opts ...func(*optsConfig)) (flow.IdentityList, []p2p.LibP2PNode, []network.Middleware, []observable.Observable, []*UpdatableIDProvider) { - - ids, libP2PNodes, protectObservables := GenerateIDs(t, logger, n, opts...) - mws, providers := GenerateMiddlewares(t, logger, ids, libP2PNodes, codec, consumer, opts...) - return ids, libP2PNodes, mws, protectObservables, providers -} - -type optsConfig struct { - idOpts []func(*flow.Identity) - dhtPrefix string - dhtOpts []dht.Option - unicastRateLimiters *ratelimit.RateLimiters - peerUpdateInterval time.Duration - networkMetrics module.NetworkMetrics - peerManagerFilters []p2p.PeerFilter - unicastRateLimiterDistributor p2p.UnicastRateLimiterDistributor - connectionGaterFactory func() p2p.ConnectionGater - createStreamRetryInterval time.Duration -} - -func WithCreateStreamRetryInterval(delay time.Duration) func(*optsConfig) { - return func(o *optsConfig) { - o.createStreamRetryInterval = delay - } -} - -func WithUnicastRateLimiterDistributor(distributor p2p.UnicastRateLimiterDistributor) func(*optsConfig) { - return func(o *optsConfig) { - o.unicastRateLimiterDistributor = distributor - } -} - -func WithIdentityOpts(idOpts ...func(*flow.Identity)) func(*optsConfig) { - return func(o *optsConfig) { - o.idOpts = idOpts - } -} - -func WithDHT(prefix string, dhtOpts ...dht.Option) func(*optsConfig) { - return func(o *optsConfig) { - o.dhtPrefix = prefix - o.dhtOpts = dhtOpts - } -} - -func WithPeerUpdateInterval(interval time.Duration) func(*optsConfig) { - return func(o *optsConfig) { - o.peerUpdateInterval = interval - } -} - -func WithPeerManagerFilters(filters ...p2p.PeerFilter) func(*optsConfig) { - return func(o *optsConfig) { - o.peerManagerFilters = filters - } -} - -func WithUnicastRateLimiters(limiters *ratelimit.RateLimiters) func(*optsConfig) { - return func(o *optsConfig) { - o.unicastRateLimiters = limiters - } -} - -func WithConnectionGaterFactory(connectionGaterFactory func() p2p.ConnectionGater) func(*optsConfig) { - return func(o *optsConfig) { - o.connectionGaterFactory = connectionGaterFactory - } -} - -func WithNetworkMetrics(m module.NetworkMetrics) func(*optsConfig) { - return func(o *optsConfig) { - o.networkMetrics = m - } -} - -func GenerateIDsMiddlewaresNetworks(t *testing.T, - n int, - log zerolog.Logger, - codec network.Codec, - consumer slashing.ViolationsConsumer, - opts ...func(*optsConfig)) (flow.IdentityList, []p2p.LibP2PNode, []network.Middleware, []network.Network, []observable.Observable) { - ids, libp2pNodes, mws, observables, _ := GenerateIDsAndMiddlewares(t, n, log, codec, consumer, opts...) - sms := GenerateSubscriptionManagers(t, mws) - networks := NetworksFixture(t, log, ids, mws, sms) - - return ids, libp2pNodes, mws, networks, observables -} - // GenerateEngines generates MeshEngines for the given networks func GenerateEngines(t *testing.T, nets []network.Network) []*MeshEngine { count := len(nets) @@ -455,81 +339,6 @@ func StopComponents[R module.ReadyDoneAware](t *testing.T, rda []R, duration tim unittest.RequireComponentsDoneBefore(t, duration, comps...) } -type nodeBuilderOption func(p2p.NodeBuilder) - -func withDHT(prefix string, dhtOpts ...dht.Option) nodeBuilderOption { - return func(nb p2p.NodeBuilder) { - nb.SetRoutingSystem(func(c context.Context, h host.Host) (routing.Routing, error) { - return p2pdht.NewDHT(c, h, pc.ID(protocols.FlowDHTProtocolIDPrefix+prefix), zerolog.Nop(), metrics.NewNoopCollector(), dhtOpts...) - }) - } -} - -func withPeerManagerOptions(connectionPruning bool, updateInterval time.Duration) nodeBuilderOption { - return func(nb p2p.NodeBuilder) { - nb.SetPeerManagerOptions(connectionPruning, updateInterval) - } -} - -func withRateLimiterDistributor(distributor p2p.UnicastRateLimiterDistributor) nodeBuilderOption { - return func(nb p2p.NodeBuilder) { - nb.SetRateLimiterDistributor(distributor) - } -} - -func withConnectionGater(connectionGater p2p.ConnectionGater) nodeBuilderOption { - return func(nb p2p.NodeBuilder) { - nb.SetConnectionGater(connectionGater) - } -} - -func withUnicastManagerOpts(delay time.Duration) nodeBuilderOption { - return func(nb p2p.NodeBuilder) { - nb.SetStreamCreationRetryInterval(delay) - } -} - -// TODO: this should be replaced by node fixture: https://github.com/onflow/flow-go/blob/master/network/p2p/test/fixtures.go -// generateLibP2PNode generates a `LibP2PNode` on localhost using a port assigned by the OS -func generateLibP2PNode(t *testing.T, logger zerolog.Logger, key crypto.PrivateKey, idProvider module.IdentityProvider, opts ...nodeBuilderOption) (p2p.LibP2PNode, observable.Observable) { - defaultFlowConfig, err := config.DefaultConfig() - require.NoError(t, err) - - // Inject some logic to be able to observe connections of this node - connManager, err := NewTagWatchingConnManager(logger, metrics.NewNoopCollector(), &defaultFlowConfig.NetworkConfig.ConnectionManagerConfig) - require.NoError(t, err) - - builder := p2pbuilder.NewNodeBuilder( - logger, - &p2pconfig.MetricsConfig{ - HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), - Metrics: metrics.NewNoopCollector(), - }, - network.PrivateNetwork, - unittest.DefaultAddress, - key, - sporkID, - idProvider, - &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, - &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, - &p2p.DisallowListCacheConfig{ - MaxSize: uint32(1000), - Metrics: metrics.NewNoopCollector(), - }). - SetConnectionManager(connManager). - SetResourceManager(NewResourceManager(t)). - SetStreamCreationRetryInterval(unicast.DefaultRetryDelay) - - for _, opt := range opts { - opt(builder) - } - - libP2PNode, err := builder.Build() - require.NoError(t, err) - - return libP2PNode, connManager -} - // OptionalSleep introduces a sleep to allow nodes to heartbeat and discover each other (only needed when using PubSub) func OptionalSleep(send ConduitSendWrapperFunc) { sendFuncName := runtime.FuncForPC(reflect.ValueOf(send).Pointer()).Name() @@ -538,24 +347,6 @@ func OptionalSleep(send ConduitSendWrapperFunc) { } } -// generateNetworkingKey generates a Flow ECDSA key using the given seed -func generateNetworkingKey(s flow.Identifier) (crypto.PrivateKey, error) { - seed := make([]byte, crypto.KeyGenSeedMinLen) - copy(seed, s[:]) - return crypto.GeneratePrivateKey(crypto.ECDSASecp256k1, seed) -} - -// GenerateSubscriptionManagers creates and returns a ChannelSubscriptionManager for each middleware object. -func GenerateSubscriptionManagers(t *testing.T, mws []network.Middleware) []network.SubscriptionManager { - require.NotEmpty(t, mws) - - sms := make([]network.SubscriptionManager, len(mws)) - for i, mw := range mws { - sms[i] = subscription.NewChannelSubscriptionManager(mw) - } - return sms -} - // NetworkPayloadFixture creates a blob of random bytes with the given size (in bytes) and returns it. // The primary goal of utilizing this helper function is to apply stress tests on the network layer by // sending large messages to transmit. @@ -593,20 +384,6 @@ func NetworkPayloadFixture(t *testing.T, size uint) []byte { return payload } -// NewResourceManager creates a new resource manager for testing with no limits. -func NewResourceManager(t *testing.T) p2pNetwork.ResourceManager { - return &p2pNetwork.NullResourceManager{} -} - -// NewConnectionGater creates a new connection gater for testing with given allow listing filter. -func NewConnectionGater(idProvider module.IdentityProvider, allowListFilter p2p.PeerFilter) p2p.ConnectionGater { - filters := []p2p.PeerFilter{allowListFilter} - return connection.NewConnGater(unittest.Logger(), - idProvider, - connection.WithOnInterceptPeerDialFilters(filters), - connection.WithOnInterceptSecuredFilters(filters)) -} - // IsRateLimitedPeerFilter returns a p2p.PeerFilter that will return an error if the peer is rate limited. func IsRateLimitedPeerFilter(rateLimiter p2p.RateLimiter) p2p.PeerFilter { return func(p peer.ID) error { diff --git a/network/mocknetwork/connector.go b/network/mocknetwork/connector.go index 7f6a50e317c..deedbd4f815 100644 --- a/network/mocknetwork/connector.go +++ b/network/mocknetwork/connector.go @@ -15,9 +15,9 @@ type Connector struct { mock.Mock } -// UpdatePeers provides a mock function with given fields: ctx, peerIDs -func (_m *Connector) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) { - _m.Called(ctx, peerIDs) +// Connect provides a mock function with given fields: ctx, peerChan +func (_m *Connector) Connect(ctx context.Context, peerChan <-chan peer.AddrInfo) { + _m.Called(ctx, peerChan) } type mockConstructorTestingTNewConnector interface { diff --git a/network/mocknetwork/connector_factory.go b/network/mocknetwork/connector_factory.go new file mode 100644 index 00000000000..b1baeb4f749 --- /dev/null +++ b/network/mocknetwork/connector_factory.go @@ -0,0 +1,56 @@ +// Code generated by mockery v2.21.4. DO NOT EDIT. + +package mocknetwork + +import ( + host "github.com/libp2p/go-libp2p/core/host" + mock "github.com/stretchr/testify/mock" + + p2p "github.com/onflow/flow-go/network/p2p" +) + +// ConnectorFactory is an autogenerated mock type for the ConnectorFactory type +type ConnectorFactory struct { + mock.Mock +} + +// Execute provides a mock function with given fields: _a0 +func (_m *ConnectorFactory) Execute(_a0 host.Host) (p2p.Connector, error) { + ret := _m.Called(_a0) + + var r0 p2p.Connector + var r1 error + if rf, ok := ret.Get(0).(func(host.Host) (p2p.Connector, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(host.Host) p2p.Connector); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(p2p.Connector) + } + } + + if rf, ok := ret.Get(1).(func(host.Host) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewConnectorFactory interface { + mock.TestingT + Cleanup(func()) +} + +// NewConnectorFactory creates a new instance of ConnectorFactory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewConnectorFactory(t mockConstructorTestingTNewConnectorFactory) *ConnectorFactory { + mock := &ConnectorFactory{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/network/p2p/builder.go b/network/p2p/builder.go index 9e6eac022e6..3bd8e278716 100644 --- a/network/p2p/builder.go +++ b/network/p2p/builder.go @@ -122,7 +122,6 @@ type NodeBuilder interface { SetConnectionManager(connmgr.ConnManager) NodeBuilder SetConnectionGater(ConnectionGater) NodeBuilder SetRoutingSystem(func(context.Context, host.Host) (routing.Routing, error)) NodeBuilder - SetPeerManagerOptions(bool, time.Duration) NodeBuilder // EnableGossipSubPeerScoring enables peer scoring for the GossipSub pubsub system. // Arguments: diff --git a/network/p2p/connection/connManager_test.go b/network/p2p/connection/connManager_test.go index a9c66179969..39016a09fc3 100644 --- a/network/p2p/connection/connManager_test.go +++ b/network/p2p/connection/connManager_test.go @@ -12,9 +12,9 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/flow-go/config" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/module/metrics" - mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/netconf" "github.com/onflow/flow-go/network/p2p/connection" @@ -117,14 +117,14 @@ func TestConnectionManager_Watermarking(t *testing.T) { metrics.NewNoopCollector(), cfg) require.NoError(t, err) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) thisNode, identity := p2ptest.NodeFixture( t, sporkId, t.Name(), idProvider, p2ptest.WithConnectionManager(thisConnMgr)) - idProvider.On("ByPeerID", thisNode.Host().ID()).Return(&identity, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&identity}) otherNodes, _ := p2ptest.NodesFixture(t, sporkId, t.Name(), 5, idProvider) diff --git a/network/p2p/connection/connection_gater_test.go b/network/p2p/connection/connection_gater_test.go index 07c3f0e2115..0277fc6b632 100644 --- a/network/p2p/connection/connection_gater_test.go +++ b/network/p2p/connection/connection_gater_test.go @@ -17,9 +17,10 @@ import ( mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" - "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" + "github.com/onflow/flow-go/network/p2p/connection" mockp2p "github.com/onflow/flow-go/network/p2p/mock" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/unicast/stream" "github.com/onflow/flow-go/utils/unittest" @@ -39,7 +40,7 @@ func TestConnectionGating(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(p peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { if !node1Peers.Has(p) { return fmt.Errorf("id not found: %s", p.String()) } @@ -53,7 +54,7 @@ func TestConnectionGating(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(p peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { if !node2Peers.Has(p) { return fmt.Errorf("id not found: %s", p.String()) } @@ -152,7 +153,7 @@ func TestConnectionGating_ResourceAllocation_AllowListing(t *testing.T) { p2ptest.WithMetricsCollector(node2Metrics), // we use default resource manager rather than the test resource manager to ensure that the metrics are called. p2ptest.WithDefaultResourceManager(), - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(p peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { return nil // allow all connections. }))) idProvider.On("ByPeerID", node1.Host().ID()).Return(&node1Id, true).Maybe() @@ -197,7 +198,7 @@ func TestConnectionGating_ResourceAllocation_DisAllowListing(t *testing.T) { p2ptest.WithMetricsCollector(node2Metrics), // we use default resource manager rather than the test resource manager to ensure that the metrics are called. p2ptest.WithDefaultResourceManager(), - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(p peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { return fmt.Errorf("disallowed connection") // rejecting all connections. }))) idProvider.On("ByPeerID", node1.Host().ID()).Return(&node1Id, true).Maybe() @@ -249,7 +250,11 @@ func TestConnectionGater_InterceptUpgrade(t *testing.T) { p2ptest.WithRole(flow.RoleConsensus), p2ptest.WithDefaultStreamHandler(handler), // enable peer manager, with a 1-second refresh rate, and connection pruning enabled. - p2ptest.WithPeerManagerEnabled(true, 1*time.Second, func() peer.IDSlice { + p2ptest.WithPeerManagerEnabled(&p2pconfig.PeerManagerConfig{ + ConnectionPruning: true, + UpdateInterval: 1 * time.Second, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + }, func() peer.IDSlice { list := make(peer.IDSlice, 0) for _, pid := range allPeerIds { if !disallowedPeerIds.Has(pid) { @@ -327,7 +332,11 @@ func TestConnectionGater_Disallow_Integration(t *testing.T) { p2ptest.WithRole(flow.RoleConsensus), p2ptest.WithDefaultStreamHandler(handler), // enable peer manager, with a 1-second refresh rate, and connection pruning enabled. - p2ptest.WithPeerManagerEnabled(true, 1*time.Second, func() peer.IDSlice { + p2ptest.WithPeerManagerEnabled(&p2pconfig.PeerManagerConfig{ + ConnectionPruning: true, + UpdateInterval: 1 * time.Second, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + }, func() peer.IDSlice { list := make(peer.IDSlice, 0) for _, id := range ids { if disallowedList.Has(id) { @@ -341,7 +350,7 @@ func TestConnectionGater_Disallow_Integration(t *testing.T) { } return list }), - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { return disallowedList.ForEach(func(id *flow.Identity, _ struct{}) error { bid, err := unittest.PeerIDFromFlowID(id) require.NoError(t, err) diff --git a/network/p2p/connection/connector.go b/network/p2p/connection/connector.go index 0065c395d46..e185d38c69b 100644 --- a/network/p2p/connection/connector.go +++ b/network/p2p/connection/connector.go @@ -2,10 +2,8 @@ package connection import ( "context" - "fmt" "github.com/libp2p/go-libp2p/core/peer" - discoveryBackoff "github.com/libp2p/go-libp2p/p2p/discovery/backoff" "github.com/rs/zerolog" "github.com/onflow/flow-go/network/internal/p2putils" @@ -26,16 +24,16 @@ const ( PruningDisabled = false ) -// Libp2pConnector is a libp2p based Connector implementation to connect and disconnect from peers -type Libp2pConnector struct { - backoffConnector *discoveryBackoff.BackoffConnector +// PeerUpdater is a connector that connects to a list of peers and disconnects from any other connection that the libp2p node might have. +type PeerUpdater struct { + connector p2p.Connector host p2p.ConnectorHost log zerolog.Logger pruneConnections bool } -// ConnectorConfig is the configuration for the libp2p based connector. -type ConnectorConfig struct { +// PeerUpdaterConfig is the configuration for the libp2p based connector. +type PeerUpdaterConfig struct { // PruneConnections is a boolean flag to enable pruning of connections to peers that are not part of the explicit update list. PruneConnections bool @@ -45,32 +43,23 @@ type ConnectorConfig struct { // Host is the libp2p host to be used by the connector. Host p2p.ConnectorHost - // BackoffConnectorFactory is a factory function to create a new BackoffConnector. - BackoffConnectorFactory func() (*discoveryBackoff.BackoffConnector, error) + // ConnectorFactory is a factory function to create a new connector. + Connector p2p.Connector } -var _ p2p.Connector = &Libp2pConnector{} +var _ p2p.PeerUpdater = (*PeerUpdater)(nil) -// NewLibp2pConnector creates a new libp2p based connector +// NewPeerUpdater creates a new libp2p based connector // Args: // - cfg: configuration for the connector // // Returns: -// - *Libp2pConnector: a new libp2p based connector +// - *PeerUpdater: a new libp2p based connector // - error: an error if there is any error while creating the connector. The errors are irrecoverable and unexpected. -func NewLibp2pConnector(cfg *ConnectorConfig) (*Libp2pConnector, error) { - connector, err := cfg.BackoffConnectorFactory() - if err != nil { - return nil, fmt.Errorf("failed to create libP2P connector: %w", err) - } - - if err != nil { - return nil, fmt.Errorf("failed to create peer ID slice shuffler: %w", err) - } - - libP2PConnector := &Libp2pConnector{ +func NewPeerUpdater(cfg *PeerUpdaterConfig) (*PeerUpdater, error) { + libP2PConnector := &PeerUpdater{ log: cfg.Logger, - backoffConnector: connector, + connector: cfg.Connector, host: cfg.Host, pruneConnections: cfg.PruneConnections, } @@ -80,7 +69,7 @@ func NewLibp2pConnector(cfg *ConnectorConfig) (*Libp2pConnector, error) { // UpdatePeers is the implementation of the Connector.UpdatePeers function. It connects to all of the ids and // disconnects from any other connection that the libp2p node might have. -func (l *Libp2pConnector) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) { +func (l *PeerUpdater) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) { // connect to each of the peer.AddrInfo in pInfos l.connectToPeers(ctx, peerIDs) @@ -93,7 +82,7 @@ func (l *Libp2pConnector) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) } // connectToPeers connects each of the peer in pInfos -func (l *Libp2pConnector) connectToPeers(ctx context.Context, peerIDs peer.IDSlice) { +func (l *PeerUpdater) connectToPeers(ctx context.Context, peerIDs peer.IDSlice) { // create a channel of peer.AddrInfo as expected by the connector peerCh := make(chan peer.AddrInfo, len(peerIDs)) @@ -120,13 +109,13 @@ func (l *Libp2pConnector) connectToPeers(ctx context.Context, peerIDs peer.IDSli close(peerCh) // ask the connector to connect to all the peers - l.backoffConnector.Connect(ctx, peerCh) + l.connector.Connect(ctx, peerCh) } // pruneAllConnectionsExcept trims all connections of the node from peers not part of peerIDs. // A node would have created such extra connections earlier when the identity list may have been different, or // it may have been target of such connections from node which have now been excluded. -func (l *Libp2pConnector) pruneAllConnectionsExcept(peerIDs peer.IDSlice) { +func (l *PeerUpdater) pruneAllConnectionsExcept(peerIDs peer.IDSlice) { // convert the peerInfos to a peer.ID -> bool map peersToKeep := make(map[peer.ID]bool, len(peerIDs)) for _, pid := range peerIDs { diff --git a/network/p2p/connection/connector_factory.go b/network/p2p/connection/connector_factory.go index c3ecfaeee9c..aed13a9d168 100644 --- a/network/p2p/connection/connector_factory.go +++ b/network/p2p/connection/connector_factory.go @@ -7,6 +7,8 @@ import ( "github.com/libp2p/go-libp2p/core/host" discoveryBackoff "github.com/libp2p/go-libp2p/p2p/discovery/backoff" + + "github.com/onflow/flow-go/network/p2p" ) const ( @@ -35,8 +37,8 @@ const ( // DefaultLibp2pBackoffConnectorFactory is a factory function to create a new BackoffConnector. It uses the default // values for the backoff connector. // (https://github.com/libp2p/go-libp2p-pubsub/blob/master/discovery.go#L34) -func DefaultLibp2pBackoffConnectorFactory(host host.Host) func() (*discoveryBackoff.BackoffConnector, error) { - return func() (*discoveryBackoff.BackoffConnector, error) { +func DefaultLibp2pBackoffConnectorFactory() p2p.ConnectorFactory { + return func(host host.Host) (p2p.Connector, error) { rngSrc := rand.NewSource(rand.Int63()) cacheSize := 100 diff --git a/network/p2p/connection/peerManager.go b/network/p2p/connection/peerManager.go index 05cc7c47129..83dee63359e 100644 --- a/network/p2p/connection/peerManager.go +++ b/network/p2p/connection/peerManager.go @@ -31,7 +31,7 @@ type PeerManager struct { logger zerolog.Logger peersProvider p2p.PeersProvider // callback to retrieve list of peers to connect to peerRequestQ chan struct{} // a channel to queue a peer update request - connector p2p.Connector // connector to connect or disconnect from peers + connector p2p.PeerUpdater // connector to connect or disconnect from peers peerUpdateInterval time.Duration // interval the peer manager runs on peersProviderMu sync.RWMutex @@ -39,7 +39,7 @@ type PeerManager struct { // NewPeerManager creates a new peer manager which calls the peersProvider callback to get a list of peers to connect to // and it uses the connector to actually connect or disconnect from peers. -func NewPeerManager(logger zerolog.Logger, updateInterval time.Duration, connector p2p.Connector) *PeerManager { +func NewPeerManager(logger zerolog.Logger, updateInterval time.Duration, connector p2p.PeerUpdater) *PeerManager { pm := &PeerManager{ logger: logger, connector: connector, diff --git a/network/p2p/connection/peerManager_integration_test.go b/network/p2p/connection/peerManager_integration_test.go index ca0d3ce513b..684acfbdb8a 100644 --- a/network/p2p/connection/peerManager_integration_test.go +++ b/network/p2p/connection/peerManager_integration_test.go @@ -14,7 +14,6 @@ import ( "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/irrecoverable" - mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -23,7 +22,7 @@ import ( "github.com/onflow/flow-go/utils/unittest" ) -// TestPeerManager_Integration tests the correctness of integration between PeerManager and Libp2pConnector over +// TestPeerManager_Integration tests the correctness of integration between PeerManager and PeerUpdater over // a fully connected topology. // PeerManager should be able to connect to all peers using the connector, and must also tear down the connection to // peers that are excluded from its identity provider. @@ -34,12 +33,9 @@ func TestPeerManager_Integration(t *testing.T) { signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) // create nodes - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_peer_manager", count, idProvider) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() - - } + idProvider.SetIdentities(identities) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -53,19 +49,21 @@ func TestPeerManager_Integration(t *testing.T) { thisNode.Host().Peerstore().SetAddrs(i.ID, i.Addrs, peerstore.PermanentAddrTTL) } + connector, err := connection.DefaultLibp2pBackoffConnectorFactory()(thisNode.Host()) + require.NoError(t, err) // setup - connector, err := connection.NewLibp2pConnector(&connection.ConnectorConfig{ - PruneConnections: connection.PruningEnabled, - Logger: unittest.Logger(), - Host: connection.NewConnectorHost(thisNode.Host()), - BackoffConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(thisNode.Host()), + peerUpdater, err := connection.NewPeerUpdater(&connection.PeerUpdaterConfig{ + PruneConnections: connection.PruningEnabled, + Logger: unittest.Logger(), + Host: connection.NewConnectorHost(thisNode.Host()), + Connector: connector, }) require.NoError(t, err) idTranslator, err := translator.NewFixedTableIdentityTranslator(identities) require.NoError(t, err) - peerManager := connection.NewPeerManager(unittest.Logger(), connection.DefaultPeerUpdateInterval, connector) + peerManager := connection.NewPeerManager(unittest.Logger(), connection.DefaultPeerUpdateInterval, peerUpdater) peerManager.SetPeersProvider(func() peer.IDSlice { // peerManager is furnished with a full topology that connects to all nodes // in the topologyPeers. diff --git a/network/p2p/connection/peerManager_test.go b/network/p2p/connection/peerManager_test.go index f2a9305c31b..2b4c8e367e9 100644 --- a/network/p2p/connection/peerManager_test.go +++ b/network/p2p/connection/peerManager_test.go @@ -18,9 +18,9 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network/internal/p2pfixtures" - "github.com/onflow/flow-go/network/mocknetwork" "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/keyutils" + mockp2p "github.com/onflow/flow-go/network/p2p/mock" "github.com/onflow/flow-go/utils/unittest" ) @@ -60,8 +60,8 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { pids := suite.generatePeerIDs(10) // create the connector mock to check ids requested for connect and disconnect - connector := new(mocknetwork.Connector) - connector.On("UpdatePeers", mock.Anything, mock.AnythingOfType("peer.IDSlice")). + peerUpdater := mockp2p.NewPeerUpdater(suite.T()) + peerUpdater.On("UpdatePeers", mock.Anything, mock.AnythingOfType("peer.IDSlice")). Run(func(args mock.Arguments) { idArg := args[1].(peer.IDSlice) assert.ElementsMatch(suite.T(), pids, idArg) @@ -69,7 +69,7 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { Return(nil) // create the peer manager (but don't start it) - pm := connection.NewPeerManager(suite.log, connection.DefaultPeerUpdateInterval, connector) + pm := connection.NewPeerManager(suite.log, connection.DefaultPeerUpdateInterval, peerUpdater) pm.SetPeersProvider(func() peer.IDSlice { return pids }) @@ -77,7 +77,7 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { // very first call to updatepeer suite.Run("updatePeers only connects to all peers the first time", func() { pm.ForceUpdatePeers(ctx) - connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 1) + peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 1) }) // a subsequent call to updatePeers should request a connector.UpdatePeers to existing ids and new ids @@ -87,7 +87,7 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { pids = append(pids, newPIDs...) pm.ForceUpdatePeers(ctx) - connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 2) + peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 2) }) // when ids are only excluded, connector.UpdatePeers should be called @@ -96,7 +96,7 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { pids = removeRandomElement(pids) pm.ForceUpdatePeers(ctx) - connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 3) + peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 3) }) // addition and deletion of ids should result in a call to connector.UpdatePeers @@ -111,7 +111,7 @@ func (suite *PeerManagerTestSuite) TestUpdatePeers() { pm.ForceUpdatePeers(ctx) - connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 4) + peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 4) }) } @@ -131,13 +131,13 @@ func (suite *PeerManagerTestSuite) TestPeriodicPeerUpdate() { // create some test ids pids := suite.generatePeerIDs(10) - connector := new(mocknetwork.Connector) + peerUpdater := mockp2p.NewPeerUpdater(suite.T()) wg := &sync.WaitGroup{} // keeps track of number of calls on `ConnectPeers` mu := &sync.Mutex{} // provides mutual exclusion on calls to `ConnectPeers` count := 0 times := 2 // we expect it to be called twice at least wg.Add(times) - connector.On("UpdatePeers", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + peerUpdater.On("UpdatePeers", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { mu.Lock() defer mu.Unlock() @@ -148,7 +148,7 @@ func (suite *PeerManagerTestSuite) TestPeriodicPeerUpdate() { }).Return(nil) peerUpdateInterval := 10 * time.Millisecond - pm := connection.NewPeerManager(suite.log, peerUpdateInterval, connector) + pm := connection.NewPeerManager(suite.log, peerUpdateInterval, peerUpdater) pm.SetPeersProvider(func() peer.IDSlice { return pids }) @@ -173,15 +173,15 @@ func (suite *PeerManagerTestSuite) TestOnDemandPeerUpdate() { // chooses peer interval rate deliberately long to capture on demand peer update peerUpdateInterval := time.Hour - // creates mock connector + // creates mock peerUpdater wg := &sync.WaitGroup{} // keeps track of number of calls on `ConnectPeers` mu := &sync.Mutex{} // provides mutual exclusion on calls to `ConnectPeers` count := 0 times := 2 // we expect it to be called twice overall wg.Add(1) // this accounts for one invocation, the other invocation is subsequent - connector := new(mocknetwork.Connector) + peerUpdater := mockp2p.NewPeerUpdater(suite.T()) // captures the first periodic update initiated after start to complete - connector.On("UpdatePeers", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + peerUpdater.On("UpdatePeers", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { mu.Lock() defer mu.Unlock() @@ -191,7 +191,7 @@ func (suite *PeerManagerTestSuite) TestOnDemandPeerUpdate() { } }).Return(nil) - pm := connection.NewPeerManager(suite.log, peerUpdateInterval, connector) + pm := connection.NewPeerManager(suite.log, peerUpdateInterval, peerUpdater) pm.SetPeersProvider(func() peer.IDSlice { return pids }) @@ -220,17 +220,17 @@ func (suite *PeerManagerTestSuite) TestConcurrentOnDemandPeerUpdate() { // create some test ids pids := suite.generatePeerIDs(10) - connector := new(mocknetwork.Connector) - // connectPeerGate channel gates the return of the connector + peerUpdater := mockp2p.NewPeerUpdater(suite.T()) + // connectPeerGate channel gates the return of the peerUpdater connectPeerGate := make(chan time.Time) defer close(connectPeerGate) // choose the periodic interval as a high value so that periodic runs don't interfere with this test peerUpdateInterval := time.Hour - connector.On("UpdatePeers", mock.Anything, mock.Anything).Return(nil). + peerUpdater.On("UpdatePeers", mock.Anything, mock.Anything).Return(nil). WaitUntil(connectPeerGate) // blocks call for connectPeerGate channel - pm := connection.NewPeerManager(suite.log, peerUpdateInterval, connector) + pm := connection.NewPeerManager(suite.log, peerUpdateInterval, peerUpdater) pm.SetPeersProvider(func() peer.IDSlice { return pids }) @@ -243,7 +243,7 @@ func (suite *PeerManagerTestSuite) TestConcurrentOnDemandPeerUpdate() { // assert that the first update started assert.Eventually(suite.T(), func() bool { - return connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 1) + return peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 1) }, 3*time.Second, 100*time.Millisecond) // makes 10 concurrent request for peer update @@ -255,6 +255,6 @@ func (suite *PeerManagerTestSuite) TestConcurrentOnDemandPeerUpdate() { // assert that only two calls to UpdatePeers were made (one by the periodic update and one by the on-demand update) assert.Eventually(suite.T(), func() bool { - return connector.AssertNumberOfCalls(suite.T(), "UpdatePeers", 2) + return peerUpdater.AssertNumberOfCalls(suite.T(), "UpdatePeers", 2) }, 10*time.Second, 100*time.Millisecond) } diff --git a/network/p2p/connector.go b/network/p2p/connector.go index 5ba291d7063..f9c5897352c 100644 --- a/network/p2p/connector.go +++ b/network/p2p/connector.go @@ -3,12 +3,14 @@ package p2p import ( "context" + "github.com/libp2p/go-libp2p/core/host" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" ) -// Connector connects to peer and disconnects from peer using the underlying networking library -type Connector interface { +// PeerUpdater connects to the given peer.IDs. It also disconnects from any other peers with which it may have +// previously established connection. +type PeerUpdater interface { // UpdatePeers connects to the given peer.IDs. It also disconnects from any other peers with which it may have // previously established connection. // UpdatePeers implementation should be idempotent such that multiple calls to connect to the same peer should not @@ -16,6 +18,22 @@ type Connector interface { UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) } +// Connector is an interface that allows connecting to a peer.ID. +type Connector interface { + // Connect connects to the given peer.ID. + // Note that connection may be established asynchronously. Any error encountered while connecting to the peer.ID + // is benign and should not be returned. Also, Connect implementation should not cause any blocking or crash. + // Args: + // ctx: context.Context to be used for the connection + // peerChan: channel to which the peer.AddrInfo of the connected peer.ID is sent. + // Returns: + // none. + Connect(ctx context.Context, peerChan <-chan peer.AddrInfo) +} + +// ConnectorFactory is a factory function to create a new Connector. +type ConnectorFactory func(host host.Host) (Connector, error) + type PeerFilter func(peer.ID) error // AllowAllPeerFilter returns a peer filter that does not do any filtering. diff --git a/network/p2p/dht/dht_test.go b/network/p2p/dht/dht_test.go index d26dfc3fe31..5ea0ee70e6a 100644 --- a/network/p2p/dht/dht_test.go +++ b/network/p2p/dht/dht_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/flow-go/model/flow" libp2pmsg "github.com/onflow/flow-go/model/libp2p/message" "github.com/onflow/flow-go/module/irrecoverable" mockmodule "github.com/onflow/flow-go/module/mock" @@ -36,18 +37,14 @@ func TestFindPeerWithDHT(t *testing.T) { golog.SetAllLoggers(golog.LevelFatal) // change this to Debug if libp2p logs are needed sporkId := unittest.IdentifierFixture() - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) dhtServerNodes, serverIDs := p2ptest.NodesFixture(t, sporkId, "dht_test", 2, idProvider, p2ptest.WithDHTOptions(dht.AsServer())) require.Len(t, dhtServerNodes, 2) dhtClientNodes, clientIDs := p2ptest.NodesFixture(t, sporkId, "dht_test", count-2, idProvider, p2ptest.WithDHTOptions(dht.AsClient())) - ids := append(serverIDs, clientIDs...) nodes := append(dhtServerNodes, dhtClientNodes...) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&ids[i], true).Maybe() - - } + idProvider.SetIdentities(append(serverIDs, clientIDs...)) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) diff --git a/network/p2p/mock/connector.go b/network/p2p/mock/connector.go index d1e6733cbab..2c8a49c9070 100644 --- a/network/p2p/mock/connector.go +++ b/network/p2p/mock/connector.go @@ -15,9 +15,9 @@ type Connector struct { mock.Mock } -// UpdatePeers provides a mock function with given fields: ctx, peerIDs -func (_m *Connector) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) { - _m.Called(ctx, peerIDs) +// Connect provides a mock function with given fields: ctx, peerChan +func (_m *Connector) Connect(ctx context.Context, peerChan <-chan peer.AddrInfo) { + _m.Called(ctx, peerChan) } type mockConstructorTestingTNewConnector interface { diff --git a/network/p2p/mock/connector_factory.go b/network/p2p/mock/connector_factory.go new file mode 100644 index 00000000000..a22788969f8 --- /dev/null +++ b/network/p2p/mock/connector_factory.go @@ -0,0 +1,56 @@ +// Code generated by mockery v2.21.4. DO NOT EDIT. + +package mockp2p + +import ( + host "github.com/libp2p/go-libp2p/core/host" + mock "github.com/stretchr/testify/mock" + + p2p "github.com/onflow/flow-go/network/p2p" +) + +// ConnectorFactory is an autogenerated mock type for the ConnectorFactory type +type ConnectorFactory struct { + mock.Mock +} + +// Execute provides a mock function with given fields: _a0 +func (_m *ConnectorFactory) Execute(_a0 host.Host) (p2p.Connector, error) { + ret := _m.Called(_a0) + + var r0 p2p.Connector + var r1 error + if rf, ok := ret.Get(0).(func(host.Host) (p2p.Connector, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(host.Host) p2p.Connector); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(p2p.Connector) + } + } + + if rf, ok := ret.Get(1).(func(host.Host) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +type mockConstructorTestingTNewConnectorFactory interface { + mock.TestingT + Cleanup(func()) +} + +// NewConnectorFactory creates a new instance of ConnectorFactory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewConnectorFactory(t mockConstructorTestingTNewConnectorFactory) *ConnectorFactory { + mock := &ConnectorFactory{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/network/p2p/mock/node_builder.go b/network/p2p/mock/node_builder.go index dbe0302bb9d..97ab398f37a 100644 --- a/network/p2p/mock/node_builder.go +++ b/network/p2p/mock/node_builder.go @@ -199,22 +199,6 @@ func (_m *NodeBuilder) SetGossipSubTracer(_a0 p2p.PubSubTracer) p2p.NodeBuilder return r0 } -// SetPeerManagerOptions provides a mock function with given fields: _a0, _a1 -func (_m *NodeBuilder) SetPeerManagerOptions(_a0 bool, _a1 time.Duration) p2p.NodeBuilder { - ret := _m.Called(_a0, _a1) - - var r0 p2p.NodeBuilder - if rf, ok := ret.Get(0).(func(bool, time.Duration) p2p.NodeBuilder); ok { - r0 = rf(_a0, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(p2p.NodeBuilder) - } - } - - return r0 -} - // SetRateLimiterDistributor provides a mock function with given fields: _a0 func (_m *NodeBuilder) SetRateLimiterDistributor(_a0 p2p.UnicastRateLimiterDistributor) p2p.NodeBuilder { ret := _m.Called(_a0) diff --git a/network/p2p/mock/peer_updater.go b/network/p2p/mock/peer_updater.go new file mode 100644 index 00000000000..7a708e6c3df --- /dev/null +++ b/network/p2p/mock/peer_updater.go @@ -0,0 +1,36 @@ +// Code generated by mockery v2.21.4. DO NOT EDIT. + +package mockp2p + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + peer "github.com/libp2p/go-libp2p/core/peer" +) + +// PeerUpdater is an autogenerated mock type for the PeerUpdater type +type PeerUpdater struct { + mock.Mock +} + +// UpdatePeers provides a mock function with given fields: ctx, peerIDs +func (_m *PeerUpdater) UpdatePeers(ctx context.Context, peerIDs peer.IDSlice) { + _m.Called(ctx, peerIDs) +} + +type mockConstructorTestingTNewPeerUpdater interface { + mock.TestingT + Cleanup(func()) +} + +// NewPeerUpdater creates a new instance of PeerUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewPeerUpdater(t mockConstructorTestingTNewPeerUpdater) *PeerUpdater { + mock := &PeerUpdater{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/network/p2p/p2pbuilder/config/config.go b/network/p2p/p2pbuilder/config/config.go index a950a6b2fb1..f784edee0cb 100644 --- a/network/p2p/p2pbuilder/config/config.go +++ b/network/p2p/p2pbuilder/config/config.go @@ -29,4 +29,15 @@ type PeerManagerConfig struct { ConnectionPruning bool // UpdateInterval interval used by the libp2p node peer manager component to periodically request peer updates. UpdateInterval time.Duration + // ConnectorFactory is a factory function to create a new connector. + ConnectorFactory p2p.ConnectorFactory +} + +// PeerManagerDisableConfig returns a configuration that disables the peer manager. +func PeerManagerDisableConfig() *PeerManagerConfig { + return &PeerManagerConfig{ + ConnectionPruning: false, + UpdateInterval: 0, + ConnectorFactory: nil, + } } diff --git a/network/p2p/p2pbuilder/libp2pNodeBuilder.go b/network/p2p/p2pbuilder/libp2pNodeBuilder.go index bf61b8b0054..4d30b1fff02 100644 --- a/network/p2p/p2pbuilder/libp2pNodeBuilder.go +++ b/network/p2p/p2pbuilder/libp2pNodeBuilder.go @@ -65,8 +65,7 @@ type LibP2PNodeBuilder struct { connManager connmgr.ConnManager connGater p2p.ConnectionGater routingFactory func(context.Context, host.Host) (routing.Routing, error) - peerManagerEnablePruning bool - peerManagerUpdateInterval time.Duration + peerManagerConfig *p2pconfig.PeerManagerConfig createNode p2p.CreateNodeFunc createStreamRetryInterval time.Duration rateLimiterDistributor p2p.UnicastRateLimiterDistributor @@ -84,6 +83,7 @@ func NewNodeBuilder( idProvider module.IdentityProvider, rCfg *p2pconf.ResourceManagerConfig, rpcInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig, + peerManagerConfig *p2pconfig.PeerManagerConfig, disallowListCacheCfg *p2p.DisallowListCacheConfig) *LibP2PNodeBuilder { return &LibP2PNodeBuilder{ logger: logger, @@ -101,6 +101,7 @@ func NewNodeBuilder( sporkId, idProvider, rpcInspectorCfg), + peerManagerConfig: peerManagerConfig, } } @@ -167,13 +168,6 @@ func (builder *LibP2PNodeBuilder) EnableGossipSubPeerScoring(config *p2p.PeerSco return builder } -// SetPeerManagerOptions sets the peer manager options. -func (builder *LibP2PNodeBuilder) SetPeerManagerOptions(connectionPruning bool, updateInterval time.Duration) p2p.NodeBuilder { - builder.peerManagerEnablePruning = connectionPruning - builder.peerManagerUpdateInterval = updateInterval - return builder -} - func (builder *LibP2PNodeBuilder) SetGossipSubTracer(tracer p2p.PubSubTracer) p2p.NodeBuilder { builder.gossipSubBuilder.SetGossipSubTracer(tracer) builder.gossipSubTracer = tracer @@ -298,18 +292,22 @@ func (builder *LibP2PNodeBuilder) Build() (p2p.LibP2PNode, error) { } var peerManager p2p.PeerManager - if builder.peerManagerUpdateInterval > 0 { - connector, err := connection.NewLibp2pConnector(&connection.ConnectorConfig{ - PruneConnections: builder.peerManagerEnablePruning, - Logger: builder.logger, - Host: connection.NewConnectorHost(h), - BackoffConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(h), + if builder.peerManagerConfig.UpdateInterval > 0 { + connector, err := builder.peerManagerConfig.ConnectorFactory(h) + if err != nil { + return nil, fmt.Errorf("failed to create libp2p connector: %w", err) + } + peerUpdater, err := connection.NewPeerUpdater(&connection.PeerUpdaterConfig{ + PruneConnections: builder.peerManagerConfig.ConnectionPruning, + Logger: builder.logger, + Host: connection.NewConnectorHost(h), + Connector: connector, }) if err != nil { return nil, fmt.Errorf("failed to create libp2p connector: %w", err) } - peerManager = connection.NewPeerManager(builder.logger, builder.peerManagerUpdateInterval, connector) + peerManager = connection.NewPeerManager(builder.logger, builder.peerManagerConfig.UpdateInterval, peerUpdater) if builder.rateLimiterDistributor != nil { builder.rateLimiterDistributor.AddConsumer(peerManager) @@ -480,6 +478,7 @@ func DefaultNodeBuilder( idProvider, rCfg, rpcInspectorCfg, + peerManagerCfg, disallowListCacheCfg). SetBasicResolver(resolver). SetConnectionManager(connManager). @@ -487,7 +486,6 @@ func DefaultNodeBuilder( SetRoutingSystem(func(ctx context.Context, host host.Host) (routing.Routing, error) { return dht.NewDHT(ctx, host, protocols.FlowDHTProtocolID(sporkId), logger, metricsCfg.Metrics, dht.AsServer()) }). - SetPeerManagerOptions(peerManagerCfg.ConnectionPruning, peerManagerCfg.UpdateInterval). SetStreamCreationRetryInterval(uniCfg.StreamRetryInterval). SetCreateNode(DefaultCreateNodeFunc). SetRateLimiterDistributor(uniCfg.RateLimiterDistributor) diff --git a/network/p2p/p2pnode/disallow_listing_test.go b/network/p2p/p2pnode/disallow_listing_test.go index 0249c3ee91f..566b2d6ec5e 100644 --- a/network/p2p/p2pnode/disallow_listing_test.go +++ b/network/p2p/p2pnode/disallow_listing_test.go @@ -11,9 +11,9 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network" - "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" ) @@ -35,11 +35,15 @@ func TestDisconnectingFromDisallowListedNode(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithPeerManagerEnabled(true, connection.DefaultPeerUpdateInterval, + p2ptest.WithPeerManagerEnabled(&p2pconfig.PeerManagerConfig{ + ConnectionPruning: true, + UpdateInterval: connection.DefaultPeerUpdateInterval, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + }, func() peer.IDSlice { return peerIDSlice }), - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(p peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { // allow all the connections, except for the ones that are disallow-listed, which are determined when // this connection gater object queries the disallow listing oracle that will be provided to it by // the libp2p node. So, here, we don't need to do anything except just enabling the connection gater. diff --git a/network/p2p/p2pnode/libp2pNode_test.go b/network/p2p/p2pnode/libp2pNode_test.go index 3644bd3dbf2..519a0579163 100644 --- a/network/p2p/p2pnode/libp2pNode_test.go +++ b/network/p2p/p2pnode/libp2pNode_test.go @@ -24,7 +24,6 @@ import ( "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" "github.com/onflow/flow-go/network/internal/p2putils" - "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/p2pnode" p2ptest "github.com/onflow/flow-go/network/p2p/test" @@ -114,8 +113,8 @@ func TestAddPeers(t *testing.T) { count := 3 ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) - // create nodes + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) + nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_add_peers", count, idProvider) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -136,7 +135,7 @@ func TestRemovePeers(t *testing.T) { count := 3 ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) // create nodes nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_remove_peers", count, idProvider) peerInfos, errs := utils.PeerInfosFromIDs(identities) @@ -173,7 +172,7 @@ func TestConnGater(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { if !node1Peers.Has(pid) { return fmt.Errorf("peer id not found: %s", pid.String()) } @@ -192,7 +191,7 @@ func TestConnGater(t *testing.T) { t, sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { if !node2Peers.Has(pid) { return fmt.Errorf("id not found: %s", pid.String()) } @@ -230,7 +229,7 @@ func TestConnGater(t *testing.T) { func TestNode_HasSubscription(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) sporkID := unittest.IdentifierFixture() node, _ := p2ptest.NodeFixture(t, sporkID, "test_has_subscription", idProvider) @@ -263,13 +262,14 @@ func TestCreateStream_SinglePairwiseConnection(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) nodes, ids := p2ptest.NodesFixture(t, sporkId, "test_create_stream_single_pairwise_connection", nodeCount, idProvider, p2ptest.WithDefaultResourceManager()) + idProvider.SetIdentities(ids) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -337,7 +337,7 @@ func TestCreateStream_SinglePeerDial(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { // avoid connection gating outbound messages on sender return nil })), @@ -353,7 +353,7 @@ func TestCreateStream_SinglePeerDial(t *testing.T) { sporkID, t.Name(), idProvider, - p2ptest.WithConnectionGater(testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { // connection gate all incoming connections forcing the senders unicast manager to perform retries return fmt.Errorf("gate keep") })), diff --git a/network/p2p/p2pnode/libp2pStream_test.go b/network/p2p/p2pnode/libp2pStream_test.go index e3b7bf281b3..551cabca4d0 100644 --- a/network/p2p/p2pnode/libp2pStream_test.go +++ b/network/p2p/p2pnode/libp2pStream_test.go @@ -11,9 +11,6 @@ import ( "testing" "time" - "github.com/onflow/flow-go/network/p2p" - p2ptest "github.com/onflow/flow-go/network/p2p/test" - "github.com/libp2p/go-libp2p/core" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peerstore" @@ -21,6 +18,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/flow-go/network/p2p" + p2ptest "github.com/onflow/flow-go/network/p2p/test" + "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module/irrecoverable" mockmodule "github.com/onflow/flow-go/module/mock" @@ -42,7 +42,7 @@ func TestStreamClosing(t *testing.T) { var msgRegex = regexp.MustCompile("^hello[0-9]") handler, streamCloseWG := mockStreamHandlerForMessages(t, ctx, count, msgRegex) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) // Creates nodes nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), @@ -50,10 +50,8 @@ func TestStreamClosing(t *testing.T) { 2, idProvider, p2ptest.WithDefaultStreamHandler(handler)) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() + idProvider.SetIdentities(identities) - } p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -153,17 +151,14 @@ func testCreateStream(t *testing.T, sporkId flow.Identifier, unicasts []protocol count := 2 ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) nodes, identities := p2ptest.NodesFixture(t, sporkId, "test_create_stream", count, idProvider, p2ptest.WithPreferredUnicasts(unicasts)) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() - - } + idProvider.SetIdentities(identities) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -285,14 +280,11 @@ func TestCreateStream_FallBack(t *testing.T) { func TestCreateStreamIsConcurrencySafe(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) // create two nodes nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), "test_create_stream_is_concurrency_safe", 2, idProvider) require.Len(t, identities, 2) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() - - } + idProvider.SetIdentities(flow.IdentityList{identities[0], identities[1]}) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -336,7 +328,7 @@ func TestNoBackoffWhenCreatingStream(t *testing.T) { ctx2, cancel2 := context.WithCancel(ctx) signalerCtx2 := irrecoverable.NewMockSignalerContext(t, ctx2) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) count := 2 // Creates nodes nodes, identities := p2ptest.NodesFixture(t, @@ -347,10 +339,7 @@ func TestNoBackoffWhenCreatingStream(t *testing.T) { ) node1 := nodes[0] node2 := nodes[1] - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() - - } + idProvider.SetIdentities(flow.IdentityList{identities[0], identities[1]}) p2ptest.StartNode(t, signalerCtx1, node1, 100*time.Millisecond) p2ptest.StartNode(t, signalerCtx2, node2, 100*time.Millisecond) @@ -497,7 +486,7 @@ func TestUnicastOverStream_Fallback(t *testing.T) { func TestCreateStreamTimeoutWithUnresponsiveNode(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) // creates a regular node nodes, identities := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), @@ -506,10 +495,7 @@ func TestCreateStreamTimeoutWithUnresponsiveNode(t *testing.T) { idProvider, ) require.Len(t, identities, 1) - for i, node := range nodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&identities[i], true).Maybe() - - } + idProvider.SetIdentities(identities) p2ptest.StartNodes(t, signalerCtx, nodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, nodes, cancel, 100*time.Millisecond) @@ -542,7 +528,7 @@ func TestCreateStreamTimeoutWithUnresponsiveNode(t *testing.T) { func TestCreateStreamIsConcurrent(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) // create two regular node goodNodes, goodNodeIds := p2ptest.NodesFixture(t, unittest.IdentifierFixture(), @@ -551,10 +537,7 @@ func TestCreateStreamIsConcurrent(t *testing.T) { idProvider, ) require.Len(t, goodNodeIds, 2) - for i, node := range goodNodes { - idProvider.On("ByPeerID", node.Host().ID()).Return(&goodNodeIds[i], true).Maybe() - - } + idProvider.SetIdentities(goodNodeIds) p2ptest.StartNodes(t, signalerCtx, goodNodes, 100*time.Millisecond) defer p2ptest.StopNodes(t, goodNodes, cancel, 100*time.Millisecond) diff --git a/network/p2p/test/fixtures.go b/network/p2p/test/fixtures.go index d2d8ebfac9c..5ee82dd4ab5 100644 --- a/network/p2p/test/fixtures.go +++ b/network/p2p/test/fixtures.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "crypto/rand" + crand "math/rand" "testing" "time" @@ -14,6 +15,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/protocol" "github.com/libp2p/go-libp2p/core/routing" + discoveryBackoff "github.com/libp2p/go-libp2p/p2p/discovery/backoff" mh "github.com/multiformats/go-multihash" "github.com/rs/zerolog" "github.com/stretchr/testify/require" @@ -27,7 +29,6 @@ import ( flownet "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" - "github.com/onflow/flow-go/network/internal/testutils" "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/network/p2p/connection" p2pdht "github.com/onflow/flow-go/network/p2p/dht" @@ -63,6 +64,11 @@ func NodeFixture( require.NoError(t, err) logger := unittest.Logger().Level(zerolog.WarnLevel) + require.NotNil(t, idProvider) + connectionGater := NewConnectionGater(idProvider, func(p peer.ID) error { + return nil + }) + require.NotNil(t, connectionGater) parameters := &NodeFixtureParameters{ NetworkingType: flownet.PrivateNetwork, HandlerFunc: func(network.Stream) {}, @@ -72,12 +78,15 @@ func NodeFixture( Logger: logger, Role: flow.RoleCollection, CreateStreamRetryDelay: unicast.DefaultRetryDelay, + IdProvider: idProvider, MetricsCfg: &p2pconfig.MetricsConfig{ HeroCacheFactory: metrics.NewNoopHeroCacheMetricsFactory(), Metrics: metrics.NewNoopCollector(), }, - ResourceManager: testutils.NewResourceManager(t), + ResourceManager: &network.NullResourceManager{}, GossipSubPeerScoreTracerInterval: 0, // disabled by default + ConnGater: connectionGater, + PeerManagerConfig: PeerManagerConfigFixture(), // disabled by default GossipSubRPCInspectorCfg: &defaultFlowConfig.NetworkConfig.GossipSubRPCInspectorsConfig, } @@ -105,6 +114,7 @@ func NodeFixture( parameters.IdProvider, &defaultFlowConfig.NetworkConfig.ResourceManagerConfig, parameters.GossipSubRPCInspectorCfg, + parameters.PeerManagerConfig, &p2p.DisallowListCacheConfig{ MaxSize: uint32(1000), Metrics: metrics.NewNoopCollector(), @@ -138,11 +148,6 @@ func NodeFixture( builder.EnableGossipSubPeerScoring(parameters.PeerScoreConfig) } - if parameters.UpdateInterval != 0 { - require.NotNil(t, parameters.PeerProvider) - builder.SetPeerManagerOptions(parameters.ConnectionPruning, parameters.UpdateInterval) - } - if parameters.GossipSubFactory != nil && parameters.GossipSubConfig != nil { builder.SetGossipSubFactory(parameters.GossipSubFactory, parameters.GossipSubConfig) } @@ -155,13 +160,19 @@ func NodeFixture( builder.SetGossipSubTracer(parameters.PubSubTracer) } + if parameters.UnicastRateLimitDistributor != nil { + builder.SetRateLimiterDistributor(parameters.UnicastRateLimitDistributor) + } + builder.SetGossipSubScoreTracerInterval(parameters.GossipSubPeerScoreTracerInterval) n, err := builder.Build() require.NoError(t, err) - err = n.WithDefaultUnicastProtocol(parameters.HandlerFunc, parameters.Unicasts) - require.NoError(t, err) + if parameters.HandlerFunc != nil { + err = n.WithDefaultUnicastProtocol(parameters.HandlerFunc, parameters.Unicasts) + require.NoError(t, err) + } // get the actual IP and port that have been assigned by the subsystem ip, port, err := n.GetIPPort() @@ -189,8 +200,7 @@ type NodeFixtureParameters struct { PeerScoringEnabled bool IdProvider module.IdentityProvider PeerScoreConfig *p2p.PeerScoringConfig - ConnectionPruning bool // peer manager parameter - UpdateInterval time.Duration // peer manager parameter + PeerManagerConfig *p2pconfig.PeerManagerConfig PeerProvider p2p.PeersProvider // peer manager parameter ConnGater p2p.ConnectionGater ConnManager connmgr.ConnManager @@ -201,8 +211,15 @@ type NodeFixtureParameters struct { PubSubTracer p2p.PubSubTracer GossipSubPeerScoreTracerInterval time.Duration // intervals at which the peer score is updated and logged. CreateStreamRetryDelay time.Duration - GossipSubRPCInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig + UnicastRateLimitDistributor p2p.UnicastRateLimiterDistributor GossipSubRpcInspectorSuiteFactory p2p.GossipSubRpcInspectorSuiteFactoryFunc + GossipSubRPCInspectorCfg *p2pconf.GossipSubRPCInspectorsConfig +} + +func WithUnicastRateLimitDistributor(distributor p2p.UnicastRateLimiterDistributor) NodeFixtureParameterOption { + return func(p *NodeFixtureParameters) { + p.UnicastRateLimitDistributor = distributor + } } func OverrideGossipSubRpcInspectorSuiteFactory(factory p2p.GossipSubRpcInspectorSuiteFactoryFunc) NodeFixtureParameterOption { @@ -242,10 +259,9 @@ func WithDefaultStreamHandler(handler network.StreamHandler) NodeFixtureParamete } } -func WithPeerManagerEnabled(connectionPruning bool, updateInterval time.Duration, peerProvider p2p.PeersProvider) NodeFixtureParameterOption { +func WithPeerManagerEnabled(cfg *p2pconfig.PeerManagerConfig, peerProvider p2p.PeersProvider) NodeFixtureParameterOption { return func(p *NodeFixtureParameters) { - p.ConnectionPruning = connectionPruning - p.UpdateInterval = updateInterval + p.PeerManagerConfig = cfg p.PeerProvider = peerProvider } } @@ -324,6 +340,50 @@ func WithDefaultResourceManager() NodeFixtureParameterOption { } } +func WithUnicastHandlerFunc(handler network.StreamHandler) NodeFixtureParameterOption { + return func(p *NodeFixtureParameters) { + p.HandlerFunc = handler + } +} + +// PeerManagerConfigFixture is a test fixture that sets the default config for the peer manager. +func PeerManagerConfigFixture(opts ...func(*p2pconfig.PeerManagerConfig)) *p2pconfig.PeerManagerConfig { + cfg := &p2pconfig.PeerManagerConfig{ + ConnectionPruning: true, + UpdateInterval: 1 * time.Second, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + } + for _, opt := range opts { + opt(cfg) + } + return cfg +} + +// WithZeroJitterAndZeroBackoff is a test fixture that sets the default config for the peer manager. +// It uses a backoff connector with zero jitter and zero backoff. +func WithZeroJitterAndZeroBackoff(t *testing.T) func(*p2pconfig.PeerManagerConfig) { + return func(cfg *p2pconfig.PeerManagerConfig) { + cfg.ConnectorFactory = func(host host.Host) (p2p.Connector, error) { + cacheSize := 100 + dialTimeout := time.Minute * 2 + backoff := discoveryBackoff.NewExponentialBackoff( + 1*time.Second, + 1*time.Hour, + func(_, _, _ time.Duration, _ *crand.Rand) time.Duration { + return 0 // no jitter + }, + time.Second, + 1, + 0, + crand.NewSource(crand.Int63()), + ) + backoffConnector, err := discoveryBackoff.NewBackoffConnector(host, cacheSize, dialTimeout, backoff) + require.NoError(t, err) + return backoffConnector, nil + } + } +} + // NodesFixture is a test fixture that creates a number of libp2p nodes with the given callback function for stream handling. // It returns the nodes and their identities. func NodesFixture(t *testing.T, sporkID flow.Identifier, dhtPrefix string, count int, idProvider module.IdentityProvider, opts ...NodeFixtureParameterOption) ([]p2p.LibP2PNode, @@ -604,3 +664,12 @@ func PeerIdSliceFixture(t *testing.T, n int) peer.IDSlice { } return ids } + +// NewConnectionGater creates a new connection gater for testing with given allow listing filter. +func NewConnectionGater(idProvider module.IdentityProvider, allowListFilter p2p.PeerFilter) p2p.ConnectionGater { + filters := []p2p.PeerFilter{allowListFilter} + return connection.NewConnGater(unittest.Logger(), + idProvider, + connection.WithOnInterceptPeerDialFilters(filters), + connection.WithOnInterceptSecuredFilters(filters)) +} diff --git a/network/p2p/test/sporking_test.go b/network/p2p/test/sporking_test.go index bee29c54aed..14571b59e02 100644 --- a/network/p2p/test/sporking_test.go +++ b/network/p2p/test/sporking_test.go @@ -5,23 +5,22 @@ import ( "testing" "time" - "github.com/onflow/flow-go/model/flow" - libp2pmessage "github.com/onflow/flow-go/model/libp2p/message" - "github.com/onflow/flow-go/network" - "github.com/onflow/flow-go/network/message" - "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/flow-go/model/flow" + libp2pmessage "github.com/onflow/flow-go/model/libp2p/message" + "github.com/onflow/flow-go/network" + "github.com/onflow/flow-go/network/message" + "github.com/onflow/flow-go/network/p2p" p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/utils" "github.com/onflow/flow-go/module/irrecoverable" - mockmodule "github.com/onflow/flow-go/module/mock" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/p2pfixtures" flowpubsub "github.com/onflow/flow-go/network/validator/pubsub" @@ -41,7 +40,7 @@ import ( // TestCrosstalkPreventionOnNetworkKeyChange tests that a node from the old chain cannot talk to a node in the new chain // if it's network key is updated while the libp2p protocol ID remains the same func TestCrosstalkPreventionOnNetworkKeyChange(t *testing.T) { - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -64,7 +63,7 @@ func TestCrosstalkPreventionOnNetworkKeyChange(t *testing.T) { idProvider, p2ptest.WithNetworkingPrivateKey(node1key), ) - idProvider.On("ByPeerID", node1.Host().ID()).Return(&id1, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&id1}) p2ptest.StartNode(t, signalerCtx1, node1, 100*time.Millisecond) defer p2ptest.StopNode(t, node1, cancel1, 100*time.Millisecond) @@ -80,7 +79,7 @@ func TestCrosstalkPreventionOnNetworkKeyChange(t *testing.T) { idProvider, p2ptest.WithNetworkingPrivateKey(node2key), ) - idProvider.On("ByPeerID", node2.Host().ID()).Return(&id2, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&id1, &id2}) p2ptest.StartNode(t, signalerCtx2, node2, 100*time.Millisecond) @@ -105,7 +104,7 @@ func TestCrosstalkPreventionOnNetworkKeyChange(t *testing.T) { p2ptest.WithNetworkingPrivateKey(node2keyNew), p2ptest.WithNetworkingAddress(id2.Address), ) - idProvider.On("ByPeerID", node2.Host().ID()).Return(&id2New, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&id1, &id2New}) p2ptest.StartNode(t, signalerCtx2a, node2, 100*time.Millisecond) defer p2ptest.StopNode(t, node2, cancel2a, 100*time.Millisecond) @@ -122,7 +121,7 @@ func TestCrosstalkPreventionOnNetworkKeyChange(t *testing.T) { // TestOneToOneCrosstalkPrevention tests that a node from the old chain cannot talk directly to a node in the new chain // if the Flow libp2p protocol ID is updated while the network keys are kept the same. func TestOneToOneCrosstalkPrevention(t *testing.T) { - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -139,7 +138,6 @@ func TestOneToOneCrosstalkPrevention(t *testing.T) { // create and start node 1 on localhost and random port node1, id1 := p2ptest.NodeFixture(t, sporkId1, "test_one_to_one_crosstalk_prevention", idProvider) - idProvider.On("ByPeerID", node1.Host().ID()).Return(&id1, true).Maybe() p2ptest.StartNode(t, signalerCtx1, node1, 100*time.Millisecond) defer p2ptest.StopNode(t, node1, cancel1, 100*time.Millisecond) @@ -149,8 +147,8 @@ func TestOneToOneCrosstalkPrevention(t *testing.T) { // create and start node 2 on localhost and random port node2, id2 := p2ptest.NodeFixture(t, sporkId1, "test_one_to_one_crosstalk_prevention", idProvider) - idProvider.On("ByPeerID", node2.Host().ID()).Return(&id2, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&id1, &id2}) p2ptest.StartNode(t, signalerCtx2, node2, 100*time.Millisecond) // create stream from node 2 to node 1 @@ -167,7 +165,7 @@ func TestOneToOneCrosstalkPrevention(t *testing.T) { idProvider, p2ptest.WithNetworkingAddress(id2.Address), ) - idProvider.On("ByPeerID", node2.Host().ID()).Return(&id2New, true).Maybe() + idProvider.SetIdentities(flow.IdentityList{&id1, &id2New}) p2ptest.StartNode(t, signalerCtx2a, node2, 100*time.Millisecond) defer p2ptest.StopNode(t, node2, cancel2a, 100*time.Millisecond) @@ -183,7 +181,7 @@ func TestOneToOneCrosstalkPrevention(t *testing.T) { // TestOneToKCrosstalkPrevention tests that a node from the old chain cannot talk to a node in the new chain via PubSub // if the channel is updated while the network keys are kept the same. func TestOneToKCrosstalkPrevention(t *testing.T) { - idProvider := mockmodule.NewIdentityProvider(t) + idProvider := unittest.NewUpdatableIDProvider(flow.IdentityList{}) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -202,10 +200,10 @@ func TestOneToKCrosstalkPrevention(t *testing.T) { "test_one_to_k_crosstalk_prevention", idProvider, ) - idProvider.On("ByPeerID", node1.Host().ID()).Return(&id1, true).Maybe() + p2ptest.StartNode(t, signalerCtx1, node1, 100*time.Millisecond) defer p2ptest.StopNode(t, node1, cancel1, 100*time.Millisecond) - + idProvider.SetIdentities(flow.IdentityList{&id1}) // create and start node 2 on localhost and random port with the same root block ID node2, id2 := p2ptest.NodeFixture(t, previousSporkId, diff --git a/network/p2p/unicast/manager.go b/network/p2p/unicast/manager.go index f45c2ce7bcd..d8af81ed49d 100644 --- a/network/p2p/unicast/manager.go +++ b/network/p2p/unicast/manager.go @@ -69,12 +69,12 @@ func NewUnicastManager(logger zerolog.Logger, // as the core handler for other unicast protocols, e.g., compressions. func (m *Manager) WithDefaultHandler(defaultHandler libp2pnet.StreamHandler) { defaultProtocolID := protocols.FlowProtocolID(m.sporkId) - m.defaultHandler = defaultHandler - if len(m.protocols) > 0 { panic("default handler must be set only once before any unicast registration") } + m.defaultHandler = defaultHandler + m.protocols = []protocols.Protocol{ &PlainStream{ protocolId: defaultProtocolID, diff --git a/network/test/blob_service_test.go b/network/test/blob_service_test.go index bcce039fa35..40c052111d7 100644 --- a/network/test/blob_service_test.go +++ b/network/test/blob_service_test.go @@ -3,7 +3,6 @@ package test import ( "context" "fmt" - "os" "testing" "time" @@ -11,12 +10,13 @@ import ( "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/sync" blockstore "github.com/ipfs/go-ipfs-blockstore" - "github.com/rs/zerolog" "github.com/stretchr/testify/suite" "go.uber.org/atomic" + "github.com/onflow/flow-go/network/p2p/connection" "github.com/onflow/flow-go/network/p2p/dht" - + p2pconfig "github.com/onflow/flow-go/network/p2p/p2pbuilder/config" + p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/utils/unittest" "github.com/onflow/flow-go/model/flow" @@ -26,7 +26,6 @@ import ( "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/testutils" - "github.com/onflow/flow-go/network/mocknetwork" ) // conditionalTopology is a topology that behaves like the underlying topology when the condition is true, @@ -71,8 +70,6 @@ func (suite *BlobServiceTestSuite) putBlob(ds datastore.Batching, blob blobs.Blo func (suite *BlobServiceTestSuite) SetupTest() { suite.numNodes = 3 - logger := zerolog.New(os.Stdout) - // Bitswap listens to connect events but doesn't iterate over existing connections, and fixing this without // race conditions is tricky given the way the code is architected. As a result, libP2P hosts must first listen // on Bitswap before connecting to each other, otherwise their Bitswap requests may never reach each other. @@ -84,22 +81,21 @@ func (suite *BlobServiceTestSuite) SetupTest() { signalerCtx := irrecoverable.NewMockSignalerContext(suite.T(), ctx) - ids, nodes, mws, networks, _ := testutils.GenerateIDsMiddlewaresNetworks( - suite.T(), + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(suite.T(), suite.numNodes, - logger, - unittest.NetworkCodec(), - mocknetwork.NewViolationsConsumer(suite.T()), - testutils.WithDHT("blob_service_test", dht.AsServer()), - testutils.WithPeerUpdateInterval(time.Second), - ) - suite.networks = networks - - testutils.StartNodesAndNetworks(signalerCtx, suite.T(), nodes, networks, 100*time.Millisecond) + p2ptest.WithDHTOptions(dht.AsServer()), + p2ptest.WithPeerManagerEnabled(&p2pconfig.PeerManagerConfig{ + UpdateInterval: 1 * time.Second, + ConnectionPruning: true, + ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), + }, nil)) + mws, _ := testutils.MiddlewareFixtures(suite.T(), ids, nodes, testutils.MiddlewareConfigFixture(suite.T())) + suite.networks = testutils.NetworksFixture(suite.T(), ids, mws) + testutils.StartNodesAndNetworks(signalerCtx, suite.T(), nodes, suite.networks, 100*time.Millisecond) blobExchangeChannel := channels.Channel("blob-exchange") - for i, net := range networks { + for i, net := range suite.networks { ds := sync.MutexWrap(datastore.NewMapDatastore()) suite.datastores = append(suite.datastores, ds) blob := blobs.NewBlob([]byte(fmt.Sprintf("foo%v", i))) @@ -107,7 +103,7 @@ func (suite *BlobServiceTestSuite) SetupTest() { suite.putBlob(ds, blob) blobService, err := net.RegisterBlobService(blobExchangeChannel, ds) suite.Require().NoError(err) - <-blobService.Ready() + unittest.RequireCloseBefore(suite.T(), blobService.Ready(), 100*time.Millisecond, "blob service not ready") suite.blobServices = append(suite.blobServices, blobService) } diff --git a/network/test/echoengine_test.go b/network/test/echoengine_test.go index d04c1a6007c..eb170cbf266 100644 --- a/network/test/echoengine_test.go +++ b/network/test/echoengine_test.go @@ -3,16 +3,12 @@ package test import ( "context" "fmt" - "os" "strings" "sync" "testing" "time" - "github.com/onflow/flow-go/network/p2p" - "github.com/ipfs/go-log" - "github.com/rs/zerolog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -23,7 +19,7 @@ import ( "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/channels" "github.com/onflow/flow-go/network/internal/testutils" - "github.com/onflow/flow-go/network/mocknetwork" + "github.com/onflow/flow-go/network/p2p" "github.com/onflow/flow-go/utils/unittest" ) @@ -48,7 +44,6 @@ func TestStubEngineTestSuite(t *testing.T) { func (suite *EchoEngineTestSuite) SetupTest() { const count = 2 - logger := zerolog.New(os.Stderr).Level(zerolog.ErrorLevel) log.SetAllLoggers(log.LevelError) ctx, cancel := context.WithCancel(context.Background()) @@ -58,14 +53,9 @@ func (suite *EchoEngineTestSuite) SetupTest() { // both nodes should be of the same role to get connected on epidemic dissemination var nodes []p2p.LibP2PNode - suite.ids, nodes, suite.mws, suite.nets, _ = testutils.GenerateIDsMiddlewaresNetworks( - suite.T(), - count, - logger, - unittest.NetworkCodec(), - mocknetwork.NewViolationsConsumer(suite.T()), - ) - + suite.ids, nodes, _ = testutils.LibP2PNodeForMiddlewareFixture(suite.T(), count) + suite.mws, _ = testutils.MiddlewareFixtures(suite.T(), suite.ids, nodes, testutils.MiddlewareConfigFixture(suite.T())) + suite.nets = testutils.NetworksFixture(suite.T(), suite.ids, suite.mws) testutils.StartNodesAndNetworks(signalerCtx, suite.T(), nodes, suite.nets, 100*time.Millisecond) } diff --git a/network/test/epochtransition_test.go b/network/test/epochtransition_test.go index 8b7c0a655bd..e471b1d8f48 100644 --- a/network/test/epochtransition_test.go +++ b/network/test/epochtransition_test.go @@ -24,7 +24,6 @@ import ( "github.com/onflow/flow-go/module/irrecoverable" "github.com/onflow/flow-go/network" "github.com/onflow/flow-go/network/internal/testutils" - "github.com/onflow/flow-go/network/mocknetwork" mockprotocol "github.com/onflow/flow-go/state/protocol/mock" "github.com/onflow/flow-go/utils/unittest" ) @@ -181,13 +180,9 @@ func (suite *MutableIdentityTableSuite) addNodes(count int) { signalerCtx := irrecoverable.NewMockSignalerContext(suite.T(), ctx) // create the ids, middlewares and networks - ids, nodes, mws, nets, _ := testutils.GenerateIDsMiddlewaresNetworks( - suite.T(), - count, - suite.logger, - unittest.NetworkCodec(), - mocknetwork.NewViolationsConsumer(suite.T()), - ) + ids, nodes, _ := testutils.LibP2PNodeForMiddlewareFixture(suite.T(), count) + mws, _ := testutils.MiddlewareFixtures(suite.T(), ids, nodes, testutils.MiddlewareConfigFixture(suite.T())) + nets := testutils.NetworksFixture(suite.T(), ids, mws) suite.cancels = append(suite.cancels, cancel) testutils.StartNodesAndNetworks(signalerCtx, suite.T(), nodes, nets, 100*time.Millisecond) diff --git a/network/test/meshengine_test.go b/network/test/meshengine_test.go index 221bba44bc2..612d7679796 100644 --- a/network/test/meshengine_test.go +++ b/network/test/meshengine_test.go @@ -20,7 +20,6 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "github.com/onflow/flow-go/network/mocknetwork" "github.com/onflow/flow-go/network/p2p/middleware" "github.com/onflow/flow-go/network/p2p/p2pnode" @@ -74,15 +73,9 @@ func (suite *MeshEngineTestSuite) SetupTest() { signalerCtx := irrecoverable.NewMockSignalerContext(suite.T(), ctx) var nodes []p2p.LibP2PNode - suite.ids, nodes, suite.mws, suite.nets, obs = testutils.GenerateIDsMiddlewaresNetworks( - suite.T(), - count, - logger, - unittest.NetworkCodec(), - mocknetwork.NewViolationsConsumer(suite.T()), - testutils.WithIdentityOpts(unittest.WithAllRoles()), - ) - + suite.ids, nodes, obs = testutils.LibP2PNodeForMiddlewareFixture(suite.T(), count) + suite.mws, _ = testutils.MiddlewareFixtures(suite.T(), suite.ids, nodes, testutils.MiddlewareConfigFixture(suite.T())) + suite.nets = testutils.NetworksFixture(suite.T(), suite.ids, suite.mws) testutils.StartNodesAndNetworks(signalerCtx, suite.T(), nodes, suite.nets, 100*time.Millisecond) for _, observableConnMgr := range obs { diff --git a/network/test/middleware_test.go b/network/test/middleware_test.go index 811b100e52f..8c0c1adb4f0 100644 --- a/network/test/middleware_test.go +++ b/network/test/middleware_test.go @@ -38,7 +38,6 @@ import ( p2ptest "github.com/onflow/flow-go/network/p2p/test" "github.com/onflow/flow-go/network/p2p/unicast/ratelimit" "github.com/onflow/flow-go/network/p2p/utils/ratelimiter" - "github.com/onflow/flow-go/network/slashing" "github.com/onflow/flow-go/utils/unittest" ) @@ -80,12 +79,10 @@ type MiddlewareTestSuite struct { ids []*flow.Identity metrics *metrics.NoopCollector // no-op performance monitoring simulation logger zerolog.Logger - providers []*testutils.UpdatableIDProvider + providers []*unittest.UpdatableIDProvider mwCancel context.CancelFunc mwCtx irrecoverable.SignalerContext - - slashingViolationsConsumer slashing.ViolationsConsumer } // TestMiddlewareTestSuit runs all the test methods in this test suit @@ -109,14 +106,8 @@ func (m *MiddlewareTestSuite) SetupTest() { log: m.logger, } - m.slashingViolationsConsumer = mocknetwork.NewViolationsConsumer(m.T()) - - m.ids, m.nodes, m.mws, obs, m.providers = testutils.GenerateIDsAndMiddlewares(m.T(), - m.size, - m.logger, - unittest.NetworkCodec(), - m.slashingViolationsConsumer) - + m.ids, m.nodes, obs = testutils.LibP2PNodeForMiddlewareFixture(m.T(), m.size) + m.mws, m.providers = testutils.MiddlewareFixtures(m.T(), m.ids, m.nodes, testutils.MiddlewareConfigFixture(m.T())) for _, observableConnMgr := range obs { observableConnMgr.Subscribe(&ob) } @@ -166,9 +157,8 @@ func (m *MiddlewareTestSuite) TestUpdateNodeAddresses() { irrecoverableCtx := irrecoverable.NewMockSignalerContext(m.T(), ctx) // create a new staked identity - ids, libP2PNodes, _ := testutils.GenerateIDs(m.T(), m.logger, 1) - - mws, providers := testutils.GenerateMiddlewares(m.T(), m.logger, ids, libP2PNodes, unittest.NetworkCodec(), m.slashingViolationsConsumer) + ids, libP2PNodes, _ := testutils.LibP2PNodeForMiddlewareFixture(m.T(), 1) + mws, providers := testutils.MiddlewareFixtures(m.T(), ids, libP2PNodes, testutils.MiddlewareConfigFixture(m.T())) require.Len(m.T(), ids, 1) require.Len(m.T(), providers, 1) require.Len(m.T(), mws, 1) @@ -248,33 +238,26 @@ func (m *MiddlewareTestSuite) TestUnicastRateLimit_Messages() { opts := []ratelimit.RateLimitersOption{ratelimit.WithMessageRateLimiter(messageRateLimiter), ratelimit.WithNotifier(distributor), ratelimit.WithDisabledRateLimiting(false)} rateLimiters := ratelimit.NewRateLimiters(opts...) - idProvider := testutils.NewUpdatableIDProvider(m.ids) - // create a new staked identity - connGaterFactory := func() p2p.ConnectionGater { - return testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + idProvider := unittest.NewUpdatableIDProvider(m.ids) + + ids, libP2PNodes, _ := testutils.LibP2PNodeForMiddlewareFixture(m.T(), + 1, + p2ptest.WithUnicastRateLimitDistributor(distributor), + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { if messageRateLimiter.IsRateLimited(pid) { return fmt.Errorf("rate-limited peer") } return nil - }) - } - - ids, libP2PNodes, _ := testutils.GenerateIDs(m.T(), - m.logger, - 1, - testutils.WithUnicastRateLimiterDistributor(distributor), - testutils.WithConnectionGaterFactory(connGaterFactory)) + }))) idProvider.SetIdentities(append(m.ids, ids...)) // create middleware - mws, providers := testutils.GenerateMiddlewares(m.T(), - m.logger, + mws, providers := testutils.MiddlewareFixtures(m.T(), ids, libP2PNodes, - unittest.NetworkCodec(), - m.slashingViolationsConsumer, - testutils.WithUnicastRateLimiters(rateLimiters), - testutils.WithPeerManagerFilters(testutils.IsRateLimitedPeerFilter(messageRateLimiter))) + testutils.MiddlewareConfigFixture(m.T()), + middleware.WithUnicastRateLimiters(rateLimiters), + middleware.WithPeerManagerFilters([]p2p.PeerFilter{testutils.IsRateLimitedPeerFilter(messageRateLimiter)})) require.Len(m.T(), ids, 1) require.Len(m.T(), providers, 1) @@ -406,34 +389,28 @@ func (m *MiddlewareTestSuite) TestUnicastRateLimit_Bandwidth() { opts := []ratelimit.RateLimitersOption{ratelimit.WithBandwidthRateLimiter(bandwidthRateLimiter), ratelimit.WithNotifier(distributor), ratelimit.WithDisabledRateLimiting(false)} rateLimiters := ratelimit.NewRateLimiters(opts...) - idProvider := testutils.NewUpdatableIDProvider(m.ids) - // create connection gater, connection gater will refuse connections from rate limited nodes - connGaterFactory := func() p2p.ConnectionGater { - return testutils.NewConnectionGater(idProvider, func(pid peer.ID) error { + idProvider := unittest.NewUpdatableIDProvider(m.ids) + // create a new staked identity + ids, libP2PNodes, _ := testutils.LibP2PNodeForMiddlewareFixture(m.T(), + 1, + p2ptest.WithUnicastRateLimitDistributor(distributor), + p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(pid peer.ID) error { + // create connection gater, connection gater will refuse connections from rate limited nodes if bandwidthRateLimiter.IsRateLimited(pid) { return fmt.Errorf("rate-limited peer") } return nil - }) - } - // create a new staked identity - ids, libP2PNodes, _ := testutils.GenerateIDs(m.T(), - m.logger, - 1, - testutils.WithUnicastRateLimiterDistributor(distributor), - testutils.WithConnectionGaterFactory(connGaterFactory)) + }))) idProvider.SetIdentities(append(m.ids, ids...)) // create middleware - mws, providers := testutils.GenerateMiddlewares(m.T(), - m.logger, + mws, providers := testutils.MiddlewareFixtures(m.T(), ids, libP2PNodes, - unittest.NetworkCodec(), - m.slashingViolationsConsumer, - testutils.WithUnicastRateLimiters(rateLimiters), - testutils.WithPeerManagerFilters(testutils.IsRateLimitedPeerFilter(bandwidthRateLimiter))) + testutils.MiddlewareConfigFixture(m.T()), + middleware.WithUnicastRateLimiters(rateLimiters), + middleware.WithPeerManagerFilters([]p2p.PeerFilter{testutils.IsRateLimitedPeerFilter(bandwidthRateLimiter)})) require.Len(m.T(), ids, 1) require.Len(m.T(), providers, 1) require.Len(m.T(), mws, 1) @@ -524,7 +501,7 @@ func (m *MiddlewareTestSuite) TestUnicastRateLimit_Bandwidth() { require.Equal(m.T(), uint64(1), rateLimits.Load()) } -func (m *MiddlewareTestSuite) createOverlay(provider *testutils.UpdatableIDProvider) *mocknetwork.Overlay { +func (m *MiddlewareTestSuite) createOverlay(provider *unittest.UpdatableIDProvider) *mocknetwork.Overlay { overlay := &mocknetwork.Overlay{} overlay.On("Identities").Maybe().Return(func() flow.IdentityList { return provider.Identities(filter.Any) diff --git a/network/test/unicast_authorization_test.go b/network/test/unicast_authorization_test.go index 6fe4d0b8b58..f4a4171944d 100644 --- a/network/test/unicast_authorization_test.go +++ b/network/test/unicast_authorization_test.go @@ -47,7 +47,7 @@ type UnicastAuthorizationTestSuite struct { // receiverID the identity on the mw sending the message receiverID *flow.Identity // providers id providers generated at beginning of a test run - providers []*testutils.UpdatableIDProvider + providers []*unittest.UpdatableIDProvider // cancel is the cancel func from the context that was used to start the middlewares in a test run cancel context.CancelFunc // waitCh is the channel used to wait for the middleware to perform authorization and invoke the slashing @@ -74,8 +74,10 @@ func (u *UnicastAuthorizationTestSuite) TearDownTest() { // setupMiddlewaresAndProviders will setup 2 middlewares that will be used as a sender and receiver in each suite test. func (u *UnicastAuthorizationTestSuite) setupMiddlewaresAndProviders(slashingViolationsConsumer slashing.ViolationsConsumer) { - ids, libP2PNodes, _ := testutils.GenerateIDs(u.T(), u.logger, 2) - mws, providers := testutils.GenerateMiddlewares(u.T(), u.logger, ids, libP2PNodes, unittest.NetworkCodec(), slashingViolationsConsumer) + ids, libP2PNodes, _ := testutils.LibP2PNodeForMiddlewareFixture(u.T(), 2) + cfg := testutils.MiddlewareConfigFixture(u.T()) + cfg.SlashingViolationsConsumer = slashingViolationsConsumer + mws, providers := testutils.MiddlewareFixtures(u.T(), ids, libP2PNodes, cfg) require.Len(u.T(), ids, 2) require.Len(u.T(), providers, 2) require.Len(u.T(), mws, 2) diff --git a/network/internal/testutils/updatable_provider.go b/utils/unittest/updatable_provider.go similarity index 98% rename from network/internal/testutils/updatable_provider.go rename to utils/unittest/updatable_provider.go index 014ae696b99..9661f7039a6 100644 --- a/network/internal/testutils/updatable_provider.go +++ b/utils/unittest/updatable_provider.go @@ -1,4 +1,4 @@ -package testutils +package unittest import ( "sync"