mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
* p2p: initial implementation of peer behaviour * [p2p] re-use newMockPeer * p2p: add inline docs for peer_behaviour interface * [p2p] Align PeerBehaviour interface (#3558) * [p2p] make switchedPeerHebaviour private * [p2p] make storePeerHebaviour private * [p2p] Add CHANGELOG_PENDING entry for PeerBehaviour * [p2p] Adjustment naming for PeerBehaviour * [p2p] Add coarse lock around storedPeerBehaviour * [p2p]: Fix non-pointer methods in storedPeerBehaviour + Structs with embeded locks must specify all methods with pointer receivers to avoid creating a copy of the embeded lock. * [p2p] Thorough refactoring based on comments in #3552 + Decouple PeerBehaviour interface from Peer by parametrizing methods with `p2p.ID` instead of `p2p.Peer` + Setter methods wrapped in a write lock + Getter methods wrapped in a read lock + Getter methods on storedPeerBehaviour now take a `p2p.ID` + Getter methods return a copy of underlying stored behaviours + Add doc strings to public types and methods * [p2p] make structs public * [p2p] Test empty StoredPeerBehaviour * [p2p] typo fix * [p2p] add TestStoredPeerBehaviourConcurrency + Add a test which uses StoredPeerBehaviour in multiple goroutines to ensure thread-safety. * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour_test.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * Update p2p/peer_behaviour.go Co-Authored-By: brapse <brapse@gmail.com> * [p2p] field ordering convention * p2p: peer behaviour refactor + Change naming of reporting behaviour to `Report` + Remove the responsibility of distinguishing between the categories of good and bad behaviour and instead focus on reporting behaviour. * p2p: rename PeerReporter -> PeerBehaviourReporter
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package p2p
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
)
|
|
|
|
// PeerBehaviour are types of reportable behaviours about peers.
|
|
type PeerBehaviour int
|
|
|
|
const (
|
|
PeerBehaviourBadMessage = iota
|
|
PeerBehaviourMessageOutOfOrder
|
|
PeerBehaviourVote
|
|
PeerBehaviourBlockPart
|
|
)
|
|
|
|
// PeerBehaviourReporter provides an interface for reactors to report the behaviour
|
|
// of peers synchronously to other components.
|
|
type PeerBehaviourReporter interface {
|
|
Report(peerID ID, behaviour PeerBehaviour) error
|
|
}
|
|
|
|
// SwitchPeerBehaviouReporter reports peer behaviour to an internal Switch
|
|
type SwitchPeerBehaviourReporter struct {
|
|
sw *Switch
|
|
}
|
|
|
|
// Return a new SwitchPeerBehaviourReporter instance which wraps the Switch.
|
|
func NewSwitchPeerBehaviourReporter(sw *Switch) *SwitchPeerBehaviourReporter {
|
|
return &SwitchPeerBehaviourReporter{
|
|
sw: sw,
|
|
}
|
|
}
|
|
|
|
// Report reports the behaviour of a peer to the Switch
|
|
func (spbr *SwitchPeerBehaviourReporter) Report(peerID ID, behaviour PeerBehaviour) error {
|
|
peer := spbr.sw.Peers().Get(peerID)
|
|
if peer == nil {
|
|
return errors.New("Peer not found")
|
|
}
|
|
|
|
switch behaviour {
|
|
case PeerBehaviourVote, PeerBehaviourBlockPart:
|
|
spbr.sw.MarkPeerAsGood(peer)
|
|
case PeerBehaviourBadMessage:
|
|
spbr.sw.StopPeerForError(peer, "Bad message")
|
|
case PeerBehaviourMessageOutOfOrder:
|
|
spbr.sw.StopPeerForError(peer, "Message out of order")
|
|
default:
|
|
return errors.New("Unknown behaviour")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// MockPeerBehaviourReporter serves a mock concrete implementation of the
|
|
// PeerBehaviourReporter interface used in reactor tests to ensure reactors
|
|
// report the correct behaviour in manufactured scenarios.
|
|
type MockPeerBehaviourReporter struct {
|
|
mtx sync.RWMutex
|
|
pb map[ID][]PeerBehaviour
|
|
}
|
|
|
|
// NewMockPeerBehaviourReporter returns a PeerBehaviourReporter which records all reported
|
|
// behaviours in memory.
|
|
func NewMockPeerBehaviourReporter() *MockPeerBehaviourReporter {
|
|
return &MockPeerBehaviourReporter{
|
|
pb: map[ID][]PeerBehaviour{},
|
|
}
|
|
}
|
|
|
|
// Report stores the PeerBehaviour produced by the peer identified by peerID.
|
|
func (mpbr *MockPeerBehaviourReporter) Report(peerID ID, behaviour PeerBehaviour) {
|
|
mpbr.mtx.Lock()
|
|
defer mpbr.mtx.Unlock()
|
|
mpbr.pb[peerID] = append(mpbr.pb[peerID], behaviour)
|
|
}
|
|
|
|
// GetBehaviours returns all behaviours reported on the peer identified by peerID.
|
|
func (mpbr *MockPeerBehaviourReporter) GetBehaviours(peerID ID) []PeerBehaviour {
|
|
mpbr.mtx.RLock()
|
|
defer mpbr.mtx.RUnlock()
|
|
if items, ok := mpbr.pb[peerID]; ok {
|
|
result := make([]PeerBehaviour, len(items))
|
|
copy(result, items)
|
|
|
|
return result
|
|
} else {
|
|
return []PeerBehaviour{}
|
|
}
|
|
}
|