diff --git a/fraudserv/service.go b/fraudserv/service.go index 9cf2b1d..53511cf 100644 --- a/fraudserv/service.go +++ b/fraudserv/service.go @@ -177,12 +177,22 @@ func (f *ProofService[H]) processIncoming( proofType fraud.ProofType, from peer.ID, msg *pubsub.Message, -) pubsub.ValidationResult { +) (res pubsub.ValidationResult) { ctx, span := tracer.Start(ctx, "process_proof", trace.WithAttributes( attribute.String("proof_type", string(proofType)), )) defer span.End() + defer func() { + r := recover() + if r != nil { + err := fmt.Errorf("PANIC while processing a proof: %s", r) + log.Error(err) + span.RecordError(err) + res = pubsub.ValidationReject + } + }() + // unmarshal message to the Proof. // Peer will be added to black list if unmarshalling fails. proof, err := f.unmarshal.Unmarshal(proofType, msg.Data) diff --git a/fraudserv/service_test.go b/fraudserv/service_test.go index 7239bdc..5431847 100644 --- a/fraudserv/service_test.go +++ b/fraudserv/service_test.go @@ -19,6 +19,28 @@ import ( "github.com/celestiaorg/go-fraud/fraudtest" ) +func TestService_processIncomingRecovery(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + t.Cleanup(cancel) + + serv := newTestService(ctx, t, false) + require.NoError(t, serv.Start(ctx)) + + fraud := fraudtest.NewPanickingProof[*headertest.DummyHeader]() + sub, err := serv.Subscribe(fraud.Type()) + require.NoError(t, err) + defer sub.Cancel() + + err = serv.Broadcast(ctx, fraud) + require.Error(t, err) + + ctx2, cancel := context.WithTimeout(context.Background(), time.Millisecond*100) + t.Cleanup(cancel) + + _, err = sub.Proof(ctx2) + require.Error(t, err) +} + func TestService_SubscribeBroadcastValid(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second) t.Cleanup(cancel) diff --git a/fraudtest/dummy_proof.go b/fraudtest/dummy_proof.go index 3313ae8..62d68be 100644 --- a/fraudtest/dummy_proof.go +++ b/fraudtest/dummy_proof.go @@ -11,15 +11,20 @@ import ( const DummyProofType fraud.ProofType = "DummyProof" type DummyProof[H header.Header[H]] struct { - Valid bool + Valid bool + Panics bool } func NewValidProof[H header.Header[H]]() *DummyProof[H] { - return &DummyProof[H]{true} + return &DummyProof[H]{true, false} } func NewInvalidProof[H header.Header[H]]() *DummyProof[H] { - return &DummyProof[H]{false} + return &DummyProof[H]{false, false} +} + +func NewPanickingProof[H header.Header[H]]() *DummyProof[H] { + return &DummyProof[H]{false, true} } func (m *DummyProof[H]) Type() fraud.ProofType { @@ -35,6 +40,9 @@ func (m *DummyProof[H]) Height() uint64 { } func (m *DummyProof[H]) Validate(H) error { + if m.Panics { + panic("crippling anxiety panic attack") + } if !m.Valid { return errors.New("DummyProof: proof is not valid") }