Skip to content

Commit

Permalink
Add LoggingMisbehaviorService
Browse files Browse the repository at this point in the history
  • Loading branch information
neekolas committed Jan 15, 2025
1 parent 93e176c commit 7666a1b
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pkg/misbehavior/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package misbehavior

type MisbehaviorService interface {
SafetyFailure(report *SafetyFailureReport) error
// TODO:nm add liveness failures
}
34 changes: 34 additions & 0 deletions pkg/misbehavior/misbehavior.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package misbehavior

import (
"errors"

"go.uber.org/zap"
)

// LoggingMisbehaviorService provides an implementation of the MisbehaviorService interface that
// logs misbehavior reports without storing them or forwarding to the network.
type LoggingMisbehaviorService struct {
log *zap.Logger
}

func NewLoggingMisbehaviorService(log *zap.Logger) *LoggingMisbehaviorService {
return &LoggingMisbehaviorService{
log: log.Named("misbehavior"),
}
}

func (m *LoggingMisbehaviorService) SafetyFailure(report *SafetyFailureReport) error {
if report == nil {
return errors.New("report is nil")
}
m.log.Warn(
"misbehavior detected",
zap.String("misbehavior_type", report.misbehaviorType.String()),
zap.Uint32("misbehaving_node_id", report.misbehavingNodeId),
zap.Bool("submitted_by_node", report.submittedByNode),
zap.Any("envelopes", report.envelopes),
)

return nil
}
77 changes: 77 additions & 0 deletions pkg/misbehavior/misbehavior_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package misbehavior

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/xmtp/xmtpd/pkg/envelopes"
proto "github.com/xmtp/xmtpd/pkg/proto/xmtpv4/message_api"
testEnvelopes "github.com/xmtp/xmtpd/pkg/testutils/envelopes"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
)

func TestLoggingMisbehaviorService(t *testing.T) {
env1, err := envelopes.NewOriginatorEnvelope(testEnvelopes.CreateOriginatorEnvelope(t, 1, 1))
require.NoError(t, err)
env2, err := envelopes.NewOriginatorEnvelope(testEnvelopes.CreateOriginatorEnvelope(t, 1, 2))
require.NoError(t, err)

report, err := NewSafetyFailureReport(
1,
proto.Misbehavior_MISBEHAVIOR_DUPLICATE_SEQUENCE_ID,
true,
[]*envelopes.OriginatorEnvelope{env1, env2},
)
require.NoError(t, err)

core, observedLogs := observer.New(zapcore.DebugLevel)
logger := zap.New(core)
service := NewLoggingMisbehaviorService(logger)

err = service.SafetyFailure(report)
require.NoError(t, err)

logs := observedLogs.All()
require.Len(t, logs, 1)
logEntry := logs[0]
require.Equal(t, "misbehavior detected", logEntry.Message)
require.Equal(t, "MISBEHAVIOR_DUPLICATE_SEQUENCE_ID", logEntry.ContextMap()["misbehavior_type"])
require.Equal(t, uint32(1), logEntry.ContextMap()["misbehaving_node_id"])
require.Equal(t, true, logEntry.ContextMap()["submitted_by_node"])
require.Len(t, logEntry.ContextMap()["envelopes"], 2)
}

func TestNewSafetyFailureReportValidations(t *testing.T) {
// Test case: No envelopes provided
_, err := NewSafetyFailureReport(
1,
proto.Misbehavior_MISBEHAVIOR_DUPLICATE_SEQUENCE_ID,
true,
nil,
)
require.Error(t, err)
require.Equal(t, "no envelopes provided", err.Error())

// Test case: Misbehaving node ID is zero
env, _ := envelopes.NewOriginatorEnvelope(testEnvelopes.CreateOriginatorEnvelope(t, 1, 1))
_, err = NewSafetyFailureReport(
0,
proto.Misbehavior_MISBEHAVIOR_DUPLICATE_SEQUENCE_ID,
true,
[]*envelopes.OriginatorEnvelope{env},
)
require.Error(t, err)
require.Equal(t, "misbehaving node id is required", err.Error())

// Test case: Misbehavior type is unspecified
_, err = NewSafetyFailureReport(
1,
proto.Misbehavior_MISBEHAVIOR_UNSPECIFIED,
true,
[]*envelopes.OriginatorEnvelope{env},
)
require.Error(t, err)
require.Equal(t, "misbehavior type is required", err.Error())
}
41 changes: 41 additions & 0 deletions pkg/misbehavior/report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package misbehavior

import (
"errors"

"github.com/xmtp/xmtpd/pkg/envelopes"
proto "github.com/xmtp/xmtpd/pkg/proto/xmtpv4/message_api"
)

type SafetyFailureReport struct {
misbehavingNodeId uint32
misbehaviorType proto.Misbehavior
submittedByNode bool
envelopes []*envelopes.OriginatorEnvelope
}

func NewSafetyFailureReport(
misbehavingNodeId uint32,
misbehaviorType proto.Misbehavior,
submittedByNode bool,
envs []*envelopes.OriginatorEnvelope,
) (*SafetyFailureReport, error) {
if len(envs) == 0 {
return nil, errors.New("no envelopes provided")
}

if misbehavingNodeId == 0 {
return nil, errors.New("misbehaving node id is required")
}

if misbehaviorType == proto.Misbehavior_MISBEHAVIOR_UNSPECIFIED {
return nil, errors.New("misbehavior type is required")
}

return &SafetyFailureReport{
misbehavingNodeId: misbehavingNodeId,
misbehaviorType: misbehaviorType,
submittedByNode: submittedByNode,
envelopes: envs,
}, nil
}

0 comments on commit 7666a1b

Please sign in to comment.