You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
2.2 KiB

  1. package behaviour
  2. import (
  3. "errors"
  4. "sync"
  5. "github.com/tendermint/tendermint/p2p"
  6. )
  7. // Reporter provides an interface for reactors to report the behaviour
  8. // of peers synchronously to other components.
  9. type Reporter interface {
  10. Report(behaviour PeerBehaviour) error
  11. }
  12. // SwitchReporter reports peer behaviour to an internal Switch.
  13. type SwitchReporter struct {
  14. sw *p2p.Switch
  15. }
  16. // NewSwitchReporter return a new SwitchReporter instance which wraps the Switch.
  17. func NewSwitcReporter(sw *p2p.Switch) *SwitchReporter {
  18. return &SwitchReporter{
  19. sw: sw,
  20. }
  21. }
  22. // Report reports the behaviour of a peer to the Switch.
  23. func (spbr *SwitchReporter) Report(behaviour PeerBehaviour) error {
  24. peer := spbr.sw.Peers().Get(behaviour.peerID)
  25. if peer == nil {
  26. return errors.New("peer not found")
  27. }
  28. switch reason := behaviour.reason.(type) {
  29. case consensusVote, blockPart:
  30. spbr.sw.MarkPeerAsGood(peer)
  31. case badMessage:
  32. spbr.sw.StopPeerForError(peer, reason.explanation)
  33. case messageOutOfOrder:
  34. spbr.sw.StopPeerForError(peer, reason.explanation)
  35. default:
  36. return errors.New("unknown reason reported")
  37. }
  38. return nil
  39. }
  40. // MockReporter is a concrete implementation of the Reporter
  41. // interface used in reactor tests to ensure reactors report the correct
  42. // behaviour in manufactured scenarios.
  43. type MockReporter struct {
  44. mtx sync.RWMutex
  45. pb map[p2p.ID][]PeerBehaviour
  46. }
  47. // NewMockReporter returns a Reporter which records all reported
  48. // behaviours in memory.
  49. func NewMockReporter() *MockReporter {
  50. return &MockReporter{
  51. pb: map[p2p.ID][]PeerBehaviour{},
  52. }
  53. }
  54. // Report stores the PeerBehaviour produced by the peer identified by peerID.
  55. func (mpbr *MockReporter) Report(behaviour PeerBehaviour) {
  56. mpbr.mtx.Lock()
  57. defer mpbr.mtx.Unlock()
  58. mpbr.pb[behaviour.peerID] = append(mpbr.pb[behaviour.peerID], behaviour)
  59. }
  60. // GetBehaviours returns all behaviours reported on the peer identified by peerID.
  61. func (mpbr *MockReporter) GetBehaviours(peerID p2p.ID) []PeerBehaviour {
  62. mpbr.mtx.RLock()
  63. defer mpbr.mtx.RUnlock()
  64. if items, ok := mpbr.pb[peerID]; ok {
  65. result := make([]PeerBehaviour, len(items))
  66. copy(result, items)
  67. return result
  68. } else {
  69. return []PeerBehaviour{}
  70. }
  71. }