Skip to content

Commit

Permalink
feat(dot/peerset): Implement peer scoring (ChainSafe#1791)
Browse files Browse the repository at this point in the history
* Implement peerState and PSM (Peer Set Manager) and add test cases.

* Address comments and add unit test.

* Remove channel from sorted peers
  • Loading branch information
arijitAD authored and timwu20 committed Dec 6, 2021
1 parent 4e049d1 commit 05f7e32
Show file tree
Hide file tree
Showing 43 changed files with 2,405 additions and 205 deletions.
5 changes: 3 additions & 2 deletions chain/dev/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
package dev

import (
log "github.com/ChainSafe/log15"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
log "github.com/ChainSafe/log15"
)

var (
Expand Down Expand Up @@ -76,7 +77,7 @@ var (
// NetworkConfig

// DefaultNetworkPort network port
DefaultNetworkPort = uint32(7001)
DefaultNetworkPort = uint16(7001)
// DefaultNetworkBootnodes network bootnodes
DefaultNetworkBootnodes = []string(nil)
// DefaultNoBootstrap disables bootstrap
Expand Down
5 changes: 3 additions & 2 deletions chain/gssmr/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ package gssmr
import (
"time"

log "github.com/ChainSafe/log15"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
log "github.com/ChainSafe/log15"
)

var (
Expand Down Expand Up @@ -78,7 +79,7 @@ var (
// NetworkConfig

// DefaultNetworkPort network port
DefaultNetworkPort = uint32(7001)
DefaultNetworkPort = uint16(7001)
// DefaultNetworkBootnodes network bootnodes
DefaultNetworkBootnodes = []string(nil)
// DefaultNoBootstrap disables bootstrap
Expand Down
5 changes: 3 additions & 2 deletions chain/kusama/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
package kusama

import (
log "github.com/ChainSafe/log15"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
log "github.com/ChainSafe/log15"
)

var (
Expand Down Expand Up @@ -72,7 +73,7 @@ var (
// NetworkConfig

// DefaultNetworkPort network port
DefaultNetworkPort = uint32(7001)
DefaultNetworkPort = uint16(7001)
// DefaultNetworkBootnodes network bootnodes
DefaultNetworkBootnodes = []string(nil)
// DefaultNoBootstrap disables bootstrap
Expand Down
5 changes: 3 additions & 2 deletions chain/polkadot/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
package polkadot

import (
log "github.com/ChainSafe/log15"

"github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
log "github.com/ChainSafe/log15"
)

var (
Expand Down Expand Up @@ -73,7 +74,7 @@ var (
// NetworkConfig

// DefaultNetworkPort network port
DefaultNetworkPort = uint32(7001)
DefaultNetworkPort = uint16(7001)
// DefaultNetworkBootnodes network bootnodes
DefaultNetworkBootnodes = []string(nil)
// DefaultNoBootstrap disables bootstrap
Expand Down
2 changes: 1 addition & 1 deletion cmd/gossamer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ func setDotNetworkConfig(ctx *cli.Context, tomlCfg ctoml.NetworkConfig, cfg *dot

// check --port flag and update node configuration
if port := ctx.GlobalUint(PortFlag.Name); port != 0 {
cfg.Port = uint32(port)
cfg.Port = uint16(port)
}

// check --bootnodes flag and update node configuration
Expand Down
5 changes: 3 additions & 2 deletions dot/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import (
"encoding/json"
"time"

log "github.com/ChainSafe/log15"

"github.com/ChainSafe/gossamer/chain/dev"
"github.com/ChainSafe/gossamer/chain/gssmr"
"github.com/ChainSafe/gossamer/chain/kusama"
"github.com/ChainSafe/gossamer/chain/polkadot"
"github.com/ChainSafe/gossamer/dot/state/pruner"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/genesis"
log "github.com/ChainSafe/log15"
)

// TODO: update config to have toml rules and perhaps un-export some fields, since we don't want to expose all
Expand Down Expand Up @@ -85,7 +86,7 @@ type AccountConfig struct {

// NetworkConfig is to marshal/unmarshal toml network config vars
type NetworkConfig struct {
Port uint32
Port uint16
Bootnodes []string
ProtocolID string
NoBootstrap bool
Expand Down
2 changes: 1 addition & 1 deletion dot/config/toml/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type AccountConfig struct {

// NetworkConfig is to marshal/unmarshal toml network config vars
type NetworkConfig struct {
Port uint32 `toml:"port,omitempty"`
Port uint16 `toml:"port,omitempty"`
Bootnodes []string `toml:"bootnodes,omitempty"`
ProtocolID string `toml:"protocol,omitempty"`
NoBootstrap bool `toml:"nobootstrap,omitempty"`
Expand Down
4 changes: 4 additions & 0 deletions dot/core/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import (
"math/big"
"sync"

"github.com/libp2p/go-libp2p-core/peer"

"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/peerset"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/runtime"
Expand Down Expand Up @@ -86,6 +89,7 @@ type TransactionState interface {
type Network interface {
GossipMessage(network.NotificationsMessage)
IsSynced() bool
ReportPeer(change peerset.ReputationChange, p peer.ID)
}

// EpochState is the interface for state.EpochState
Expand Down
19 changes: 18 additions & 1 deletion dot/core/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@
package core

import (
"errors"

"github.com/libp2p/go-libp2p-core/peer"

"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/peerset"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/runtime"
"github.com/ChainSafe/gossamer/lib/transaction"
)

// HandleTransactionMessage validates each transaction in the message and
// adds valid transactions to the transaction queue of the BABE session
// returns boolean for transaction propagation, true - transactions should be propagated
func (s *Service) HandleTransactionMessage(msg *network.TransactionMessage) (bool, error) {
func (s *Service) HandleTransactionMessage(peerID peer.ID, msg *network.TransactionMessage) (bool, error) {
logger.Debug("received TransactionMessage")

if !s.net.IsSynced() {
Expand Down Expand Up @@ -64,6 +70,12 @@ func (s *Service) HandleTransactionMessage(msg *network.TransactionMessage) (boo
externalExt := types.Extrinsic(append([]byte{byte(types.TxnExternal)}, tx...))
val, err := rt.ValidateTransaction(externalExt)
if err != nil {
if errors.Is(err, runtime.ErrInvalidTransaction) {
s.net.ReportPeer(peerset.ReputationChange{
Value: peerset.BadTransactionValue,
Reason: peerset.BadTransactionReason,
}, peerID)
}
logger.Debug("failed to validate transaction", "err", err)
return nil
}
Expand All @@ -88,6 +100,11 @@ func (s *Service) HandleTransactionMessage(msg *network.TransactionMessage) (boo
}
}

s.net.ReportPeer(peerset.ReputationChange{
Value: peerset.GoodTransactionValue,
Reason: peerset.GoodTransactionReason,
}, peerID)

msg.Extrinsics = toPropagate
return len(msg.Extrinsics) > 0, nil
}
Expand Down
17 changes: 10 additions & 7 deletions dot/core/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import (
"testing"
"time"

"github.com/centrifuge/go-substrate-rpc-client/v3/signature"
ctypes "github.com/centrifuge/go-substrate-rpc-client/v3/types"
"github.com/stretchr/testify/require"

"github.com/ChainSafe/gossamer/dot/core/mocks"
"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/state"
Expand All @@ -31,11 +35,6 @@ import (
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/lib/runtime"
"github.com/ChainSafe/gossamer/pkg/scale"

"github.com/centrifuge/go-substrate-rpc-client/v3/signature"
ctypes "github.com/centrifuge/go-substrate-rpc-client/v3/types"

"github.com/stretchr/testify/require"
)

func createExtrinsic(t *testing.T, rt runtime.Instance, genHash common.Hash, nonce uint64) types.Extrinsic {
Expand Down Expand Up @@ -128,6 +127,10 @@ func TestService_HandleBlockProduced(t *testing.T) {
}

func TestService_HandleTransactionMessage(t *testing.T) {
t.Parallel()

const peer1 = "testPeer1"

kp, err := sr25519.GenerateKeypair()
require.NoError(t, err)

Expand Down Expand Up @@ -158,7 +161,7 @@ func TestService_HandleTransactionMessage(t *testing.T) {

extBytes := createExtrinsic(t, rt, genHash, 0)
msg := &network.TransactionMessage{Extrinsics: []types.Extrinsic{extBytes}}
b, err := s.HandleTransactionMessage(msg)
b, err := s.HandleTransactionMessage(peer1, msg)
require.NoError(t, err)
require.True(t, b)

Expand All @@ -168,7 +171,7 @@ func TestService_HandleTransactionMessage(t *testing.T) {

extBytes = []byte(`bogus extrinsic`)
msg = &network.TransactionMessage{Extrinsics: []types.Extrinsic{extBytes}}
b, err = s.HandleTransactionMessage(msg)
b, err = s.HandleTransactionMessage(peer1, msg)
require.NoError(t, err)
require.False(t, b)
}
9 changes: 9 additions & 0 deletions dot/core/mocks/Network.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 5 additions & 9 deletions dot/core/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ import (
"path/filepath"
"testing"

log "github.com/ChainSafe/log15"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

coremocks "github.com/ChainSafe/gossamer/dot/core/mocks"
"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
Expand All @@ -32,9 +35,6 @@ import (
rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage"
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
"github.com/ChainSafe/gossamer/lib/utils"
log "github.com/ChainSafe/log15"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

// NewTestService creates a new test core service
Expand Down Expand Up @@ -127,6 +127,7 @@ func NewTestService(t *testing.T, cfg *Config) *Service {
net := new(coremocks.Network)
net.On("GossipMessage", mock.AnythingOfType("*network.TransactionMessage"))
net.On("IsSynced").Return(true)
net.On("ReportPeer", mock.AnythingOfType("peerset.ReputationChange"), mock.AnythingOfType("peer.ID"))
cfg.Network = net
}

Expand All @@ -148,10 +149,5 @@ func NewTestService(t *testing.T, cfg *Config) *Service {
s, err := NewService(cfg)
require.NoError(t, err)

if net, ok := cfg.Network.(*network.Service); ok {
net.SetTransactionHandler(s)
_ = net.Stop()
}

return s
}
4 changes: 2 additions & 2 deletions dot/network/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const (
DefaultBasePath = "~/.gossamer/gssmr"

// DefaultPort the default value for Config.Port
DefaultPort = uint32(7000)
DefaultPort = uint16(7000)

// DefaultRandSeed the default value for Config.RandSeed (0 = non-deterministic)
DefaultRandSeed = int64(0)
Expand Down Expand Up @@ -74,7 +74,7 @@ type Config struct {
TransactionHandler TransactionHandler

// Port the network port used for listening
Port uint32
Port uint16
// RandSeed the seed used to generate the network p2p identity (0 = non-deterministic random seed)
RandSeed int64
// Bootnodes the peer addresses used for bootstrapping
Expand Down
Loading

0 comments on commit 05f7e32

Please sign in to comment.